PigPen

Member
ServUO Version
Publish Unknown
Ultima Expansion
Mondain's Legacy
(My shard runs on RunUO Version 2.1)

I am hoping the community can help me on this one.

I have been trying to make a container (chest and/or crate) to place in dungeons or have drop on quests where the contents on being filled can vary based on the 'Luck' of the player opening the chest for the 'very fist time'.

My current problem is my use of OnDoubleClick, where a test item 'PowderOfTranslocation' is sadly getting dropped and then dropped again every time the container is opened instead of only dropping the first time.

Somehow (I think) I need the 'private void Fill' section to check the player's Luck and then add the item but I don not know how to set up and pass the 'Luck' of the player to the 'private void Fill' section.

Any help on this would be greatly appreciated.

Here is the script (my current attempt):

Code:
using System;
using System.Collections;
using Server;
using Server.Misc;
using Server.Gumps;
using Server.Multis;
using Server.Network;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Plants;
using Server.Engines.PartySystem;
using Server.SpellCrafting.Items;
using System.Collections.Generic;

namespace Server.Items
{
    public class NewDungeonChest : LockableContainer
    {
        private static int[] m_ItemIDs = new int[]
        {
            0xE3D, 0xE3E, 0x9AB, 0xE3C, 0xE40, 0xE43, 0xE41, 0xE42, 0xE7C, 0xE3F
        };

        [Constructable]
        public NewDungeonChest( int level ) : base( Utility.RandomList( m_ItemIDs ) )
        {
            if (ItemID == 0x9AB || ItemID == 0xE40 || ItemID == 0xE41 || ItemID == 0xE7C)
            {
                Name = "a Metal Chest";
            }
            if (ItemID == 0xE43 || ItemID == 0xE42)
            {
                Name = "a Wooden Chest";
            }
            if (ItemID == 0xE3D || ItemID == 0xE3C ||  ItemID == 0xE3F || ItemID == 0xE3E )
            {
                Name = "a Crate";
            }

            Hue = 0;
            Fill( level );
        }

        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );

            list.Add( "From Tartarus Dungeons"  );
        }

        public override void OnDoubleClick( Mobile from )
        {
            if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
            {
                if (from.Luck >= 500)
                {
                    this.DropItem( new PowderOfTranslocation(50) );
                }

                if (from.Luck >= 1000)
                {
                    this.DropItem( new PowderOfTranslocation(100) );
                }

                if (from.Luck >= 2000)
                {
                    this.DropItem( new PowderOfTranslocation(200) );
                }

                Open( from );
            }
            else
                from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
        }

        private void Fill( int level )
        {
            TrapType = TrapType.ExplosionTrap;
            TrapPower = level * 25;
            TrapLevel = level;
            Locked = true;

            switch ( level )
            {
                case 1: RequiredSkill = 36; break;
                case 2: RequiredSkill = 76; break;
                case 3: RequiredSkill = 84; break;
                case 4: RequiredSkill = 92; break;
                case 5: RequiredSkill = 100; break;
            }

            LockLevel = RequiredSkill - 10;
            MaxLockLevel = RequiredSkill + 40;

            for ( int i = 0; i < level * 2; ++i )
            {
                Item item;

                if ( Core.AOS )
                    item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
                else
                    item = Loot.RandomArmorOrShieldOrWeapon();

                if ( item is BaseWeapon )
                {
                    BaseWeapon weapon = (BaseWeapon)item;

                    if ( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;

                        GetRandomAOSStats( out attributeCount, out min, out max );
                        BaseRunicTool.ApplyAttributesTo( weapon, attributeCount, min, max );
                    }
                    else
                    {
                        weapon.DamageLevel = (WeaponDamageLevel)Utility.Random( 6 );
                        weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random( 6 );
                        weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random( 6 );
                    }

                    DropItem( item );
                }

                else if ( item is BaseArmor )
                {
                    BaseArmor armor = (BaseArmor)item;

                    if ( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats( out attributeCount, out min, out max );
                        BaseRunicTool.ApplyAttributesTo( armor, attributeCount, min, max );
                    }
                    else
                    {
                        armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random( 6 );
                        armor.Durability = (ArmorDurabilityLevel)Utility.Random( 6 );
                    }

                    DropItem( item );
                }

                else if( item is BaseHat )
                {
                    BaseHat hat = (BaseHat)item;

                    if( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats( out attributeCount, out min, out  max );

                        BaseRunicTool.ApplyAttributesTo( hat, attributeCount, min, max );
                    }

                    DropItem( item );
                }
                else if( item is BaseJewel )
                {
                    int attributeCount;
                    int min, max;
                    GetRandomAOSStats( out attributeCount, out min, out max );

                    BaseRunicTool.ApplyAttributesTo( (BaseJewel)item, attributeCount, min, max );

                    DropItem( item );
                }
            }
        }

        private static void GetRandomAOSStats( out int attributeCount, out int min, out int max )
        {

            int rnd = Utility.Random( 7 );

            if ( rnd < 1 )
            {
                attributeCount = Utility.RandomMinMax( 6, 8 );
                min = 50; max = 100;
            }
            else if ( rnd < 3 )
            {
                attributeCount = Utility.RandomMinMax( 6, 8 );
                min = 50; max = 90;
            }
            else if ( rnd < 5 )
            {
                attributeCount = Utility.RandomMinMax( 5, 7 );
                min = 50; max = 80;
            }
            else if ( rnd < 7 )
            {
                attributeCount = Utility.RandomMinMax( 4, 6 );
                min = 50; max = 70;
            }
            else
            {
                attributeCount = 5;
                min = 50; max = 60;
            }
        }

        public NewDungeonChest( Serial serial ) : base( serial )
        {
        }

        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );

            writer.Write( (int) 0 ); // version

            //writer.Write( m_Name );
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );

            int version = reader.ReadInt();

            //m_Name = Utility.Intern( reader.ReadString() );
        }
    }
}

