Okay so I released a Militia system last night and as I stated in my post, I am continually updating it for various reasons; anyway I found a dupe bug in it and I've been working for 8 hours trying various code, researching both the OnBeforeDeath and OnDeath methods and nothing seems to work as a fix.

The problem I am having is when the mobile dies, it's bonded, so I have 2 instances of his backpack. One instance is on the corpse on the ground and the other instance is his grayed-out dead bonded body. It doesn't matter whether or not I ressurect him makes no difference... there will always be 2 packs and that the player owner can open.

Either by clicking once on the grayed-out dead bonded body and using the mobiles context menu to open its paperdoll and then select Open Backpack... or by double-clicking the corpse. This was mean to be like that and I'd rather not change it by deleting the mobiles pack.

Rather all I want to do is delete the contents of the corpse's pack while leaving the grayed-out dead bonded body's pack untouched. Right now when this mobile dies all of his possessions that were in his pack remain there on the grayed-out dead bonded body. However if there was gold on him when he dies, an additional instance of the gold amount originally in his pack on death now appear in game; one instance that is on his grayed-out dead bonded body (which is meant to be) and one instance in the corpse backpack which I'm trying to delete unsuccessfully.

Any help would be appreciated, thank you.

Code:
public virtual bool OnDeath(Container c)
{
	//Container c = this.Backpack;

         if (this.Backpack != null)
         {
                Item gold = c.FindItemByType(typeof(Gold));
                    if (gold != null)
                    gold.Consume();
          }
            //if (Backpack != null && item is Gold)
            base.OnDeath(c);
 }
 
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

using Server;
using Server.Items;
using Server.ContextMenus;
using Server.Multis;
using Server.Targeting;
using Server.Gumps;
using Server.Mobiles;
using Server.Engines.Craft;
using Server.Misc;
using Server.Network;

namespace Server.Mobiles
{
    [CorpseName("corpse of a fallen warrior")]
    public class Militia_Archery : BaseHire_Militia
    {
        #region npcActor's Attack, Hurt, And Death Sounds

        public override int GetAttackSound()
        {
            return 0x239;
        }
        public override int GetHurtSound()
        {
            return 0x155;
        }
        public override int GetDeathSound()
        {
            return 0x426;
        }

        #endregion

        [Constructable]
        public Militia_Archery() : base( AIType.AI_Archer )
        {
            Title = "";
            SpeechHue = Utility.RandomDyedHue();

            #region npcActor's Characteristics

            Hue = Utility.RandomSkinHue();

            if (this.Female = Utility.RandomBool())
            {
                Body = 0x191;
                Name = NameList.RandomName("female");
            }
            else
            {
                Body = 0x190;
                Name = NameList.RandomName("male");
            }

            Item hair = new Item(Utility.RandomList(0x203B, 0x2049, 0x2048, 0x204A));
            hair.Hue = Utility.RandomNondyedHue();
            hair.Layer = Layer.Hair;
            hair.Movable = false;
            AddItem(hair);

            if (Utility.RandomBool() && !this.Female)
            {
                Item beard = new Item(Utility.RandomList(0x203E, 0x203F, 0x2040, 0x2041, 0x204B, 0x204C, 0x204D));

                beard.Hue = hair.Hue;
                beard.Layer = Layer.FacialHair;
                beard.Movable = false;

                AddItem(beard);
            }

            #endregion

            SetStr(95, 125);
            SetDex(75, 100);
            SetInt(95, 125);

            SetSkill(SkillName.Anatomy, 100, 120);
            SetSkill(SkillName.Healing, 100, 120);
            SetSkill(SkillName.Tactics, 100, 120);
            SetSkill(SkillName.MagicResist, 100, 120);
            SetSkill(SkillName.Parry, 100, 120);
            SetSkill(SkillName.Chivalry, 100, 120);
            SetSkill(SkillName.Bushido, 100, 120);
            SetSkill(SkillName.Ninjitsu, 100, 120.0);
            SetSkill(SkillName.Archery, 100, 120);
            SetSkill(SkillName.Wrestling, 100, 120);

            SetDamage(10, 15);

            SetDamageType(ResistanceType.Physical, 100, 100);
            SetDamageType(ResistanceType.Fire, 25, 50);
            SetDamageType(ResistanceType.Cold, 25, 50);
            SetDamageType(ResistanceType.Energy, 25, 50);
            SetDamageType(ResistanceType.Poison, 25, 50);

            SetResistance(ResistanceType.Physical, 100, 100);
            SetResistance(ResistanceType.Fire, 25, 50);
            SetResistance(ResistanceType.Cold, 25, 50);
            SetResistance(ResistanceType.Energy, 25, 50);
            SetResistance(ResistanceType.Poison, 25, 50);

            #region npcActor's Properties [Props
            //Customizable In-Game By Server Admin

            VirtualArmor = 5;
            Fame = 1000;
            Karma = 10000;
            ControlSlots = 2;
            IsBonded = true;
            CantWalk = false;

            #endregion

            #region npcActor's Personal Property
           
            #region Militia Pack

            Container pack = Backpack;

			if ( pack != null )
				pack.Delete();

            pack = new Militia_Pack();
			pack.Movable = false;

			AddItem( pack );

            PackItem(new Arrow(1000));
            PackItem(new Bolt(1000));
            PackGold(1000, 1500);
            PackItem(new Bandage(500));

            PackItem(new BookOfNinjitsu());
            PackItem(new BookOfBushido());
            PackItem(new BookOfChivalry());

            #endregion

            #region Militia Arms
           
            switch (Utility.Random(5))
            {
                case 0: AddItem(new Militia_Composite()); break;
                case 1: AddItem(new Militia_Longbow()); break;
                case 2: AddItem(new Militia_Shortbow()); break;
                case 3: AddItem(new Militia_Crossbow()); break;
                case 4: AddItem(new Militia_Repeating()); break;
            }

            AddItem(new Militia_Chest());
            AddItem(new Militia_Arms());
            AddItem(new Militia_Gloves());
            AddItem(new Militia_Gorget());
            AddItem(new Militia_Legs());
            AddItem(new Militia_BodySash());
           
            #endregion
           
            #endregion
        }

