Full Version : Healing .grab command.
xmlspawner >>Scripting Support >>Healing .grab command.
<< Prev | Next >>
Galfaroth- 02-17-2006
Hello all. Here is my .grab command, but it has one bug:

CODE
using System; using System.IO; using System.Text; using Server.Items; using System.Reflection;
using System.Collections;
using Server;
namespace Server.Scripts.Commands
{
public class GrabCommand
{
public static void Initialize()
{
Server.Commands.Register( "Grab", AccessLevel.Player, new CommandEventHandler( Grab_OnCommand ) );
}
public static void Grab_OnCommand(CommandEventArgs e){
Mobile from = e.Mobile;
ArrayList range = new ArrayList();
IPooledEnumerable eable = from.Map.GetItemsInRange( from.Location, 3 );
foreach ( Item check in eable )
{
if ( check is Corpse ){
range.AddRange( check.Items );
}
else
range.Add( check );
}
eable.Free();
foreach ( Item item in range )
{
if ( item.Movable ) {
from.Emote("*Yoink*");
from.AddToBackpack( item );
}
}
}
}
}

BUG:
1. They takie all items in one second with one emote, but they should take one item per one second and every taking should be noticed by emote. If there is stackable thing (like gold or regs) they should take all type by one take, so in one second they take all gold, and in next all sulphurous ash, next ginseng etc.
Is there anyway to do this ?
ArteGordon- 02-17-2006
to have it automatically take an item per second you will basically have to put all of this

QUOTE
Mobile from = e.Mobile; ArrayList range = new ArrayList(); IPooledEnumerable eable = from.Map.GetItemsInRange( from.Location, 3 ); foreach ( Item check in eable ) {
if ( check is Corpse ){
range.AddRange( check.Items );
}
else
range.Add( check );
}
eable.Free();
foreach ( Item item in range )
{
if ( item.Movable ) {
from.Emote("*Yoink*");
from.AddToBackpack( item );
break;
}
}

into the OnTick method of a timer configured tick once a second.
To get it to take only one item per tick, you just have to add a break into your loop that removes items.
Galfaroth- 02-17-2006

CODE
using System; using System.IO; using System.Text; using Server.Items; using System.Reflection;
using System.Collections;
using Server;
namespace Server.Scripts.Commands
{
public class GrabCommand
{
public static void Initialize()
{
Server.Commands.Register( "Grab", AccessLevel.Player, new CommandEventHandler( Grab_OnCommand ) );
}
public static void Grab_OnCommand(CommandEventArgs e){
Mobile from = e.Mobile;
ArrayList range = new ArrayList();
IPooledEnumerable eable = from.Map.GetItemsInRange( from.Location, 3 );
foreach ( Item check in eable )
{
if ( check is Corpse ){
return;
}
else
range.Add( check );
}
eable.Free();
foreach ( Item item in range )
{
if ( item.Movable ) {
from.Emote("*Zbiera*");
from.AddToBackpack( item );
Break;
}
}
}
}
public class GrabTimer : Timer
{
private Mobile m;
public GrabTimer( Mobile from ) : base( TimeSpan.FromSeconds( 1 ) )
{
Priority = TimerPriority.OneSecond;
m = from;
}
protected override void OnTick()
{
GrabTimer grabTimer = new GrabTimer( m );
PlayerMobile pm = m as PlayerMobile;
if ( !(Item item in range) )
{
Stop();
}
}
}
}

What should I do there to finish this?
ArteGordon- 02-17-2006
you need to move all of the corpse and item search code into your OnTick. Your Grab_OnCommand will basically do nothing except start the timer.
Galfaroth- 02-17-2006

CODE
using System; using System.IO; using System.Text; using Server.Items; using System.Reflection;
using System.Collections;
using Server;
namespace Server.Scripts.Commands
{
public class GrabCommand
{
public static void Initialize()
{
Server.Commands.Register( "Grab", AccessLevel.Player, new CommandEventHandler( Grab_OnCommand ) );
}
public static void Grab_OnCommand(CommandEventArgs e)
{
Mobile m = e.Mobile;
GrabTimer grabTimer = new GrabTimer( m );
}
public class GrabTimer : Timer
{
private Mobile m;
public GrabTimer( Mobile from ) : base( TimeSpan.FromSeconds( 1 ) )
{
Priority = TimerPriority.OneSecond;
m = from;
}
protected override void OnTick()
{
//PlayerMobile pm = m as PlayerMobile;
ArrayList range = new ArrayList();
IPooledEnumerable eable = m.Map.GetItemsInRange( m.Location, 3 );
foreach ( Item check in eable )
{
if ( check is Corpse ){
return;
}
else
range.Add( check );
}
eable.Free();
foreach ( Item item in range )
{
if ( item.Movable ) {
m.Emote("*Zbiera*");
m.AddToBackpack( item );
//Break;
}
}
Stop();
}
}
} }

