Full Version : One target after another
xmlspawner >>Scripting Support >>One target after another


<< Prev | Next >>

Fafnir- 03-29-2006
I've gotten a good start on this by studying existing scripts, but I've come up against a wall and would like a hint. I'm working on a command that will sort or move any of a given object in a player's backpack into a sub pack or bag.

The problem I am running into is how to offer a target for the item to sort, followed by a target for the destination bag. When I just have one target, I get the target, but when I add the second, I get nothing at all. My code is below. It does not have the actually sort command fleshed out, but I don't think I will have a problem with that, if I can get the item and the destination collected.

CODE

using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using Server.Gumps;
using Server.Network;

namespace Server.AdminCommands
{
public class Command
{
 public static void Initialize()
 {
  Server.Commands.Register( "Sort", AccessLevel.Player, new CommandEventHandler( SendCommand ) );
 }
 [Usage( "Sort" )]
 public static void SendCommand( CommandEventArgs e )
 {
  Mobile from = e.Mobile;
  from.Target = new SortTarget();
  from.SendMessage("Select the item to sort");
 }

 public static void SendSecondCommand( CommandEventArgs e)
 {
  Mobile from = e.Mobile;
  from.Target = new SortDestination();
  from.SendMessage("Select the bag to sort to");
 }
 public class SortTarget : Target
 {
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
  if (o is Item)
              {
                  from.SendMessage(1150, o.ToString() );
              }
          }
      }
   public class SortDestination : Target
 {
  public SortDestination() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object d )
  {
  if (d is BaseContainer)
              {
                  from.SendMessage(1150, d.ToString() );
              }
          }
      }
  }
}


ArteGordon- 03-29-2006
you just need to assign the destination target in the OnTarget method of the first target.

QUOTE

public class SortTarget : Target
{
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
  if (o is Item)
              {
                  from.SendMessage(1150, o.ToString() );
from.Target = new SortDestination();
              }
          }
      }

Odee- 03-29-2006
I like the idea. If you could e-mail me the complete de-bugged script, I would like to implement into my test server and play around with it. Thanks, keep up the good work.

My email is ---- odee115@hotmail.com. Please make the subject [Sort Command

Fafnir- 03-29-2006
Thanks Arte! I'll see where I can go with it now.

And Odee, I'll gladly share when it is completed. I was surprised that none had thought to do this before, but I coul dnot find anything like it.

Fafnir- 03-29-2006
Ok, I am stuck again. There is more than one thing I do not understand.

My compile errors are:

- Error: Scripts\Misc\sort.cs: CS0246: (line 45, column 58) The type or namespa
ce name 'o' could not be found (are you missing a using directive or an assembly
reference?)
- Error: Scripts\Misc\sort.cs: CS0117: (line 49, column 8) 'System.Array' does
not contain a definition for 'parent'

My code is below. Is my concept sound? I seem to have a scope problem, but I can't figure it out.

CODE

using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using Server.Misc;
using Server.Prompts;
using Server.ContextMenus;
using Server.Multis;

namespace Server.AdminCommands
{
public class Command
{
 public static void Initialize()
 {
  Server.Commands.Register( "Sort", AccessLevel.Player, new CommandEventHandler( SendCommand ) );
 }
 [Usage( "Sort" )]
 public static void SendCommand( CommandEventArgs e )
 {
  Mobile from = e.Mobile;
  from.Target = new SortTarget();
  from.SendMessage("Select the item to sort");
 }


 public class SortTarget : Target
 {
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
   
   if ( o is Item)
   {
    from.SendMessage(1150, o.ToString() );
    from.Target = new SortDestination();
    from.SendMessage("Select the bag to sort to");
    Container pack = from.Backpack;
    if ( pack != null )
    {
     Item[] SortObjects = pack.FindItemsByType( typeof( o ));//Line 45
     int i;
     for ( i=0; i < SortObjects.Length; ++i )
     {
      SortObjects.parent[i] = new SortDestination();//Line 49
     }
     ++i; //make i = number of sorted items
     from.SendMessage(1150, i.ToString(), " items sorted" );
    }
   }
   
  }
 }
 public class SortDestination : Target
 {
  public SortDestination() : base( -1, true, TargetFlags.None )
  {
  }
   protected override void OnTarget( Mobile from, object d )
   {
    if (d is BaseContainer)
   {
    from.SendMessage(1150, d.ToString() );
   }
  }
 }
}

}


I have marked the line numbers for the error lines.

ArteGordon- 03-30-2006
you want something like this for that line

CODE

Item[] SortObjects = pack.FindItemsByType(o.GetType());//Line 45


and here

CODE

SortObjects.parent[i] = new SortDestination();//Line 49


you should use one of the Container class methods used for adding items to the container, such as DropItem instead of just setting the Parent property since the container also needs to keep track of what it has in it, and setting the Parent of the item doesnt do that.