Many thanks for any time and assistance available.
 
Try with this:

C#:
public override void OnDoubleClick( Mobile from )
{
    if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
    {
        if (!HasAlreadyDroppedPowder(from)) // Check if the powder has already been dropped
        {
            if (from.Luck >= 500)
            {
                this.DropItem( new PowderOfTranslocation(50) );
            }

            if (from.Luck >= 1000)
            {
                this.DropItem( new PowderOfTranslocation(100) );
            }

            if (from.Luck >= 2000)
            {
                this.DropItem( new PowderOfTranslocation(200) );
            }
        }

        Open( from );
    }
    else
        from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
}

private bool HasAlreadyDroppedPowder(Mobile from)
{
    foreach (Item item in this.Items)
    {
        if (item is PowderOfTranslocation)
        {
            // PowderOfTranslocation is already in the container
            return true;
        }
    }
    
    return false;
}
 
Thank you 'Unlimited' for your eyes on this for me.

While I did wonder if your suggestion would carry over after Reboots/Saves etc. it did look like a solution to my problem.

However . . when I edited my script and tested it . . the problem persists. If the player opens the chest and takes out (removes) the test item (PowderOfTranslocation), more PowderOfTranslocation keeps getting added every time the chest is reopened. So, players can get an endless supply by opening/removing/reopening.

Here is my current script including your suggestion (which I do really appreciate):

Code:
using System;
using System.Collections;
using Server;
using Server.Misc;
using Server.Gumps;
using Server.Multis;
using Server.Network;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Plants;
using Server.Engines.PartySystem;
using Server.SpellCrafting.Items;
using System.Collections.Generic;

namespace Server.Items
{
    public class NewDungeonChest : LockableContainer
    {
        private static int[] m_ItemIDs = new int[]
        {
            0xE3D, 0xE3E, 0x9AB, 0xE3C, 0xE40, 0xE43, 0xE41, 0xE42, 0xE7C, 0xE3F 
        };