        public override bool AlwaysMurderer { get { return false; } }
        public override bool IsInvulnerable { get { return false; } }

        public override bool AllowEquipFrom(Mobile from) { return (ControlMaster != null && ControlMaster == from); }
        public override bool ClickTitle { get { return false; } }
        public override bool CanPaperdollBeOpenedBy(Mobile from) { return true; }
        public override bool CanBeRenamedBy(Mobile from) { return false; }

        public override bool AutoDispel { get { return true; } }
        public override bool IsScaredOfScaryThings { get { return false; } }
        public override bool IsScaryToPets { get { return false; } }

        public override bool BardImmune { get { return !Core.AOS; } }
        public override Poison PoisonImmune { get { return Poison.Lethal; } }

        public override bool CanHeal { get { return true; } }
        public override bool CanHealOwner { get { return true; } }

        public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) { return PackAnimal.CheckAccess(this, from); }
        public override bool CheckNonlocalLift(Mobile from, Item item) { return PackAnimal.CheckAccess(this, from); }
        public override bool IsSnoop(Mobile from) { if (PackAnimal.CheckAccess(this, from)) return false; return base.IsSnoop(from); }
        public override bool CanRummageCorpses { get { return true; } }

        public override bool DeleteOnRelease { get { return true; } }
        //public override bool DeleteCorpseOnDeath { get { return true; } }

        #region npcActor's Duty To Keep The Battle Field Clean

        private DateTime m_NextPickup;

        public override void OnThink()
        {
            base.OnThink();

            if (DateTime.Now < m_NextPickup)
                return;

            m_NextPickup = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(0, 0));

            Container pack = this.Backpack;

            if (pack == null)
                return;

            ArrayList list = new ArrayList();

            foreach (Item item in this.GetItemsInRange(3))
            {
                if (item is Militia_Legs || item is Militia_BodySash || item is Militia_Gloves || item is Militia_Chest
                  || item is Militia_Gorget || item is Bandage || item is Gold || item.Stackable)
                    list.Add(item);
            }

            int pickedUp = 0;