Also, the logic of the code isnt going to work. What you need to do is to pass the first targeted item as an argument to the SortDestination constructor, and then in the OnTarget method of the SortDestination target is where you need to do the actual sorting.

Fafnir- 03-30-2006
Thanks again Arte! I'm learning a lot here!

Fafnir- 03-30-2006
Well, after many re-writes and many errors, my code is error and warning free, but, it is not doing what I intend yet.

I'm not getting into my OnTarget method for SortDestination at all it seems. I have added some WriteLines to test and I don't know why, but it does nothing in that method.

Code below:

CODE

using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using Server.Misc;
using Server.Prompts;
using Server.ContextMenus;
using Server.Multis;

namespace Server.Scripts.Commands
{
public class Command
{
 public static void Initialize()
 {
  Server.Commands.Register( "Sort", AccessLevel.Player, new CommandEventHandler( SendCommand ) );
 }
 [Usage( "Sort" )]
 public static void SendCommand( CommandEventArgs e )
 {
  Mobile from = e.Mobile;
  from.Target = new SortTarget();
  from.SendMessage("Select the item to sort");
 }


 public class SortTarget : Target
 {
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
   if ( o is Item)
   {
    Bag bag = null;
    from.SendMessage(1150, o.ToString() );
    from.Target = new SortDestination( from, o, bag );
    from.SendMessage("Select the bag to sort to");
   }
  }
 }
 public class SortDestination  : Target
 {
  Bag bag = null;
  Mobile m = null;
  object thing = null;
 
  public SortDestination( Mobile m, object o, Bag bag ) : base( -1, true, TargetFlags.None )
  {
   thing = o;
   m.SendMessage(1150, thing.ToString()); //have it here!
 
  }
  protected void OnTarget( Mobile m, Bag bag )
  {
   Console.WriteLine("OnTarget entry");//not getting here at all
   
   m.SendMessage(1150, thing.ToString(), " Destination" );//no message here - second target shows and seems to select bag
   m.SendMessage(1150, bag.ToString() );
   Container pack = m.Backpack;
   if ( pack != null )
   {
   Item[] SortObjects = pack.FindItemsByType( thing.GetType());
   int i;
   for ( i=0; i < SortObjects.Length; ++i )
   {
    bag.DropItem( SortObjects[i]);
   }
   ++i; //make i = number of sorted items
   m.SendMessage(1150, i.ToString(), " items sorted" );
   }
  }
 }
}

}

ArteGordon- 03-31-2006
that is because when you changed the arguments and omitted the override you created a new method here

CODE

protected void OnTarget( Mobile m, Bag bag )


rather than overriding the method that actually gets called that looks like

CODE

protected override void OnTarget( Mobile from, object o )


The Target class automatically calls the OnTarget method above, but it wont know anything about your new OnTarget method.

Now you probably tried the override and it complained about no override with those arguments. That is because the OnTarget method takes a mobile and an object arg, not a mobile and a bag.

Note that since you define the bag variable in your SortDestination class like this

QUOTE

public class SortDestination  : Target
{
  Bag bag = null;
  Mobile m = null;
  object thing = null;

  public SortDestination( Mobile m, object o, Bag bag ) : base( -1, true, TargetFlags.None )
  {
  thing = o;
  m.SendMessage(1150, thing.ToString()); //have it here!

  }



you can access that variable anywhere within the class, including within your OnTarget method. So you dont have to explicitly pass bag as an arg to your OnTarget method.
I'm not exactly sure what purpose the bag arg is supposed to serve anyway. I thought that was what you were picking as the second target.

Fafnir- 03-31-2006
I'm not sure what I was trying to do there either with the bag. Like a said, I've had many errors and they seemed to toggle back and forth. I'm sure it has to do with my lack of understanding somewhere. I'll see what I can do given your comments. Thanks!

ArteGordon- 03-31-2006
yeah, I think that you just want to assign the bag based on the object that is passed into the OnTarget method of SortDestination. You dont need to pass it around as an argument.

Fafnir- 03-31-2006
OK, I changed my OnTargets back to Mobile, Object variable and I am getting this error:

- Error: Scripts\Misc\sort.cs: CS0117: (line 70, column 7) 'object' does not co
ntain a definition for 'DropItem'

Below is my second OnTarget method: How do I turn that object into a bag, so that it will use my DropItem method?

CODE

protected void OnTarget( Mobile m, object d )
  {
   Console.WriteLine("OnTarget entry");//not getting here at all
   
   m.SendMessage(1150, thing.ToString(), " Destination" );//no message here - second target shows and seems to select bag
   m.SendMessage(1150, d.ToString() );
   Container pack = m.Backpack;
   if ( pack != null & (d is Bag) )
   {
    Item[] SortObjects = pack.FindItemsByType( thing.GetType());
    int i;
    for ( i=0; i < SortObjects.Length; ++i )
    {
     d.DropItem( SortObjects[i]);
    }
    ++i; //make i = number of sorted items
    m.SendMessage(1150, i.ToString(), " items sorted" );
   }
  }

Fafnir- 03-31-2006
Well, I figured that one out myself, casting and it seems to work. At least I don't get the error, but it still doesn't do anything with my second OnTarget.

Thanks for all of your help Arte. Code is below. Same results as before. I get both targets and my messages show the item I target first, but do not show any message for the bag targeted and the item is not dropped to the bag.

CODE
using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using Server.Misc;
using Server.Prompts;
using Server.ContextMenus;
using Server.Multis;

namespace Server.Scripts.Commands
{
public class Command
{
 public static void Initialize()
 {
  Server.Commands.Register( "Sort", AccessLevel.Player, new CommandEventHandler( SendCommand ) );
 }
 [Usage( "Sort" )]
 public static void SendCommand( CommandEventArgs e )
 {
  Mobile from = e.Mobile;
  from.Target = new SortTarget();
  from.SendMessage("Select the item to sort");
 }