        [Constructable]
        public NewDungeonChest( int level ) : base( Utility.RandomList( m_ItemIDs ) )
        {
            if (ItemID == 0x9AB || ItemID == 0xE40 || ItemID == 0xE41 || ItemID == 0xE7C) 
            {
                Name = "a Metal Chest";
            }
            if (ItemID == 0xE43 || ItemID == 0xE42)
            {
                Name = "a Wooden Chest";
            }
            if (ItemID == 0xE3D || ItemID == 0xE3C ||  ItemID == 0xE3F || ItemID == 0xE3E )
            {
                Name = "a Crate";
            }

            Hue = 0;
            Fill( level );
        }

        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );

            list.Add( "From Tartarus Dungeons"  );
        }

        public override void OnDoubleClick( Mobile from )
        {
            if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) )
            {

                //Insert Check For Luck Here:

                if (!HasAlreadyDroppedPowder(from)) // Check if the powder has already been dropped
                {
                    if (from.Luck >= 2000)
                    {
                        this.DropItem( new PowderOfTranslocation(200) );
                    }

                    else if (from.Luck >= 1000)
                    {
                        this.DropItem( new PowderOfTranslocation(100) );
                    }

                    else if (from.Luck >= 500)
                    {
                        this.DropItem( new PowderOfTranslocation(50) );
                    }
                }

                Open( from );
            }
            else
                from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
        }

        private bool HasAlreadyDroppedPowder(Mobile from)
        {
                foreach (Item item in this.Items)
                {
                if (item is PowderOfTranslocation)
                {
                            // PowderOfTranslocation is already in the container
                    return true;
                    }
                }
                return false;
        }

        private void Fill( int level )
        {
            TrapType = TrapType.ExplosionTrap;
            TrapPower = level * 25;
            TrapLevel = level;
            Locked = true;

            switch ( level )
            {
                case 1: RequiredSkill = 36; break;
                case 2: RequiredSkill = 76; break;
                case 3: RequiredSkill = 84; break;
                case 4: RequiredSkill = 92; break;
                case 5: RequiredSkill = 100; break;
            }

            LockLevel = RequiredSkill - 10;
            MaxLockLevel = RequiredSkill + 40;

            for ( int i = 0; i < level * 2; ++i )
            {
                Item item;

                if ( Core.AOS )
                    item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
                else
                    item = Loot.RandomArmorOrShieldOrWeapon();

                if ( item is BaseWeapon )
                {
                    BaseWeapon weapon = (BaseWeapon)item;

                    if ( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;

                        GetRandomAOSStats( out attributeCount, out min, out max );
                        BaseRunicTool.ApplyAttributesTo( weapon, attributeCount, min, max );
                    }
                    else
                    {
                        weapon.DamageLevel = (WeaponDamageLevel)Utility.Random( 6 );
                        weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random( 6 );
                        weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random( 6 );
                    }

                    DropItem( item );
                }

                else if ( item is BaseArmor )
                {
                    BaseArmor armor = (BaseArmor)item;

                    if ( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats( out attributeCount, out min, out max );
                        BaseRunicTool.ApplyAttributesTo( armor, attributeCount, min, max );
                    }
                    else
                    {
                        armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random( 6 );
                        armor.Durability = (ArmorDurabilityLevel)Utility.Random( 6 );
                    }

                    DropItem( item );
                }

                else if( item is BaseHat )
                {
                    BaseHat hat = (BaseHat)item;

                    if( Core.AOS )
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats( out attributeCount, out min, out  max );

                        BaseRunicTool.ApplyAttributesTo( hat, attributeCount, min, max );
                    }

                    DropItem( item );
                }
                else if( item is BaseJewel )
                {
                    int attributeCount;
                    int min, max;
                    GetRandomAOSStats( out attributeCount, out min, out max );

                    BaseRunicTool.ApplyAttributesTo( (BaseJewel)item, attributeCount, min, max );

                    DropItem( item );
                }
            }
        }

        private static void GetRandomAOSStats( out int attributeCount, out int min, out int max )
        {

            int rnd = Utility.Random( 7 );

            if ( rnd < 1 )
            {
                attributeCount = Utility.RandomMinMax( 6, 8 );
                min = 50; max = 100;
            }
            else if ( rnd < 3 )
            {
                attributeCount = Utility.RandomMinMax( 6, 8 );
                min = 50; max = 90;
            }
            else if ( rnd < 5 )
            {
                attributeCount = Utility.RandomMinMax( 5, 7 );
                min = 50; max = 80;
            }
            else if ( rnd < 7 )
            {
                attributeCount = Utility.RandomMinMax( 4, 6 );
                min = 50; max = 70;
            }
            else
            {
                attributeCount = 5;
                min = 50; max = 60;
            }
        }

        public NewDungeonChest( Serial serial ) : base( serial )
        {
        }

        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );

            writer.Write( (int) 0 ); // version

            //writer.Write( m_Name );
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );

            int version = reader.ReadInt();

            //m_Name = Utility.Intern( reader.ReadString() );
        }
    }
}
 
