Ultima Expansion
Endless Journey
All armor and weapons have the name double, same name on 2 lines, if I comment out base.AddNameProperties(list); then it only shows the next property once. Anyone know why it's showing twice?
 
Sure thing, here is the baseweapon.cs:
C#:
#region References
using System;
using System.Collections.Generic;
using System.Linq;

using Server.ContextMenus;
using Server.Engines.Craft;
using Server.Engines.XmlSpawner2;
using Server.Ethics;
using Server.Factions;
using Server.Mobiles;
using Server.Network;
using Server.Services.Virtues;
using Server.SkillHandlers;
using Server.Spells;
using Server.Spells.Bushido;
using Server.Spells.Chivalry;
using Server.Spells.Necromancy;
using Server.Spells.Ninjitsu;
using Server.Spells.Sixth;
using Server.Spells.Spellweaving;
using Server.Spells.SkillMasteries;
#endregion

namespace Server.Items
{
    public interface ISlayer
    {
        SlayerName Slayer { get; set; }
        SlayerName Slayer2 { get; set; }
    }

    public abstract class BaseWeapon : Item, IWeapon, IFactionItem, IUsesRemaining, ICraftable, ISlayer, IDurability, ISetItem, IVvVItem, IOwnerRestricted, IResource, IArtifact, ICombatEquipment, IEngravable, IQuality
    {
        #region Damage Helpers
        public static BaseWeapon GetDamageOutput(Mobile wielder, out int min, out int max)
        {
            return GetDamageOutput(wielder, null, out min, out max);
        }

        public static BaseWeapon GetDamageOutput(Mobile wielder, BaseWeapon weapon, out int min, out int max)
        {
            int minRaw, maxRaw;

            return GetDamageOutput(wielder, weapon, out minRaw, out maxRaw, out min, out max);
        }

        public static BaseWeapon GetDamageOutput(
            Mobile wielder,
            out int minRaw,
            out int maxRaw,
            out int minVal,
            out int maxVal)
        {
            return GetDamageOutput(wielder, null, out minRaw, out maxRaw, out minVal, out maxVal);
        }

        public static BaseWeapon GetDamageOutput(
            Mobile wielder,
            BaseWeapon weapon,
            out int minRaw,
            out int maxRaw,
            out int minVal,
            out int maxVal)
        {
            minRaw = maxRaw = 0;
            minVal = maxVal = 0;

            if (wielder == null)
            {
                return null;
            }

            if (weapon == null)
            {
                weapon = wielder.Weapon as BaseWeapon ?? Fists;
            }

            if (weapon == null)
            {
                return null;
            }

            weapon.GetBaseDamageRange(wielder, out minVal, out maxVal);

            if (wielder is BaseCreature)
            {
                if (((BaseCreature)wielder).DamageMin >= 0 || (weapon is Fists && !wielder.Body.IsHuman))
                {
                    minRaw = minVal;
                    maxRaw = maxVal;
                    return weapon;
                }
            }

            minRaw = weapon.MinDamage;
            maxRaw = weapon.MaxDamage;

            if (Core.AOS)
            {
                minVal = (int)weapon.ScaleDamageAOS(wielder, minVal, false);
                maxVal = (int)weapon.ScaleDamageAOS(wielder, maxVal, false);
            }
            else
            {
                minVal = (int)weapon.ScaleDamageOld(wielder, minVal, false);
                maxVal = (int)weapon.ScaleDamageOld(wielder, maxVal, false);
            }

            return weapon;
        }
        #endregion

        private string m_EngravedText;

        [CommandProperty(AccessLevel.GameMaster)]
        public string EngravedText
        {
            get { return m_EngravedText; }
            set
            {
                m_EngravedText = value;
                InvalidateProperties();
            }
        }

        #region Factions
        private FactionItem m_FactionState;

        public FactionItem FactionItemState
        {
            get { return m_FactionState; }
            set
            {
                m_FactionState = value;

                if (m_FactionState == null)
                {
                    Hue = CraftResources.GetHue(Resource);
                }

                LootType = (m_FactionState == null ? LootType.Regular : LootType.Blessed);
            }
        }
        #endregion

        #region IUsesRemaining members
        private int m_UsesRemaining;
        private bool m_ShowUsesRemaining;
        
        [CommandProperty(AccessLevel.GameMaster)]
        public int UsesRemaining { get { return m_UsesRemaining; } set { m_UsesRemaining = value; InvalidateProperties(); } }

        public bool ShowUsesRemaining { get { return m_ShowUsesRemaining; } set { m_ShowUsesRemaining = value; InvalidateProperties(); } }
        
        public void ScaleUses()
        {
            m_UsesRemaining = (m_UsesRemaining * GetUsesScalar()) / 100;
            InvalidateProperties();
        }

        public void UnscaleUses()
        {
            m_UsesRemaining = (m_UsesRemaining * 100) / GetUsesScalar();
        }

        public int GetUsesScalar()
        {
            if (m_Quality == ItemQuality.Exceptional)
                return 200;

            return 100;
        }
        #endregion
        
        private bool _VvVItem;
        private Mobile _Owner;
        private string _OwnerName;