 public class SortTarget : Target
 {
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
   if ( o is Item)
   {
    from.SendMessage(1150, o.ToString() );
    from.Target = new SortDestination( from, o );
    from.SendMessage("Select the bag to sort to");
   }
  }
 }
 public class SortDestination  : Target
 {
  Bag bag = null;
  Mobile m = null;
  object thing = null;
 
  public SortDestination( Mobile m, object o ) : base( -1, true, TargetFlags.None )
  {
   thing = o;
   m.SendMessage(1150, thing.ToString()); //have it here!
 
  }
  protected void OnTarget( Mobile m, object d )
  {
   Console.WriteLine("OnTarget entry");//not getting here at all
   
   m.SendMessage(1150, thing.ToString(), " Destination" );//no message here - second target shows and seems to select bag
   m.SendMessage(1150, d.ToString() );
   Container pack = m.Backpack;
   bag = (Bag) d;
   if ( pack != null & (d is Bag) )
   {
    Item[] SortObjects = pack.FindItemsByType( thing.GetType());
    int i;
    for ( i=0; i < SortObjects.Length; ++i )
    {
     bag.DropItem( SortObjects[i]);
    }
    ++i; //make i = number of sorted items
    m.SendMessage(1150, i.ToString(), " items sorted" );
   }
  }
 }
}

}

ArteGordon- 03-31-2006
you need to override the existing OnTarget method rather than declare a new one

CODE

protected void OnTarget( Mobile m, object d )


to this

CODE

protected override void OnTarget( Mobile m, object d )

Fafnir- 03-31-2006
Heh, yeah, I saw that one on my own. I originally had it as an override, but removed it trying to resolve an error!

My finshed, working code is below. It is donated to the community. If anyone improves on my code, I'd appreciate a copy of the resulting code.

Thanks again Arte for your patient scripting help!

CODE
///Fafnir - [sortv0.1 31 Mar 2006
///This command allows a player to move (sort) any number of items in their pack
///into a sub pack.
///
///My thanks to Arte Gordon for his patient coding aid to this newbie scripter!


using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using Server.Misc;
using Server.Prompts;
using Server.ContextMenus;
using Server.Multis;

namespace Server.Scripts.Commands
{
public class Command
{
 public static void Initialize()
 {
  Server.Commands.Register( "Sort", AccessLevel.Player, new CommandEventHandler( SendCommand ) );
 }
 [Usage( "Sort" )]
 public static void SendCommand( CommandEventArgs e )
 {
  Mobile from = e.Mobile;
  from.Target = new SortTarget();
  from.SendMessage("Select the item to sort");
 }


 public class SortTarget : Target
 {
  public SortTarget() : base( -1, true, TargetFlags.None )
  {
  }
  protected override void OnTarget( Mobile from, object o )
  {
   if ( o is Item)
   {
    from.Target = new SortDestination( from, o );
    from.SendMessage("Select the bag to sort to");
   }
  }
 }
 public class SortDestination  : Target
 {
  Bag bag = null;
  Mobile m = null;
  object thing = null;
 
  public SortDestination( Mobile m, object o ) : base( -1, true, TargetFlags.None )
  {
   thing = o;
  }
  protected override void OnTarget( Mobile m, object d )
  {
   Container pack = m.Backpack;
   bag = d as Bag;
   if ( pack != null & (d is Bag) )
   {
    Item[] SortObjects = pack.FindItemsByType( thing.GetType());
    int i;
    for ( i=0; i < SortObjects.Length; ++i )
    {
     bag.DropItem( SortObjects[i]);
    }
    m.SendMessage(1150, i.ToString());
    m.SendMessage(1150, "items moved");
   }
  }
 }
}

}