            for (int i = 0; i < list.Count; ++i)
            {
                Item item = (Item)list[i];

                if (!pack.CheckHold(this, item, false, true))
                    return;

                bool rejected;
                LRReason reject;

                NextActionTime = Core.TickCount;

                Lift(item, item.Amount, out rejected, out reject);

                if (rejected)
                    continue;

                Drop(this, Point3D.Zero);

                if (++pickedUp == 3)
                    break;
            }
        }

        #endregion

        public override void OnDoubleClick(Mobile from)
        {
            PackAnimal.TryPackOpen(this, from);
        }

        #region npcActor's Ability To Flee Quick When Damanged
        //Serialize: writer.Write(m_SpeedBoost); || Deserialize: m_SpeedBoost = reader.ReadBool();

        private bool m_SpeedBoost;

        public override void OnDamage(int amount, Mobile from, bool willKill)
        {
            CheckSpeedBoost();
            base.OnDamage(amount, from, willKill);
        }

        private const double SpeedBoostScalar = 1.2;

        private void CheckSpeedBoost()
        {
            if (Hits < (HitsMax / 4))
            {
                if (!m_SpeedBoost)
                {
                    ActiveSpeed /= SpeedBoostScalar;
                    PassiveSpeed /= SpeedBoostScalar;
                    m_SpeedBoost = true;
                }
            }
            else if (m_SpeedBoost)
            {
                ActiveSpeed *= SpeedBoostScalar;
                PassiveSpeed *= SpeedBoostScalar;
                m_SpeedBoost = false;
            }
        }

        #endregion

        public override WeaponAbility GetWeaponAbility()
        {
            switch (Utility.Random(12))
            {
                default:
                case 0: return WeaponAbility.ArmorIgnore;
                case 1: return WeaponAbility.BleedAttack;
                case 2: return WeaponAbility.ConcussionBlow;
                case 3: return WeaponAbility.CrushingBlow;
                case 4: return WeaponAbility.Disarm;

                case 5: return WeaponAbility.Dismount;
                case 6: return WeaponAbility.DoubleStrike;
                case 7: return WeaponAbility.InfectiousStrike;
                case 8: return WeaponAbility.MovingShot;
                case 9: return WeaponAbility.ParalyzingBlow;

                case 10: return WeaponAbility.WhirlwindAttack;
                case 11: return WeaponAbility.ShadowStrike;
            }
        }

        #region npcActor's Combatant Roles On The Battle Field

        public override OppositionGroup OppositionGroup
        {
            get { return OppositionGroup.SavagesAndOrcs; }
        }

        public override bool IsEnemy(Mobile m)
        {
            if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask)
                return false;

            return base.IsEnemy(m);
        }

        public virtual bool OnDeath(Container c)
        {
            //Container c = this.Backpack;

            if (this.Backpack != null)
            {
                Item gold = c.FindItemByType(typeof(Gold));

                if (gold != null)
                    gold.Consume();
            }



            //if (Backpack != null && item is Gold)

            base.OnDeath(c);
        }


        #endregion

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

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

            writer.Write(m_SpeedBoost);

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

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

            m_SpeedBoost = reader.ReadBool();

            int version = reader.ReadInt();
        }
    }
}
 

Attachments

  • Militia_Archery.cs
    11.3 KB · Views: 3
Okay so this is the closest I've gotten tonight. I really need to get some sleep but here's the update so far:

The code below will delete the gold, however even with the IsBonded=true the militia_archery.cs mobile will not show up as a
    • grayed-out dead bonded body - like all bonded pets do after death unless I use staff command to get him.
That said, I'm not sure what to do. I fix one problem - the gold - and then now the pet disappears - It Doesn't Delete - I know this because my follower count still reads as 2... so when I use the command to get pets, the mobile reappears; but I can only find him using that command. Otherwise I don't know where he runs off too or if he's turning invisible.

I'm trying to accomplish 2 things... the gold deletion as stated above, and now making the grayed-out dead bonded body appear so the player can ressurect it. Anyway now I really must get sleep lol. Have a great night.


Code:
public override void OnDeath(Container c)
{
      if (this.Backpack != null && this.Backpack.ConsumeTotal(typeof(Gold), 60))
      {
             this.Say("You shall never get my treasure!");           
       }
            IsBonded = true;
}
 
The problem with the gold is from your BaseHire_Militia

The code below counts the amount of gold on the mobile before it dies, then creates a new instance of gold on the corpse. It doesn't move the gold.

Code:
public override bool OnBeforeDeath()
        {
            // Stop the pay timer if its running
            if (m_PayTimer != null)
                m_PayTimer.Stop();

            m_PayTimer = null;

            // Get all of the gold on the hireling and add up the total amount
            if (this.Backpack != null)
            {
                Item[] AllGold = this.Backpack.FindItemsByType(typeof(Gold), true);
                if (AllGold != null)
                {
                    foreach (Gold g in AllGold)
                        this.m_GoldOnDeath += g.Amount;
                }
            }

            return base.OnBeforeDeath();
        }

        public override void OnDeath(Container c)
        {
            if (this.m_GoldOnDeath > 0)
                c.DropItem(new Gold(this.m_GoldOnDeath));

            base.OnDeath(c);
        }
 
Both are now fixed... Thank you zerodowned for finding the resolution this issue :)

And... thank you frankieowns for offering your help as well. I was wracking my brain on the mobile scripts so much that I didn't think to look inside the BaseHire_Militia inside the BaseMilitia_Core.cs
 
Back