        [CommandProperty(AccessLevel.GameMaster)]
        public bool IsVvVItem
        {
            get { return _VvVItem; }
            set { _VvVItem = value; InvalidateProperties(); }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Mobile Owner
        {
            get { return _Owner; }
            set { _Owner = value; if (_Owner != null) _OwnerName = _Owner.Name; InvalidateProperties(); }
        }

        public virtual string OwnerName
        {
            get { return _OwnerName; }
            set { _OwnerName = value; InvalidateProperties(); }
        }

        /* Weapon internals work differently now (Mar 13 2003)
        *
        * The attributes defined below default to -1.
        * If the value is -1, the corresponding virtual 'Aos/Old' property is used.
        * If not, the attribute value itself is used. Here's the list:
        *  - MinDamage
        *  - MaxDamage
        *  - Speed
        *  - HitSound
        *  - MissSound
        *  - StrRequirement, DexRequirement, IntRequirement
        *  - WeaponType
        *  - WeaponAnimation
        *  - MaxRange
        */

        #region Var declarations
        // Instance values. These values are unique to each weapon.
        private WeaponDamageLevel m_DamageLevel;
        private WeaponAccuracyLevel m_AccuracyLevel;
        private WeaponDurabilityLevel m_DurabilityLevel;
        private ItemQuality m_Quality;
        private Mobile m_Crafter;
        private Poison m_Poison;
        private int m_PoisonCharges;
        private bool m_Identified;
        private int m_Hits;
        private int m_MaxHits;
        private SlayerName m_Slayer;
        private SlayerName m_Slayer2;

        #region Mondain's Legacy
        private TalismanSlayerName m_Slayer3;
        #endregion

        private SkillMod m_SkillMod, m_MageMod, m_MysticMod;
        private CraftResource m_Resource;
        private bool m_PlayerConstructed;

        private bool m_Altered;

        private AosAttributes m_AosAttributes;
        private AosWeaponAttributes m_AosWeaponAttributes;
        private AosSkillBonuses m_AosSkillBonuses;
        private AosElementAttributes m_AosElementDamages;
        private SAAbsorptionAttributes m_SAAbsorptionAttributes;
        private NegativeAttributes m_NegativeAttributes;
        private ExtendedWeaponAttributes m_ExtendedWeaponAttributes;

        // Overridable values. These values are provided to override the defaults which get defined in the individual weapon scripts.
        private int m_StrReq, m_DexReq, m_IntReq;
        private int m_MinDamage, m_MaxDamage;
        private int m_HitSound, m_MissSound;
        private float m_Speed;
        private int m_MaxRange;
        private SkillName m_Skill;
        private WeaponType m_Type;
        private WeaponAnimation m_Animation;

        #region Stygian Abyss
        private int m_TimesImbued;
        private bool m_IsImbued;
        private bool m_DImodded;
        #endregion

        #region Runic Reforging
        private ItemPower m_ItemPower;
        private ReforgedPrefix m_ReforgedPrefix;
        private ReforgedSuffix m_ReforgedSuffix;
        #endregion
        #endregion

        #region Virtual Properties
        public virtual WeaponAbility PrimaryAbility { get { return null; } }
        public virtual WeaponAbility SecondaryAbility { get { return null; } }

        public virtual int DefMaxRange { get { return 1; } }
        public virtual int DefHitSound { get { return 0; } }
        public virtual int DefMissSound { get { return 0; } }
        public virtual SkillName DefSkill { get { return SkillName.Swords; } }
        public virtual WeaponType DefType { get { return WeaponType.Slashing; } }
        public virtual WeaponAnimation DefAnimation { get { return WeaponAnimation.Slash1H; } }

        public virtual int AosStrengthReq { get { return 0; } }
        public virtual int AosDexterityReq { get { return 0; } }
        public virtual int AosIntelligenceReq { get { return 0; } }
        public virtual int AosMinDamage { get { return 0; } }
        public virtual int AosMaxDamage { get { return 0; } }
        public virtual int AosSpeed { get { return 0; } }
        public virtual float MlSpeed { get { return 0.0f; } }
        public virtual int AosMaxRange { get { return DefMaxRange; } }
        public virtual int AosHitSound { get { return DefHitSound; } }
        public virtual int AosMissSound { get { return DefMissSound; } }
        public virtual SkillName AosSkill { get { return DefSkill; } }
        public virtual WeaponType AosType { get { return DefType; } }
        public virtual WeaponAnimation AosAnimation { get { return DefAnimation; } }

        public virtual int OldStrengthReq { get { return 0; } }
        public virtual int OldDexterityReq { get { return 0; } }
        public virtual int OldIntelligenceReq { get { return 0; } }
        public virtual int OldMinDamage { get { return 0; } }
        public virtual int OldMaxDamage { get { return 0; } }
        public virtual int OldSpeed { get { return 0; } }
        public virtual int OldMaxRange { get { return DefMaxRange; } }
        public virtual int OldHitSound { get { return DefHitSound; } }
        public virtual int OldMissSound { get { return DefMissSound; } }
        public virtual SkillName OldSkill { get { return DefSkill; } }
        public virtual WeaponType OldType { get { return DefType; } }
        public virtual WeaponAnimation OldAnimation { get { return DefAnimation; } }

        public virtual int InitMinHits { get { return 0; } }
        public virtual int InitMaxHits { get { return 0; } }

        public virtual bool CanFortify { get { return !IsImbued && NegativeAttributes.Antique < 4; } }
        public virtual bool CanRepair { get { return m_NegativeAttributes.NoRepair == 0; } }
        public virtual bool CanAlter { get { return true; } }

        public override int PhysicalResistance { get { return m_AosWeaponAttributes.ResistPhysicalBonus; } }
        public override int FireResistance { get { return m_AosWeaponAttributes.ResistFireBonus; } }
        public override int ColdResistance { get { return m_AosWeaponAttributes.ResistColdBonus; } }
        public override int PoisonResistance { get { return m_AosWeaponAttributes.ResistPoisonBonus; } }
        public override int EnergyResistance { get { return m_AosWeaponAttributes.ResistEnergyBonus; } }

        public virtual SkillName AccuracySkill { get { return SkillName.Tactics; } }

        public override double DefaultWeight
        {
            get
            {
                if (NegativeAttributes == null || NegativeAttributes.Unwieldly == 0)
                    return base.DefaultWeight;

                return 50;
            }
        }

        #region Personal Bless Deed
        private Mobile m_BlessedBy;

        [CommandProperty(AccessLevel.GameMaster)]
        public Mobile BlessedBy
        {
            get { return m_BlessedBy; }
            set
            {
                m_BlessedBy = value;
                InvalidateProperties();
            }
        }

        private class UnBlessEntry : ContextMenuEntry
        {
            private readonly Mobile m_From;
            private readonly BaseWeapon m_Weapon; // BaseArmor, BaseWeapon or BaseClothing

            public UnBlessEntry(Mobile from, BaseWeapon weapon)
                : base(6208, -1)
            {
                m_From = from;
                m_Weapon = weapon;
            }

            public override void OnClick()
            {
                m_Weapon.BlessedFor = null;
                m_Weapon.BlessedBy = null;

                Container pack = m_From.Backpack;

                if (pack != null)
                {
                    pack.DropItem(new PersonalBlessDeed(m_From));
                    m_From.SendLocalizedMessage(1062200); // A personal bless deed has been placed in your backpack.
                }
            }
        }
        #endregion

        #endregion

        #region Getters & Setters
        [CommandProperty(AccessLevel.GameMaster)]
        public AosAttributes Attributes { get { return m_AosAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public AosWeaponAttributes WeaponAttributes { get { return m_AosWeaponAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public AosSkillBonuses SkillBonuses { get { return m_AosSkillBonuses; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public AosElementAttributes AosElementDamages { get { return m_AosElementDamages; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public SAAbsorptionAttributes AbsorptionAttributes { get { return m_SAAbsorptionAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public NegativeAttributes NegativeAttributes { get { return m_NegativeAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public ExtendedWeaponAttributes ExtendedWeaponAttributes { get { return m_ExtendedWeaponAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public ConsecratedWeaponContext ConsecratedContext { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool Identified
        {
            get { return m_Identified; }
            set
            {
                m_Identified = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitPoints
        {
            get { return m_Hits; }
            set
            {
                if (m_Hits == value)
                {
                    return;
                }

                if (value > m_MaxHits)
                {
                    value = m_MaxHits;
                }

                m_Hits = value;

                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MaxHitPoints
        {
            get { return m_MaxHits; }
            set
            {
                m_MaxHits = value;

                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int PoisonCharges
        {
            get { return m_PoisonCharges; }
            set
            {
                m_PoisonCharges = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Poison Poison
        {
            get { return m_Poison; }
            set
            {
                m_Poison = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public ItemQuality Quality
        {
            get { return m_Quality; }
            set
            {
                UnscaleDurability();
                UnscaleUses();
                m_Quality = value;
                ScaleDurability();
                ScaleUses();
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public Mobile Crafter
        {
            get { return m_Crafter; }
            set
            {
                m_Crafter = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SlayerName Slayer
        {
            get { return m_Slayer; }
            set
            {
                m_Slayer = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public SlayerName Slayer2
        {
            get { return m_Slayer2; }
            set
            {
                m_Slayer2 = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public TalismanSlayerName Slayer3
        {
            get { return m_Slayer3; }
            set
            {
                m_Slayer3 = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public CraftResource Resource
        {
            get { return m_Resource; }
            set
            {
                UnscaleDurability();
                m_Resource = value;
                Hue = CraftResources.GetHue(m_Resource);
                InvalidateProperties();
                ScaleDurability();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public WeaponDamageLevel DamageLevel
        {
            get { return m_DamageLevel; }
            set
            {
                m_DamageLevel = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public WeaponDurabilityLevel DurabilityLevel
        {
            get { return m_DurabilityLevel; }
            set
            {
                UnscaleDurability();
                m_DurabilityLevel = value;
                InvalidateProperties();
                ScaleDurability();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool PlayerConstructed { get { return m_PlayerConstructed; } set { m_PlayerConstructed = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MaxRange
        {
            get { return (m_MaxRange == -1 ? Core.AOS ? AosMaxRange : OldMaxRange : m_MaxRange); }
            set
            {
                m_MaxRange = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public WeaponAnimation Animation { get { return (m_Animation == (WeaponAnimation)(-1) ? Core.AOS ? AosAnimation : OldAnimation : m_Animation); } set { m_Animation = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public WeaponType Type { get { return (m_Type == (WeaponType)(-1) ? Core.AOS ? AosType : OldType : m_Type); } set { m_Type = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public SkillName Skill
        {
            get { return (m_Skill == (SkillName)(-1) ? Core.AOS ? AosSkill : OldSkill : m_Skill); }
            set
            {
                m_Skill = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int HitSound { get { return (m_HitSound == -1 ? Core.AOS ? AosHitSound : OldHitSound : m_HitSound); } set { m_HitSound = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MissSound { get { return (m_MissSound == -1 ? Core.AOS ? AosMissSound : OldMissSound : m_MissSound); } set { m_MissSound = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MinDamage
        {
            get { return (m_MinDamage == -1 ? Core.AOS ? AosMinDamage : OldMinDamage : m_MinDamage); }
            set
            {
                m_MinDamage = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int MaxDamage
        {
            get { return (m_MaxDamage == -1 ? Core.AOS ? AosMaxDamage : OldMaxDamage : m_MaxDamage); }
            set
            {
                m_MaxDamage = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public float Speed
        {
            get
            {
                if (m_Speed != -1)
                {
                    return m_Speed;
                }

                if (Core.ML)
                {
                    return MlSpeed;
                }
                else if (Core.AOS)
                {
                    return AosSpeed;
                }

                return OldSpeed;
            }
            set
            {
                m_Speed = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int StrRequirement
        {
            get
            {
                if (m_NegativeAttributes.Massive > 0)
                {
                    return 125;
                }

                return m_StrReq == -1 ? Core.AOS ? AosStrengthReq : OldStrengthReq : m_StrReq;
            }
            set
            {
                m_StrReq = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int DexRequirement { get { return (m_DexReq == -1 ? Core.AOS ? AosDexterityReq : OldDexterityReq : m_DexReq); } set { m_DexReq = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int IntRequirement { get { return (m_IntReq == -1 ? Core.AOS ? AosIntelligenceReq : OldIntelligenceReq : m_IntReq); } set { m_IntReq = value; } }

        [CommandProperty(AccessLevel.GameMaster)]
        public WeaponAccuracyLevel AccuracyLevel
        {
            get { return m_AccuracyLevel; }
            set
            {
                if (m_AccuracyLevel != value)
                {
                    m_AccuracyLevel = value;

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

                            m_SkillMod = null;
                        }
                        else if (m_SkillMod == null && Parent is Mobile)
                        {
                            m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
                            ((Mobile)Parent).AddSkillMod(m_SkillMod);
                        }
                        else if (m_SkillMod != null)
                        {
                            m_SkillMod.Value = (int)m_AccuracyLevel * 5;
                        }
                    }

                    InvalidateProperties();
                }
            }
        }

        public Mobile FocusWeilder { get; set; }
        public Mobile EnchantedWeilder { get; set; }

        public int LastParryChance { get; set; }

        #region Stygian Abyss
        [CommandProperty(AccessLevel.GameMaster)]
        public int TimesImbued
        {
            get { return m_TimesImbued; }
            set { m_TimesImbued = value; }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool IsImbued
        {
            get
            {
                if (TimesImbued >= 1 && !m_IsImbued)
                    m_IsImbued = true;

                return m_IsImbued;
            }
            set
            {
                if (TimesImbued >= 1)
                    m_IsImbued = true;
                else
                    m_IsImbued = value; InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool DImodded
        {
            get { return m_DImodded; }
            set { m_DImodded = value; }
        }

        public int[] BaseResists
        {
            get
            {
                return new int[] { 0, 0, 0, 0, 0 };
            }
        }

        public virtual void OnAfterImbued(Mobile m, int mod, int value)
        {
        }
        #endregion

        [CommandProperty(AccessLevel.GameMaster)]
        public bool SearingWeapon
        {
            get { return HasSocket<SearingWeapon>(); }
            set
            {
                if (!value)
                {
                    RemoveSocket<SearingWeapon>();
                }
                else if (!SearingWeapon)
                {
                    AttachSocket(new SearingWeapon(this));
                }
            }
        }

        #region Runic Reforging

        [CommandProperty(AccessLevel.GameMaster)]
        public ItemPower ItemPower
        {
            get { return m_ItemPower; }
            set { m_ItemPower = value; InvalidateProperties(); }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public ReforgedPrefix ReforgedPrefix
        {
            get { return m_ReforgedPrefix; }
            set { m_ReforgedPrefix = value; InvalidateProperties(); }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public ReforgedSuffix ReforgedSuffix
        {
            get { return m_ReforgedSuffix; }
            set { m_ReforgedSuffix = value; InvalidateProperties(); }
        }
        #endregion
        #endregion

        public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
        {
            base.GetContextMenuEntries(from, list);

            if (SearingWeapon && Parent == from)
            {
                list.Add(new SearingWeapon.ToggleExtinguishEntry(from, this));
            }

            if (BlessedFor == from && BlessedBy == from && RootParent == from)
            {
                list.Add(new UnBlessEntry(from, this));
            }

            // Xml Spawner 3.26c XmlLevelItem - SOF
            XmlLevelItem levitem = XmlAttach.FindAttachment(this, typeof(XmlLevelItem)) as XmlLevelItem;

            if (levitem != null)
            {
                list.Add(new LevelInfoEntry(from, this, AttributeCategory.Melee));
            }
            // Xml Spawner 3.26c XmlLevelItem - EOF
        }

        public override void OnAfterDuped(Item newItem)
        {
            base.OnAfterDuped(newItem);

            BaseWeapon weap = newItem as BaseWeapon;

            if (weap == null)
            {
                return;
            }

            weap.m_AosAttributes = new AosAttributes(newItem, m_AosAttributes);
            weap.m_AosElementDamages = new AosElementAttributes(newItem, m_AosElementDamages);
            weap.m_AosSkillBonuses = new AosSkillBonuses(newItem, m_AosSkillBonuses);
            weap.m_AosWeaponAttributes = new AosWeaponAttributes(newItem, m_AosWeaponAttributes);
            weap.m_NegativeAttributes = new NegativeAttributes(newItem, m_NegativeAttributes);
            weap.m_ExtendedWeaponAttributes = new ExtendedWeaponAttributes(newItem, m_ExtendedWeaponAttributes);

            #region Mondain's Legacy
            weap.m_SetAttributes = new AosAttributes(newItem, m_SetAttributes);
            weap.m_SetSkillBonuses = new AosSkillBonuses(newItem, m_SetSkillBonuses);
            #endregion

            #region SA
            weap.m_SAAbsorptionAttributes = new SAAbsorptionAttributes(newItem, m_SAAbsorptionAttributes);
            #endregion
        }

        public virtual void UnscaleDurability()
        {
            int scale = 100 + GetDurabilityBonus();

            m_Hits = ((m_Hits * 100) + (scale - 1)) / scale;
            m_MaxHits = ((m_MaxHits * 100) + (scale - 1)) / scale;

            InvalidateProperties();
        }

        public virtual void ScaleDurability()
        {
            int scale = 100 + GetDurabilityBonus();

            m_Hits = ((m_Hits * scale) + 99) / 100;
            m_MaxHits = ((m_MaxHits * scale) + 99) / 100;

            if (m_MaxHits > 255)
                m_MaxHits = 255;

            if (m_Hits > 255)
                m_Hits = 255;

            InvalidateProperties();
        }

        public int GetDurabilityBonus()
        {
            int bonus = 0;

            if (m_Quality == ItemQuality.Exceptional)
            {
                bonus += 20;
            }

            switch (m_DurabilityLevel)
            {
                case WeaponDurabilityLevel.Durable:
                    bonus += 20;
                    break;
                case WeaponDurabilityLevel.Substantial:
                    bonus += 50;
                    break;
                case WeaponDurabilityLevel.Massive:
                    bonus += 70;
                    break;
                case WeaponDurabilityLevel.Fortified:
                    bonus += 100;
                    break;
                case WeaponDurabilityLevel.Indestructible:
                    bonus += 120;
                    break;
            }

            if (Core.AOS)
            {
                bonus += m_AosWeaponAttributes.DurabilityBonus;

                #region Mondain's Legacy
                if (m_Resource == CraftResource.Heartwood)
                {
                    return bonus;
                }
                #endregion

                CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
                CraftAttributeInfo attrInfo = null;

                if (resInfo != null)
                {
                    attrInfo = resInfo.AttributeInfo;
                }

                if (attrInfo != null)
                {
                    bonus += attrInfo.WeaponDurability;
                }
            }

            return bonus;
        }

        public int GetLowerStatReq()
        {
            if (!Core.AOS)
            {
                return 0;
            }

            int v = m_AosWeaponAttributes.LowerStatReq;

            #region Mondain's Legacy
            if (m_Resource == CraftResource.Heartwood)
            {
                return v;
            }
            #endregion

            CraftResourceInfo info = CraftResources.GetInfo(m_Resource);

            if (info != null)
            {
                CraftAttributeInfo attrInfo = info.AttributeInfo;

                if (attrInfo != null)
                {
                    v += attrInfo.WeaponLowerRequirements;
                }
            }

            if (v > 100)
            {
                v = 100;
            }

            return v;
        }

        public static void BlockEquip(Mobile m, TimeSpan duration)
        {
            if (m.BeginAction(typeof(BaseWeapon)))
            {
                new ResetEquipTimer(m, duration).Start();
            }
        }

        private class ResetEquipTimer : Timer
        {
            private readonly Mobile m_Mobile;

            public ResetEquipTimer(Mobile m, TimeSpan duration)
                : base(duration)
            {
                m_Mobile = m;
            }

            protected override void OnTick()
            {
                m_Mobile.EndAction(typeof(BaseWeapon));
                m_Mobile.SendLocalizedMessage(1060168); // Your confusion has passed, you may now arm a weapon!
            }
        }

        public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer)
        {
            if (base.CheckConflictingLayer(m, item, layer))
            {
                return true;
            }

            if (Layer == Layer.TwoHanded && layer == Layer.OneHanded)
            {
                m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500214); // You already have something in both hands.
                return true;
            }
            else if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) && !(item is BaseEquipableLight))
            {
                m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500215); // // You can only wield one weapon at a time.
                return true;
            }

            return false;
        }

        public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
        {
            if (!Ethic.CheckTrade(from, to, newOwner, this))
            {
                return false;
            }

            return base.AllowSecureTrade(from, to, newOwner, accepted);
        }

        public virtual Race RequiredRace { get { return null; } }
        //On OSI, there are no weapons with race requirements, this is for custom stuff

        #region SA
        public virtual bool CanBeWornByGargoyles { get { return false; } }
        #endregion

        public override bool CanEquip(Mobile from)
        {
            if (!Ethic.CheckEquip(from, this))
            {
                return false;
            }

            if (from.IsPlayer())
            {
                if (_Owner != null && _Owner != from)
                {
                    from.SendLocalizedMessage(501023); // You must be the owner to use this item.
                    return false;
                }

                if (this is IAccountRestricted && ((IAccountRestricted)this).Account != null)
                {
                    Accounting.Account acct = from.Account as Accounting.Account;

                    if (acct == null || acct.Username != ((IAccountRestricted)this).Account)
                    {
                        from.SendLocalizedMessage(1071296); // This item is Account Bound and your character is not bound to it. You cannot use this item.
                        return false;
                    }
                }

                if (IsVvVItem && !Engines.VvV.ViceVsVirtueSystem.IsVvV(from))
                {
                    from.SendLocalizedMessage(1155496); // This item can only be used by VvV participants!
                    return false;
                }
            }

            bool morph = from.FindItemOnLayer(Layer.Earrings) is MorphEarrings;

            if (from.Race == Race.Gargoyle && !CanBeWornByGargoyles && from.IsPlayer())
            {
                from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1111708); // Gargoyles can't wear this.
                return false;
            }

            if (RequiredRace != null && from.Race != RequiredRace && !morph)
            {
                if (RequiredRace == Race.Elf)
                {
                    from.SendLocalizedMessage(1072203); // Only Elves may use this.
                }
                else if (RequiredRace == Race.Gargoyle)
                {
                    from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1111707); // Only gargoyles can wear this.
                }
                else
                {
                    from.SendMessage("Only {0} may use ", RequiredRace.PluralName);
                }

                return false;
            }
            else if (from.Dex < DexRequirement)
            {
                from.SendLocalizedMessage(1071936); // You cannot equip that.
                return false;
            }
            else if (from.Str < AOS.Scale(StrRequirement, 100 - GetLowerStatReq()))
            {
                from.SendLocalizedMessage(500213); // You are not strong enough to equip that.
                return false;
            }
            else if (from.Int < IntRequirement)
            {
                from.SendLocalizedMessage(1071936); // You cannot equip that.
                return false;
            }
            else if (!from.CanBeginAction(typeof(BaseWeapon)))
            {
                from.SendLocalizedMessage(3000201); // You must wait to perform another action.
                return false;
            }
                #region Personal Bless Deed
            else if (BlessedBy != null && BlessedBy != from)
            {
                from.SendLocalizedMessage(1075277); // That item is blessed by another player.

                return false;
            }
            else if (!XmlAttach.CheckCanEquip(this, from))
            {
                return false;
            }
                #endregion

            else
            {
                return base.CanEquip(from);
            }
        }

        public virtual bool UseSkillMod { get { return !Core.AOS; } }

        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);

            InDoubleStrike = 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

                if (HasSocket<Caddellite>())
                {
                    Caddellite.UpdateBuff(from);
                }

                if (ExtendedWeaponAttributes.Focus > 0)
                {
                    Focus.UpdateBuff(from);
                }

                from.CheckStatTimers();
                from.Delta(MobileDelta.WeaponDamage);
            }
        }

        public override void OnRemoved(object parent)
        {
            if (parent is Mobile)
            {
                Mobile m = (Mobile)parent;
                BaseWeapon weapon = m.Weapon as BaseWeapon;

                string modName = Serial.ToString();

                m.RemoveStatMod(modName + "Str");
                m.RemoveStatMod(modName + "Dex");
                m.RemoveStatMod(modName + "Int");

                if (weapon != null)
                {
                    m.NextCombatTime = Core.TickCount + (int)weapon.GetDelay(m).TotalMilliseconds;
                }

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

                if (m_MageMod != null)
                {
                    m_MageMod.Remove();
                    m_MageMod = null;
                }

                if (Core.AOS)
                {
                    m_AosSkillBonuses.Remove();
                }

                ImmolatingWeaponSpell.StopImmolating(this, (Mobile)parent);
                Spells.Mysticism.EnchantSpell.OnWeaponRemoved(this, m);

                if (FocusWeilder != null)
                    FocusWeilder = null;

                SkillMasterySpell.OnWeaponRemoved(m, this);

                #region Mondain's Legacy Sets
                if (IsSetItem && m_SetEquipped)
                {
                    SetHelper.RemoveSetBonus(m, SetID, this);
                }
                #endregion

                if (HasSocket<Caddellite>())
                {
                    Caddellite.UpdateBuff(m);
                }

                if (SearingWeapon)
                {
                    Server.Items.SearingWeapon.OnWeaponRemoved(this);
                }

                if (ExtendedWeaponAttributes.Focus > 0)
                {
                    Focus.UpdateBuff(m);
                }

                m.CheckStatTimers();

                m.Delta(MobileDelta.WeaponDamage);

                XmlAttach.CheckOnRemoved(this, parent);
            }

            LastParryChance = 0;
        }

        public void AddMysticMod(Mobile from)
        {
            if (m_MysticMod != null)
                m_MysticMod.Remove();

            int value = m_ExtendedWeaponAttributes.MysticWeapon;

            if (Enhancement.GetValue(from, ExtendedWeaponAttribute.MysticWeapon) > value)
                value = Enhancement.GetValue(from, ExtendedWeaponAttribute.MysticWeapon);

            m_MysticMod = new DefaultSkillMod(SkillName.Mysticism, true, -30 + value);
            from.AddSkillMod(m_MysticMod);
        }

        public void RemoveMysticMod()
        {
            if (m_MysticMod != null)
            {
                m_MysticMod.Remove();
                m_MysticMod = null;
            }
        }

        public virtual SkillName GetUsedSkill(Mobile m, bool checkSkillAttrs)
        {
            SkillName sk;

            if (checkSkillAttrs && m_AosWeaponAttributes.UseBestSkill != 0)
            {
                double swrd = m.Skills[SkillName.Swords].Value;
                double fenc = m.Skills[SkillName.Fencing].Value;
                double mcng = m.Skills[SkillName.Macing].Value;
                double val;

                sk = SkillName.Swords;
                val = swrd;

                if (fenc > val)
                {
                    sk = SkillName.Fencing;
                    val = fenc;
                }
                if (mcng > val)
                {
                    sk = SkillName.Macing;
                    val = mcng;
                }
            }
            else if (m_AosWeaponAttributes.MageWeapon != 0)
            {
                if (m.Skills[SkillName.Magery].Value > m.Skills[Skill].Value)
                {
                    sk = SkillName.Magery;
                }
                else
                {
                    sk = Skill;
                }
            }
            else if (m_ExtendedWeaponAttributes.MysticWeapon != 0 || Enhancement.GetValue(m, ExtendedWeaponAttribute.MysticWeapon) > 0)
            {
                if (m.Skills[SkillName.Mysticism].Value > m.Skills[Skill].Value)
                {
                    sk = SkillName.Mysticism;
                }
                else
                {
                    sk = Skill;
                }
            }
            else
            {
                sk = Skill;

                if (sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman &&
                    m.Skills[SkillName.Wrestling].Value > m.Skills[sk].Value)
                {
                    sk = SkillName.Wrestling;
                }
            }

            return sk;
        }

        public virtual double GetAttackSkillValue(Mobile attacker, Mobile defender)
        {
            return attacker.Skills[GetUsedSkill(attacker, true)].Value;
        }

        public virtual double GetDefendSkillValue(Mobile attacker, Mobile defender)
        {
            return defender.Skills[GetUsedSkill(defender, true)].Value;
        }

        public static bool CheckAnimal(Mobile m, Type type)
        {
            return AnimalForm.UnderTransformation(m, type);
        }

        public virtual bool CheckHit(Mobile attacker, IDamageable damageable)
        {
            Mobile defender = damageable as Mobile;

            if (defender == null)
            {
                if (damageable is IDamageableItem)
                    return ((IDamageableItem)damageable).CheckHit(attacker);

                return true;
            }

            BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
            BaseWeapon defWeapon = defender.Weapon as BaseWeapon;

            Skill atkSkill = attacker.Skills[atkWeapon.Skill];
            Skill defSkill = defender.Skills[defWeapon.Skill];

            double atkValue = atkWeapon.GetAttackSkillValue(attacker, defender);
            double defValue = defWeapon.GetDefendSkillValue(attacker, defender);

            double ourValue, theirValue;

            int bonus = GetHitChanceBonus();

            if (Core.AOS)
            {
                if (atkValue <= -20.0)
                    atkValue = -19.9;

                if (defValue <= -20.0)
                    defValue = -19.9;

                bonus += AosAttributes.GetValue(attacker, AosAttribute.AttackChance);

                //SA Gargoyle cap is 50, else 45
                bonus = Math.Min(attacker.Race == Race.Gargoyle ? 50 : 45, bonus);

                ourValue = (atkValue + 20.0) * (100 + bonus);

                bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance);

                ForceArrow.ForceArrowInfo info = ForceArrow.GetInfo(attacker, defender);

                if (info != null && info.Defender == defender)
                    bonus -= info.DefenseChanceMalus;

                int max = 45 + BaseArmor.GetRefinedDefenseChance(defender);

                // Defense Chance Increase = 45%
                if (bonus > max)
                    bonus = max;

                theirValue = (defValue + 20.0) * (100 + bonus);

                bonus = 0;
            }
            else
            {
                if (atkValue <= -50.0)
                {
                    atkValue = -49.9;
                }

                if (defValue <= -50.0)
                {
                    defValue = -49.9;
                }

                ourValue = (atkValue + 50.0);
                theirValue = (defValue + 50.0);
            }

            double chance = ourValue / (theirValue * 2.0);

            chance *= 1.0 + ((double)bonus / 100);

            if (Core.SA)
            {
                if (atkWeapon is BaseThrown)
                {
                    //Distance malas
                    if (attacker.InRange(defender, 1))    //Close Quarters
                    {
                        chance -= (.12 - (double)Math.Min(12, (attacker.Skills[SkillName.Throwing].Value + (double)attacker.RawDex) / 20) / 10);
                    }
                    else if (attacker.GetDistanceToSqrt(defender) < ((BaseThrown)atkWeapon).MinThrowRange)     //too close
                    {
                        chance -= .12;
                    }

                    //shield penalty
                    BaseShield shield = attacker.FindItemOnLayer(Layer.TwoHanded) as BaseShield;

                    if (shield != null)
                    {
                        double malus = Math.Min(90, 1200 / Math.Max(1.0, attacker.Skills[SkillName.Parry].Value));

                        chance = chance - (chance * (malus / 100));
                    }
                }

                if (defWeapon is BaseThrown)
                {
                    BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;

                    if (shield != null)
                    {
                        double malus = Math.Min(90, 1200 / Math.Max(1.0, defender.Skills[SkillName.Parry].Value));

                        chance = chance + (chance * (malus / 100));
                    }
                }
            }

            if (Core.AOS && chance < 0.02)
            {
                chance = 0.02;
            }

            if (Core.AOS && m_AosWeaponAttributes.MageWeapon > 0 && attacker.Skills[SkillName.Magery].Value > atkSkill.Value)
                return attacker.CheckSkill(SkillName.Magery, chance);

            return attacker.CheckSkill(atkSkill.SkillName, chance);
        }

        public virtual TimeSpan GetDelay(Mobile m)
        {
            double speed = Speed;

            if (speed == 0)
            {
                return TimeSpan.FromHours(1.0);
            }

            double delayInSeconds;

            if (Core.SE)
            {
                /*
                * This is likely true for Core.AOS as well... both guides report the same
                * formula, and both are wrong.
                * The old formula left in for AOS for legacy & because we aren't quite 100%
                * Sure that AOS has THIS formula
                */
                int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);

                if (bonus > 60)
                {
                    bonus = 60;
                }

                double ticks;

                if (Core.ML)
                {
                    int stamTicks = m.Stam / 30;

                    ticks = speed * 4;
                    ticks = Math.Floor((ticks - stamTicks) * (100.0 / (100 + bonus)));
                }
                else
                {
                    speed = Math.Floor(speed * (bonus + 100.0) / 100.0);

                    if (speed <= 0)
                    {
                        speed = 1;
                    }

                    ticks = Math.Floor((80000.0 / ((m.Stam + 100) * speed)) - 2);
                }

                // Swing speed currently capped at one swing every 1.25 seconds (5 ticks).
                if (ticks < 5)
                {
                    ticks = 5;
                }

                delayInSeconds = ticks * 0.25;
            }
            else if (Core.AOS)
            {
                int v = (m.Stam + 100) * (int)speed;

                int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);

                v += AOS.Scale(v, bonus);

                if (v <= 0)
                {
                    v = 1;
                }

                delayInSeconds = Math.Floor(40000.0 / v) * 0.5;

                // Maximum swing rate capped at one swing per second
                // OSI dev said that it has and is supposed to be 1.25
                if (delayInSeconds < 1.25)
                {
                    delayInSeconds = 1.25;
                }
            }
            else
            {
                int v = (m.Stam + 100) * (int)speed;

                if (v <= 0)
                {
                    v = 1;
                }

                delayInSeconds = 15000.0 / v;
            }

            return TimeSpan.FromSeconds(delayInSeconds);
        }

        public virtual void OnBeforeSwing(Mobile attacker, IDamageable damageable)
        {
            Mobile defender = damageable as Mobile;

            WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);

            if (a != null && (!a.OnBeforeSwing(attacker, defender)))
            {
                WeaponAbility.ClearCurrentAbility(attacker);
            }

            SpecialMove move = SpecialMove.GetCurrentMove(attacker);

            if (move != null && !move.OnBeforeSwing(attacker, defender))
            {
                SpecialMove.ClearCurrentMove(attacker);
            }
        }

        public virtual TimeSpan OnSwing(Mobile attacker, IDamageable damageable)
        {
            return OnSwing(attacker, damageable, 1.0);
        }

        public virtual TimeSpan OnSwing(Mobile attacker, IDamageable damageable, double damageBonus)
        {
            bool canSwing = true;

            if (Core.AOS)
            {
                canSwing = (!attacker.Paralyzed && !attacker.Frozen);

                if (canSwing)
                {
                    Spell sp = attacker.Spell as Spell;

                    canSwing = (sp == null || !sp.IsCasting || !sp.BlocksMovement);
                }

                if (canSwing)
                {
                    PlayerMobile p = attacker as PlayerMobile;

                    canSwing = (p == null || p.PeacedUntil <= DateTime.UtcNow);
                }
            }

            if (canSwing && attacker.HarmfulCheck(damageable))
            {
                attacker.DisruptiveAction();

                if (attacker.NetState != null)
                {
                    attacker.Send(new Swing(0, attacker, damageable));
                }

                if (attacker is BaseCreature)
                {
                    BaseCreature bc = (BaseCreature)attacker;
                    WeaponAbility ab = bc.TryGetWeaponAbility();

                    if (ab != null)
                    {
                        if (bc.WeaponAbilityChance > Utility.RandomDouble())
                        {
                            WeaponAbility.SetCurrentAbility(bc, ab);
                        }
                        else
                        {
                            WeaponAbility.ClearCurrentAbility(bc);
                        }
                    }
                }

                if (CheckHit(attacker, damageable))
                {
                    OnHit(attacker, damageable, damageBonus);
                }
                else
                {
                    OnMiss(attacker, damageable);
                }
            }

            return GetDelay(attacker);
        }

        #region Sounds
        public virtual int GetHitAttackSound(Mobile attacker, Mobile defender)
        {
            int sound = attacker.GetAttackSound();

            if (sound == -1)
            {
                sound = HitSound;
            }

            return sound;
        }

        public virtual int GetHitDefendSound(Mobile attacker, Mobile defender)
        {
            return defender.GetHurtSound();
        }

        public virtual int GetMissAttackSound(Mobile attacker, Mobile defender)
        {
            if (attacker.GetAttackSound() == -1)
            {
                return MissSound;
            }
            else
            {
                return -1;
            }
        }

        public virtual int GetMissDefendSound(Mobile attacker, Mobile defender)
        {
            return -1;
        }
        #endregion

        public static bool CheckParry(Mobile defender)
        {
            if (defender == null)
            {
                return false;
            }

            BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;

            double parry = defender.Skills[SkillName.Parry].Value;
            double bushidoNonRacial = defender.Skills[SkillName.Bushido].NonRacialValue;
            double bushido = defender.Skills[SkillName.Bushido].Value;

            if (shield != null || !defender.Player)
            {
                double chance = (parry - bushidoNonRacial) / 400.0;
                    // As per OSI, no negitive effect from the Racial stuffs, ie, 120 parry and '0' bushido with humans

                if (chance < 0) // chance shouldn't go below 0
                {
                    chance = defender.Player ? 0 : .1;
                }

                // Skill Masteries
                chance += HeightenedSensesSpell.GetParryBonus(defender);

                // Parry/Bushido over 100 grants a 5% bonus.
                if (parry >= 100.0 || bushido >= 100.0)
                {
                    chance += 0.05;
                }

                // Evasion grants a variable bonus post ML. 50% prior.
                if (Evasion.IsEvading(defender))
                {
                    chance *= Evasion.GetParryScalar(defender);
                }

                // Low dexterity lowers the chance.
                if (defender.Player && defender.Dex < 80)
                {
                    chance = chance * (20 + defender.Dex) / 100;
                }

                bool success = defender.CheckSkill(SkillName.Parry, chance);

                if (shield != null && Core.EJ && success)
                {
                    shield.LastParryChance = (int)(chance * 100);
                    shield.InvalidateProperties();
                }

                return success;
            }
            else if (!(defender.Weapon is Fists) && !(defender.Weapon is BaseRanged))
            {
                BaseWeapon weapon = defender.Weapon as BaseWeapon;

                if (Core.HS && weapon.Attributes.BalancedWeapon > 0)
                {
                    return false;
                }

                double divisor = (weapon.Layer == Layer.OneHanded && defender.Player) ? 48000.0 : 41140.0;

                double chance = (parry * bushido) / divisor;

                double aosChance = parry / 800.0;

                // Parry or Bushido over 100 grant a 5% bonus.
                if (parry >= 100.0)
                {
                    chance += 0.05;
                    aosChance += 0.05;
                }
                else if (bushido >= 100.0)
                {
                    chance += 0.05;
                }

                // Evasion grants a variable bonus post ML. 50% prior.
                if (Evasion.IsEvading(defender))
                {
                    chance *= Evasion.GetParryScalar(defender);
                }

                // Low dexterity lowers the chance.
                if (defender.Dex < 80)
                {
                    chance = chance * (20 + defender.Dex) / 100;
                }

                bool success;

                if (chance > aosChance)
                {
                    success = defender.CheckSkill(SkillName.Parry, chance);
                }
                else
                {
                    success = (aosChance > Utility.RandomDouble());
                        // Only skillcheck if wielding a shield & there's no effect from Bushido
                }

                if (Core.EJ && success)
                {
                    weapon.LastParryChance = (int)(chance * 100);
                    weapon.InvalidateProperties();
                }

                return success;
            }

            return false;
        }

        public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage)
        {
            int originalDamage = damage;

            bool blocked = false;

            if (defender.Player || defender.Body.IsHuman || (defender is BaseCreature &&
                                                            ((BaseCreature)defender).Controlled &&
                                                            defender.Skills[SkillName.Wrestling].Base >= 100))
            {
                blocked = CheckParry(defender);
                BaseWeapon weapon = defender.Weapon as BaseWeapon;

                if (blocked)
                {
                    defender.FixedEffect(0x37B9, 10, 16);
                    damage = 0;

                    if (Core.SA)
                    {
                        defender.Animate(AnimationType.Parry, 0);
                    }

                    // Successful block removes the Honorable Execution penalty.
                    HonorableExecution.RemovePenalty(defender);

                    if (CounterAttack.IsCountering(defender) && defender.InRange(attacker.Location, 1))
                    {
                        if (weapon != null)
                        {
                            var combatant = defender.Combatant;

                            defender.FixedParticles(0x3779, 1, 15, 0x158B, 0x0, 0x3, EffectLayer.Waist);
                            weapon.OnSwing(defender, attacker);

                            if (combatant != null && defender.Combatant != combatant && combatant.Alive)
                                defender.Combatant = combatant;
                        }

                        CounterAttack.StopCountering(defender);
                    }

                    if (Confidence.IsConfident(defender))
                    {
                        defender.SendLocalizedMessage(1063117);
                            // Your confidence reassures you as you successfully block your opponent's blow.

                        double bushido = defender.Skills.Bushido.Value;

                        defender.Hits += Utility.RandomMinMax(1, (int)(bushido / 12)) + MasteryInfo.AnticipateHitBonus(defender) / 10;
                        defender.Stam += Utility.RandomMinMax(1, (int)(bushido / 5)) + MasteryInfo.AnticipateHitBonus(defender) / 10;
                    }

                    BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;

                    if (shield != null)
                    {
                        shield.OnHit(this, damage);

                        #region Stygian Abyss
                        if (shield.ArmorAttributes.ReactiveParalyze > 0 && 30 > Utility.Random(100))
                        {
                            int secs = (int)Math.Max(1, Math.Max(8, defender.Skills[SkillName.EvalInt].Value / 10) - attacker.Skills[SkillName.MagicResist].Value / 10);

                            attacker.Paralyze(TimeSpan.FromSeconds(secs));
                            attacker.PlaySound(0x204);
                            attacker.FixedEffect(0x376A, 6, 1);
                        }
                        #endregion

                        XmlAttach.OnArmorHit(attacker, defender, shield, this, originalDamage);
                    }

                    #region Stygian Abyss
                    else if (weapon != null && weapon.Layer == Layer.TwoHanded && weapon.WeaponAttributes.ReactiveParalyze > 0 && 30 > Utility.Random(100))
                    {
                        int secs = (int)Math.Max(1, Math.Max(8, defender.Skills[SkillName.EvalInt].Value / 10) - attacker.Skills[SkillName.MagicResist].Value / 10);

                        attacker.Paralyze(TimeSpan.FromSeconds(secs));
                        attacker.PlaySound(0x204);
                        attacker.FixedEffect(0x376A, 6, 1);
                    }
                    #endregion

                    //Skill Masteries
                    SkillMasterySpell.OnParried(attacker, defender);
                }
            }

            if (!blocked)
            {
                IWearableDurability toHit = GetRandomValidItem(defender) as IWearableDurability;

                if (toHit != null)
                {
                    toHit.OnHit(this, damage); // call OnHit to lose durability

                    if (toHit is Item && !((Item)toHit).Deleted && (attacker is VeriteElemental || attacker is ValoriteElemental))
                        VeriteElemental.OnHit(defender, (Item)toHit, damage);

                    damage -= XmlAttach.OnArmorHit(attacker, defender, (Item)toHit, this, originalDamage);
                }
            }

            return damage;
        }

        private Item GetRandomValidItem(Mobile m)
        {
            Item[] items = m.Items.Where(item => _DamageLayers.Contains(item.Layer) && item is IWearableDurability).ToArray();

            if (items.Length == 0)
                return null;

            return items[Utility.Random(items.Length)];
        }

        private List<Layer> _DamageLayers = new List<Layer>()
        {
            Layer.FirstValid,
            Layer.OneHanded,
            Layer.TwoHanded,
            Layer.Shoes,
            Layer.Pants,
            Layer.Shirt,
            Layer.Helm,
            Layer.Arms,
            Layer.Gloves,
            Layer.Ring,
            Layer.Talisman,
            Layer.Neck,
            Layer.Waist,
            Layer.InnerTorso,
            Layer.Bracelet,
            Layer.MiddleTorso,
            Layer.Earrings,
            Layer.Cloak,
            Layer.OuterTorso,
            Layer.OuterLegs,
            Layer.InnerLegs,
        };

        public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage)
        {
            if (Core.AOS)
            {
                return AbsorbDamageAOS(attacker, defender, damage);
            }

            BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
            if (shield != null)
            {
                damage = shield.OnHit(this, damage);
            }

            double chance = Utility.RandomDouble();

            Item armorItem;

            if (chance < 0.07)
            {
                armorItem = defender.NeckArmor;
            }
            else if (chance < 0.14)
            {
                armorItem = defender.HandArmor;
            }
            else if (chance < 0.28)
            {
                armorItem = defender.ArmsArmor;
            }
            else if (chance < 0.43)
            {
                armorItem = defender.HeadArmor;
            }
            else if (chance < 0.65)
            {
                armorItem = defender.LegsArmor;
            }
            else
            {
                armorItem = defender.ChestArmor;
            }

            IWearableDurability armor = armorItem as IWearableDurability;

            if (armor != null)
            {
                damage = armor.OnHit(this, damage);
            }

            var virtualArmor = defender.ArmorRating;

            damage -= XmlAttach.OnArmorHit(attacker, defender, armorItem, this, damage);
            damage -= XmlAttach.OnArmorHit(attacker, defender, shield, this, damage);

            if (virtualArmor > 0)
            {
                double scalar;

                if (chance < 0.14)
                {
                    scalar = 0.07;
                }
                else if (chance < 0.28)
                {
                    scalar = 0.14;
                }
                else if (chance < 0.43)
                {
                    scalar = 0.15;
                }
                else if (chance < 0.65)
                {
                    scalar = 0.22;
                }
                else
                {
                    scalar = 0.35;
                }

                int from = (int)(virtualArmor * scalar) / 2;
                int to = (int)(virtualArmor * scalar);

                damage -= Utility.Random(from, (to - from) + 1);
            }

            return damage;
        }

        public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender)
        {
            if (attacker.Player || defender.Player)
            {
                return 0;
            }

            BaseCreature bc = attacker as BaseCreature;

            if (bc == null || bc.PackInstinct == PackInstinct.None || (!bc.Controlled && !bc.Summoned))
            {
                return 0;
            }

            Mobile master = bc.ControlMaster;

            if (master == null)
            {
                master = bc.SummonMaster;
            }

            if (master == null)
            {
                return 0;
            }

            int inPack = 1;

            IPooledEnumerable eable = defender.GetMobilesInRange(1);

            foreach (Mobile m in eable)
            {
                if (m != attacker && m is BaseCreature)
                {
                    BaseCreature tc = (BaseCreature)m;

                    if ((tc.PackInstinct & bc.PackInstinct) == 0 || (!tc.Controlled && !tc.Summoned))
                    {
                        continue;
                    }

                    Mobile theirMaster = tc.ControlMaster;

                    if (theirMaster == null)
                    {
                        theirMaster = tc.SummonMaster;
                    }

                    if (master == theirMaster && tc.Combatant == defender)
                    {
                        ++inPack;
                    }
                }
            }

            eable.Free();

            if (inPack >= 5)
            {
                return 100;
            }
            else if (inPack >= 4)
            {
                return 75;
            }
            else if (inPack >= 3)
            {
                return 50;
            }
            else if (inPack >= 2)
            {
                return 25;
            }

            return 0;
        }

        private bool m_InDoubleStrike;
        private bool m_ProcessingMultipleHits;

        public bool InDoubleStrike
        {
            get { return m_InDoubleStrike; }
            set
            {
                m_InDoubleStrike = value;

                if (m_InDoubleStrike)
                    ProcessingMultipleHits = true;
                else
                    ProcessingMultipleHits = false;
            }
        }

        public bool ProcessingMultipleHits
        {
            get { return m_ProcessingMultipleHits; }
            set
            {
                m_ProcessingMultipleHits = value;

                if (!m_ProcessingMultipleHits)
                    BlockHitEffects = false;
            }
        }

        public bool EndDualWield { get; set; }
        public bool BlockHitEffects { get; set; }
        public DateTime NextSelfRepair { get; set; }

        //daat99 OWLTR start - make it virtual
        public virtual void OnHit(Mobile attacker, IDamageable damageable)
        //daat99 OWLTR end - make it virtual
        {
            OnHit(attacker, damageable, 1.0);
        }

        public virtual void OnHit(Mobile attacker, IDamageable damageable, double damageBonus)
        {
            if (EndDualWield)
            {
                ProcessingMultipleHits = false;
                EndDualWield = false;
            }

            Mobile defender = damageable as Mobile;
            Clone clone = null;

            if (defender != null)
            {
                clone = MirrorImage.GetDeflect(attacker, defender);
            }

            if (clone != null)
            {
                defender = clone;
            }

            PlaySwingAnimation(attacker);

            if(defender != null)
                PlayHurtAnimation(defender);

            attacker.PlaySound(GetHitAttackSound(attacker, defender));

            if(defender != null)
                defender.PlaySound(GetHitDefendSound(attacker, defender));

            int damage = ComputeDamage(attacker, defender);

            WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);
            SpecialMove move = SpecialMove.GetCurrentMove(attacker);

            bool ranged = this is BaseRanged;
            int phys, fire, cold, pois, nrgy, chaos, direct;

            if ((Core.TOL && a is MovingShot) || SkillMasterySpell.HasSpell<ShieldBashSpell>(attacker))
            {
                phys = 100;
                fire = cold = pois = nrgy = chaos = direct = 0;
            }
            else
            {
                GetDamageTypes(attacker, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);

                if (!OnslaughtSpell.HasOnslaught(attacker, defender) &&
                    ConsecratedContext != null &&
                    ConsecratedContext.Owner == attacker &&
                    ConsecratedContext.ConsecrateProcChance >= Utility.Random(100))
                {
                    phys = damageable.PhysicalResistance;
                    fire = damageable.FireResistance;
                    cold = damageable.ColdResistance;
                    pois = damageable.PoisonResistance;
                    nrgy = damageable.EnergyResistance;

                    int low = phys, type = 0;

                    if (fire < low) { low = fire; type = 1; }
                    if (cold < low) { low = cold; type = 2; }
                    if (pois < low) { low = pois; type = 3; }
                    if (nrgy < low) { low = nrgy; type = 4; }

                    phys = fire = cold = pois = nrgy = chaos = direct = 0;

                    if (type == 0) phys = 100;
                    else if (type == 1) fire = 100;
                    else if (type == 2) cold = 100;
                    else if (type == 3) pois = 100;
                    else if (type == 4) nrgy = 100;
                }
                else if (Core.ML && ranged)
                {
                    IRangeDamage rangeDamage = attacker.FindItemOnLayer(Layer.Cloak) as IRangeDamage;

                    if (rangeDamage != null)
                    {
                        rangeDamage.AlterRangedDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct);
                    }
                }
            }

            bool splintering = false;

            if (m_AosWeaponAttributes.SplinteringWeapon > 0 && m_AosWeaponAttributes.SplinteringWeapon > Utility.Random(100))
            {
                if (SplinteringWeaponContext.CheckHit(attacker, defender, a, this))
                    splintering = true;
            }

            double chance = NegativeAttributes.Antique > 0 ? 5 : 0;
            bool acidicTarget = MaxRange <= 1 && m_AosAttributes.SpellChanneling == 0 && !(this is Fists) && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime);

            if (acidicTarget || (defender != null && splintering) || Utility.Random(40) <= chance)
            {
                if (MaxRange <= 1 && acidicTarget)
                {
                    attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!*
                }

                int selfRepair = !Core.AOS ? 0 : m_AosWeaponAttributes.SelfRepair + (IsSetItem && m_SetEquipped ? m_SetSelfRepair : 0);

                if (selfRepair > 0 && NextSelfRepair < DateTime.UtcNow)
                {
                    HitPoints += selfRepair;

                    NextSelfRepair = DateTime.UtcNow + TimeSpan.FromSeconds(60);
                }
                else
                {
                    if (m_MaxHits > 0)
                    {
                        if (m_Hits >= 1)
                        {
                            if (splintering)
                            {
                                HitPoints = Math.Max(0, HitPoints - 10);
                            }
                            else
                            {
                                HitPoints--;
                            }
                        }
                        else if (m_MaxHits > 0)
                        {
                            MaxHitPoints--;

                            if (Parent is Mobile)
                                ((Mobile)Parent).LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121); // Your equipment is severely damaged.

                            if (m_MaxHits <= 0)
                                Delete();
                        }
                    }
                }
            }

            WeaponAbility weavabil;
            bool bladeweaving = Bladeweave.BladeWeaving(attacker, out weavabil);
            bool ignoreArmor = (a is ArmorIgnore || (move != null && move.IgnoreArmor(attacker)) || (bladeweaving && weavabil is ArmorIgnore));

            // object is not a mobile, so we end here
            if (defender == null)
            {
                AOS.Damage(damageable, attacker, damage, ignoreArmor, phys, fire, cold, pois, nrgy, chaos, direct, false, ranged ? Server.DamageType.Ranged : Server.DamageType.Melee);

                // TODO: WeaponAbility/SpecialMove OnHit(...) convert target to IDamageable
                // Figure out which specials work on items. For now AI only.
                if (ignoreArmor)
                {
                    Effects.PlaySound(damageable.Location, damageable.Map, 0x56);
                    Effects.SendTargetParticles(damageable, 0x3728, 200, 25, 0, 0, 9942, EffectLayer.Waist, 0);
                }

                WeaponAbility.ClearCurrentAbility(attacker);
                SpecialMove.ClearCurrentMove(attacker);

                if (WeaponAttributes.HitLeechHits > 0)
                {
                    attacker.SendLocalizedMessage(1152566); // You fail to leech life from your target!
                }

                return;
            }

            #region Damage Multipliers
            /*
            * The following damage bonuses multiply damage by a factor.
            * Capped at x3 (300%).
            */
            int percentageBonus = 0;

            if (a != null)
            {
                percentageBonus += (int)(a.DamageScalar * 100) - 100;
            }

            if (move != null)
            {
                percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100;
            }

            if (ConsecratedContext != null && ConsecratedContext.Owner == attacker)
            {
                percentageBonus += ConsecratedContext.ConsecrateDamageBonus;
            }

            percentageBonus += (int)(damageBonus * 100) - 100;

            CheckSlayerResult cs1 = CheckSlayers(attacker, defender, Slayer);
            CheckSlayerResult cs2 = CheckSlayers(attacker, defender, Slayer2);
            CheckSlayerResult suit = CheckSlayers(attacker, defender, SetHelper.GetSetSlayer(attacker));
            CheckSlayerResult tal = CheckTalismanSlayer(attacker, defender);

            if (cs1 == CheckSlayerResult.None && cs2 == CheckSlayerResult.None)
            {
                cs1 = CheckSlayers(attacker, defender, SlayerSocket.GetSlayer(this));
            }

            if (cs1 != CheckSlayerResult.None)
            {
                if (cs1 == CheckSlayerResult.SuperSlayer)
                    percentageBonus += 100;
                else if (cs1 == CheckSlayerResult.Slayer)
                    percentageBonus += 200;
            }

            if (cs2 != CheckSlayerResult.None)
            {
                if (cs2 == CheckSlayerResult.SuperSlayer)
                    percentageBonus += 100;
                else if (cs2 == CheckSlayerResult.Slayer)
                    percentageBonus += 200;
            }

            if (suit != CheckSlayerResult.None)
            {
                percentageBonus += 100;
            }

            if (tal != CheckSlayerResult.None)
            {
                percentageBonus += 100;
            }

            if (CheckSlayerOpposition(attacker, defender) != CheckSlayerResult.None)
            {
                percentageBonus += 100;
                defender.FixedEffect(0x37B9, 10, 5);
            }
            else if (cs1 != CheckSlayerResult.None || cs2 != CheckSlayerResult.None || suit != CheckSlayerResult.None || tal != CheckSlayerResult.None)
            {
                defender.FixedEffect(0x37B9, 10, 5);
            }

            #region Enemy of One
            var enemyOfOneContext = EnemyOfOneSpell.GetContext(defender);

            if (enemyOfOneContext != null && !enemyOfOneContext.IsWaitingForEnemy && !enemyOfOneContext.IsEnemy(attacker))
            {
                percentageBonus += 100;
            }
            else
            {
                enemyOfOneContext = EnemyOfOneSpell.GetContext(attacker);

                if (enemyOfOneContext != null)
                {
                    enemyOfOneContext.OnHit(defender);

                    if (enemyOfOneContext.IsEnemy(defender))
                    {
                        defender.FixedEffect(0x37B9, 10, 5, 1160, 0);
                        percentageBonus += enemyOfOneContext.DamageScalar;
                    }
                }
            }
            #endregion

            int packInstinctBonus = GetPackInstinctBonus(attacker, defender);

            if (packInstinctBonus != 0)
            {
                percentageBonus += packInstinctBonus;
            }

            if (m_InDoubleStrike)
            {
                percentageBonus -= 10;
            }

            TransformContext context = TransformationSpellHelper.GetContext(defender);

            if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver || SetHelper.GetSetSlayer(attacker) == SlayerName.Silver)
                && ((context != null && context.Spell is NecromancerSpell && context.Type != typeof(HorrificBeastSpell))
                || (defender is BaseCreature && (defender.Body == 747 || defender.Body == 748 || defender.Body == 749 || defender.Hue == 0x847E))))
            {
                // Every necromancer transformation other than horrific beast takes an additional 25% damage
                percentageBonus += 25;
            }

            if (attacker is PlayerMobile && !(Core.ML && defender is PlayerMobile))
            {
                PlayerMobile pmAttacker = (PlayerMobile)attacker;

                if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1))
                {
                    percentageBonus += 25;
                }

                if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender)
                {
                    percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus;
                }
            }

            percentageBonus -= Block.GetMeleeReduction(defender);

            #region Stygian Abyss
            percentageBonus += BattleLust.GetBonus(attacker, defender);

            if (this is BaseThrown)
            {
                double dist = attacker.GetDistanceToSqrt(defender);
                int max = ((BaseThrown)this).MaxThrowRange;

                if (dist > max)
                    percentageBonus -= 47;
            }

            if (RunedSashOfWarding.IsUnderEffects(defender, WardingEffect.WeaponDamage))
                percentageBonus -= 10;
            #endregion

            #region Mondain's Legacy
            if (Core.ML)
            {
                BaseTalisman talisman = attacker.Talisman as BaseTalisman;

                if (talisman != null && talisman.Killer != null)
                {
                    percentageBonus += talisman.Killer.DamageBonus(defender);
                }

                if (this is ButchersWarCleaver)
                {
                    if (defender is Bull || defender is Cow || defender is Gaman)
                    {
                        percentageBonus += 100;
                    }
                }
            }
            #endregion

            percentageBonus += ForceOfNature.GetBonus(attacker, defender);

            if (m_ExtendedWeaponAttributes.AssassinHoned > 0 && GetOppositeDir(attacker.Direction) == defender.Direction)
            {
                if (!ranged || 0.5 > Utility.RandomDouble())
                {
                    percentageBonus += (int)(146.0 / MlSpeed);
                }
            }

            if (m_ExtendedWeaponAttributes.Focus > 0)
            {
                percentageBonus += Focus.GetBonus(attacker, defender);
                Focus.OnHit(attacker, defender);
            }

            percentageBonus = Math.Min(percentageBonus, 300);

            // bonus is seprate from weapon damage, ie not capped
            percentageBonus += Spells.Mysticism.StoneFormSpell.GetMaxResistBonus(attacker);

            damage = AOS.Scale(damage, 100 + percentageBonus);
            #endregion

            damage = AbsorbDamage(attacker, defender, damage);

            if (!Core.AOS && damage < 1)
            {
                damage = 1;
            }
            else if (Core.AOS && damage == 0) // parried
            {
                if ((a != null && a.Validate(attacker)) || (move != null && move.Validate(attacker)))
                    // Parried special moves have no mana cost - era specific
                {
                    if (Core.SE || (a != null && a.CheckMana(attacker, true)))
                    {
                        WeaponAbility.ClearCurrentAbility(attacker);
                        SpecialMove.ClearCurrentMove(attacker);

                        attacker.SendLocalizedMessage(1061140); // Your attack was parried!
                    }
                }

                return;
            }

            // Skill Masteries
            if (WhiteTigerFormSpell.CheckEvasion(defender))
            {
                defender.Emote("*evades*"); // Is this right?
                return;
            }

            #region Mondain's Legacy
            if (ImmolatingWeaponSpell.IsImmolating(attacker, this))
            {
                int d = ImmolatingWeaponSpell.GetImmolatingDamage(attacker);
                d = AOS.Damage(defender, attacker, d, 0, 100, 0, 0, 0);

                ImmolatingWeaponSpell.DoDelayEffect(attacker, defender);

                if (d > 0)
                {
                    defender.Damage(d);
                }
            }
            #endregion

            #region SA
            if (defender != null && Server.Items.SearingWeapon.CanSear(this) && attacker.Mana > 0)
            {
                int d = SearingWeaponContext.Damage;

                if ((ranged && 10 > Utility.Random(100)) || 20 > Utility.Random(100))
                {
                    AOS.Damage(defender, attacker, d, 0, 100, 0, 0, 0);
                    AOS.Damage(attacker, null, 4, false, 0, 0, 0, 0, 0, 0, 100, false, false, false);

                    defender.FixedParticles(0x36F4, 1, 11, 0x13A8, 0, 0, EffectLayer.Waist);

                    SearingWeaponContext.CheckHit(attacker, defender);
                    attacker.Mana--;
                }
            }
            #endregion

            #region BoneBreaker/Swarm/Sparks
            bool sparks = false;
            if (a == null && move == null)
            {
                if (m_ExtendedWeaponAttributes.BoneBreaker > 0)
                    damage += BoneBreakerContext.CheckHit(attacker, defender);

                if (m_ExtendedWeaponAttributes.HitSwarm > 0 && Utility.Random(100) < m_ExtendedWeaponAttributes.HitSwarm)
                    SwarmContext.CheckHit(attacker, defender);

                if (m_ExtendedWeaponAttributes.HitSparks > 0 && Utility.Random(100) < m_ExtendedWeaponAttributes.HitSparks)
                {
                    SparksContext.CheckHit(attacker, defender);
                    sparks = true;
                }
            }
            #endregion

            Timer.DelayCall(d => AddBlood(d, damage), defender);

            int damageGiven = damage;

            if (a != null && !a.OnBeforeDamage(attacker, defender))
            {
                WeaponAbility.ClearCurrentAbility(attacker);
                a = null;
            }

            if (move != null && !move.OnBeforeDamage(attacker, defender))
            {
                SpecialMove.ClearCurrentMove(attacker);
                move = null;
            }

            if (Feint.Registry.ContainsKey(defender) && Feint.Registry[defender].Enemy == attacker)
                damage -= (int)((double)damage * ((double)Feint.Registry[defender].DamageReduction / 100));

            // Skill Masteries
            if (this is Fists)
                damage += (int)((double)damage * ((double)MasteryInfo.GetKnockoutModifier(attacker, defender is PlayerMobile) / 100.0));

            SkillMasterySpell.OnHit(attacker, defender, ref damage);

            // Bane
            if (m_ExtendedWeaponAttributes.Bane > 0 && defender.Hits < defender.HitsMax / 2)
            {
                double inc = Math.Min(350, (double)defender.HitsMax * .3);
                inc -= (double)((double)defender.Hits / (double)defender.HitsMax) * inc;

                Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0x30, 3);

                damage += (int)inc;
            }

            damageGiven = AOS.Damage(
                defender,
                attacker,
                damage,
                ignoreArmor,
                phys,
                fire,
                cold,
                pois,
                nrgy,
                chaos,
                direct,
                false,
                ranged ? Server.DamageType.Ranged : Server.DamageType.Melee);

            DualWield.DoHit(attacker, defender, damage);

            if (sparks)
            {
                int mana = attacker.Mana + damageGiven;
                if (!defender.Player) mana *= 2;
                attacker.Mana = Math.Min(attacker.ManaMax, attacker.Mana + mana);
            }

            double propertyBonus = (move == null) ? 1.0 : move.GetPropertyBonus(attacker);

            if (Core.AOS)
            {
                int lifeLeech = 0;
                int stamLeech = 0;
                int manaLeech = 0;

                if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) >
                    Utility.Random(100))
                {
                    stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina
                }

                if (Core.SA)
                {
                    lifeLeech = (int)(WeaponAttributes.HitLeechHits * propertyBonus);
                    manaLeech = (int)(WeaponAttributes.HitLeechMana * propertyBonus);
                }
                else
                {
                    if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) >
                        Utility.Random(100))
                    {
                        lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points
                    }

                    if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) >
                        Utility.Random(100))
                    {
                        manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana
                    }
                }

                int toHealCursedWeaponSpell = 0;

                if (CurseWeaponSpell.IsCursed(attacker, this))
                {
                    toHealCursedWeaponSpell += (int)(AOS.Scale(damageGiven, 50)); // Additional 50% life leech for cursed weapons (necro spell)
                }

                context = TransformationSpellHelper.GetContext(attacker);

                if (stamLeech != 0)
                {
                    attacker.Stam += AOS.Scale(damageGiven, stamLeech);
                }

                if (Core.SA) // New formulas
                {
                    if (lifeLeech != 0)
                    {
                        int toHeal = Utility.RandomMinMax(0, (int)(AOS.Scale(damageGiven, lifeLeech) * 0.3));

                        if (defender is BaseCreature && ((BaseCreature)defender).TaintedLifeAura)
                        {                           
                            AOS.Damage(attacker, defender, toHeal, false, 0, 0, 0, 0, 0, 0, 100, false, false, false);                           
                            attacker.SendLocalizedMessage(1116778); //The tainted life force energy damages you as your body tries to absorb it.
                        }
                        else
                        {
                            attacker.Hits += toHeal;
                        }

                        Effects.SendPacket(defender.Location, defender.Map, new ParticleEffect(EffectType.FixedFrom, defender.Serial, Serial.Zero, 0x377A, defender.Location, defender.Location, 1, 15, false, false, 1926, 0, 0, 9502, 1, defender.Serial, 16, 0));
                        Effects.SendPacket(defender.Location, defender.Map, new ParticleEffect(EffectType.FixedFrom, defender.Serial, Serial.Zero, 0x3728, defender.Location, defender.Location, 1, 12, false, false, 1963, 0, 0, 9042, 1, defender.Serial, 16, 0));
                    }

                    if (toHealCursedWeaponSpell != 0 && !(defender is BaseCreature && ((BaseCreature)defender).TaintedLifeAura))
                    {
                        attacker.Hits += toHealCursedWeaponSpell;
                    }

                    if (manaLeech != 0)
                    {
                        attacker.Mana += Utility.RandomMinMax(0, (int)(AOS.Scale(damageGiven, manaLeech) * 0.4));
                    }
                }
                else // Old formulas
                {
                    if (toHealCursedWeaponSpell != 0)
                    {
                        attacker.Hits += toHealCursedWeaponSpell;
                    }

                    if (lifeLeech != 0)
                    {
                        attacker.Hits += AOS.Scale(damageGiven, lifeLeech);
                    }

                    if (manaLeech != 0)
                    {
                        attacker.Mana += AOS.Scale(damageGiven, manaLeech);
                    }
                }

                if (lifeLeech != 0 || stamLeech != 0 || manaLeech != 0 || toHealCursedWeaponSpell != 0)
                {
                    attacker.PlaySound(0x44D);
                }
            }

            if (attacker is VampireBatFamiliar || attacker is VampireBat)
            {
                BaseCreature bc = (BaseCreature)attacker;
                Mobile caster = bc.ControlMaster;

                if (caster == null)
                {
                    caster = bc.SummonMaster;
                }

                if (caster != null && caster.Map == bc.Map && caster.InRange(bc, 2))
                {
                    caster.Hits += damage;
                }
                else
                {
                    bc.Hits += damage;
                }
            }

            if (Core.AOS && !BlockHitEffects)
            {
                int physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * propertyBonus);
                int fireChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus);
                int coldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus);
                int poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * propertyBonus);
                int nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * propertyBonus);

                if (physChance != 0 && physChance > Utility.Random(100))
                {
                    DoAreaAttack(attacker, defender, damageGiven, 0x10E, 50, 100, 0, 0, 0, 0);
                }

                if (fireChance != 0 && fireChance > Utility.Random(100))
                {
                    DoAreaAttack(attacker, defender, damageGiven, 0x11D, 1160, 0, 100, 0, 0, 0);
                }

                if (coldChance != 0 && coldChance > Utility.Random(100))
                {
                    DoAreaAttack(attacker, defender, damageGiven, 0x0FC, 2100, 0, 0, 100, 0, 0);
                }

                if (poisChance != 0 && poisChance > Utility.Random(100))
                {
                    DoAreaAttack(attacker, defender, damageGiven, 0x205, 1166, 0, 0, 0, 100, 0);
                }

                if (nrgyChance != 0 && nrgyChance > Utility.Random(100))
                {
                    DoAreaAttack(attacker, defender, damageGiven, 0x1F1, 120, 0, 0, 0, 0, 100);
                }

                int maChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus);
                int harmChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitHarm) * propertyBonus);
                int fireballChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireball) * propertyBonus);
                int lightningChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLightning) * propertyBonus);
                int dispelChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus);
                int explosChance = (int)(ExtendedWeaponAttributes.GetValue(attacker, ExtendedWeaponAttribute.HitExplosion) * propertyBonus);

                #region Mondains Legacy
                int velocityChance = this is BaseRanged ? (int)((BaseRanged)this).Velocity : 0;
                #endregion

                #region Stygian Abyss
                int curseChance = (int)(m_AosWeaponAttributes.HitCurse * propertyBonus);
                int fatigueChance = (int)(m_AosWeaponAttributes.HitFatigue * propertyBonus);
                int manadrainChance = (int)(m_AosWeaponAttributes.HitManaDrain * propertyBonus);
                #endregion

                if (maChance != 0 && maChance > Utility.Random(100))
                {
                    DoMagicArrow(attacker, defender);
                }

                if (harmChance != 0 && harmChance > Utility.Random(100))
                {
                    DoHarm(attacker, defender);
                }

                if (fireballChance != 0 && fireballChance > Utility.Random(100))
                {
                    DoFireball(attacker, defender);
                }

                if (lightningChance != 0 && lightningChance > Utility.Random(100))
                {
                    DoLightning(attacker, defender);
                }

                if (dispelChance != 0 && dispelChance > Utility.Random(100))
                {
                    DoDispel(attacker, defender);
                }

                if (explosChance != 0 && explosChance > Utility.Random(100))
                {
                    DoExplosion(attacker, defender);
                }

                #region Mondains Legacy
                if (Core.ML && velocityChance != 0 && velocityChance > Utility.Random(100))
                {
                    DoHitVelocity(attacker, damageable);
                }
                #endregion

                #region Stygian Abyss
                if (curseChance != 0 && curseChance > Utility.Random(100))
                {
                    DoCurse(attacker, defender);
                }

                if (fatigueChance != 0 && fatigueChance > Utility.Random(100))
                {
                    DoFatigue(attacker, defender, damageGiven);
                }

                if (manadrainChance != 0 && manadrainChance > Utility.Random(100))
                {
                    DoManaDrain(attacker, defender, damageGiven);
                }
                #endregion

                int laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * propertyBonus);

                if (laChance != 0 && laChance > Utility.Random(100))
                {
                    DoLowerAttack(attacker, defender);
                }

                if (!Core.HS)
                {
                    int ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * propertyBonus);

                    if (ldChance != 0 && ldChance > Utility.Random(100))
                    {
                        DoLowerDefense(attacker, defender);
                    }
                }
                else
                {
                    int hldWep = m_AosWeaponAttributes.HitLowerDefend;
                    int hldGlasses = 0;
                    
                    var helm = attacker.FindItemOnLayer(Layer.Helm);

                    if (helm != null)
                    {
                        var attrs = RunicReforging.GetAosWeaponAttributes(helm);

                        if(attrs != null)
                            hldGlasses = attrs.HitLowerDefend;
                    }

                    if ((hldWep > 0 && hldWep > Utility.Random(100)) || (hldGlasses > 0 && hldGlasses > Utility.Random(100)))
                    {
                        DoLowerDefense(attacker, defender);
                    }
                }
            }

            if (attacker is BaseCreature)
            {
                ((BaseCreature)attacker).OnGaveMeleeAttack(defender);
            }

            if (defender is BaseCreature)
            {
                ((BaseCreature)defender).OnGotMeleeAttack(attacker);
            }

            if (a != null)
            {
                a.OnHit(attacker, defender, damage);
            }

            if (move != null)
            {
                move.OnHit(attacker, defender, damage);
            }

            if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
            {
                ((IHonorTarget)defender).ReceivedHonorContext.OnTargetHit(attacker);
            }

            if (!ranged)
            {
                if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent)))
                {
                    defender.ApplyPoison(attacker, Poison.Lesser);
                }

                if (AnimalForm.UnderTransformation(defender, typeof(BullFrog)))
                {
                    attacker.ApplyPoison(defender, Poison.Regular);
                }
            }

            BaseFamiliar.OnHit(attacker, damageable);
            WhiteTigerFormSpell.OnHit(attacker, defender);
            XmlAttach.OnWeaponHit(this, attacker, defender, damageGiven);
        }

        public Direction GetOppositeDir(Direction d)
        {
            Direction direction = Direction.Down;

            if (d == Direction.West)
                direction = Direction.East;

            if (d == Direction.East)
                direction = Direction.West;

            if (d == Direction.North)
                direction = Direction.South;

            if (d == Direction.South)
                direction = Direction.North;

            if (d == Direction.Right)
                direction = Direction.Left;

            if (d == Direction.Left)
                direction = Direction.Right;

            if (d == Direction.Up)
                direction = Direction.Down;

            if (d == Direction.Down)
                direction = Direction.Up;

            return direction;
        }

        public virtual double GetAosSpellDamage(Mobile attacker, Mobile defender, int bonus, int dice, int sides)
        {
            int damage = Utility.Dice(dice, sides, bonus) * 100;
            int damageBonus = 0;

            int inscribeSkill = attacker.Skills[SkillName.Inscribe].Fixed;
            int inscribeBonus = (inscribeSkill + (1000 * (inscribeSkill / 1000))) / 200;

            damageBonus += inscribeBonus;
            damageBonus += attacker.Int / 10;
            damageBonus += SpellHelper.GetSpellDamageBonus(attacker, defender, SkillName.Magery, attacker is PlayerMobile && defender is PlayerMobile);
            damage = AOS.Scale(damage, 100 + damageBonus);

            if (defender != null && Feint.Registry.ContainsKey(defender) && Feint.Registry[defender].Enemy == attacker)
                damage -= (int)((double)damage * ((double)Feint.Registry[defender].DamageReduction / 100));

            // All hit spells use 80 eval
            int evalScale = 30 + ((9 * 800) / 100);

            damage = AOS.Scale(damage, evalScale);

            return damage / 100;
        }

        #region Do<AoSEffect>
        public virtual void DoMagicArrow(Mobile attacker, Mobile defender)
        {
            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            double damage = GetAosSpellDamage(attacker, defender, 10, 1, 4);

            attacker.MovingParticles(defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0);
            attacker.PlaySound(0x1E5);

            SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0);

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoHarm(Mobile attacker, Mobile defender)
        {
            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            double damage = GetAosSpellDamage(attacker, defender, 17, 1, 5);

            if (!defender.InRange(attacker, 2))
            {
                damage *= 0.25; // 1/4 damage at > 2 tile range
            }
            else if (!defender.InRange(attacker, 1))
            {
                damage *= 0.50; // 1/2 damage at 2 tile range
            }

            defender.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist);
            defender.PlaySound(0x0FC);

            SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 100, 0, 0);

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoFireball(Mobile attacker, Mobile defender)
        {
            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            double damage = GetAosSpellDamage(attacker, defender, 19, 1, 5);

            attacker.MovingParticles(defender, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160);
            attacker.PlaySound(0x15E);

            SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0);

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoLightning(Mobile attacker, Mobile defender)
        {
            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            double damage = GetAosSpellDamage(attacker, defender, 23, 1, 4);

            defender.BoltEffect(0);

            SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 0, 0, 100);

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoDispel(Mobile attacker, Mobile defender)
        {
            bool dispellable = false;

            if (defender is BaseCreature)
            {
                dispellable = ((BaseCreature)defender).Summoned && !((BaseCreature)defender).IsAnimatedDead;
            }

            if (!dispellable)
            {
                return;
            }

            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            MagerySpell sp = new DispelSpell(attacker, null);

            if (sp.CheckResisted(defender))
            {
                defender.FixedEffect(0x3779, 10, 20);
            }
            else
            {
                Effects.SendLocationParticles(
                    EffectItem.Create(defender.Location, defender.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
                Effects.PlaySound(defender, defender.Map, 0x201);

                defender.Delete();
            }
        }

        public virtual void DoExplosion(Mobile attacker, Mobile defender)
        {
            if (!attacker.CanBeHarmful(defender, false))
            {
                return;
            }

            attacker.DoHarmful(defender);

            double damage = GetAosSpellDamage(attacker, defender, 40, 1, 5);

            defender.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
            defender.PlaySound(0x307);

            SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0);

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoHitVelocity(Mobile attacker, IDamageable damageable)
        {
            int bonus = (int)attacker.GetDistanceToSqrt(damageable);

            if (bonus > 0)
            {
                AOS.Damage(damageable, attacker, bonus * 3, 100, 0, 0, 0, 0);

                if (attacker.Player)
                {
                    attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity!
                }

                if (damageable is Mobile && ((Mobile)damageable).Player)
                {
                    ((Mobile)damageable).SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity!
                }
            }

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        #region Stygian Abyss
        public virtual void DoCurse(Mobile attacker, Mobile defender)
        {
            attacker.SendLocalizedMessage(1113717); // You have hit your target with a curse effect.
            defender.SendLocalizedMessage(1113718); // You have been hit with a curse effect.

            defender.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist);
            defender.PlaySound(0x1EA);
            TimeSpan duration = TimeSpan.FromSeconds(30);

            defender.AddStatMod(
                new StatMod(StatType.Str, String.Format("[Magic] {0} Curse", StatType.Str), -10, duration));
            defender.AddStatMod(
                new StatMod(StatType.Dex, String.Format("[Magic] {0} Curse", StatType.Dex), -10, duration));
            defender.AddStatMod(
                new StatMod(StatType.Int, String.Format("[Magic] {0} Curse", StatType.Int), -10, duration));

            int percentage = -10; //(int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
            string args = String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", percentage, percentage, percentage, 10, 10, 10, 10);

            Server.Spells.Fourth.CurseSpell.AddEffect(defender, duration, 10, 10, 10);
            BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, duration, defender, args));

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoFatigue(Mobile attacker, Mobile defender, int damagegiven)
        {
            // Message?
            // Effects?
            defender.Stam -= (damagegiven * (100 - m_AosWeaponAttributes.HitFatigue)) / 100;

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }

        public virtual void DoManaDrain(Mobile attacker, Mobile defender, int damagegiven)
        {
            // Message?
            defender.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head);
            defender.PlaySound(0x1F8);
            defender.Mana -= (damagegiven * (100 - m_AosWeaponAttributes.HitManaDrain)) / 100;

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }
        #endregion

        public virtual void DoLowerAttack(Mobile from, Mobile defender)
        {
            if (HitLower.ApplyAttack(defender))
            {
                defender.PlaySound(0x28E);
                Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0xA, 3);
            }
        }

        public virtual void DoLowerDefense(Mobile from, Mobile defender)
        {
            if (HitLower.ApplyDefense(defender))
            {
                defender.PlaySound(0x28E);
                Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0x23, 3);
            }
        }

        public virtual void DoAreaAttack(Mobile from, Mobile defender, int damageGiven, int sound, int hue, int phys, int fire, int cold, int pois, int nrgy)
        {
            Map map = from.Map;

            if (map == null)
            {
                return;
            }

            var list = SpellHelper.AcquireIndirectTargets(from, from, from.Map, 5);

            var count = 0;

            foreach(var m in list)
            {
                ++count;

                from.DoHarmful(m, true);
                m.FixedEffect(0x3779, 1, 15, hue, 0);
                AOS.Damage(m, from, (int)(damageGiven / 2), phys, fire, cold, pois, nrgy, Server.DamageType.SpellAOE);
            }

            if (count > 0)
            {
                Effects.PlaySound(from.Location, map, sound);
            }

            if (ProcessingMultipleHits)
                BlockHitEffects = true;
        }
        #endregion

        public virtual CheckSlayerResult CheckSlayers(Mobile attacker, Mobile defender, SlayerName slayer)
        {
            if (slayer == SlayerName.None)
                return CheckSlayerResult.None;

            BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
            SlayerEntry atkSlayer = SlayerGroup.GetEntryByName(slayer);

            if (atkSlayer != null && atkSlayer.Slays(defender) && _SuperSlayers.Contains(atkSlayer.Name))
            {
                return CheckSlayerResult.SuperSlayer;
            }

            if (atkSlayer != null && atkSlayer.Slays(defender))
            {
                return CheckSlayerResult.Slayer;
            }

            return CheckSlayerResult.None;
        }

        public CheckSlayerResult CheckSlayerOpposition(Mobile attacker, Mobile defender)
        {
            ISlayer defISlayer = Spellbook.FindEquippedSpellbook(defender);

            if (defISlayer == null)
            {
                defISlayer = defender.Weapon as ISlayer;
            }

            if (defISlayer != null)
            {
                SlayerEntry defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer);
                SlayerEntry defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2);
                SlayerEntry defSetSlayer = SlayerGroup.GetEntryByName(SetHelper.GetSetSlayer(defender));

                if (defISlayer is Item && defSlayer == null && defSlayer2 == null)
                {
                    defSlayer = SlayerGroup.GetEntryByName(SlayerSocket.GetSlayer((Item)defISlayer));
                }

                if (defSlayer != null && defSlayer.Group.OppositionSuperSlays(attacker) ||
                    defSlayer2 != null && defSlayer2.Group.OppositionSuperSlays(attacker) ||
                    defSetSlayer != null && defSetSlayer.Group.OppositionSuperSlays(attacker))
                {
                    return CheckSlayerResult.Opposition;
                }
            }

            return CheckSlayerResult.None;
        }

        public CheckSlayerResult CheckTalismanSlayer(Mobile attacker, Mobile defender)
        {
            BaseTalisman talisman = attacker.Talisman as BaseTalisman;

            if (talisman != null && TalismanSlayer.Slays(talisman.Slayer, defender))
            {
                return CheckSlayerResult.Slayer;
            }
            else if (Slayer3 != TalismanSlayerName.None && TalismanSlayer.Slays(Slayer3, defender))
            {
                return CheckSlayerResult.Slayer;
            }

            return CheckSlayerResult.None;
        }

        private List<SlayerName> _SuperSlayers = new List<SlayerName>()
        {
            SlayerName.Repond, SlayerName.Silver, SlayerName.Fey,
            SlayerName.ElementalBan, SlayerName.Exorcism, SlayerName.ArachnidDoom,
            SlayerName.ReptilianDeath, SlayerName.Dinosaur, SlayerName.Myrmidex,
            SlayerName.Eodon
        };

        #region Blood
        public void AddBlood(Mobile defender, int damage)
        {
            if (damage <= 5 || defender == null || defender.Map == null || !defender.HasBlood || !CanDrawBlood(defender))
            {
                return;
            }

            var m = defender.Map;
            var b = new Rectangle2D(defender.X - 2, defender.Y - 2, 5, 5);

            var count = Core.AOS ? Utility.RandomMinMax(2, 3) : Utility.RandomMinMax(1, 2);

            for (var i = 0; i < count; i++)
            {
                AddBlood(defender, m.GetRandomSpawnPoint(b), m);
            }
        }

        protected virtual void AddBlood(Mobile defender, Point3D target, Map map)
        {
            var blood = CreateBlood(defender);

            var id = blood.ItemID;

            blood.ItemID = 1; // No Draw

            blood.OnBeforeSpawn(target, map);
            blood.MoveToWorld(target, map);
            blood.OnAfterSpawn();

            Effects.SendMovingEffect(defender, blood, id, 7, 10, true, false, blood.Hue, 0);

            Timer.DelayCall(TimeSpan.FromMilliseconds(500), b => b.ItemID = id, blood);
        }

        protected virtual bool CanDrawBlood(Mobile defender)
        {
            return defender.HasBlood;
        }

        protected virtual Blood CreateBlood(Mobile defender)
        {
            return new Blood
            {
                Hue = defender.BloodHue
            };
        }
        #endregion

        #region Elemental Damage
        public static int[] GetElementDamages(Mobile m)
        {
            var o = new[] {100, 0, 0, 0, 0, 0, 0};

            var w = m.Weapon as BaseWeapon ?? Fists;

            if (w != null)
            {
                w.GetDamageTypes(m, out o[0], out o[1], out o[2], out o[3], out o[4], out o[5], out o[6]);
            }

            return o;
        }

        public virtual void GetDamageTypes(
            Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct)
        {
            if (wielder is BaseCreature)
            {
                BaseCreature bc = (BaseCreature)wielder;

                phys = bc.PhysicalDamage;
                fire = bc.FireDamage;
                cold = bc.ColdDamage;
                pois = bc.PoisonDamage;
                nrgy = bc.EnergyDamage;
                chaos = bc.ChaosDamage;
                direct = bc.DirectDamage;
            }
            else
            {
                fire = m_AosElementDamages.Fire;
                cold = m_AosElementDamages.Cold;
                pois = m_AosElementDamages.Poison;
                nrgy = m_AosElementDamages.Energy;
                chaos = m_AosElementDamages.Chaos;
                direct = m_AosElementDamages.Direct;

                phys = 100 - fire - cold - pois - nrgy - chaos - direct;

                CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);

                if (resInfo != null)
                {
                    CraftAttributeInfo attrInfo = resInfo.AttributeInfo;

                    if (attrInfo != null)
                    {
                        int left = phys;

                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponColdDamage, ref cold, left);
                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponEnergyDamage, ref nrgy, left);
                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponFireDamage, ref fire, left);
                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponPoisonDamage, ref pois, left);
                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponChaosDamage, ref chaos, left);
                        left = ApplyCraftAttributeElementDamage(attrInfo.WeaponDirectDamage, ref direct, left);

                        phys = left;
                    }
                }
            }
        }

        private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining)
        {
            if (totalRemaining <= 0)
            {
                return 0;
            }

            if (attrDamage <= 0)
            {
                return totalRemaining;
            }

            int appliedDamage = attrDamage;

            if ((appliedDamage + element) > 100)
            {
                appliedDamage = 100 - element;
            }

            if (appliedDamage > totalRemaining)
            {
                appliedDamage = totalRemaining;
            }

            element += appliedDamage;

            return totalRemaining - appliedDamage;
        }
        #endregion

        public virtual void OnMiss(Mobile attacker, IDamageable damageable)
        {
            Mobile defender = damageable as Mobile;

            PlaySwingAnimation(attacker);
            attacker.PlaySound(GetMissAttackSound(attacker, defender));

            if(defender != null)
                defender.PlaySound(GetMissDefendSound(attacker, defender));

            WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker);

            if (ability != null)
            {
                ability.OnMiss(attacker, defender);
            }

            SpecialMove move = SpecialMove.GetCurrentMove(attacker);

            if (move != null)
            {
                move.OnMiss(attacker, defender);
            }

            if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
            {
                ((IHonorTarget)defender).ReceivedHonorContext.OnTargetMissed(attacker);
            }

            SkillMasterySpell.OnMiss(attacker, defender);
        }

        public virtual void GetBaseDamageRange(Mobile attacker, out int min, out int max)
        {
            if (attacker is BaseCreature)
            {
                BaseCreature c = (BaseCreature)attacker;

                if (c.DamageMin >= 0)
                {
                    min = c.DamageMin;
                    max = c.DamageMax;
                    return;
                }

                if (this is Fists && !attacker.Body.IsHuman)
                {
                    min = attacker.Str / 28;
                    max = attacker.Str / 28;
                    return;
                }
            }

            if (this is Fists && TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell)))
            {
                min = 5;
                max = 15;
            }
            else
            {
                min = MinDamage;
                max = MaxDamage;
            }
        }

        public virtual double GetBaseDamage(Mobile attacker)
        {
            int min, max;

            GetBaseDamageRange(attacker, out min, out max);

            int damage = Utility.RandomMinMax(min, max);

            if (Core.AOS)
            {
                return damage;
            }

            /* Apply damage level offset
             * : Regular : 0
             * : Ruin    : 1
             * : Might   : 3
             * : Force   : 5
             * : Power   : 7
             * : Vanq    : 9
             */
            if (m_DamageLevel != WeaponDamageLevel.Regular)
            {
                damage += (2 * (int)m_DamageLevel) - 1;
            }

            return damage;
        }

        public virtual double GetBonus(double value, double scalar, double threshold, double offset)
        {
            double bonus = value * scalar;

            if (value >= threshold)
            {
                bonus += offset;
            }

            return bonus / 100;
        }

        public virtual int GetHitChanceBonus()
        {
            if (!Core.AOS)
            {
                return 0;
            }

            int bonus = 0;

            switch (m_AccuracyLevel)
            {
                case WeaponAccuracyLevel.Accurate:
                    bonus += 02;
                    break;
                case WeaponAccuracyLevel.Surpassingly:
                    bonus += 04;
                    break;
                case WeaponAccuracyLevel.Eminently:
                    bonus += 06;
                    break;
                case WeaponAccuracyLevel.Exceedingly:
                    bonus += 08;
                    break;
                case WeaponAccuracyLevel.Supremely:
                    bonus += 10;
                    break;
            }

            return bonus;
        }

        public virtual int GetDamageBonus()
        {
            #region Stygian Abyss
            if (m_DImodded)
                return 0;
            #endregion

            int bonus = VirtualDamageBonus;

            if (!Core.AOS)
            {
                switch (m_Quality)
                {
                    case ItemQuality.Low:
                        bonus -= 20;
                        break;
                    case ItemQuality.Exceptional:
                        bonus += 20;
                        break;
                }

                switch (m_DamageLevel)
                {
                    case WeaponDamageLevel.Ruin:
                        bonus += 15;
                        break;
                    case WeaponDamageLevel.Might:
                        bonus += 20;
                        break;
                    case WeaponDamageLevel.Force:
                        bonus += 25;
                        break;
                    case WeaponDamageLevel.Power:
                        bonus += 30;
                        break;
                    case WeaponDamageLevel.Vanq:
                        bonus += 35;
                        break;
                }
            }

            return bonus;
        }

        public virtual void GetStatusDamage(Mobile from, out int min, out int max)
        {
            int baseMin, baseMax;

            GetBaseDamageRange(from, out baseMin, out baseMax);

            if (Core.AOS)
            {
                min = Math.Max((int)ScaleDamageAOS(from, baseMin, false), 1);
                max = Math.Max((int)ScaleDamageAOS(from, baseMax, false), 1);
            }
            else
            {
                min = Math.Max((int)ScaleDamageOld(from, baseMin, false), 1);
                max = Math.Max((int)ScaleDamageOld(from, baseMax, false), 1);
            }
        }

        public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills)
        {
            if (checkSkills)
            {
                attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap);
                    // Passively check tactics for gain
                attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap);
                    // Passively check Anatomy for gain

                if (Type == WeaponType.Axe)
                {
                    attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
                }
            }

            #region Physical bonuses
            /*
            * These are the bonuses given by the physical characteristics of the mobile.
            * No caps apply.
            */
            double strengthBonus = GetBonus(attacker.Str, 0.300, 100.0, 5.00);
            double anatomyBonus = GetBonus(attacker.Skills[SkillName.Anatomy].Value, 0.500, 100.0, 5.00);
            double tacticsBonus = GetBonus(attacker.Skills[SkillName.Tactics].Value, 0.625, 100.0, 6.25);
            double lumberBonus = GetBonus(attacker.Skills[SkillName.Lumberjacking].Value, 0.200, 100.0, 10.00);

            if (Type != WeaponType.Axe)
            {
                lumberBonus = 0.0;
            }
            #endregion

            #region Modifiers
            /*
            * The following are damage modifiers whose effect shows on the status bar.
            * Capped at 100% total.
            */
            int damageBonus = AosAttributes.GetValue(attacker, AosAttribute.WeaponDamage);

            if (damageBonus > 100)
            {
                damageBonus = 100;
            }
            #endregion

            double totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus +
                                ((GetDamageBonus() + damageBonus) / 100.0);

            return damage + (int)(damage * totalBonus);
        }

