zerodowned

Moderator
mirror thread: http://www.playuo.org/emu/index.php?threads/help-with-using-list.1329/
-----
I'm working on this code below as part learning and part planned update to my spellbar script.
What I cannot figure out is how to Remove a button from the list.

I've tried a few ways to do it
list.Remove( new SpellBarButton ( 1, "Spell 1", 1 ));
and using a foreach statement to go through the list and remove a button, but that caused a crash.
Any help would be appreciated.

C#:
using System;
using Server;
using Server.Network;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using System.Collections.Generic;
using Server.Spells;
using Server.Spells.First;
using Server.Commands;
namespace Server.Gumps
{
    public class SpellBarButton
    {
        public int SpellID{ set; get; }
        public string SpellName { set; get; }
        public int ButtonID{ set; get; }
     
        public SpellBarButton(int spellID, string spellName, int buttonID)
        {
            this.SpellID = spellID;
            this.SpellName = spellName;
            this.ButtonID = buttonID;
        }
     
    }
    public class SpellBarTest : Gump
    {
        public static void Initialize()
            {
             CommandSystem.Register( "spellbartest", AccessLevel.Player, new CommandEventHandler( spellbartest_OnCommand ) );
            }
     
           [Usage("spellbartest")]
            [Description("test")]
          public static void spellbartest_OnCommand( CommandEventArgs e )
          {     
            if (e.Mobile.HasGump(typeof(SpellBarTest)) ); {
                e.Mobile.CloseGump(typeof(SpellBarTest));
            }
             
            e.Mobile.SendGump( new SpellBarTest(e.Mobile) );
        }
 
        public List<SpellBarButton> list = new List<SpellBarButton>();
     
        public static bool HasSpell( Mobile from, int spellID )
        {
            Spellbook book = Spellbook.Find( from, spellID );
            return ( book != null && book.HasSpell( spellID ) );
        }
     
        public SpellBarTest( Mobile from ) : base( 0, 0 )
        {
            Closable=true; Disposable=true; Dragable=true; Resizable=false;
         
            AddPage(0);
         
            AddBackground(0, 0, 400, 100, 9200);
         
            list.Add( new SpellBarButton ( 1, "Spell 1", 1 ));
            list.Add( new SpellBarButton ( 2, "Spell 2", 2 ));
            list.Add( new SpellBarButton ( 3, "Spell 3", 3 ));
         
         
            int x = 0;
            foreach( SpellBarButton button in list)
            {
                x+=25;
                AddButton( x, 10, 2084, 2084, button.ButtonID, GumpButtonType.Reply, 0);
            }
        }
 
        public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;
         
            foreach( SpellBarButton button in list)
            {
                switch ( button.ButtonID )
                {
                    case 1:
                    {       
                        if ( HasSpell( from, 0 ) )
                        new ClumsySpell( from, null ).Cast();
                        break;
                    }
                    case 2:
                    {        
                        if ( HasSpell( from, 1 ) )
                        new CreateFoodSpell( from, null ).Cast();
                        break;
                    }
                    case 3:
                    {        
                        if ( HasSpell( from, 2 ) )
                        new FeeblemindSpell( from, null ).Cast();
                        break;
                    }
                }
            }
        }
    }
}
 
You can use linq to easily do what you want.

list.RemoveAll(x=> x.SpellID==1);

//Edit, it's not linq, brain is fried. It should work for you though.
 
Last edited:
I wouldn't worry about defining the ButtonID's in each entry either - the SpellID's are unique, so you can use them as the buttonID in AddButton.
Button's don't have to begin at ID 0 and increment from there, you can assign any number you want as long as each buttonID is unique.
Since 0 is usually reserved for the Close button, it may be best to use SpellID + 1.

ButtonID's are just one less thing to worry about then :)

Also, you won't need to switch/case each SpellID!
You can use: SpellRegistry.NewSpell(int spellID, Mobile caster, Item scroll)
C#:
Spell spell = SpellRegistry.NewSpell( spellID, caster, null);

if( spell.Cast() )
{
    caster.SendMessage( "Cast {0} from Spell Bar success!", spell.Name );
}
 
thank you both very much

rewrote it like so
probably not the finished version but it definitely saves hundreds of lines of code. figuratively if not literally.


Code:
public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;
          
            int spellID = (info.ButtonID - 1);
          
            Spell spell = SpellRegistry.NewSpell( spellID, from, null);
          
            if( HasSpell( from, spellID ) )
                spell.Cast();
            else
            {
                list.RemoveAll( i=> i.SpellID == info.ButtonID );
                return;
            }
        }

full code after some extra edits

