So.. I decided that it was time to test things out and delete the test save folder and let it regenerate. When I restarted the server I got this error.

Code:
Loading Ultima Live map changes
...done (0 items, 0 mobiles, 0 customs) (0.05 seconds)
Error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidCastException: Unable to cast object of type 'Server.Mobiles.Kevin' to type 'Server.Mobiles.PlayerMobile'.
   at Server.Items.BaseWeapon.OnEquip(Mobile from)
   at Server.Mobiles.BaseCreature.AddItem(Item item)
   at Server.Mobiles.BaseVendor..ctor(String title)
   at Server.Engines.Quests.HumilityQuestMobile..ctor(String name, String title)
   at Server.Mobiles.Kevin..ctor()
   at Server.Engines.Quests.HumilityShrinePersistence.SetupMobiles()
   at Server.Engines.Quests.HumilityShrinePersistence.Initialize()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Server.ScriptCompiler.Invoke(String method) in k:\AlfheimRebornServer\Ultima Server2\Server\ScriptCompiler.cs:line 667
   at Server.Core.Main(String[] args) in k:\AlfheimRebornServer\Ultima Server2\Server\Main.cs:line 558
This exception is fatal, press return to exit

I've made no changes to the quest system however have made changes to basearmor/baseweapon/basecreature, I'm just not sure which change caused the fail.
 
I suspect this is something in baseweapon as i added onequip changes, and the kevin script equips a weapon
 
Post your "OnEquip(Mobile from)" method in BaseWeapon.

My guess is that you cast from to PlayerMobile as if only a player might equip a weapon. While it is OK to assume this, you must then make a quick check to see if from actually IS a playermobile, and Stop the next part of the code if it is not.
 
Here is the requested snippit. I only assume its this , it does state the basearmor and others
Code:
        public override bool OnEquip(Mobile from)
        {
            int strBonus = m_AosAttributes.BonusStr;
            int dexBonus = m_AosAttributes.BonusDex;
            int intBonus = m_AosAttributes.BonusInt;

            if ((strBonus != 0 || dexBonus != 0 || intBonus != 0))
            {
                Mobile m = from;

                string modName = Serial.ToString();

                if (strBonus != 0)
                {
                    m.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero));
                }

                if (dexBonus != 0)
                {
                    m.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero));
                }

                if (intBonus != 0)
                {
                    m.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero));
                }
            }

            from.NextCombatTime = Core.TickCount + (int)GetDelay(from).TotalMilliseconds;

            if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular)
            {
                if (m_SkillMod != null)
                {
                    m_SkillMod.Remove();
                }

                m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
                from.AddSkillMod(m_SkillMod);
            }

            if (Core.AOS && m_AosWeaponAttributes.MageWeapon != 0 && m_AosWeaponAttributes.MageWeapon != 30)
            {
                if (m_MageMod != null)
                {
                    m_MageMod.Remove();
                }

                m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + m_AosWeaponAttributes.MageWeapon);
                from.AddSkillMod(m_MageMod);
            }

            if (Core.TOL)
            {
                if ((m_ExtendedWeaponAttributes.MysticWeapon != 0 && m_ExtendedWeaponAttributes.MysticWeapon != 30) || Enhancement.GetValue(from, ExtendedWeaponAttribute.MysticWeapon) > 0)
                    AddMysticMod(from);
            }

            XmlAttach.CheckOnEquip(this, from);

//////CUSTOMIZATION - Alfheim Online!////// This is for Human Weapons.
            var validTypeHumanWeapon1 = IsValidTypeHumanWeapon( this.GetType( ) );
            if ( validTypeHumanWeapon1 )
            {
                if ( from.Body == 0x190 || from.Body == 0x191)
                {
                    PlayerMobile pm = (PlayerMobile)from;
                    BaseWeapon weapon = (BaseWeapon)this;
                    XmlSockets armorsockets = (XmlSockets)XmlAttach.FindAttachment(this, typeof(XmlSockets));
                    XmlLevelItem levelitem = (XmlLevelItem)XmlAttach.FindAttachment(this, typeof(XmlLevelItem));
                    XmlSocketable socketable = (XmlSocketable)XmlAttach.FindAttachment(this, typeof(XmlSocketable));
               
                    if (levelitem == null)
                    {
                        from.SendMessage( "The weapon starts to crave exp, it feels almost alive..." );
                        levelitem = new XmlLevelItem();
                        armorsockets = new XmlSockets(Utility.RandomMinMax(1, 4));
                        socketable = new XmlSocketable(Utility.RandomMinMax(5, 10));
                        XmlAttach.AttachTo(this, levelitem);
                        XmlAttach.AttachTo(this, armorsockets);
                        XmlAttach.AttachTo(this, socketable);
                    //    armorsockets = new XmlSockets(Utility.RandomList(1, 2, 3, 4)));
                    }
               
                    if (levelitem.Level > pm.Levell )
                    {       
                        from.SendMessage( "You Lack the Level to Equip this!" );
                        return false;
                    }
               
                    else
                    {
                        return true;
                    }
                }
                else if ( from.Body != 0x190 || from.Body != 0x191)
                {
                    from.SendMessage( "You can't figure out how to wield this stange human weapon..." );
                    return false;
                }
            }
       