        public virtual int VirtualDamageBonus { get { return 0; } }

        public virtual int ComputeDamageAOS(Mobile attacker, Mobile defender)
        {
            return (int)ScaleDamageAOS(attacker, GetBaseDamage(attacker), true);
        }

        public virtual double ScaleDamageOld(Mobile attacker, double damage, bool checkSkills)
        {
            if (checkSkills)
            {
                attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap);
                    // Passively check tactics for gain
                attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap);
                    // Passively check Anatomy for gain

                //daat99 OWLTR start - allow lumberjacking past 100
                if (Type == WeaponType.Axe)
                    attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 120.0); // Passively check Lumberjacking for gain
                //daat99 OWLTR end - allow lumberjacking past 100
            }

            /* Compute tactics modifier
            * :   0.0 = 50% loss
            * :  50.0 = unchanged
            * : 100.0 = 50% bonus
            */
            damage += (damage * ((attacker.Skills[SkillName.Tactics].Value - 50.0) / 100.0));

            /* Compute strength modifier
            * : 1% bonus for every 5 strength
            */
            double modifiers = (attacker.Str / 5.0) / 100.0;

            /* Compute anatomy modifier
            * : 1% bonus for every 5 points of anatomy
            * : +10% bonus at Grandmaster or higher
            */
            double anatomyValue = attacker.Skills[SkillName.Anatomy].Value;
            modifiers += ((anatomyValue / 5.0) / 100.0);

            if (anatomyValue >= 100.0)
            {
                modifiers += 0.1;
            }

            /* Compute lumberjacking bonus
            * : 1% bonus for every 5 points of lumberjacking
            * : +10% bonus at Grandmaster or higher
            */

            if (Type == WeaponType.Axe)
            {
                double lumberValue = attacker.Skills[SkillName.Lumberjacking].Value;
                lumberValue = (lumberValue/5.0)/100.0;
                if (lumberValue > 0.2)
                    lumberValue = 0.2;

                modifiers += lumberValue;

                if (lumberValue >= 100.0)
                {
                    modifiers += 0.1;
                }
            }

            // New quality bonus:
            if (m_Quality != ItemQuality.Normal)
            {
                modifiers += (((int)m_Quality - 1) * 0.2);
            }

            // Virtual damage bonus:
            if (VirtualDamageBonus != 0)
            {
                modifiers += (VirtualDamageBonus / 100.0);
            }

            // Apply bonuses
            damage += (damage * modifiers);

            return ScaleDamageByDurability((int)damage);
        }

        public virtual int ScaleDamageByDurability(int damage)
        {
            int scale = 100;

            if (m_MaxHits > 0 && m_Hits < m_MaxHits)
            {
                scale = 50 + ((50 * m_Hits) / m_MaxHits);
            }

            return AOS.Scale(damage, scale);
        }

        public virtual int ComputeDamage(Mobile attacker, Mobile defender)
        {
            if (Core.AOS)
            {
                return ComputeDamageAOS(attacker, defender);
            }

            int damage = (int)ScaleDamageOld(attacker, GetBaseDamage(attacker), true);

            // pre-AOS, halve damage if the defender is a player or the attacker is not a player
            if (defender is PlayerMobile || !(attacker is PlayerMobile))
            {
                damage = (int)(damage / 2.0);
            }

            return damage;
        }

        public virtual void PlayHurtAnimation(Mobile from)
        {
            if (from.Mounted)
            {
                return;
            }

            if (Core.SA)
            {
                from.Animate(AnimationType.Impact, 0);
            }
            else
            {
                int action;
                int frames;

                switch (from.Body.Type)
                {
                    case BodyType.Sea:
                    case BodyType.Animal:
                        {
                            action = 7;
                            frames = 5;
                            break;
                        }
                    case BodyType.Monster:
                        {
                            action = 10;
                            frames = 4;
                            break;
                        }
                    case BodyType.Human:
                        {
                            action = 20;
                            frames = 5;
                            break;
                        }
                    default:
                        return;
                }

                from.Animate(action, frames, 1, true, false, 0);
            }
        }

        public virtual void PlaySwingAnimation(Mobile from)
        {
            int action;

            if (Core.SA)
            {
                action = GetNewAnimationAction(from);

                from.Animate(AnimationType.Attack, action);
            }
            else
            {
                switch (from.Body.Type)
                {
                    case BodyType.Sea:
                    case BodyType.Animal:
                        {
                            action = Utility.Random(5, 2);
                            break;
                        }
                    case BodyType.Monster:
                        {
                            switch (Animation)
                            {
                                default:
                                case WeaponAnimation.Wrestle:
                                case WeaponAnimation.Bash1H:
                                case WeaponAnimation.Pierce1H:
                                case WeaponAnimation.Slash1H:
                                case WeaponAnimation.Bash2H:
                                case WeaponAnimation.Pierce2H:
                                case WeaponAnimation.Slash2H:
                                    action = Utility.Random(4, 3);
                                    break;
                                case WeaponAnimation.ShootBow:
                                    return; // 7
                                case WeaponAnimation.ShootXBow:
                                    return; // 8
                            }

                            break;
                        }
                    case BodyType.Human:
                        {
                            if (!from.Mounted)
                            {
                                action = (int)Animation;
                            }
                            else
                            {
                                switch (Animation)
                                {
                                    default:
                                    case WeaponAnimation.Wrestle:
                                    case WeaponAnimation.Bash1H:
                                    case WeaponAnimation.Pierce1H:
                                    case WeaponAnimation.Slash1H:
                                        action = 26;
                                        break;
                                    case WeaponAnimation.Bash2H:
                                    case WeaponAnimation.Pierce2H:
                                    case WeaponAnimation.Slash2H:
                                        action = 29;
                                        break;
                                    case WeaponAnimation.ShootBow:
                                        action = 27;
                                        break;
                                    case WeaponAnimation.ShootXBow:
                                        action = 28;
                                        break;
                                }
                            }

                            break;
                        }
                    default:
                        return;
                }

                from.Animate(action, 7, 1, true, false, 0);
            }
        }

        public int GetNewAnimationAction(Mobile from)
        {
            switch (Animation)
            {
                default:
                case WeaponAnimation.Wrestle: return 0;
                case WeaponAnimation.Bash1H: return 3;
                case WeaponAnimation.Pierce1H: return 5;
                case WeaponAnimation.Slash1H: return 4;
                case WeaponAnimation.Bash2H: return 6;
                case WeaponAnimation.Pierce2H: return 8;
                case WeaponAnimation.Slash2H: return 7;
                case WeaponAnimation.ShootBow: return 1;
                case WeaponAnimation.ShootXBow: return 2;
                case WeaponAnimation.Throwing: return 9;
            }
        }

        #region Serialization/Deserialization
        private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf)
        {
            if (setIf)
            {
                flags |= toSet;
            }
        }

        private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet)
        {
            return ((flags & toGet) != 0);
        }

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

            writer.Write(19); // version

            // Version 19 - Removes m_SearingWeapon as its handled as a socket now
            // Version 18 - removed VvV Item (handled in VvV System) and BlockRepair (Handled as negative attribute)

            writer.Write(m_UsesRemaining);
            writer.Write(m_ShowUsesRemaining);

            writer.Write(_Owner);
            writer.Write(_OwnerName);

            // Version 15 converts old leech to new leech

            //Version 14
            writer.Write(m_IsImbued);

            //version 13, converted SaveFlags to long, added negative attributes

            //version 12
            #region Runic Reforging
            writer.Write((int)m_ReforgedPrefix);
            writer.Write((int)m_ReforgedSuffix);
            writer.Write((int)m_ItemPower);
            #endregion

            writer.Write(m_DImodded);

            // Version 11
            writer.Write(m_TimesImbued);
            // Version 10
            writer.Write(m_BlessedBy); // Bless Deed

            #region Veteran Rewards
            writer.Write(m_EngravedText);
            #endregion

            #region Mondain's Legacy
            writer.Write((int)m_Slayer3);
            #endregion

            #region Mondain's Legacy Sets
            SetFlag sflags = SetFlag.None;

            SetSaveFlag(ref sflags, SetFlag.Attributes, !m_SetAttributes.IsEmpty);
            SetSaveFlag(ref sflags, SetFlag.SkillBonuses, !m_SetSkillBonuses.IsEmpty);
            SetSaveFlag(ref sflags, SetFlag.Hue, m_SetHue != 0);
            SetSaveFlag(ref sflags, SetFlag.LastEquipped, m_LastEquipped);
            SetSaveFlag(ref sflags, SetFlag.SetEquipped, m_SetEquipped);
            SetSaveFlag(ref sflags, SetFlag.SetSelfRepair, m_SetSelfRepair != 0);
            SetSaveFlag(ref sflags, SetFlag.PhysicalBonus, m_SetPhysicalBonus != 0);
            SetSaveFlag(ref sflags, SetFlag.FireBonus, m_SetFireBonus != 0);
            SetSaveFlag(ref sflags, SetFlag.ColdBonus, m_SetColdBonus != 0);
            SetSaveFlag(ref sflags, SetFlag.PoisonBonus, m_SetPoisonBonus != 0);
            SetSaveFlag(ref sflags, SetFlag.EnergyBonus, m_SetEnergyBonus != 0);

            writer.WriteEncodedInt((int)sflags);

            if (GetSaveFlag(sflags, SetFlag.PhysicalBonus))
            {
                writer.WriteEncodedInt((int)m_SetPhysicalBonus);
            }

            if (GetSaveFlag(sflags, SetFlag.FireBonus))
            {
                writer.WriteEncodedInt((int)m_SetFireBonus);
            }

            if (GetSaveFlag(sflags, SetFlag.ColdBonus))
            {
                writer.WriteEncodedInt((int)m_SetColdBonus);
            }

            if (GetSaveFlag(sflags, SetFlag.PoisonBonus))
            {
                writer.WriteEncodedInt((int)m_SetPoisonBonus);
            }

            if (GetSaveFlag(sflags, SetFlag.EnergyBonus))
            {
                writer.WriteEncodedInt((int)m_SetEnergyBonus);
            }

            if (GetSaveFlag(sflags, SetFlag.Attributes))
            {
                m_SetAttributes.Serialize(writer);
            }

            if (GetSaveFlag(sflags, SetFlag.SkillBonuses))
            {
                m_SetSkillBonuses.Serialize(writer);
            }

            if (GetSaveFlag(sflags, SetFlag.Hue))
            {
                writer.Write(m_SetHue);
            }

            if (GetSaveFlag(sflags, SetFlag.LastEquipped))
            {
                writer.Write(m_LastEquipped);
            }

            if (GetSaveFlag(sflags, SetFlag.SetEquipped))
            {
                writer.Write(m_SetEquipped);
            }

            if (GetSaveFlag(sflags, SetFlag.SetSelfRepair))
            {
                writer.WriteEncodedInt(m_SetSelfRepair);
            }
            #endregion

            // Version 9
            SaveFlag flags = SaveFlag.None;

            SetSaveFlag(ref flags, SaveFlag.DamageLevel, m_DamageLevel != WeaponDamageLevel.Regular);
            SetSaveFlag(ref flags, SaveFlag.AccuracyLevel, m_AccuracyLevel != WeaponAccuracyLevel.Regular);
            SetSaveFlag(ref flags, SaveFlag.DurabilityLevel, m_DurabilityLevel != WeaponDurabilityLevel.Regular);
            SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ItemQuality.Normal);
            SetSaveFlag(ref flags, SaveFlag.Hits, m_Hits != 0);
            SetSaveFlag(ref flags, SaveFlag.MaxHits, m_MaxHits != 0);
            SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != SlayerName.None);
            SetSaveFlag(ref flags, SaveFlag.Poison, m_Poison != null);
            SetSaveFlag(ref flags, SaveFlag.PoisonCharges, m_PoisonCharges != 0);
            SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null);
            SetSaveFlag(ref flags, SaveFlag.Identified, m_Identified);
            SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1);
            SetSaveFlag(ref flags, SaveFlag.DexReq, m_DexReq != -1);
            SetSaveFlag(ref flags, SaveFlag.IntReq, m_IntReq != -1);
            SetSaveFlag(ref flags, SaveFlag.MinDamage, m_MinDamage != -1);
            SetSaveFlag(ref flags, SaveFlag.MaxDamage, m_MaxDamage != -1);
            SetSaveFlag(ref flags, SaveFlag.HitSound, m_HitSound != -1);
            SetSaveFlag(ref flags, SaveFlag.MissSound, m_MissSound != -1);
            SetSaveFlag(ref flags, SaveFlag.Speed, m_Speed != -1);
            SetSaveFlag(ref flags, SaveFlag.MaxRange, m_MaxRange != -1);
            SetSaveFlag(ref flags, SaveFlag.Skill, m_Skill != (SkillName)(-1));
            SetSaveFlag(ref flags, SaveFlag.Type, m_Type != (WeaponType)(-1));
            SetSaveFlag(ref flags, SaveFlag.Animation, m_Animation != (WeaponAnimation)(-1));
            SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != CraftResource.Iron);
            SetSaveFlag(ref flags, SaveFlag.xAttributes, !m_AosAttributes.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.xWeaponAttributes, !m_AosWeaponAttributes.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, m_PlayerConstructed);
            SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !m_AosSkillBonuses.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.Slayer2, m_Slayer2 != SlayerName.None);
            SetSaveFlag(ref flags, SaveFlag.ElementalDamages, !m_AosElementDamages.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.EngravedText, !String.IsNullOrEmpty(m_EngravedText));
            SetSaveFlag(ref flags, SaveFlag.xAbsorptionAttributes, !m_SAAbsorptionAttributes.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.xNegativeAttributes, !m_NegativeAttributes.IsEmpty);
            SetSaveFlag(ref flags, SaveFlag.Altered, m_Altered);
            SetSaveFlag(ref flags, SaveFlag.xExtendedWeaponAttributes, !m_ExtendedWeaponAttributes.IsEmpty);

            writer.Write((long)flags);

            if (GetSaveFlag(flags, SaveFlag.DamageLevel))
            {
                writer.Write((int)m_DamageLevel);
            }

            if (GetSaveFlag(flags, SaveFlag.AccuracyLevel))
            {
                writer.Write((int)m_AccuracyLevel);
            }

            if (GetSaveFlag(flags, SaveFlag.DurabilityLevel))
            {
                writer.Write((int)m_DurabilityLevel);
            }

            if (GetSaveFlag(flags, SaveFlag.Quality))
            {
                writer.Write((int)m_Quality);
            }

            if (GetSaveFlag(flags, SaveFlag.Hits))
            {
                writer.Write(m_Hits);
            }

            if (GetSaveFlag(flags, SaveFlag.MaxHits))
            {
                writer.Write(m_MaxHits);
            }

            if (GetSaveFlag(flags, SaveFlag.Slayer))
            {
                writer.Write((int)m_Slayer);
            }

            if (GetSaveFlag(flags, SaveFlag.Poison))
            {
                Poison.Serialize(m_Poison, writer);
            }

            if (GetSaveFlag(flags, SaveFlag.PoisonCharges))
            {
                writer.Write(m_PoisonCharges);
            }

            if (GetSaveFlag(flags, SaveFlag.Crafter))
            {
                writer.Write(m_Crafter);
            }

            if (GetSaveFlag(flags, SaveFlag.StrReq))
            {
                writer.Write(m_StrReq);
            }

            if (GetSaveFlag(flags, SaveFlag.DexReq))
            {
                writer.Write(m_DexReq);
            }

            if (GetSaveFlag(flags, SaveFlag.IntReq))
            {
                writer.Write(m_IntReq);
            }

            if (GetSaveFlag(flags, SaveFlag.MinDamage))
            {
                writer.Write(m_MinDamage);
            }

            if (GetSaveFlag(flags, SaveFlag.MaxDamage))
            {
                writer.Write(m_MaxDamage);
            }

            if (GetSaveFlag(flags, SaveFlag.HitSound))
            {
                writer.Write(m_HitSound);
            }

            if (GetSaveFlag(flags, SaveFlag.MissSound))
            {
                writer.Write(m_MissSound);
            }

            if (GetSaveFlag(flags, SaveFlag.Speed))
            {
                writer.Write(m_Speed);
            }

            if (GetSaveFlag(flags, SaveFlag.MaxRange))
            {
                writer.Write(m_MaxRange);
            }

            if (GetSaveFlag(flags, SaveFlag.Skill))
            {
                writer.Write((int)m_Skill);
            }

            if (GetSaveFlag(flags, SaveFlag.Type))
            {
                writer.Write((int)m_Type);
            }

            if (GetSaveFlag(flags, SaveFlag.Animation))
            {
                writer.Write((int)m_Animation);
            }

            if (GetSaveFlag(flags, SaveFlag.Resource))
            {
                writer.Write((int)m_Resource);
            }

            if (GetSaveFlag(flags, SaveFlag.xAttributes))
            {
                m_AosAttributes.Serialize(writer);
            }

            if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes))
            {
                m_AosWeaponAttributes.Serialize(writer);
            }

            if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
            {
                m_AosSkillBonuses.Serialize(writer);
            }

            if (GetSaveFlag(flags, SaveFlag.Slayer2))
            {
                writer.Write((int)m_Slayer2);
            }

            if (GetSaveFlag(flags, SaveFlag.ElementalDamages))
            {
                m_AosElementDamages.Serialize(writer);
            }

            if (GetSaveFlag(flags, SaveFlag.EngravedText))
            {
                writer.Write(m_EngravedText);
            }

            #region SA
            if (GetSaveFlag(flags, SaveFlag.xAbsorptionAttributes))
            {
                m_SAAbsorptionAttributes.Serialize(writer);
            }

            if (GetSaveFlag(flags, SaveFlag.xNegativeAttributes))
            {
                m_NegativeAttributes.Serialize(writer);
            }
            #endregion

            if (GetSaveFlag(flags, SaveFlag.xExtendedWeaponAttributes))
            {
                m_ExtendedWeaponAttributes.Serialize(writer);
            }
        }

        [Flags]
        private enum SaveFlag : long
        {
            None = 0x00000000,
            DamageLevel = 0x00000001,
            AccuracyLevel = 0x00000002,
            DurabilityLevel = 0x00000004,
            Quality = 0x00000008,
            Hits = 0x00000010,
            MaxHits = 0x00000020,
            Slayer = 0x00000040,
            Poison = 0x00000080,
            PoisonCharges = 0x00000100,
            Crafter = 0x00000200,
            Identified = 0x00000400,
            StrReq = 0x00000800,
            DexReq = 0x00001000,
            IntReq = 0x00002000,
            MinDamage = 0x00004000,
            MaxDamage = 0x00008000,
            HitSound = 0x00010000,
            MissSound = 0x00020000,
            Speed = 0x00040000,
            MaxRange = 0x00080000,
            Skill = 0x00100000,
            Type = 0x00200000,
            Animation = 0x00400000,
            Resource = 0x00800000,
            xAttributes = 0x01000000,
            xWeaponAttributes = 0x02000000,
            PlayerConstructed = 0x04000000,
            SkillBonuses = 0x08000000,
            Slayer2 = 0x10000000,
            ElementalDamages = 0x20000000,
            EngravedText = 0x40000000,
            xAbsorptionAttributes = 0x80000000,
            xNegativeAttributes = 0x100000000,
            Altered = 0x200000000,
            xExtendedWeaponAttributes = 0x400000000
        }

        #region Mondain's Legacy Sets
        private static void SetSaveFlag(ref SetFlag flags, SetFlag toSet, bool setIf)
        {
            if (setIf)
            {
                flags |= toSet;
            }
        }

        private static bool GetSaveFlag(SetFlag flags, SetFlag toGet)
        {
            return ((flags & toGet) != 0);
        }

        [Flags]
        private enum SetFlag
        {
            None = 0x00000000,
            Attributes = 0x00000001,
            WeaponAttributes = 0x00000002,
            SkillBonuses = 0x00000004,
            Hue = 0x00000008,
            LastEquipped = 0x00000010,
            SetEquipped = 0x00000020,
            SetSelfRepair = 0x00000040,
            PhysicalBonus = 0x00000080,
            FireBonus = 0x00000100,
            ColdBonus = 0x00000200,
            PoisonBonus = 0x00000400,
            EnergyBonus = 0x00000800,
        }
        #endregion

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

            int version = reader.ReadInt();

            switch (version)
            {
                case 19: // Removed SearingWeapon
                case 18:
                case 17:
                    {
                        m_UsesRemaining = reader.ReadInt();
                        m_ShowUsesRemaining = reader.ReadBool();
                        goto case 16;
                    }
                case 16:
                    {
                        if(version == 17)
                            reader.ReadBool();

                        _Owner = reader.ReadMobile();
                        _OwnerName = reader.ReadString();
                        goto case 15;
                    }
                case 15:
                case 14:
                    {
                        m_IsImbued = reader.ReadBool();
                        goto case 13;
                    }
                case 13:
                case 12:
                    {
                        #region Runic Reforging
                        m_ReforgedPrefix = (ReforgedPrefix)reader.ReadInt();
                        m_ReforgedSuffix = (ReforgedSuffix)reader.ReadInt();
                        m_ItemPower = (ItemPower)reader.ReadInt();

                        if (version < 18 && reader.ReadBool())
                        {
                            Timer.DelayCall(TimeSpan.FromSeconds(1), () =>
                            {
                                m_NegativeAttributes.NoRepair = 1;
                            });
                        }
                        #endregion

                        #region Stygian Abyss
                        m_DImodded = reader.ReadBool();

                        if (version == 18)
                        {
                            if (reader.ReadBool())
                            {
                                Timer.DelayCall(TimeSpan.FromSeconds(1), () =>
                                {
                                    AttachSocket(new SearingWeapon(this));
                                });
                            }
                        }
                        goto case 11;
                    }
                case 11:
                    {
                        m_TimesImbued = reader.ReadInt();

                        #endregion

                        goto case 10;
                    }
                case 10:
                    {
                        m_BlessedBy = reader.ReadMobile();
                        m_EngravedText = reader.ReadString();
                        m_Slayer3 = (TalismanSlayerName)reader.ReadInt();

                        SetFlag flags = (SetFlag)reader.ReadEncodedInt();
                        if (GetSaveFlag(flags, SetFlag.PhysicalBonus))
                        {
                            m_SetPhysicalBonus = reader.ReadEncodedInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.FireBonus))
                        {
                            m_SetFireBonus = reader.ReadEncodedInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.ColdBonus))
                        {
                            m_SetColdBonus = reader.ReadEncodedInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.PoisonBonus))
                        {
                            m_SetPoisonBonus = reader.ReadEncodedInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.EnergyBonus))
                        {
                            m_SetEnergyBonus = reader.ReadEncodedInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.Attributes))
                        {
                            m_SetAttributes = new AosAttributes(this, reader);
                        }
                        else
                        {
                            m_SetAttributes = new AosAttributes(this);
                        }

                        if (GetSaveFlag(flags, SetFlag.WeaponAttributes))
                        {
                            m_SetSelfRepair = (new AosWeaponAttributes(this, reader)).SelfRepair;
                        }

                        if (GetSaveFlag(flags, SetFlag.SkillBonuses))
                        {
                            m_SetSkillBonuses = new AosSkillBonuses(this, reader);
                        }
                        else
                        {
                            m_SetSkillBonuses = new AosSkillBonuses(this);
                        }

                        if (GetSaveFlag(flags, SetFlag.Hue))
                        {
                            m_SetHue = reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SetFlag.LastEquipped))
                        {
                            m_LastEquipped = reader.ReadBool();
                        }

                        if (GetSaveFlag(flags, SetFlag.SetEquipped))
                        {
                            m_SetEquipped = reader.ReadBool();
                        }

                        if (GetSaveFlag(flags, SetFlag.SetSelfRepair))
                        {
                            m_SetSelfRepair = reader.ReadEncodedInt();
                        }

                        goto case 5;
                    }
                case 9:
                case 8:
                case 7:
                case 6:
                case 5:
                    {
                        SaveFlag flags;

                        if(version < 13)
                            flags = (SaveFlag)reader.ReadInt();
                        else
                            flags = (SaveFlag)reader.ReadLong();

                        if (GetSaveFlag(flags, SaveFlag.DamageLevel))
                        {
                            m_DamageLevel = (WeaponDamageLevel)reader.ReadInt();

                            if (m_DamageLevel > WeaponDamageLevel.Vanq)
                            {
                                m_DamageLevel = WeaponDamageLevel.Ruin;
                            }
                        }

                        if (GetSaveFlag(flags, SaveFlag.AccuracyLevel))
                        {
                            m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt();

                            if (m_AccuracyLevel > WeaponAccuracyLevel.Supremely)
                            {
                                m_AccuracyLevel = WeaponAccuracyLevel.Accurate;
                            }
                        }

                        if (GetSaveFlag(flags, SaveFlag.DurabilityLevel))
                        {
                            m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt();

                            if (m_DurabilityLevel > WeaponDurabilityLevel.Indestructible)
                            {
                                m_DurabilityLevel = WeaponDurabilityLevel.Durable;
                            }
                        }

                        if (GetSaveFlag(flags, SaveFlag.Quality))
                        {
                            m_Quality = (ItemQuality)reader.ReadInt();
                        }
                        else
                        {
                            m_Quality = ItemQuality.Normal;
                        }

                        if (GetSaveFlag(flags, SaveFlag.Hits))
                        {
                            m_Hits = reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SaveFlag.MaxHits))
                        {
                            m_MaxHits = reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SaveFlag.Slayer))
                        {
                            m_Slayer = (SlayerName)reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SaveFlag.Poison))
                        {
                            m_Poison = Poison.Deserialize(reader);
                        }

                        if (GetSaveFlag(flags, SaveFlag.PoisonCharges))
                        {
                            m_PoisonCharges = reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SaveFlag.Crafter))
                        {
                            m_Crafter = reader.ReadMobile();
                        }

                        if (GetSaveFlag(flags, SaveFlag.Identified))
                        {
                            m_Identified = (version >= 6 || reader.ReadBool());
                        }

                        if (GetSaveFlag(flags, SaveFlag.StrReq))
                        {
                            m_StrReq = reader.ReadInt();
                        }
                        else
                        {
                            m_StrReq = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.DexReq))
                        {
                            m_DexReq = reader.ReadInt();
                        }
                        else
                        {
                            m_DexReq = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.IntReq))
                        {
                            m_IntReq = reader.ReadInt();
                        }
                        else
                        {
                            m_IntReq = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.MinDamage))
                        {
                            m_MinDamage = reader.ReadInt();
                        }
                        else
                        {
                            m_MinDamage = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.MaxDamage))
                        {
                            m_MaxDamage = reader.ReadInt();
                        }
                        else
                        {
                            m_MaxDamage = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.HitSound))
                        {
                            m_HitSound = reader.ReadInt();
                        }
                        else
                        {
                            m_HitSound = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.MissSound))
                        {
                            m_MissSound = reader.ReadInt();
                        }
                        else
                        {
                            m_MissSound = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.Speed))
                        {
                            if (version < 9)
                            {
                                m_Speed = reader.ReadInt();
                            }
                            else
                            {
                                m_Speed = reader.ReadFloat();
                            }
                        }
                        else
                        {
                            m_Speed = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.MaxRange))
                        {
                            m_MaxRange = reader.ReadInt();
                        }
                        else
                        {
                            m_MaxRange = -1;
                        }

                        if (GetSaveFlag(flags, SaveFlag.Skill))
                        {
                            m_Skill = (SkillName)reader.ReadInt();
                        }
                        else
                        {
                            m_Skill = (SkillName)(-1);
                        }

                        if (GetSaveFlag(flags, SaveFlag.Type))
                        {
                            m_Type = (WeaponType)reader.ReadInt();
                        }
                        else
                        {
                            m_Type = (WeaponType)(-1);
                        }

                        if (GetSaveFlag(flags, SaveFlag.Animation))
                        {
                            m_Animation = (WeaponAnimation)reader.ReadInt();
                        }
                        else
                        {
                            m_Animation = (WeaponAnimation)(-1);
                        }

                        if (GetSaveFlag(flags, SaveFlag.Resource))
                        {
                            m_Resource = (CraftResource)reader.ReadInt();
                        }
                        else
                        {
                            m_Resource = CraftResource.Iron;
                        }

                        if (GetSaveFlag(flags, SaveFlag.xAttributes))
                        {
                            m_AosAttributes = new AosAttributes(this, reader);
                        }
                        else
                        {
                            m_AosAttributes = new AosAttributes(this);
                        }

                        if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes))
                        {
                            m_AosWeaponAttributes = new AosWeaponAttributes(this, reader);
                        }
                        else
                        {
                            m_AosWeaponAttributes = new AosWeaponAttributes(this);
                        }

                        if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && Parent is Mobile)
                        {
                            m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
                            ((Mobile)Parent).AddSkillMod(m_SkillMod);
                        }

                        if (version < 7 && m_AosWeaponAttributes.MageWeapon != 0)
                        {
                            m_AosWeaponAttributes.MageWeapon = 30 - m_AosWeaponAttributes.MageWeapon;
                        }

                        if (Core.AOS && m_AosWeaponAttributes.MageWeapon != 0 && m_AosWeaponAttributes.MageWeapon != 30 &&
                            Parent is Mobile)
                        {
                            m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + m_AosWeaponAttributes.MageWeapon);
                            ((Mobile)Parent).AddSkillMod(m_MageMod);
                        }

                        if (GetSaveFlag(flags, SaveFlag.PlayerConstructed))
                        {
                            m_PlayerConstructed = true;
                        }

                        if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
                        {
                            m_AosSkillBonuses = new AosSkillBonuses(this, reader);
                        }
                        else
                        {
                            m_AosSkillBonuses = new AosSkillBonuses(this);
                        }

                        if (GetSaveFlag(flags, SaveFlag.Slayer2))
                        {
                            m_Slayer2 = (SlayerName)reader.ReadInt();
                        }

                        if (GetSaveFlag(flags, SaveFlag.ElementalDamages))
                        {
                            m_AosElementDamages = new AosElementAttributes(this, reader);
                        }
                        else
                        {
                            m_AosElementDamages = new AosElementAttributes(this);
                        }

                        if (GetSaveFlag(flags, SaveFlag.EngravedText))
                        {
                            m_EngravedText = reader.ReadString();
                        }

                        #region Stygian Abyss
                        if (version > 9 && GetSaveFlag(flags, SaveFlag.xAbsorptionAttributes))
                        {
                            m_SAAbsorptionAttributes = new SAAbsorptionAttributes(this, reader);
                        }
                        else
                        {
                            m_SAAbsorptionAttributes = new SAAbsorptionAttributes(this);
                        }

                        if (version >= 13 && GetSaveFlag(flags, SaveFlag.xNegativeAttributes))
                        {
                            m_NegativeAttributes = new NegativeAttributes(this, reader);
                        }
                        else
                        {
                            m_NegativeAttributes = new NegativeAttributes(this);
                        }
                        #endregion

                        if (GetSaveFlag(flags, SaveFlag.Altered))
                        {
                            m_Altered = true;
                        }

                        if (GetSaveFlag(flags, SaveFlag.xExtendedWeaponAttributes))
                        {
                            m_ExtendedWeaponAttributes = new ExtendedWeaponAttributes(this, reader);
                        }
                        else
                        {
                            m_ExtendedWeaponAttributes = new ExtendedWeaponAttributes(this);
                        }

                        if (Core.TOL && m_ExtendedWeaponAttributes.MysticWeapon != 0 && m_ExtendedWeaponAttributes.MysticWeapon != 30 && Parent is Mobile)
                        {
                            m_MysticMod = new DefaultSkillMod(SkillName.Mysticism, true, -30 + m_ExtendedWeaponAttributes.MysticWeapon);
                            ((Mobile)Parent).AddSkillMod(m_MysticMod);
                        }

                        break;
                    }
                case 4:
                    {
                        m_Slayer = (SlayerName)reader.ReadInt();

                        goto case 3;
                    }
                case 3:
                    {
                        m_StrReq = reader.ReadInt();
                        m_DexReq = reader.ReadInt();
                        m_IntReq = reader.ReadInt();

                        goto case 2;
                    }
                case 2:
                    {
                        m_Identified = reader.ReadBool();

                        goto case 1;
                    }
                case 1:
                    {
                        m_MaxRange = reader.ReadInt();

                        goto case 0;
                    }
                case 0:
                    {
                        if (version == 0)
                        {
                            m_MaxRange = 1; // default
                        }

                        if (version < 5)
                        {
                            m_Resource = CraftResource.Iron;
                            m_AosAttributes = new AosAttributes(this);
                            m_AosWeaponAttributes = new AosWeaponAttributes(this);
                            m_AosElementDamages = new AosElementAttributes(this);
                            m_AosSkillBonuses = new AosSkillBonuses(this);
                        }

                        m_MinDamage = reader.ReadInt();
                        m_MaxDamage = reader.ReadInt();

                        m_Speed = reader.ReadInt();

                        m_HitSound = reader.ReadInt();
                        m_MissSound = reader.ReadInt();

                        m_Skill = (SkillName)reader.ReadInt();
                        m_Type = (WeaponType)reader.ReadInt();
                        m_Animation = (WeaponAnimation)reader.ReadInt();
                        m_DamageLevel = (WeaponDamageLevel)reader.ReadInt();
                        m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt();
                        m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt();
                        m_Quality = (ItemQuality)reader.ReadInt();

                        m_Crafter = reader.ReadMobile();

                        m_Poison = Poison.Deserialize(reader);
                        m_PoisonCharges = reader.ReadInt();

                        if (m_StrReq == OldStrengthReq)
                        {
                            m_StrReq = -1;
                        }

                        if (m_DexReq == OldDexterityReq)
                        {
                            m_DexReq = -1;
                        }

                        if (m_IntReq == OldIntelligenceReq)
                        {
                            m_IntReq = -1;
                        }

                        if (m_MinDamage == OldMinDamage)
                        {
                            m_MinDamage = -1;
                        }

                        if (m_MaxDamage == OldMaxDamage)
                        {
                            m_MaxDamage = -1;
                        }

                        if (m_HitSound == OldHitSound)
                        {
                            m_HitSound = -1;
                        }

                        if (m_MissSound == OldMissSound)
                        {
                            m_MissSound = -1;
                        }

                        if (m_Speed == OldSpeed)
                        {
                            m_Speed = -1;
                        }

                        if (m_MaxRange == OldMaxRange)
                        {
                            m_MaxRange = -1;
                        }

                        if (m_Skill == OldSkill)
                        {
                            m_Skill = (SkillName)(-1);
                        }

                        if (m_Type == OldType)
                        {
                            m_Type = (WeaponType)(-1);
                        }

                        if (m_Animation == OldAnimation)
                        {
                            m_Animation = (WeaponAnimation)(-1);
                        }

                        if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && Parent is Mobile)
                        {
                            m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
                            ((Mobile)Parent).AddSkillMod(m_SkillMod);
                        }

                        break;
                    }
            }

            if (version < 15)
            {
                if (WeaponAttributes.HitLeechHits > 0 || WeaponAttributes.HitLeechMana > 0)
                {
                    WeaponAttributes.ScaleLeech(Attributes.WeaponSpeed);
                }
            }

            #region Mondain's Legacy Sets
            if (m_SetAttributes == null)
            {
                m_SetAttributes = new AosAttributes(this);
            }

            if (m_SetSkillBonuses == null)
            {
                m_SetSkillBonuses = new AosSkillBonuses(this);
            }
            #endregion

            if (Core.AOS && Parent is Mobile)
            {
                m_AosSkillBonuses.AddTo((Mobile)Parent);
            }

            int strBonus = m_AosAttributes.BonusStr;
            int dexBonus = m_AosAttributes.BonusDex;
            int intBonus = m_AosAttributes.BonusInt;

            if (Parent is Mobile && (strBonus != 0 || dexBonus != 0 || intBonus != 0))
            {
                Mobile m = (Mobile)Parent;

                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));
                }
            }

            if (Parent is Mobile)
            {
                ((Mobile)Parent).CheckStatTimers();
            }

            if (m_Hits <= 0 && m_MaxHits <= 0)
            {
                m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits);
            }

            if (version < 6)
            {
                m_PlayerConstructed = true; // we don't know, so, assume it's crafted
            }

            if (m_Slayer == SlayerName.DaemonDismissal || m_Slayer == SlayerName.BalronDamnation)
                m_Slayer = SlayerName.Exorcism;

            if (m_Slayer2 == SlayerName.DaemonDismissal || m_Slayer2 == SlayerName.BalronDamnation)
                m_Slayer2 = SlayerName.Exorcism;
        }
        #endregion

        public BaseWeapon(int itemID)
            : base(itemID)
        {
            Layer = (Layer)ItemData.Quality;

            m_Quality = ItemQuality.Normal;
            m_StrReq = -1;
            m_DexReq = -1;
            m_IntReq = -1;
            m_MinDamage = -1;
            m_MaxDamage = -1;
            m_HitSound = -1;
            m_MissSound = -1;
            m_Speed = -1;
            m_MaxRange = -1;
            m_Skill = (SkillName)(-1);
            m_Type = (WeaponType)(-1);
            m_Animation = (WeaponAnimation)(-1);

            m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits);

            m_Resource = CraftResource.Iron;

            m_AosAttributes = new AosAttributes(this);
            m_AosWeaponAttributes = new AosWeaponAttributes(this);
            m_AosSkillBonuses = new AosSkillBonuses(this);
            m_AosElementDamages = new AosElementAttributes(this);
            m_NegativeAttributes = new NegativeAttributes(this);
            m_ExtendedWeaponAttributes = new ExtendedWeaponAttributes(this);

            #region Stygian Abyss
            m_SAAbsorptionAttributes = new SAAbsorptionAttributes(this);
            #endregion

            #region Mondain's Legacy Sets
            m_SetAttributes = new AosAttributes(this);
            m_SetSkillBonuses = new AosSkillBonuses(this);
            #endregion

            m_AosSkillBonuses = new AosSkillBonuses(this);

            if (this is ITool)
            {
                m_UsesRemaining = Utility.RandomMinMax(25, 75);
            }
            else
            {
                m_UsesRemaining = 150;
            }
        }

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

        private string GetNameString()
        {
            string name = Name;

            if (name == null)
            {
                name = String.Format("#{0}", LabelNumber);
            }

            return name;
        }

        [Hue, CommandProperty(AccessLevel.GameMaster)]
        public override int Hue
        {
            get { return base.Hue; }
            set
            {
                base.Hue = value;
                InvalidateProperties();
            }
        }

        public int GetElementalDamageHue()
        {
            int phys, fire, cold, pois, nrgy, chaos, direct;
            GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
            //Order is Cold, Energy, Fire, Poison, Physical left

            int currentMax = 50;
            int hue = 0;

            if (pois >= currentMax)
            {
                hue = 1267 + (pois - 50) / 10;
                currentMax = pois;
            }

            if (fire >= currentMax)
            {
                hue = 1255 + (fire - 50) / 10;
                currentMax = fire;
            }

            if (nrgy >= currentMax)
            {
                hue = 1273 + (nrgy - 50) / 10;
                currentMax = nrgy;
            }

            if (cold >= currentMax)
            {
                hue = 1261 + (cold - 50) / 10;
                currentMax = cold;
            }

            return hue;
        }

        public override void AddNameProperty(ObjectPropertyList list)
        {
            if (m_ExtendedWeaponAttributes.AssassinHoned > 0)
            {
                list.Add(1152207); // Assassin's Edge
                return;
            }   
            
            //daat99 OWLTR start - custom resources
            string oreType = CraftResources.GetName(m_Resource);
            int level = CraftResources.GetIndex(m_Resource) + 1;
            
            if (m_Quality == ItemQuality.Exceptional)
            {
                if (level > 1 && !string.IsNullOrEmpty(oreType))
                    list.Add(1053100, "{0}\t{1}", oreType, GetNameString()); // exceptional ~1_oretype~ ~2_armortype~
                else
                    list.Add(1050040, GetNameString()); // exceptional ~1_ITEMNAME~
            }
            else
            {
                if (level > 1 && !string.IsNullOrEmpty(oreType))
                    list.Add(1053099, "{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~
                else
                    list.Add(GetNameString());
            }
            //daat99 OWLTR end - custom resources
            
            if (m_ReforgedPrefix != ReforgedPrefix.None || m_ReforgedSuffix != ReforgedSuffix.None)
            {
                if (m_ReforgedPrefix != ReforgedPrefix.None)
                {
                    int prefix = RunicReforging.GetPrefixName(m_ReforgedPrefix);

                    if (m_ReforgedSuffix == ReforgedSuffix.None)
                        list.Add(1151757, String.Format("#{0}\t{1}", prefix, GetNameString())); // ~1_PREFIX~ ~2_ITEM~
                    else
                        list.Add(1151756, String.Format("#{0}\t{1}\t#{2}", prefix, GetNameString(), RunicReforging.GetSuffixName(m_ReforgedSuffix))); // ~1_PREFIX~ ~2_ITEM~ of ~3_SUFFIX~
                }
                else if (m_ReforgedSuffix != ReforgedSuffix.None)
                {
                    RunicReforging.AddSuffixName(list, m_ReforgedSuffix, GetNameString());
                }
            }
            /* else if (oreType != 0)
            {
                list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~
            } */
            #region High Seas
            else if (SearingWeapon)
            {
                list.Add(1151318, String.Format("#{0}", LabelNumber));
            }
            #endregion
            else if (Name == null)
            {
                list.Add(LabelNumber);
            }
            else
            {
                list.Add(Name);
            }

            /*
            * Want to move this to the engraving tool, let the non-harmful
            * formatting show, and remove CLILOCs embedded: more like OSI
            * did with the books that had markup, etc.
            *
            * This will have a negative effect on a few event things imgame
            * as is.
            *
            * If we cant find a more OSI-ish way to clean it up, we can
            * easily put this back, and use it in the deserialize
            * method and engraving tool, to make it perm cleaned up.
            */

            if (!String.IsNullOrEmpty(m_EngravedText))
            {
                list.Add(1062613, m_EngravedText);
            }
            /* list.Add( 1062613, Utility.FixHtml( m_EngravedText ) ); */
        }
        //daat99 OWLTR end - custom resources

        public override bool AllowEquipedCast(Mobile from)
        {
            if (base.AllowEquipedCast(from))
            {
                return true;
            }

            return m_AosAttributes.SpellChanneling > 0 || Enhancement.GetValue(from, AosAttribute.SpellChanneling) > 0;
        }

        public virtual int ArtifactRarity { get { return 0; } }

        public override bool DisplayWeight
        {
            get
            {
                if (IsVvVItem)
                    return true;

                return base.DisplayWeight;
            }
        }

        public virtual int GetLuckBonus()
        {
            #region Mondain's Legacy
            if (m_Resource == CraftResource.Heartwood)
            {
                return 0;
            }
            #endregion

            CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);

            if (resInfo == null)
            {
                return 0;
            }

            CraftAttributeInfo attrInfo = resInfo.AttributeInfo;

            if (attrInfo == null)
            {
                return 0;
            }

            return attrInfo.WeaponLuck;
        }

        public override void AddCraftedProperties(ObjectPropertyList list)
        {
            if (OwnerName != null)
            {
                list.Add(1153213, OwnerName);
            }

            if (m_Crafter != null)
            {
                list.Add(1050043, m_Crafter.TitleName); // crafted by ~1_NAME~
            }

            if (m_Quality == ItemQuality.Exceptional)
            {
                list.Add(1060636); // Exceptional
            }

            if (IsImbued)
            {
                list.Add(1080418); // (Imbued)
            }

            if (m_Altered)
            {
                list.Add(1111880); // Altered
            }
        }

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

            if (IsVvVItem)
                list.Add(1154937); // VvV Item
        }

        public override void AddUsesRemainingProperties(ObjectPropertyList list)
        {
            if (ShowUsesRemaining)
            {
                list.Add(1060584, UsesRemaining.ToString()); // uses remaining: ~1_val~
            }
        }

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

            #region Factions
            FactionEquipment.AddFactionProperties(this, list);
            #endregion

            #region Mondain's Legacy Sets
            if (IsSetItem)
            {
                list.Add(1073491, Pieces.ToString()); // Part of a Weapon/Armor Set (~1_val~ pieces)

                if (SetID == SetItem.Bestial)
                    list.Add(1151541, BestialSetHelper.GetTotalBerserk(this).ToString()); // Berserk ~1_VAL~

                if (BardMasteryBonus)
                    list.Add(1151553); // Activate: Bard Mastery Bonus x2<br>(Effect: 1 min. Cooldown: 30 min.)

                if (m_SetEquipped)
                {
                    list.Add(1073492); // Full Weapon/Armor Set Present
                    GetSetProperties(list);
                }
                Server.Engines.XmlSpawner2.XmlAttach.AddAttachmentProperties(this, list);
            }
            #endregion

            if (m_ExtendedWeaponAttributes.Focus > 0)
            {
                list.Add(1150018); // Focus
            }

            if (m_NegativeAttributes.Brittle == 0 && m_AosAttributes.Brittle != 0)
            {
                list.Add(1116209); // Brittle
            }

            if (m_NegativeAttributes != null)
                m_NegativeAttributes.GetProperties(list, this);

            if (m_AosSkillBonuses != null)
            {
                m_AosSkillBonuses.GetProperties(list);
            }           

            if (RequiredRace == Race.Elf)
            {
                list.Add(1075086); // Elves Only
            }

            #region Stygian Abyss
            else if (RequiredRace == Race.Gargoyle)
            {
                list.Add(1111709); // Gargoyles Only
            }
            #endregion

            if (ArtifactRarity > 0)
            {
                list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~
            }

            if (m_Poison != null && m_PoisonCharges > 0 && CanShowPoisonCharges())
            {
                #region Mondain's Legacy mod
                list.Add(m_Poison.LabelNumber, m_PoisonCharges.ToString());
                #endregion
            }

            if (m_Slayer != SlayerName.None)
            {
                SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer);
                if (entry != null)
                {
                    list.Add(entry.Title);
                }
            }

            if (m_Slayer2 != SlayerName.None)
            {
                SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2);
                if (entry != null)
                {
                    list.Add(entry.Title);
                }
            }

            #region Mondain's Legacy
            if (m_Slayer3 != TalismanSlayerName.None)
            {
                if (m_Slayer3 == TalismanSlayerName.Wolf)
                {
                    list.Add(1075462);
                }
                else if (m_Slayer3 == TalismanSlayerName.Goblin)
                {
                    list.Add(1095010);
                }
                else if (m_Slayer3 == TalismanSlayerName.Undead)
                {
                    list.Add(1060479);
                }
                else
                {
                    list.Add(1072503 + (int)m_Slayer3);
                }
            }
            #endregion

            if (HasSocket<Caddellite>())
            {
                list.Add(1158662); // Caddellite Infused
            }

            double focusBonus = 1;
            int enchantBonus = 0;
            bool fcMalus = false;
            int damBonus = 0;
            SpecialMove move = null;
            AosWeaponAttribute bonus = AosWeaponAttribute.HitColdArea;

            #region Focus Attack
            if (FocusWeilder != null)
            {
                move = SpecialMove.GetCurrentMove(FocusWeilder);

                if (move is FocusAttack)
                {
                    focusBonus = move.GetPropertyBonus(FocusWeilder);
                    damBonus = (int)(move.GetDamageScalar(FocusWeilder, null) * 100) - 100;
                }
            }
            #endregion

            #region Stygian Abyss
            if (EnchantedWeilder != null)
            {
                if (Server.Spells.Mysticism.EnchantSpell.IsUnderSpellEffects(EnchantedWeilder, this))
                {
                    bonus = Server.Spells.Mysticism.EnchantSpell.BonusAttribute(EnchantedWeilder);
                    enchantBonus = Server.Spells.Mysticism.EnchantSpell.BonusValue(EnchantedWeilder);
                    fcMalus = Server.Spells.Mysticism.EnchantSpell.CastingMalus(EnchantedWeilder, this);
                }
            }
            #endregion

            int prop;
            double fprop;

            if ((prop = m_AosWeaponAttributes.DurabilityBonus) != 0)
            {
                list.Add(1151780, prop.ToString()); // durability +~1_VAL~%
            }

            if (Core.TOL)
            {
                if (m_ExtendedWeaponAttributes.Bane > 0)
                {
                    list.Add(1154671); // Bane
                }

                if (m_ExtendedWeaponAttributes.BoneBreaker > 0)
                {
                    list.Add(1157318); // Bone Breaker
                }

                if ((prop = m_ExtendedWeaponAttributes.HitSwarm) != 0)
                {
                    list.Add(1157325, prop.ToString()); // Swarm ~1_val~%
                }

                if ((prop = m_ExtendedWeaponAttributes.HitSparks) != 0)
                {
                    list.Add(1157326, prop.ToString()); // Sparks ~1_val~%
                }

                if ((prop = m_ExtendedWeaponAttributes.AssassinHoned) != 0)
                {
                    list.Add(1152206); // Assassin Honed
                }
            }

            if ((prop = m_AosWeaponAttributes.SplinteringWeapon) != 0)
            {
                list.Add(1112857, prop.ToString()); //splintering weapon ~1_val~%
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitDispel * focusBonus) != 0)
            {
                list.Add(1060417, ((int)fprop).ToString()); // hit dispel ~1_val~%
            }
            else if (bonus == AosWeaponAttribute.HitDispel && enchantBonus != 0)
            {
                list.Add(1060417, ((int)(enchantBonus * focusBonus)).ToString()); // hit dispel ~1_val~%
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitFireball * focusBonus) != 0)
            {
                list.Add(1060420, ((int)fprop).ToString()); // hit fireball ~1_val~%
            }
            else if (bonus == AosWeaponAttribute.HitFireball && enchantBonus != 0)
            {
                list.Add(1060420, ((int)((double)enchantBonus * focusBonus)).ToString()); // hit fireball ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitLightning * focusBonus) != 0)
            {
                list.Add(1060423, ((int)fprop).ToString()); // hit lightning ~1_val~%
            }
            else if (bonus == AosWeaponAttribute.HitLightning && enchantBonus != 0)
            {
                list.Add(1060423, ((int)(enchantBonus * focusBonus)).ToString()); // hit lightning ~1_val~%
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitHarm * focusBonus) != 0)
            {
                list.Add(1060421, ((int)fprop).ToString()); // hit harm ~1_val~%
            }
            else if (bonus == AosWeaponAttribute.HitHarm && enchantBonus != 0)
            {
                list.Add(1060421, ((int)(enchantBonus * focusBonus)).ToString()); // hit harm ~1_val~%
            }

            if ((fprop = (double)m_ExtendedWeaponAttributes.HitExplosion * focusBonus) != 0)
            {
                list.Add(1158922, ((int)fprop).ToString()); // hit explosion ~1_val~%
            }

            if (SearingWeapon)
            {
                list.Add(1151183); // Searing Weapon
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitMagicArrow * focusBonus) != 0)
            {
                list.Add(1060426, ((int)fprop).ToString()); // hit magic arrow ~1_val~%
            }
            else if (bonus == AosWeaponAttribute.HitMagicArrow && enchantBonus != 0)
            {
                list.Add(1060426, ((int)(enchantBonus * focusBonus)).ToString()); // hit magic arrow ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitPhysicalArea * focusBonus) != 0)
            {
                list.Add(1060428, ((int)fprop).ToString()); // hit physical area ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitFireArea * focusBonus) != 0)
            {
                list.Add(1060419, ((int)fprop).ToString()); // hit fire area ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitColdArea * focusBonus) != 0)
            {
                list.Add(1060416, ((int)fprop).ToString()); // hit cold area ~1_val~%
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitPoisonArea * focusBonus) != 0)
            {
                list.Add(1060429, ((int)fprop).ToString()); // hit poison area ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitEnergyArea * focusBonus) != 0)
            {
                list.Add(1060418, ((int)fprop).ToString()); // hit energy area ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitLeechStam * focusBonus) != 0)
            {
                list.Add(1060430, Math.Min(100, (int)fprop).ToString()); // hit stamina leech ~1_val~%
            }

            if ((fprop = (double)m_AosWeaponAttributes.HitLeechMana * focusBonus) != 0)
            {
                list.Add(1060427, Math.Min(100, (int)fprop).ToString()); // hit mana leech ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitLeechHits * focusBonus) != 0)
            {
                list.Add(1060422, Math.Min(100, (int)fprop).ToString()); // hit life leech ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitFatigue * focusBonus) != 0)
            {
                list.Add(1113700, ((int)fprop).ToString()); // Hit Fatigue ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitManaDrain * focusBonus) != 0)
            {
                list.Add(1113699, ((int)fprop).ToString()); // Hit Mana Drain ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitCurse * focusBonus) != 0)
            {
                list.Add(1113712, ((int)fprop).ToString()); // Hit Curse ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitLowerAttack * focusBonus) != 0)
            {
                list.Add(1060424, ((int)fprop).ToString()); // hit lower attack ~1_val~%
            }
            
            if ((fprop = (double)m_AosWeaponAttributes.HitLowerDefend * focusBonus) != 0)
            {
                list.Add(1060425, ((int)fprop).ToString()); // hit lower defense ~1_val~%
            }
            
            if ((prop = m_AosWeaponAttributes.BloodDrinker) != 0)
            {
                list.Add(1113591, prop.ToString()); // Blood Drinker
            }
            
            if ((prop = m_AosWeaponAttributes.BattleLust) != 0)
            {
                list.Add(1113710, prop.ToString()); // Battle Lust
            }

            if (ImmolatingWeaponSpell.IsImmolating(RootParent as Mobile, this))
            {
                list.Add(1111917); // Immolated
            }

            if (Core.ML && this is BaseRanged && (prop = ((BaseRanged)this).Velocity) != 0)
            {
                list.Add(1072793, prop.ToString()); // Velocity ~1_val~%
            }

            if ((prop = m_AosAttributes.LowerAmmoCost) != 0)
            {
                list.Add(1075208, prop.ToString()); // Lower Ammo Cost ~1_Percentage~%
            }

            if ((prop = m_ExtendedWeaponAttributes.MysticWeapon) != 0)
            {
                list.Add(1155881, (30 - prop).ToString());   // mystic weapon -~1_val~ skill
            }
            else if ((prop = Parent is Mobile ? Enhancement.GetValue((Mobile)Parent, ExtendedWeaponAttribute.MysticWeapon) : 0) != 0)
            {
                list.Add(1155881, (30 - prop).ToString());   // mystic weapon -~1_val~ skill
            }

            if ((prop = m_AosWeaponAttributes.SelfRepair) != 0)
            {
                list.Add(1060450, prop.ToString()); // self repair ~1_val~
            }
            
            if ((prop = m_AosAttributes.NightSight) != 0)
            {
                list.Add(1060441); // night sight
            }

            if ((prop = fcMalus ? 1 : m_AosAttributes.SpellChanneling) != 0)
            {
                list.Add(1060482); // spell channeling
            }
            
            if ((prop = m_AosWeaponAttributes.MageWeapon) != 0)
            {
                list.Add(1060438, (30 - prop).ToString()); // mage weapon -~1_val~ skill
            }
            
            if (Core.ML && m_AosAttributes.BalancedWeapon > 0 && Layer == Layer.TwoHanded)
            {
                list.Add(1072792); // Balanced
            }
            
            if ((prop = (GetLuckBonus() + m_AosAttributes.Luck)) != 0)
            {
                list.Add(1060436, prop.ToString()); // luck ~1_val~
            }
            
            if ((prop = m_AosAttributes.EnhancePotions) != 0)
            {
                list.Add(1060411, prop.ToString()); // enhance potions ~1_val~%
            }
            
            if ((prop = m_AosWeaponAttributes.ReactiveParalyze) != 0)
            {
                list.Add(1112364); // reactive paralyze
            }
            
            if ((prop = m_AosAttributes.BonusStr) != 0)
            {
                list.Add(1060485, prop.ToString()); // strength bonus ~1_val~
            }
            
            if ((prop = m_AosAttributes.BonusInt) != 0)
            {
                list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~
            }
            
            if ((prop = m_AosAttributes.BonusDex) != 0)
            {
                list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~
            }
            
            if ((prop = m_AosAttributes.BonusHits) != 0)
            {
                list.Add(1060431, prop.ToString()); // hit point increase ~1_val~
            }
            
            if ((prop = m_AosAttributes.BonusStam) != 0)
            {
                list.Add(1060484, prop.ToString()); // stamina increase ~1_val~
            }
            
            if ((prop = m_AosAttributes.BonusMana) != 0)
            {
                list.Add(1060439, prop.ToString()); // mana increase ~1_val~
            }
            
            if ((prop = m_AosAttributes.RegenHits) != 0)
            {
                list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~
            }
            
            if ((prop = m_AosAttributes.RegenStam) != 0)
            {
                list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~
            }
            
            if ((prop = m_AosAttributes.RegenMana) != 0)
            {
                list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~
            }
            
            if ((prop = m_AosAttributes.ReflectPhysical) != 0)
            {
                list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~%
            }
            
            if ((prop = m_AosAttributes.SpellDamage) != 0)
            {
                list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~%
            }
            
            if ((prop = m_AosAttributes.CastRecovery) != 0)
            {
                list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~
            }

            if ((prop = fcMalus ? m_AosAttributes.CastSpeed - 1 : m_AosAttributes.CastSpeed) != 0)
            {
                list.Add(1060413, prop.ToString()); // faster casting ~1_val~
            }
            
            if ((prop = (GetHitChanceBonus() + m_AosAttributes.AttackChance)) != 0)
            {
                list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~%
            }
            
            if ((prop = m_AosAttributes.DefendChance) != 0)
            {
                list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~%
            }
            
            if ((prop = m_AosAttributes.LowerManaCost) != 0)
            {
                list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~%
            }
            
            if ((prop = m_AosAttributes.LowerRegCost) != 0)
            {
                list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~%
            }

            if ((prop = m_AosAttributes.WeaponSpeed) != 0)
            {
                list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~%
            }
            
            if ((prop = (GetDamageBonus() + m_AosAttributes.WeaponDamage + damBonus)) != 0)
            {
                list.Add(1060401, prop.ToString()); // damage increase ~1_val~%
            }

            if (Core.ML && (prop = m_AosAttributes.IncreasedKarmaLoss) != 0)
            {
                list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~%
            }

            #region Stygian Abyss
            if ((prop = m_SAAbsorptionAttributes.CastingFocus) != 0)
            {
                list.Add(1113696, prop.ToString()); // Casting Focus ~1_val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterFire) != 0)
            {
                list.Add(1113593, prop.ToString()); // Fire Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterCold) != 0)
            {
                list.Add(1113594, prop.ToString()); // Cold Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterPoison) != 0)
            {
                list.Add(1113595, prop.ToString()); // Poison Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterEnergy) != 0)
            {
                list.Add(1113596, prop.ToString()); // Energy Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterKinetic) != 0)
            {
                list.Add(1113597, prop.ToString()); // Kinetic Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.EaterDamage) != 0)
            {
                list.Add(1113598, prop.ToString()); // Damage Eater ~1_Val~%
            }

            if ((prop = m_SAAbsorptionAttributes.ResonanceFire) != 0)
            {
                list.Add(1113691, prop.ToString()); // Fire Resonance ~1_val~%
            }

            if ((prop = m_SAAbsorptionAttributes.ResonanceCold) != 0)
            {
                list.Add(1113692, prop.ToString()); // Cold Resonance ~1_val~%
            }

            if ((prop = m_SAAbsorptionAttributes.ResonancePoison) != 0)
            {
                list.Add(1113693, prop.ToString()); // Poison Resonance ~1_val~%
            }

            if ((prop = m_SAAbsorptionAttributes.ResonanceEnergy) != 0)
            {
                list.Add(1113694, prop.ToString()); // Energy Resonance ~1_val~%
            }

            if ((prop = m_SAAbsorptionAttributes.ResonanceKinetic) != 0)
            {
                list.Add(1113695, prop.ToString()); // Kinetic Resonance ~1_val~%
            }
            #endregion
            
            base.AddResistanceProperties(list);
            
            if ((prop = GetLowerStatReq()) != 0)
            {
                list.Add(1060435, prop.ToString()); // lower requirements ~1_val~%
            }
            
            if ((prop = m_AosWeaponAttributes.UseBestSkill) != 0)
            {
                list.Add(1060400); // use best weapon skill
            }

            int phys, fire, cold, pois, nrgy, chaos, direct;

            GetDamageTypes(null, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);

            #region Mondain's Legacy
            if (chaos != 0)
            {
                list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~%
            }

            if (direct != 0)
            {
                list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~%
            }
            #endregion

            if (phys != 0)
            {
                list.Add(1060403, phys.ToString()); // physical damage ~1_val~%
            }

            if (fire != 0)
            {
                list.Add(1060405, fire.ToString()); // fire damage ~1_val~%
            }

            if (cold != 0)
            {
                list.Add(1060404, cold.ToString()); // cold damage ~1_val~%
            }

            if (pois != 0)
            {
                list.Add(1060406, pois.ToString()); // poison damage ~1_val~%
            }

            if (nrgy != 0)
            {
                list.Add(1060407, nrgy.ToString()); // energy damage ~1_val
            }

            if (Core.ML && chaos != 0)
            {
                list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~%
            }

            if (Core.ML && direct != 0)
            {
                list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~%
            }

            list.Add(1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString()); // weapon damage ~1_val~ - ~2_val~

            if (Core.ML)
            {
                list.Add(1061167, String.Format("{0}s", Speed)); // weapon speed ~1_val~
            }
            else
            {
                list.Add(1061167, Speed.ToString());
            }

            if (MaxRange > 1)
            {
                list.Add(1061169, MaxRange.ToString()); // range ~1_val~
            }

            int strReq = AOS.Scale(StrRequirement, 100 - GetLowerStatReq());

            if (strReq > 0)
            {
                list.Add(1061170, strReq.ToString()); // strength requirement ~1_val~
            }

            if (Layer == Layer.TwoHanded)
            {
                list.Add(1061171); // two-handed weapon
            }
            else
            {
                list.Add(1061824); // one-handed weapon
            }

            if (Core.SE || m_AosWeaponAttributes.UseBestSkill == 0)
            {
                switch (Skill)
                {
                    case SkillName.Swords:
                        list.Add(1061172);
                        break; // skill required: swordsmanship
                    case SkillName.Macing:
                        list.Add(1061173);
                        break; // skill required: mace fighting
                    case SkillName.Fencing:
                        list.Add(1061174);
                        break; // skill required: fencing
                    case SkillName.Archery:
                        list.Add(1061175);
                        break; // skill required: archery
                    case SkillName.Throwing:
                        list.Add(1112075); // skill required: throwing
                        break;
                }
            }

            XmlAttach.AddAttachmentProperties(this, list);

            if (m_Hits >= 0 && m_MaxHits > 0)
            {
                list.Add(1060639, "{0}\t{1}", m_Hits, m_MaxHits); // durability ~1_val~ / ~2_val~
            }

            if (IsSetItem && !m_SetEquipped)
            {
                list.Add(1072378); // <br>Only when full set is present:
                GetSetProperties(list);
            }

            if (Core.EJ && LastParryChance > 0)
            {
                list.Add(1158861, LastParryChance.ToString()); // Last Parry Chance: ~1_val~%
            }

           // Xml Spawner 2.36c XmlLevelItem - SOF
           XmlLevelItem levitem = XmlAttach.FindAttachment(this, typeof(XmlLevelItem)) as XmlLevelItem;

           if (levitem != null)
           {
               list.Add(1060658, "Level\t{0}", levitem.Level);

           if (LevelItems.DisplayExpProp)
               list.Add(1060659, "Experience\t{0}", levitem.Experience);

           }
           // Xml Spawner 2.36c XmlLevelItem - EOF
        }

        public override void AddItemPowerProperties(ObjectPropertyList list)
        {
            if (m_ItemPower != ItemPower.None)
            {
                if (m_ItemPower <= ItemPower.LegendaryArtifact)
                    list.Add(1151488 + ((int)m_ItemPower - 1));
                else
                    list.Add(1152281 + ((int)m_ItemPower - 9));
            }
        }

        public bool CanShowPoisonCharges()
        {
            if (PrimaryAbility == WeaponAbility.InfectiousStrike || SecondaryAbility == WeaponAbility.InfectiousStrike)
                return true;

            return RootParent is Mobile && SkillMasterySpell.HasSpell((Mobile)RootParent, typeof(InjectedStrikeSpell));
        }

        public override void OnSingleClick(Mobile from)
        {
            var attrs = new List<EquipInfoAttribute>();

            if (DisplayLootType)
            {
                if (LootType == LootType.Blessed)
                {
                    attrs.Add(new EquipInfoAttribute(1038021)); // blessed
                }
                else if (LootType == LootType.Cursed)
                {
                    attrs.Add(new EquipInfoAttribute(1049643)); // cursed
                }
            }

            #region Factions
            if (m_FactionState != null)
            {
                attrs.Add(new EquipInfoAttribute(1041350)); // faction item
            }
            #endregion

            if (m_Quality == ItemQuality.Exceptional)
            {
                attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality));
            }

            if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster)
            {
                if (m_Slayer != SlayerName.None)
                {
                    SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer);
                    if (entry != null)
                    {
                        attrs.Add(new EquipInfoAttribute(entry.Title));
                    }
                }

                if (m_Slayer2 != SlayerName.None)
                {
                    SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2);
                    if (entry != null)
                    {
                        attrs.Add(new EquipInfoAttribute(entry.Title));
                    }
                }

                if (m_DurabilityLevel != WeaponDurabilityLevel.Regular)
                {
                    attrs.Add(new EquipInfoAttribute(1038000 + (int)m_DurabilityLevel));
                }

                if (m_DamageLevel != WeaponDamageLevel.Regular)
                {
                    attrs.Add(new EquipInfoAttribute(1038015 + (int)m_DamageLevel));
                }

                if (m_AccuracyLevel != WeaponAccuracyLevel.Regular)
                {
                    attrs.Add(new EquipInfoAttribute(1038010 + (int)m_AccuracyLevel));
                }
            }
            else if (m_Slayer != SlayerName.None || m_Slayer2 != SlayerName.None ||
                     m_DurabilityLevel != WeaponDurabilityLevel.Regular || m_DamageLevel != WeaponDamageLevel.Regular ||
                     m_AccuracyLevel != WeaponAccuracyLevel.Regular)
            {
                attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified
            }

            if (m_Poison != null && m_PoisonCharges > 0)
            {
                attrs.Add(new EquipInfoAttribute(1017383, m_PoisonCharges));
            }

            int number;

            if (Name == null)
            {
                number = LabelNumber;
            }
            else
            {
                LabelTo(from, Name);
                number = 1041000;
            }

            if (attrs.Count == 0 && Crafter == null && Name != null)
            {
                return;
            }

            EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray());

            from.Send(new DisplayEquipmentInfo(this, eqInfo));
        }

        public override bool DropToWorld(Mobile from, Point3D p)
        {
            bool drop = base.DropToWorld(from, p);

            EnchantedHotItemSocket.CheckDrop(from, this);

            return drop;
        }

        public static BaseWeapon Fists { get; set; }

        #region ICraftable Members
        public int OnCraft(
            int quality,
            bool makersMark,
            Mobile from,
            CraftSystem craftSystem,
            Type typeRes,
            ITool tool,
            CraftItem craftItem,
            int resHue)
        {
            Quality = (ItemQuality)quality;

            if (makersMark)
            {
                Crafter = from;
            }

            PlayerConstructed = true;

            if (typeRes == null)
            {
                typeRes = craftItem.Resources.GetAt(0).ItemType;
            }

            if (Core.AOS)
            {
                if (!craftItem.ForceNonExceptional)
                {
                    Resource = CraftResources.GetFromType(typeRes);
                }

                CraftContext context = craftSystem.GetContext(from);

                if (Quality == ItemQuality.Exceptional)
                {
                    Attributes.WeaponDamage += 35;
                }

                if (!craftItem.ForceNonExceptional)
                {
                    if (tool is BaseRunicTool)
                    {
                        ((BaseRunicTool)tool).ApplyAttributesTo(this);
                    }
                }

                if (Core.ML && Quality == ItemQuality.Exceptional)
                {
                    double div = Siege.SiegeShard ? 12.5 : 20;

                    Attributes.WeaponDamage += (int)(from.Skills.ArmsLore.Value / div);
                    from.CheckSkill(SkillName.ArmsLore, 0, 100);
                }
            }
            else if (tool is BaseRunicTool)
            {
                if (craftItem != null && !craftItem.ForceNonExceptional)
                {
                    CraftResource thisResource = CraftResources.GetFromType(typeRes);

                    if (thisResource == ((BaseRunicTool)tool).Resource)
                    {
                        Resource = thisResource;

                        switch (thisResource)
                        {
                            case CraftResource.DullCopper:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Durable;
                                    AccuracyLevel = WeaponAccuracyLevel.Accurate;
                                    break;
                                }
                            case CraftResource.ShadowIron:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Durable;
                                    DamageLevel = WeaponDamageLevel.Ruin;
                                    break;
                                }
                            case CraftResource.Copper:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Fortified;
                                    DamageLevel = WeaponDamageLevel.Ruin;
                                    AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
                                    break;
                                }
                            case CraftResource.Bronze:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Fortified;
                                    DamageLevel = WeaponDamageLevel.Might;
                                    AccuracyLevel = WeaponAccuracyLevel.Surpassingly;
                                    break;
                                }
                            case CraftResource.Gold:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Indestructible;
                                    DamageLevel = WeaponDamageLevel.Force;
                                    AccuracyLevel = WeaponAccuracyLevel.Eminently;
                                    break;
                                }
                            case CraftResource.Agapite:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Indestructible;
                                    DamageLevel = WeaponDamageLevel.Power;
                                    AccuracyLevel = WeaponAccuracyLevel.Eminently;
                                    break;
                                }
                            case CraftResource.Verite:
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Indestructible;
                                    DamageLevel = WeaponDamageLevel.Power;
                                    AccuracyLevel = WeaponAccuracyLevel.Exceedingly;
                                    break;
                                }
                            case CraftResource.Valorite:
                            //daat99 OWLTR start - custom resources are like Valorite in Pre-AOS
                            case CraftResource.Blaze:
                            case CraftResource.Ice:
                            case CraftResource.Toxic:
                            case CraftResource.Electrum:
                            case CraftResource.Platinum:
                            //daat99 OWLTR end - custom resources are like Valorite in Pre-AOS
                                {
                                    Identified = true;
                                    DurabilityLevel = WeaponDurabilityLevel.Indestructible;
                                    DamageLevel = WeaponDamageLevel.Vanq;
                                    AccuracyLevel = WeaponAccuracyLevel.Supremely;
                                    break;
                                }
                        }
                    }
                }
            }

            if (craftItem != null && !craftItem.ForceNonExceptional)
            {
                CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);

                if (resInfo == null)
                {
                    return quality;
                }

                CraftAttributeInfo attrInfo = resInfo.AttributeInfo;

                if (attrInfo == null)
                {
                    return quality;
                }

                DistributeMaterialBonus(attrInfo);
            }
            #endregion

            return quality;
        }

        public virtual void DistributeMaterialBonus(CraftAttributeInfo attrInfo)
        {
            if (m_Resource != CraftResource.Heartwood)
            {
                m_AosAttributes.WeaponDamage += attrInfo.WeaponDamage;
                m_AosAttributes.WeaponSpeed += attrInfo.WeaponSwingSpeed;
                m_AosAttributes.AttackChance += attrInfo.WeaponHitChance;
                m_AosAttributes.RegenHits += attrInfo.WeaponRegenHits;
                m_AosWeaponAttributes.HitLeechHits += attrInfo.WeaponHitLifeLeech;
            }
            else
            {
                switch (Utility.Random(6))
                {
                    case 0: m_AosAttributes.WeaponDamage += attrInfo.WeaponDamage; break;
                    case 1: m_AosAttributes.WeaponSpeed += attrInfo.WeaponSwingSpeed; break;
                    case 2: m_AosAttributes.AttackChance += attrInfo.WeaponHitChance; break;
                    case 3: m_AosAttributes.Luck += attrInfo.WeaponLuck; break;
                    case 4: m_AosWeaponAttributes.LowerStatReq += attrInfo.WeaponLowerRequirements; break;
                    case 5: m_AosWeaponAttributes.HitLeechHits += attrInfo.WeaponHitLifeLeech; break;
                }
            }
        }

        #region Mondain's Legacy Sets
        public override bool OnDragLift(Mobile from)
        {
            if (Parent is Mobile && from == Parent)
            {
                if (IsSetItem && m_SetEquipped)
                {
                    SetHelper.RemoveSetBonus(from, SetID, this);
                }
            }

            return base.OnDragLift(from);
        }

        public virtual SetItem SetID { get { return SetItem.None; } }
        public virtual int Pieces { get { return 0; } }

        public virtual bool BardMasteryBonus
        {
            get
            {
                return (SetID == SetItem.Virtuoso);
            }
        }

        public bool IsSetItem { get { return SetID != SetItem.None; } }

        private int m_SetHue;
        private bool m_SetEquipped;
        private bool m_LastEquipped;

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetHue
        {
            get { return m_SetHue; }
            set
            {
                m_SetHue = value;
                InvalidateProperties();
            }
        }

        public bool SetEquipped { get { return m_SetEquipped; } set { m_SetEquipped = value; } }

        public bool LastEquipped { get { return m_LastEquipped; } set { m_LastEquipped = value; } }

        private AosAttributes m_SetAttributes;
        private AosSkillBonuses m_SetSkillBonuses;
        private int m_SetSelfRepair;
        private int m_SetPhysicalBonus, m_SetFireBonus, m_SetColdBonus, m_SetPoisonBonus, m_SetEnergyBonus;

        [CommandProperty(AccessLevel.GameMaster)]
        public AosAttributes SetAttributes { get { return m_SetAttributes; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public AosSkillBonuses SetSkillBonuses { get { return m_SetSkillBonuses; } set { } }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetSelfRepair
        {
            get { return m_SetSelfRepair; }
            set
            {
                m_SetSelfRepair = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetPhysicalBonus
        {
            get
            {
                return m_SetPhysicalBonus;
            }
            set
            {
                m_SetPhysicalBonus = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetFireBonus
        {
            get
            {
                return m_SetFireBonus;
            }
            set
            {
                m_SetFireBonus = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetColdBonus
        {
            get
            {
                return m_SetColdBonus;
            }
            set
            {
                m_SetColdBonus = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetPoisonBonus
        {
            get
            {
                return m_SetPoisonBonus;
            }
            set
            {
                m_SetPoisonBonus = value;
                InvalidateProperties();
            }
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SetEnergyBonus
        {
            get
            {
                return m_SetEnergyBonus;
            }
            set
            {
                m_SetEnergyBonus = value;
                InvalidateProperties();
            }
        }

        public virtual void GetSetProperties(ObjectPropertyList list)
        {
            int prop;

            if ((prop = m_SetSelfRepair) != 0 && WeaponAttributes.SelfRepair == 0)
            {
                list.Add(1060450, prop.ToString()); // self repair ~1_val~
            }

            SetHelper.GetSetProperties(list, this);
        }

        public int SetResistBonus(ResistanceType resist)
        {
            switch (resist)
            {
                case ResistanceType.Physical: return PhysicalResistance;
                case ResistanceType.Fire: return FireResistance;
                case ResistanceType.Cold: return ColdResistance;
                case ResistanceType.Poison: return PoisonResistance;
                case ResistanceType.Energy: return EnergyResistance;
            }

            return 0;
        }
        #endregion

        [CommandProperty(AccessLevel.GameMaster)]
        public bool Altered
        {
            get { return m_Altered; }
            set
            {
                m_Altered = value;
                InvalidateProperties();
            }
        }
    }

    public enum CheckSlayerResult
    {
        None,
        Slayer,
        SuperSlayer,
        Opposition
    }
}
Although the fact that is shows on clothing too makes me think it's something to do with a different core file, but I could be wrong. Thanks :)
 
Doom had the right area, but it's this outdated section of OWLTR, if the item is not Exceptional then the Name is just the name

C#:
 //daat99 OWLTR start - custom resources
            string oreType = CraftResources.GetName(m_Resource);
            int level = CraftResources.GetIndex(m_Resource) + 1;
          
            if (m_Quality == ItemQuality.Exceptional)
            {
                if (level > 1 && !string.IsNullOrEmpty(oreType))
                    list.Add(1053100, "{0}\t{1}", oreType, GetNameString()); // exceptional ~1_oretype~ ~2_armortype~
                else
                    list.Add(1050040, GetNameString()); // exceptional ~1_ITEMNAME~
            }
            else
            {
                if (level > 1 && !string.IsNullOrEmpty(oreType))
                    list.Add(1053099, "{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~
                else
                    list.Add(GetNameString());
            }
            //daat99 OWLTR end - custom resources

and then lower down, after #region High Seas [searing weapon]

C#:
/*(else if (Name == null)
            {
                list.Add(LabelNumber);
            }
            else
            {
                list.Add(Name);
            }*/
 
Last edited:
remove or block comment out the same section i did above for if the item is not exceptional and that should resolve your problem

EDIT: actually, looking again you want to keep the OWLTR edits and comment out the part in the second section of code. but i would also move the OWLTR edits to the end of AddNameProperty
 
Didn't look just assumed that's what it was because it should still have two names for runic reforging to have a magic name under the original


Example A from owltr post.
 

Attachments

  • Screenshot_20211025-125606_Chrome.jpg
    Screenshot_20211025-125606_Chrome.jpg
    989.3 KB · Views: 34
Oh very nice, thanks for the fixes guys I'll take a look at it here in a bit.

**EDIT**
Awesome zero that worked, now I just have to repeat the process for all the other base files haha..
 
Last edited:
Back