Try this:

C#:
using System;
using Server;
using Server.Items;

namespace Server.Items
{
    public class NewDungeonChest : LockableContainer
    {
        private static int[] m_ItemIDs = new int[]
        {
            0xE3D, 0xE3E, 0x9AB, 0xE3C, 0xE40, 0xE43, 0xE41, 0xE42, 0xE7C, 0xE3F
        };

        // Add a flag to track whether PowderOfTranslocation has been dropped
        private bool m_PowderDropped = false;

        [Constructable]
        public NewDungeonChest(int level) : base(Utility.RandomList(m_ItemIDs))
        {
            if (ItemID == 0x9AB || ItemID == 0xE40 || ItemID == 0xE41 || ItemID == 0xE7C)
            {
                Name = "a Metal Chest";
            }
            if (ItemID == 0xE43 || ItemID == 0xE42)
            {
                Name = "a Wooden Chest";
            }
            if (ItemID == 0xE3D || ItemID == 0xE3C || ItemID == 0xE3F || ItemID == 0xE3E)
            {
                Name = "a Crate";
            }

            Hue = 0;
            Fill(level);
        }

        public override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);

            list.Add("From Tartarus Dungeons");
        }

        public override void OnDoubleClick(Mobile from)
        {
            if (from.AccessLevel > AccessLevel.Player || from.InRange(this.GetWorldLocation(), 2))
            {
                // Check if the powder has already been dropped
                if (!m_PowderDropped)
                {
                    if (from.Luck >= 2000)
                    {
                        this.DropItem(new PowderOfTranslocation(200));
                    }
                    else if (from.Luck >= 1000)
                    {
                        this.DropItem(new PowderOfTranslocation(100));
                    }
                    else if (from.Luck >= 500)
                    {
                        this.DropItem(new PowderOfTranslocation(50));
                    }

                    // Set the flag to true to indicate that the powder has been dropped
                    m_PowderDropped = true;
                }

                Open(from);
            }
            else
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
            }
        }

        private void Fill(int level)
        {
            TrapType = TrapType.ExplosionTrap;
            TrapPower = level * 25;
            TrapLevel = level;
            Locked = true;

            switch (level)
            {
                case 1: RequiredSkill = 36; break;
                case 2: RequiredSkill = 76; break;
                case 3: RequiredSkill = 84; break;
                case 4: RequiredSkill = 92; break;
                case 5: RequiredSkill = 100; break;
            }

            LockLevel = RequiredSkill - 10;
            MaxLockLevel = RequiredSkill + 40;

            for (int i = 0; i < level * 2; ++i)
            {
                Item item;

                if (Core.AOS)
                    item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
                else
                    item = Loot.RandomArmorOrShieldOrWeapon();

                if (item is BaseWeapon)
                {
                    BaseWeapon weapon = (BaseWeapon)item;

                    if (Core.AOS)
                    {
                        int attributeCount;
                        int min, max;

                        GetRandomAOSStats(out attributeCount, out min, out max);
                        BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
                    }
                    else
                    {
                        weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6);
                        weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6);
                        weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6);
                    }

                    DropItem(item);
                }

                else if (item is BaseArmor)
                {
                    BaseArmor armor = (BaseArmor)item;

                    if (Core.AOS)
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats(out attributeCount, out min, out max);
                        BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
                    }
                    else
                    {
                        armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6);
                        armor.Durability = (ArmorDurabilityLevel)Utility.Random(6);
                    }

                    DropItem(item);
                }

                else if (item is BaseHat)
                {
                    BaseHat hat = (BaseHat)item;

                    if (Core.AOS)
                    {
                        int attributeCount;
                        int min, max;
                        GetRandomAOSStats(out attributeCount, out min, out max);

                        BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max);
                    }

                    DropItem(item);
                }
                else if (item is BaseJewel)
                {
                    int attributeCount;
                    int min, max;
                    GetRandomAOSStats(out attributeCount, out min, out max);

                    BaseRunicTool.ApplyAttributesTo((BaseJewel)item, attributeCount, min, max);

                    DropItem(item);
                }
            }
        }

        private static void GetRandomAOSStats(out int attributeCount, out int min, out int max)
        {

            int rnd = Utility.Random(7);

            if (rnd < 1)
            {
                attributeCount = Utility.RandomMinMax(6, 8);
                min = 50; max = 100;
            }
            else if (rnd < 3)
            {
                attributeCount = Utility.RandomMinMax(6, 8);
                min = 50; max = 90;
            }
            else if (rnd < 5)
            {
                attributeCount = Utility.RandomMinMax(5, 7);
                min = 50; max = 80;
            }
            else if (rnd < 7)
            {
                attributeCount = Utility.RandomMinMax(4, 6);
                min = 50; max = 70;
            }
            else
            {
                attributeCount = 5;
                min = 50; max = 60;
            }
        }

        public NewDungeonChest(Serial serial) : base(serial)
        {
        }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);

            writer.Write((int)0); // version

            //writer.Write( m_Name );
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);

            int version = reader.ReadInt();

            //m_Name = Utility.Intern( reader.ReadString() );
        }
    }
}
 