When typing .grab it doesn't do anything. There should be mistake somewhere.
ArteGordon- 02-17-2006
you need to start your timer after creating it

QUOTE
public static void Grab_OnCommand(CommandEventArgs e) { Mobile m = e.Mobile; GrabTimer grabTimer = new GrabTimer( m ); grabTimer.Start();
}

Galfaroth- 02-17-2006

CODE
using System; using System.IO; using System.Text; using Server.Items; using System.Reflection;
using System.Collections;
using Server;
namespace Server.Scripts.Commands
{
public class GrabCommand
{
public static void Initialize()
{
Server.Commands.Register( "Grab", AccessLevel.Player, new CommandEventHandler( Grab_OnCommand ) );
}
public static void Grab_OnCommand(CommandEventArgs e)
{
Mobile m = e.Mobile;
GrabTimer grabTimer = new GrabTimer( m );
grabTimer.Start();
}
public class GrabTimer : Timer
{
private Mobile m;
public GrabTimer( Mobile from ) : base( TimeSpan.FromSeconds( 1 ) )
{
Priority = TimerPriority.OneSecond;
m = from;
}
protected override void OnTick()
{
ArrayList range = new ArrayList();
IPooledEnumerable eable = m.Map.GetItemsInRange( m.Location, 3 );
foreach ( Item check in eable )
{
if ( check is Corpse ){
return;
}
else
range.Add( check );
}
eable.Free();
foreach ( Item item in range )
{
if ( item.Movable ) {
m.Emote("*Zbiera*");
m.AddToBackpack( item );
GrabTimer grabTimer = new GrabTimer( m );
grabTimer.Start();
break;
}
}
Stop();
}
}
} }

Okay works perfect (here is script for everyone). Arte one question - are those timers stopped? Because many timers started can lag server. Is it good script now?
ArteGordon- 02-17-2006
you could also do it like this

CODE
public GrabTimer( Mobile from ) : base( TimeSpan.FromSeconds( 1 ), TimeSpan.FromSeconds( 1 ) )

and then

CODE
if ( item.Movable ) { m.Emote("*Zbiera*"); m.AddToBackpack( item ); return;

which would just have the single timer running until it didnt find any more items, and then it would stop.
Galfaroth- 02-22-2006
Here is the code, but after some hours, server has 99% of usage of memory. What is bad in here?

CODE
using System; using Server.Items; using System.Collections; using Server.Misc; using Server.Mobiles;
namespace Server.Scripts.Commands
{
public class GrabCommand
{
public static void Initialize()
{
Server.Commands.Register( "Grab", AccessLevel.Player, new CommandEventHandler( Grab_OnCommand ) );
}
public static void Grab_OnCommand(CommandEventArgs e)
{
Mobile m = e.Mobile;
GrabTimer grabTimer = new GrabTimer( m );
grabTimer.Start();
}
public class GrabTimer : Timer
{
private Mobile m;
public GrabTimer( Mobile from ) : base( TimeSpan.FromSeconds( 0 ) )
{
Priority = TimerPriority.OneSecond;
m = from;
}
protected override void OnTick()
{
if ( m.Alive == false )
{
return;
}
ArrayList range = new ArrayList();
IPooledEnumerable eable = m.Map.GetItemsInRange( m.Location, 3 );
foreach ( Item check in eable )
{
if ( check is Corpse )
{
Corpse c = (Corpse)check;
if (c.Owner != null )
{
if (!(c.Owner is PlayerMobile))
{
if ( NotorietyHandlers.CorpseNotoriety( m, c ) != Notoriety.Innocent )
{
range.AddRange( check.Items );
}
else
range.Add( check );
}
else
range.Add( check );
}
else
range.Add( check );
}
else
range.Add( check );
}
eable.Free();
m.Emote("*Zbiera*");
foreach ( Item item in range )
{
if ( item.Movable && item.Visible )
{
m.AddToBackpack( item );
GrabTimer grabTimer = new GrabTimer( m );
grabTimer.Start();
break;
}
else
this.Stop();
}
}
}
} }