//////CUSTOMIZATION - Alfheim Online!////// This is for Human Weapon. (( NO XML LEVEL ITEM!))  //////
            var validTypeFairyWeaponNOXML1 = IsValidHumanWeaponTypesNoXML( this.GetType( ) );
            if ( validTypeFairyWeaponNOXML1 )
            {
           
                if ( from.Body == 0x190 || from.Body == 0x191)
                {
                    return true;
                }
                else if ( from.Body != 0x190 || from.Body != 0x191)
                {
                    from.SendMessage( "You can't figure out how to equip this human weapon..." );
                    return false;
                }
            }
       
       
//////CUSTOMIZATION - Alfheim Online!////// This is for Fairy Weapons.
            var validTypeFairyWeapon1 = IsValidTypeFairyWeapon( this.GetType( ) );
            if ( validTypeFairyWeapon1 )
            {
                if ( from.Body == 0x29A || from.Body == 0x29B)
                {
                    PlayerMobile pm = (PlayerMobile)from;
                    XmlSockets armorsockets = (XmlSockets)XmlAttach.FindAttachment(this, typeof(XmlSockets));
                    XmlLevelItem levelitem = (XmlLevelItem)XmlAttach.FindAttachment(this, typeof(XmlLevelItem));
                    XmlSocketable socketable = (XmlSocketable)XmlAttach.FindAttachment(this, typeof(XmlSocketable));
               
                    if (levelitem == null)
                    {
                        from.SendMessage( "The weapon starts to crave exp, it feels almost alive..." );
                        levelitem = new XmlLevelItem();
                        armorsockets = new XmlSockets(Utility.RandomMinMax(1, 4));
                        socketable = new XmlSocketable(Utility.RandomMinMax(5, 10));
                        XmlAttach.AttachTo(this, levelitem);
                        XmlAttach.AttachTo(this, armorsockets);
                        XmlAttach.AttachTo(this, socketable);
                    //    armorsockets = new XmlSockets(Utility.RandomList(1, 2, 3, 4)));
                    }
               
                    if (levelitem.Level > pm.Levell )
                    {       
                        from.SendMessage( "You Lack the Level to Equip this!" );
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else if ( from.Body != 0x29A || from.Body != 0x29B)
                {
                    from.SendMessage( "You can't figure out how to wield this stange fairy weapon..." );
                    return false;
                }
            }
       
//////CUSTOMIZATION - Alfheim Online!////// This is for Fairy Weapon.  (( NO XML LEVEL ITEM ATTACHMENT!! ))
            var validTypeFairyWeaponNOXML = IsValidFairyWeaponTypesNoXML( this.GetType( ) );
            if ( validTypeFairyWeaponNOXML )
            {
                if ( from.Body == 0x29A || from.Body == 0x29B)
                {
                    return true;
                }
                else if ( from.Body != 0x29A || from.Body != 0x29B)
                {
                    from.SendMessage( "You can't figure out how to equip this fairy weapon..." );
                    return false;
                }
            }
       
            return true;
        }

        public override void OnAdded(object parent)
        {
            base.OnAdded(parent);

            if (parent is Mobile)
            {
                Mobile from = (Mobile)parent;

                if (Core.AOS)
                {
                    m_AosSkillBonuses.AddTo(from);
                }

                #region Mondain's Legacy Sets
                if (IsSetItem)
                {
                    m_SetEquipped = SetHelper.FullSetEquipped(from, SetID, Pieces);

                    if (m_SetEquipped)
                    {
                        m_LastEquipped = true;
                        SetHelper.AddSetBonus(from, SetID);
                    }
                }
                #endregion

                from.CheckStatTimers();
                from.Delta(MobileDelta.WeaponDamage);
            }
        }
[doublepost=1505249301][/doublepost]Here are the actual base scripts mentioned in that error.
[doublepost=1505251947][/doublepost]Took your suggestion and applied this code at the beginning of my custom onequip section.

Code:
            if ( validTypeHumanWeapon1 )  
            {
                if (from is PlayerMobile)
                    return true;
                else
                    return false;

That allowed the humility mobs to generate. So that tells me... I have a lot of work to do with adding these checks because I'm sure this is not the only fail point.
 
Last edited:
Here is the line I was referring to:

Code:
PlayerMobile pm = (PlayerMobile)from;

Like I said, this is fine, but what you did was an OK fix.

In general, what you should do after you run this line is something like this:

Code:
if (pm != null)
{
     //run your custom code....
}
// else don't run it...

That way you won't run into a situation where something tries to reference a PlayerMobile where there was none to begin with. But, you are correct, if they are not supposed to wear it at all then you could return false if they are not a PlayerMobile. That would also prevent the bad code from getting called.
 
I ended up using this instead
Code:
if ( validTypeHumanArmor && from is PlayerMobile )

Honestly It never occurred to me to do those checks.. in the older distro I'm coming from this wasn't an issue for some reason. It makes sense though, I have a lot of custom code that is open to this kind of problem as I have a lot of references to playermobile without checking to see if its actually a playermobile, likely they will never get hit by a non playermobile but why take the risk.
 
Back