Isn't the problem that "m_PowderDropped" isn't saved for the reboot? You would need to serialize/deserialize for it. Or you could just use something else like the Weight property and use that since the chest will be unmovable anyway. Then the Weight saves for the reboots.

C#:
        public override void OnDoubleClick(Mobile from)
        {
            if (from.AccessLevel > AccessLevel.Player || from.InRange(this.GetWorldLocation(), 2))
            {
                if (Weight != 22)
                {
                    if (from.Luck >= 2000)
                    {
                        this.DropItem(new PowderOfTranslocation(200));
                    }
                    else if (from.Luck >= 1000)
                    {
                        this.DropItem(new PowderOfTranslocation(100));
                    }
                    else if (from.Luck >= 500)
                    {
                        this.DropItem(new PowderOfTranslocation(50));
                    }
                    Weight = 22;
                }
                Open(from);
            }
            else
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
            }
        }
 
Thank you both 'Unlimited' and 'Spectre'. Combined you are really helping move this in the right direction for me.

The "private bool m_PowderDropped" suggestion from 'Unlimited' works perfectly but the concern over Serialize/Deserialize did prove true because the bool status was not being saved or recognized following a server reboot.

So, I did my best to add m_PowderDropped to the Serialize/Deserialize process and on testing it seems to have finally worked.

I have a very low level of confidence in my abilities regarding Serialize/Deserialize so could you look at this (which seems to work) and comment if I have it correct?

Code:
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
            writer.Write( (int) 0 ); // version

            writer.Write((bool)m_PowderDropped);
        }

        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
            int version = reader.ReadInt();

            switch ( version )
            {
                case 0:
                {
                    m_PowderDropped = reader.ReadBool();
                    break;
                }
            }
        }

Both of you have been amazing for me on this. Thank you both.

*bows*
 
Last edited:

Active Shards

Donations

Total amount
$0.00
Goal
$1,000.00
Back