Code:
using System;
using Server;
using Server.Network;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using System.Collections.Generic;
using Server.Spells;
using Server.Spells.First;
using Server.Commands;


namespace Server.Gumps
{
    public class SpellBarButton
    {
        public int SpellID{ set; get; }
        public string SpellName { set; get; }
       
        public SpellBarButton(int spellID, string spellName)
        {
            this.SpellID = spellID;
            this.SpellName = spellName;
        }
       
    }

    public class SpellBarTest : Gump
    {
        public static void Initialize()
            {
             CommandSystem.Register( "spellbartest", AccessLevel.Player, new CommandEventHandler( spellbartest_OnCommand ) );
            }

       
           [Usage("spellbartest")]
            [Description("test")]
          public static void spellbartest_OnCommand( CommandEventArgs e )
          {       
            if (e.Mobile.HasGump(typeof(SpellBarTest)) ); {
                e.Mobile.CloseGump(typeof(SpellBarTest));
            }
               
            e.Mobile.SendGump( new SpellBarTest(e.Mobile) );
        }
   
        public List<SpellBarButton> list = new List<SpellBarButton>();
       
        public static bool HasSpell( Mobile from, int spellID )
        {
            Spellbook book = Spellbook.Find( from, spellID );
            return ( book != null && book.HasSpell( spellID ) );
        }
       
        public SpellBarTest( Mobile from ) : base( 0, 0 )
        {
            Closable=true; Disposable=true; Dragable=true; Resizable=false;
           
            AddPage(0);
           
            AddBackground(0, 0, 400, 100, 9200);
           
            list.Add( new SpellBarButton ( 0, "Spell 1"));
            list.Add( new SpellBarButton ( 1, "Spell 2"));
            list.Add( new SpellBarButton ( 2, "Spell 3"));
           
            int x = 0;
            foreach( SpellBarButton button in list)
            {
                x+=25;
                // SpellID + 1 = ButtonID. This avoid the ButtonID of 0 that would cause the gump to close
                AddButton( x, 10, 2084, 2084, button.SpellID + 1, GumpButtonType.Reply, 0);
            }
        }
   
        public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;
           
            // Convert ButtonID back to SpellID but deducting 1
            int spellID = (info.ButtonID - 1);
           
            Spell spell = SpellRegistry.NewSpell( spellID, from, null);
           
            if( HasSpell( from, spellID ) )
                spell.Cast();
            else
            {
                list.RemoveAll( i=> i.SpellID == info.ButtonID );
                return;
            }
        }
    }
}
 
Last edited:
Looks great :D

I would recommend first checking HasSpell() before creating a new Spell with NewSpell(), because if they don't have the spell, then you won't need the Spell object :)

Also one tiny thing in OnResponse() is the list.RemoveAll( i=> i.SpellID== info.ButtonID); - you may want to change info.ButtonID to spellID, or it will be removing the wrong ID.
Be sure to check if info.ButtonID - 1 is less than 0 too, because if it's -1, you can do nothing as the button click would have been to close the gump.
 
off topic with the thread title but related to the same code...

I'm running into trouble with nesting for loops.
What I'm trying to do is figure out how to make if I have only 9 things on a list, but creating 3 columns and 4 rows, how do I make it stop doing two things:

1) Placing button 1, and only button 1 ( in the 3x4 arrangement )
2) Stop it from starting over at button 1 after button 9 until it reaches the end of the column/rows

this code does the first one:
Code:
for (int i = 0; i < list.Count; i++) {
                for (int x = 0; x < colSpan; x++) {
                    for (int y = 0; y < 4; y++) {
                    // SpellID + 1 = ButtonID. This avoid the ButtonID of 0 that would cause the gump to close
                    AddButton( 45 * x, y * 45, 2259, 2259, list[i].SpellID + 1, GumpButtonType.Reply, 0);
            } } }

this code does the second one:
Code:
for (int i = 0, x = 0; i < list.Count; i++, x++) {
                for (int y = 0; y < 4; y++) {
                    // SpellID + 1 = ButtonID. This avoid the ButtonID of 0 that would cause the gump to close
                    AddButton( 45 * x, y * 45, 2259, 2259, list[i].SpellID + 1, GumpButtonType.Reply, 0);
            } }

I've tried using if( i == list.Count ) { break; } to stop the loop but it doesn't seem to do anything
 
I'm a little confused with what you are trying to accomplish here, you are trying to to create a column / row arrangement right? You could do what you are doing by using nested loops but you could also do it the following way using a single foreach loop.

Code:
int x=0;
int y=0;
foreach(SpellBarButton o in list)
{
	AddButton(45* x, y *45, 2259, 2259, o.SpellID+1, GumpButtonType.Reply, 0);
	x++;
	if (o.SpellID%3 != 0 || o.SpellID == 0) continue;
	y++;
	x = 0;
}
 
If you're using VNc, you can replace your List<T> with a Grid<T> and that will do all the hard work for you;

C#:
public Grid<SpellBarButton> Grid = new Grid<SpellBarButton>(3, 4); // 3x4 initial size

C#:
// Row 1
Grid[0, 0] = new SpellBarButton(0, "Spell 1");
Grid[1, 0] = new SpellBarButton(1, "Spell 2");
Grid[2, 0] = new SpellBarButton(2, "Spell 3");

// Row 2
Grid[0, 1] = new SpellBarButton(3, "Spell 4");
Grid[1, 1] = new SpellBarButton(4, "Spell 5");
Grid[2, 1] = new SpellBarButton(5, "Spell 6");

// Row 3
Grid[0, 2] = new SpellBarButton(6, "Spell 7");
Grid[1, 2] = new SpellBarButton(7, "Spell 8");
Grid[2, 2] = new SpellBarButton(8, "Spell 9");

// Row 4
Grid[0, 3] = new SpellBarButton(9, "Spell 10");
Grid[1, 3] = new SpellBarButton(10, "Spell 11");
Grid[2, 3] = new SpellBarButton(11, "Spell 12");

C#:
Grid.ForEach( (x, y, spb) =>
{
     if( spb != null )
         AddButton( x * 45, y * 45, 2259, 2259, spb.SpellID + 1, GumpButtonType.Reply, 0);
});
 
I'm a little confused with what you are trying to accomplish here, you are trying to to create a column / row arrangement right? You could do what you are doing by using nested loops but you could also do it the following way using a single foreach loop.

Code:
int x=0;
int y=0;
foreach(SpellBarButton o in list)
{
	AddButton(45* x, y *45, 2259, 2259, o.SpellID+1, GumpButtonType.Reply, 0);
	x++;
	if (o.SpellID%3 != 0 || o.SpellID == 0) continue;
	y++;
	x = 0;
}

oh, okay. i guess I was just trying to make it too difficult by using for loops for x and y when it wasn't neccesary.

If you're using VNc, you can replace your List<T> with a Grid<T> and that will do all the hard work for you;

C#:
public Grid<SpellBarButton> Grid = new Grid<SpellBarButton>(3, 4); // 3x4 initial size

C#:
// Row 1
Grid[0, 0] = new SpellBarButton(0, "Spell 1");
Grid[1, 0] = new SpellBarButton(1, "Spell 2");
Grid[2, 0] = new SpellBarButton(2, "Spell 3");

// Row 2
Grid[0, 1] = new SpellBarButton(3, "Spell 4");
Grid[1, 1] = new SpellBarButton(4, "Spell 5");
Grid[2, 1] = new SpellBarButton(5, "Spell 6");

// Row 3
Grid[0, 2] = new SpellBarButton(6, "Spell 7");
Grid[1, 2] = new SpellBarButton(7, "Spell 8");
Grid[2, 2] = new SpellBarButton(8, "Spell 9");

// Row 4
Grid[0, 3] = new SpellBarButton(9, "Spell 10");
Grid[1, 3] = new SpellBarButton(10, "Spell 11");
Grid[2, 3] = new SpellBarButton(11, "Spell 12");

C#:
Grid.ForEach( (x, y, spb) =>
{
     if( spb != null )
         AddButton( x * 45, y * 45, 2259, 2259, spb.SpellID + 1, GumpButtonType.Reply, 0);
});

always good to know more about VNC has to offer. but i'm not sure that would work for this particular code since the location of buttons wouldn't be static.
 
There is usually a thousand different ways to get things to work, it really just boils down to what the person that is programing is used to and comfortable with.

I like to write the least amount of code though since I am mostly writing code for microprocessors with limited amount of memory for instructions so I usually spend a long time trying to write as little as possible :)


Is that code what you are after?
 
There is usually a thousand different ways to get things to work, it really just boils down to what the person that is programing is used to and comfortable with.

I like to write the least amount of code though since I am mostly writing code for microprocessors with limited amount of memory for instructions so I usually spend a long time trying to write as little as possible :)


Is that code what you are after?
simple works for me and the code does too
Thank you :)

It can be adapted to work in any way you want; I gave examples based on experience :)

But the simple solution is what @dmurphy suggested with the x-y run.
Thank you, I'll have to take a look at that further but i think i will stick with the simple solution
 
Back