1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Help with making unidentified weapons.

Discussion in 'Script Support' started by Sirenix, Apr 18, 2014.

  1. Sirenix
    Offline

    Sirenix Member

    Joined:
    Apr 16, 2014
    Messages:
    75
    Likes Received:
    5
    Im kind of an old school UO player from back before trammel. I like a bit of mystery with the loot so i've had this enabled before on my other server. It's working now, sort of... on a few of the weapons and jewels spawned, sometimes instead of showing "unidentified" it just doesn't show anything except weight and name, and don't say unidentified. I hate to just write it off as a bug and go on. I've worked with it all day trying to figure it out and im confused. My best guess is it has something to do with bonus resistances, and slayers, but ive had a few of each spawn with those props and work. The only other difference between my script and the stock servUO script is the addition of Shipwrecked item tags, which work. The armor and talismans also work as intended.

    Thanks! :D
    Code (C#):
    1.  
    2. #region Header
    3. // **********
    4. // ServUO - BaseWeapon.cs
    5. // **********
    6. #endregion
    7.  
    8. #region References
    9. using System;
    10. using System.Text;
    11. using System.Collections.Generic;
    12.  
    13. using Server.ContextMenus;
    14. using Server.Engines.Craft;
    15. using Server.Engines.XmlSpawner2;
    16. using Server.Ethics;
    17. using Server.Factions;
    18. using Server.Mobiles;
    19. using Server.Network;
    20. using Server.SkillHandlers;
    21. using Server.Spells;
    22. using Server.Spells.Bushido;
    23. using Server.Spells.Chivalry;
    24. using Server.Spells.Necromancy;
    25. using Server.Spells.Ninjitsu;
    26. using Server.Spells.Sixth;
    27. using Server.Spells.Spellweaving;
    28. #endregion
    29.  
    30. namespace Server.Items
    31. {
    32.    public interface ISlayer
    33.    {
    34.      SlayerName Slayer { get; set; }
    35.      SlayerName Slayer2 { get; set; }
    36.    }
    37.  
    38.    public abstract class BaseWeapon : Item, IWeapon, IFactionItem, ICraftable, ISlayer, IDurability, ISetItem, IShipwreckedItem
    39.    {
    40.      private string m_EngravedText;
    41.  
    42.      [CommandProperty(AccessLevel.GameMaster)]
    43.      public string EngravedText
    44.      {
    45.        get { return m_EngravedText; }
    46.        set
    47.        {
    48.          m_EngravedText = value;
    49.          InvalidateProperties();
    50.        }
    51.      }
    52.  
    53.      #region Factions
    54.      private FactionItem m_FactionState;
    55.  
    56.      public FactionItem FactionItemState
    57.      {
    58.        get { return m_FactionState; }
    59.        set
    60.        {
    61.          m_FactionState = value;
    62.  
    63.          if (m_FactionState == null)
    64.          {
    65.            Hue = CraftResources.GetHue(Resource);
    66.          }
    67.  
    68.          LootType = (m_FactionState == null ? LootType.Regular : LootType.Blessed);
    69.        }
    70.      }
    71.      #endregion
    72.  
    73.      /* Weapon internals work differently now (Mar 13 2003)
    74.   *
    75.   * The attributes defined below default to -1.
    76.   * If the value is -1, the corresponding virtual 'Aos/Old' property is used.
    77.   * If not, the attribute value itself is used. Here's the list:
    78.   *  - MinDamage
    79.   *  - MaxDamage
    80.   *  - Speed
    81.   *  - HitSound
    82.   *  - MissSound
    83.   *  - StrRequirement, DexRequirement, IntRequirement
    84.   *  - WeaponType
    85.   *  - WeaponAnimation
    86.   *  - MaxRange
    87.   */
    88.  
    89.  
    90.      #region Var declarations
    91.      // Instance values. These values are unique to each weapon.
    92.      private WeaponDamageLevel m_DamageLevel;
    93.      private WeaponAccuracyLevel m_AccuracyLevel;
    94.      private WeaponDurabilityLevel m_DurabilityLevel;
    95.      private WeaponQuality m_Quality;
    96.      private Mobile m_Crafter;
    97.      private Poison m_Poison;
    98.      private int m_PoisonCharges;
    99.      private bool m_Identified;
    100.      private int m_Hits;
    101.      private int m_MaxHits;
    102.      private SlayerName m_Slayer;
    103.      private SlayerName m_Slayer2;
    104.  
    105.      #region Imbuing
    106.      private int m_TimesImbued;
    107.      #endregion
    108.  
    109.      #region Mondain's Legacy
    110.      private TalismanSlayerName m_Slayer3;
    111.      #endregion
    112.  
    113.      private SkillMod m_SkillMod, m_MageMod;
    114.      private CraftResource m_Resource;
    115.      private bool m_PlayerConstructed;
    116.  
    117.      private bool m_Cursed; // Is this weapon cursed via Curse Weapon necromancer spell? Temporary; not serialized.
    118.  
    119.      private bool m_Consecrated;
    120.             // Is this weapon blessed via Consecrate Weapon paladin ability? Temporary; not serialized.
    121.  
    122.      #region Mondain's Legacy
    123.      private bool m_Immolating; // Is this weapon blessed via Immolating Weapon arcanists spell? Temporary; not serialized.
    124.      #endregion
    125.  
    126.      private AosAttributes m_AosAttributes;
    127.      private AosWeaponAttributes m_AosWeaponAttributes;
    128.      private AosSkillBonuses m_AosSkillBonuses;
    129.      private AosElementAttributes m_AosElementDamages;
    130.  
    131.      #region SA
    132.      private SAAbsorptionAttributes m_SAAbsorptionAttributes;
    133.      #endregion
    134.  
    135.      // Overridable values. These values are provided to override the defaults which get defined in the individual weapon scripts.
    136.      private int m_StrReq, m_DexReq, m_IntReq;
    137.      private int m_MinDamage, m_MaxDamage;
    138.      private int m_HitSound, m_MissSound;
    139.      private float m_Speed;
    140.      private int m_MaxRange;
    141.      private SkillName m_Skill;
    142.      private WeaponType m_Type;
    143.      private WeaponAnimation m_Animation;
    144.      #endregion
    145.  
    146.      #region Virtual Properties
    147.      public virtual WeaponAbility PrimaryAbility { get { return null; } }
    148.      public virtual WeaponAbility SecondaryAbility { get { return null; } }
    149.  
    150.      public virtual int DefMaxRange { get { return 1; } }
    151.      public virtual int DefHitSound { get { return 0; } }
    152.      public virtual int DefMissSound { get { return 0; } }
    153.      public virtual SkillName DefSkill { get { return SkillName.Swords; } }
    154.      public virtual WeaponType DefType { get { return WeaponType.Slashing; } }
    155.      public virtual WeaponAnimation DefAnimation { get { return WeaponAnimation.Slash1H; } }
    156.  
    157.      public virtual int AosStrengthReq { get { return 0; } }
    158.      public virtual int AosDexterityReq { get { return 0; } }
    159.      public virtual int AosIntelligenceReq { get { return 0; } }
    160.      public virtual int AosMinDamage { get { return 0; } }
    161.      public virtual int AosMaxDamage { get { return 0; } }
    162.      public virtual int AosSpeed { get { return 0; } }
    163.      public virtual float MlSpeed { get { return 0.0f; } }
    164.      public virtual int AosMaxRange { get { return DefMaxRange; } }
    165.      public virtual int AosHitSound { get { return DefHitSound; } }
    166.      public virtual int AosMissSound { get { return DefMissSound; } }
    167.      public virtual SkillName AosSkill { get { return DefSkill; } }
    168.      public virtual WeaponType AosType { get { return DefType; } }
    169.      public virtual WeaponAnimation AosAnimation { get { return DefAnimation; } }
    170.  
    171.      public virtual int OldStrengthReq { get { return 0; } }
    172.      public virtual int OldDexterityReq { get { return 0; } }
    173.      public virtual int OldIntelligenceReq { get { return 0; } }
    174.      public virtual int OldMinDamage { get { return 0; } }
    175.      public virtual int OldMaxDamage { get { return 0; } }
    176.      public virtual int OldSpeed { get { return 0; } }
    177.      public virtual int OldMaxRange { get { return DefMaxRange; } }
    178.      public virtual int OldHitSound { get { return DefHitSound; } }
    179.      public virtual int OldMissSound { get { return DefMissSound; } }
    180.      public virtual SkillName OldSkill { get { return DefSkill; } }
    181.      public virtual WeaponType OldType { get { return DefType; } }
    182.      public virtual WeaponAnimation OldAnimation { get { return DefAnimation; } }
    183.  
    184.      public virtual int InitMinHits { get { return 0; } }
    185.      public virtual int InitMaxHits { get { return 0; } }
    186.  
    187.      public virtual bool CanFortify { get { return true; } }
    188.  
    189.      public override int PhysicalResistance { get { return m_AosWeaponAttributes.ResistPhysicalBonus; } }
    190.      public override int FireResistance { get { return m_AosWeaponAttributes.ResistFireBonus; } }
    191.      public override int ColdResistance { get { return m_AosWeaponAttributes.ResistColdBonus; } }
    192.      public override int PoisonResistance { get { return m_AosWeaponAttributes.ResistPoisonBonus; } }
    193.      public override int EnergyResistance { get { return m_AosWeaponAttributes.ResistEnergyBonus; } }
    194.  
    195.      public virtual SkillName AccuracySkill { get { return SkillName.Tactics; } }
    196.  
    197.      #region Personal Bless Deed
    198.      private Mobile m_BlessedBy;
    199.  
    200.      [CommandProperty(AccessLevel.GameMaster)]
    201.      public Mobile BlessedBy
    202.      {
    203.        get { return m_BlessedBy; }
    204.        set
    205.        {
    206.          m_BlessedBy = value;
    207.          InvalidateProperties();
    208.        }
    209.      }
    210.  
    211.      private class UnBlessEntry : ContextMenuEntry
    212.      {
    213.        private readonly Mobile m_From;
    214.        private readonly BaseWeapon m_Weapon; // BaseArmor, BaseWeapon or BaseClothing
    215.  
    216.        public UnBlessEntry(Mobile from, BaseWeapon weapon)
    217.          : base(6208, -1)
    218.        {
    219.          m_From = from;
    220.          m_Weapon = weapon;
    221.        }
    222.  
    223.        public override void OnClick()
    224.        {
    225.          m_Weapon.BlessedFor = null;
    226.          m_Weapon.BlessedBy = null;
    227.  
    228.          Container pack = m_From.Backpack;
    229.  
    230.          if (pack != null)
    231.          {
    232.            pack.DropItem(new PersonalBlessDeed(m_From));
    233.            m_From.SendLocalizedMessage(1062200); // A personal bless deed has been placed in your backpack.
    234.          }
    235.        }
    236.      }
    237.      #endregion
    238.  
    239.      #endregion
    240.  
    241.      #region Getters & Setters
    242.      [CommandProperty(AccessLevel.GameMaster)]
    243.      public int TimesImbued
    244.      {
    245.        get { return m_TimesImbued; }
    246.        set
    247.        {
    248.          m_TimesImbued = value;
    249.          InvalidateProperties();
    250.        }
    251.      }
    252.  
    253.      [CommandProperty(AccessLevel.GameMaster)]
    254.      public AosAttributes Attributes { get { return m_AosAttributes; } set { } }
    255.  
    256.      [CommandProperty(AccessLevel.GameMaster)]
    257.      public AosWeaponAttributes WeaponAttributes { get { return m_AosWeaponAttributes; } set { } }
    258.  
    259.      [CommandProperty(AccessLevel.GameMaster)]
    260.      public AosSkillBonuses SkillBonuses { get { return m_AosSkillBonuses; } set { } }
    261.  
    262.      [CommandProperty(AccessLevel.GameMaster)]
    263.      public AosElementAttributes AosElementDamages { get { return m_AosElementDamages; } set { } }
    264.  
    265.      #region Stygian Abyss
    266.      [CommandProperty(AccessLevel.GameMaster)]
    267.      public SAAbsorptionAttributes AbsorptionAttributes { get { return m_SAAbsorptionAttributes; } set { } }
    268.      #endregion
    269.  
    270.      [CommandProperty(AccessLevel.GameMaster)]
    271.      public bool Cursed { get { return m_Cursed; } set { m_Cursed = value; } }
    272.  
    273.      [CommandProperty(AccessLevel.GameMaster)]
    274.      public bool Consecrated { get { return m_Consecrated; } set { m_Consecrated = value; } }
    275.  
    276.      #region Mondain's Legacy
    277.      [CommandProperty(AccessLevel.GameMaster)]
    278.      public bool Immolating { get { return m_Immolating; } set { m_Immolating = value; } }
    279.      #endregion
    280.  
    281.      [CommandProperty(AccessLevel.GameMaster)]
    282.      public bool Identified
    283.      {
    284.        get { return m_Identified; }
    285.        set
    286.        {
    287.          m_Identified = value;
    288.          InvalidateProperties();
    289.        }
    290.      }
    291.  
    292.      [CommandProperty(AccessLevel.GameMaster)]
    293.      public int HitPoints
    294.      {
    295.        get { return m_Hits; }
    296.        set
    297.        {
    298.          if (m_Hits == value)
    299.          {
    300.            return;
    301.          }
    302.  
    303.          if (value > m_MaxHits)
    304.          {
    305.            value = m_MaxHits;
    306.          }
    307.  
    308.          m_Hits = value;
    309.  
    310.          InvalidateProperties();
    311.        }
    312.      }
    313.  
    314.      [CommandProperty(AccessLevel.GameMaster)]
    315.      public int MaxHitPoints
    316.      {
    317.        get { return m_MaxHits; }
    318.        set
    319.        {
    320.          m_MaxHits = value;
    321.          InvalidateProperties();
    322.        }
    323.      }
    324.  
    325.      [CommandProperty(AccessLevel.GameMaster)]
    326.      public int PoisonCharges
    327.      {
    328.        get { return m_PoisonCharges; }
    329.        set
    330.        {
    331.          m_PoisonCharges = value;
    332.          InvalidateProperties();
    333.        }
    334.      }
    335.  
    336.      [CommandProperty(AccessLevel.GameMaster)]
    337.      public Poison Poison
    338.      {
    339.        get { return m_Poison; }
    340.        set
    341.        {
    342.          m_Poison = value;
    343.          InvalidateProperties();
    344.        }
    345.      }
    346.  
    347.      [CommandProperty(AccessLevel.GameMaster)]
    348.      public WeaponQuality Quality
    349.      {
    350.        get { return m_Quality; }
    351.        set
    352.        {
    353.          UnscaleDurability();
    354.          m_Quality = value;
    355.          ScaleDurability();
    356.          InvalidateProperties();
    357.        }
    358.      }
    359.  
    360.      [CommandProperty(AccessLevel.GameMaster)]
    361.      public Mobile Crafter
    362.      {
    363.        get { return m_Crafter; }
    364.        set
    365.        {
    366.          m_Crafter = value;
    367.          InvalidateProperties();
    368.        }
    369.      }
    370.  
    371.      [CommandProperty(AccessLevel.GameMaster)]
    372.      public SlayerName Slayer
    373.      {
    374.        get { return m_Slayer; }
    375.        set
    376.        {
    377.          m_Slayer = value;
    378.          InvalidateProperties();
    379.        }
    380.      }
    381.  
    382.      [CommandProperty(AccessLevel.GameMaster)]
    383.      public SlayerName Slayer2
    384.      {
    385.        get { return m_Slayer2; }
    386.        set
    387.        {
    388.          m_Slayer2 = value;
    389.          InvalidateProperties();
    390.        }
    391.      }
    392.  
    393.      [CommandProperty(AccessLevel.GameMaster)]
    394.      public TalismanSlayerName Slayer3
    395.      {
    396.        get { return m_Slayer3; }
    397.        set
    398.        {
    399.          m_Slayer3 = value;
    400.          InvalidateProperties();
    401.        }
    402.      }
    403.  
    404.      [CommandProperty(AccessLevel.GameMaster)]
    405.      public CraftResource Resource
    406.      {
    407.        get { return m_Resource; }
    408.        set
    409.        {
    410.          UnscaleDurability();
    411.          m_Resource = value;
    412.          Hue = CraftResources.GetHue(m_Resource);
    413.          InvalidateProperties();
    414.          ScaleDurability();
    415.        }
    416.      }
    417.  
    418.      [CommandProperty(AccessLevel.GameMaster)]
    419.      public WeaponDamageLevel DamageLevel
    420.      {
    421.        get { return m_DamageLevel; }
    422.        set
    423.        {
    424.          m_DamageLevel = value;
    425.          InvalidateProperties();
    426.        }
    427.      }
    428.  
    429.      [CommandProperty(AccessLevel.GameMaster)]
    430.      public WeaponDurabilityLevel DurabilityLevel
    431.      {
    432.        get { return m_DurabilityLevel; }
    433.        set
    434.        {
    435.          UnscaleDurability();
    436.          m_DurabilityLevel = value;
    437.          InvalidateProperties();
    438.          ScaleDurability();
    439.        }
    440.      }
    441.  
    442.      [CommandProperty(AccessLevel.GameMaster)]
    443.      public bool PlayerConstructed { get { return m_PlayerConstructed; } set { m_PlayerConstructed = value; } }
    444.  
    445.      [CommandProperty(AccessLevel.GameMaster)]
    446.      public int MaxRange
    447.      {
    448.        get { return (m_MaxRange == -1 ? Core.AOS ? AosMaxRange : OldMaxRange : m_MaxRange); }
    449.        set
    450.        {
    451.          m_MaxRange = value;
    452.          InvalidateProperties();
    453.        }
    454.      }
    455.  
    456.      [CommandProperty(AccessLevel.GameMaster)]
    457.      public WeaponAnimation Animation { get { return (m_Animation == (WeaponAnimation)(-1) ? Core.AOS ? AosAnimation : OldAnimation : m_Animation); } set { m_Animation = value; } }
    458.  
    459.      [CommandProperty(AccessLevel.GameMaster)]
    460.      public WeaponType Type { get { return (m_Type == (WeaponType)(-1) ? Core.AOS ? AosType : OldType : m_Type); } set { m_Type = value; } }
    461.  
    462.      [CommandProperty(AccessLevel.GameMaster)]
    463.      public SkillName Skill
    464.      {
    465.        get { return (m_Skill == (SkillName)(-1) ? Core.AOS ? AosSkill : OldSkill : m_Skill); }
    466.        set
    467.        {
    468.          m_Skill = value;
    469.          InvalidateProperties();
    470.        }
    471.      }
    472.  
    473.      [CommandProperty(AccessLevel.GameMaster)]
    474.      public int HitSound { get { return (m_HitSound == -1 ? Core.AOS ? AosHitSound : OldHitSound : m_HitSound); } set { m_HitSound = value; } }
    475.  
    476.      [CommandProperty(AccessLevel.GameMaster)]
    477.      public int MissSound { get { return (m_MissSound == -1 ? Core.AOS ? AosMissSound : OldMissSound : m_MissSound); } set { m_MissSound = value; } }
    478.  
    479.      [CommandProperty(AccessLevel.GameMaster)]
    480.      public int MinDamage
    481.      {
    482.        get { return (m_MinDamage == -1 ? Core.AOS ? AosMinDamage : OldMinDamage : m_MinDamage); }
    483.        set
    484.        {
    485.          m_MinDamage = value;
    486.          InvalidateProperties();
    487.        }
    488.      }
    489.  
    490.      [CommandProperty(AccessLevel.GameMaster)]
    491.      public int MaxDamage
    492.      {
    493.        get { return (m_MaxDamage == -1 ? Core.AOS ? AosMaxDamage : OldMaxDamage : m_MaxDamage); }
    494.        set
    495.        {
    496.          m_MaxDamage = value;
    497.          InvalidateProperties();
    498.        }
    499.      }
    500.  
    501.      [CommandProperty(AccessLevel.GameMaster)]
    502.      public float Speed
    503.      {
    504.        get
    505.        {
    506.          if (m_Speed != -1)
    507.          {
    508.            return m_Speed;
    509.          }
    510.  
    511.          if (Core.ML)
    512.          {
    513.            return MlSpeed;
    514.          }
    515.          else if (Core.AOS)
    516.          {
    517.            return AosSpeed;
    518.          }
    519.  
    520.          return OldSpeed;
    521.        }
    522.        set
    523.        {
    524.          m_Speed = value;
    525.          InvalidateProperties();
    526.        }
    527.      }
    528.  
    529.      [CommandProperty(AccessLevel.GameMaster)]
    530.      public int StrRequirement
    531.      {
    532.        get { return (m_StrReq == -1 ? Core.AOS ? AosStrengthReq : OldStrengthReq : m_StrReq); }
    533.        set
    534.        {
    535.          m_StrReq = value;
    536.          InvalidateProperties();
    537.        }
    538.      }
    539.  
    540.      [CommandProperty(AccessLevel.GameMaster)]
    541.      public int DexRequirement { get { return (m_DexReq == -1 ? Core.AOS ? AosDexterityReq : OldDexterityReq : m_DexReq); } set { m_DexReq = value; } }
    542.  
    543.      [CommandProperty(AccessLevel.GameMaster)]
    544.      public int IntRequirement { get { return (m_IntReq == -1 ? Core.AOS ? AosIntelligenceReq : OldIntelligenceReq : m_IntReq); } set { m_IntReq = value; } }
    545.  
    546.      [CommandProperty(AccessLevel.GameMaster)]
    547.      public WeaponAccuracyLevel AccuracyLevel
    548.      {
    549.        get { return m_AccuracyLevel; }
    550.        set
    551.        {
    552.          if (m_AccuracyLevel != value)
    553.          {
    554.            m_AccuracyLevel = value;
    555.  
    556.            if (UseSkillMod)
    557.            {
    558.              if (m_AccuracyLevel == WeaponAccuracyLevel.Regular)
    559.              {
    560.                if (m_SkillMod != null)
    561.                {
    562.                  m_SkillMod.Remove();
    563.                }
    564.  
    565.                m_SkillMod = null;
    566.              }
    567.              else if (m_SkillMod == null && Parent is Mobile)
    568.              {
    569.                m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
    570.                ((Mobile)Parent).AddSkillMod(m_SkillMod);
    571.              }
    572.              else if (m_SkillMod != null)
    573.              {
    574.                m_SkillMod.Value = (int)m_AccuracyLevel * 5;
    575.              }
    576.            }
    577.  
    578.            InvalidateProperties();
    579.          }
    580.        }
    581.      }
    582.      #endregion
    583.  
    584.      public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
    585.      {
    586.        base.GetContextMenuEntries(from, list);
    587.  
    588.        if (BlessedFor == from && BlessedBy == from && RootParent == from)
    589.        {
    590.          list.Add(new UnBlessEntry(from, this));
    591.        }
    592.  
    593.        XmlLevelItem levitem = XmlAttach.FindAttachment(this, typeof(XmlLevelItem)) as XmlLevelItem;
    594.  
    595.        if (levitem != null)
    596.        {
    597.          list.Add(new LevelInfoEntry(from, this, AttributeCategory.Melee));
    598.        }
    599.      }
    600.  
    601.      public override void OnAfterDuped(Item newItem)
    602.      {
    603.        BaseWeapon weap = newItem as BaseWeapon;
    604.  
    605.        if (weap == null)
    606.        {
    607.          return;
    608.        }
    609.  
    610.        weap.m_AosAttributes = new AosAttributes(newItem, m_AosAttributes);
    611.        weap.m_AosElementDamages = new AosElementAttributes(newItem, m_AosElementDamages);
    612.        weap.m_AosSkillBonuses = new AosSkillBonuses(newItem, m_AosSkillBonuses);
    613.        weap.m_AosWeaponAttributes = new AosWeaponAttributes(newItem, m_AosWeaponAttributes);
    614.  
    615.        #region Mondain's Legacy
    616.        weap.m_SetAttributes = new AosAttributes(newItem, m_SetAttributes);
    617.        weap.m_SetSkillBonuses = new AosSkillBonuses(newItem, m_SetSkillBonuses);
    618.        #endregion
    619.  
    620.        #region SA
    621.        weap.m_SAAbsorptionAttributes = new SAAbsorptionAttributes(newItem, m_SAAbsorptionAttributes);
    622.        #endregion
    623.      }
    624.  
    625.      public virtual void UnscaleDurability()
    626.      {
    627.        int scale = 100 + GetDurabilityBonus();
    628.  
    629.        m_Hits = ((m_Hits * 100) + (scale - 1)) / scale;
    630.        m_MaxHits = ((m_MaxHits * 100) + (scale - 1)) / scale;
    631.        InvalidateProperties();
    632.      }
    633.  
    634.      public virtual void ScaleDurability()
    635.      {
    636.        int scale = 100 + GetDurabilityBonus();
    637.  
    638.        m_Hits = ((m_Hits * scale) + 99) / 100;
    639.        m_MaxHits = ((m_MaxHits * scale) + 99) / 100;
    640.        InvalidateProperties();
    641.      }
    642.  
    643.      public int GetDurabilityBonus()
    644.      {
    645.        int bonus = 0;
    646.  
    647.        if (m_Quality == WeaponQuality.Exceptional)
    648.        {
    649.          bonus += 20;
    650.        }
    651.  
    652.        switch (m_DurabilityLevel)
    653.        {
    654.          case WeaponDurabilityLevel.Durable:
    655.            bonus += 20;
    656.            break;
    657.          case WeaponDurabilityLevel.Substantial:
    658.            bonus += 50;
    659.            break;
    660.          case WeaponDurabilityLevel.Massive:
    661.            bonus += 70;
    662.            break;
    663.          case WeaponDurabilityLevel.Fortified:
    664.            bonus += 100;
    665.            break;
    666.          case WeaponDurabilityLevel.Indestructible:
    667.            bonus += 120;
    668.            break;
    669.        }
    670.  
    671.        if (Core.AOS)
    672.        {
    673.          bonus += m_AosWeaponAttributes.DurabilityBonus;
    674.  
    675.          #region Mondain's Legacy
    676.          if (m_Resource == CraftResource.Heartwood)
    677.          {
    678.            return bonus;
    679.          }
    680.          #endregion
    681.  
    682.          CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
    683.          CraftAttributeInfo attrInfo = null;
    684.  
    685.          if (resInfo != null)
    686.          {
    687.            attrInfo = resInfo.AttributeInfo;
    688.          }
    689.  
    690.          if (attrInfo != null)
    691.          {
    692.            bonus += attrInfo.WeaponDurability;
    693.          }
    694.        }
    695.  
    696.        return bonus;
    697.      }
    698.  
    699.      public int GetLowerStatReq()
    700.      {
    701.        if (!Core.AOS)
    702.        {
    703.          return 0;
    704.        }
    705.  
    706.        int v = m_AosWeaponAttributes.LowerStatReq;
    707.  
    708.        #region Mondain's Legacy
    709.        if (m_Resource == CraftResource.Heartwood)
    710.        {
    711.          return v;
    712.        }
    713.        #endregion
    714.  
    715.        CraftResourceInfo info = CraftResources.GetInfo(m_Resource);
    716.  
    717.        if (info != null)
    718.        {
    719.          CraftAttributeInfo attrInfo = info.AttributeInfo;
    720.  
    721.          if (attrInfo != null)
    722.          {
    723.            v += attrInfo.WeaponLowerRequirements;
    724.          }
    725.        }
    726.  
    727.        if (v > 100)
    728.        {
    729.          v = 100;
    730.        }
    731.  
    732.        return v;
    733.      }
    734.  
    735.      public static void BlockEquip(Mobile m, TimeSpan duration)
    736.      {
    737.        if (m.BeginAction(typeof(BaseWeapon)))
    738.        {
    739.          new ResetEquipTimer(m, duration).Start();
    740.        }
    741.      }
    742.  
    743.      private class ResetEquipTimer : Timer
    744.      {
    745.        private readonly Mobile m_Mobile;
    746.  
    747.        public ResetEquipTimer(Mobile m, TimeSpan duration)
    748.          : base(duration)
    749.        {
    750.          m_Mobile = m;
    751.        }
    752.  
    753.        protected override void OnTick()
    754.        {
    755.          m_Mobile.EndAction(typeof(BaseWeapon));
    756.        }
    757.      }
    758.  
    759.      public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer)
    760.      {
    761.        if (base.CheckConflictingLayer(m, item, layer))
    762.        {
    763.          return true;
    764.        }
    765.  
    766.        if (Layer == Layer.TwoHanded && layer == Layer.OneHanded)
    767.        {
    768.          m.SendLocalizedMessage(500214); // You already have something in both hands.
    769.          return true;
    770.        }
    771.        else if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) && !(item is BaseEquipableLight))
    772.        {
    773.          m.SendLocalizedMessage(500215); // You can only wield one weapon at a time.
    774.          return true;
    775.        }
    776.  
    777.        return false;
    778.      }
    779.  
    780.      public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
    781.      {
    782.        if (!Ethic.CheckTrade(from, to, newOwner, this))
    783.        {
    784.          return false;
    785.        }
    786.  
    787.        return base.AllowSecureTrade(from, to, newOwner, accepted);
    788.      }
    789.  
    790.      public virtual Race RequiredRace { get { return null; } }
    791.      //On OSI, there are no weapons with race requirements, this is for custom stuff
    792.  
    793.      #region SA
    794.      public virtual bool CanBeWornByGargoyles { get { return false; } }
    795.      #endregion
    796.  
    797.      public override bool CanEquip(Mobile from)
    798.      {
    799.        if (!Ethic.CheckEquip(from, this))
    800.        {
    801.          return false;
    802.        }
    803.  
    804.        #region Stygian Abyss
    805.        if (from.Race == Race.Gargoyle && !CanBeWornByGargoyles && from.IsPlayer())
    806.        {
    807.          from.SendLocalizedMessage(1111708); // Gargoyles can't wear this.
    808.          return false;
    809.        }
    810.        #endregion
    811.  
    812.        if (RequiredRace != null && from.Race != RequiredRace)
    813.        {
    814.          if (RequiredRace == Race.Elf)
    815.          {
    816.            from.SendLocalizedMessage(1072203); // Only Elves may use this.
    817.          }
    818.            #region SA
    819.          else if (RequiredRace == Race.Gargoyle)
    820.          {
    821.            from.SendLocalizedMessage(1111707); // Only gargoyles can wear this.
    822.          }
    823.            #endregion
    824.  
    825.          else
    826.          {
    827.            from.SendMessage("Only {0} may use this.", RequiredRace.PluralName);
    828.          }
    829.  
    830.          return false;
    831.        }
    832. #region ItemID_Mods
    833.   else if (m_Identified == false)
    834.        {
    835.   from.SendMessage("You are hesitant to use something that is unknown to you.");
    836.          return false;
    837.        }
    838. #endregion
    839.        else if (from.Dex < DexRequirement)
    840.        {
    841.          from.SendMessage("You are not nimble enough to equip that.");
    842.          return false;
    843.        }
    844.        else if (from.Str < AOS.Scale(StrRequirement, 100 - GetLowerStatReq()))
    845.        {
    846.          from.SendLocalizedMessage(500213); // You are not strong enough to equip that.
    847.          return false;
    848.        }
    849.        else if (from.Int < IntRequirement)
    850.        {
    851.          from.SendMessage("You are not smart enough to equip that.");
    852.          return false;
    853.        }
    854.        else if (!from.CanBeginAction(typeof(BaseWeapon)))
    855.        {
    856.          return false;
    857.        }
    858.          #region Personal Bless Deed
    859.        else if (BlessedBy != null && BlessedBy != from)
    860.        {
    861.          from.SendLocalizedMessage(1075277); // That item is blessed by another player.
    862.  
    863.          return false;
    864.        }
    865.        else if (!XmlAttach.CheckCanEquip(this, from))
    866.        {
    867.          return false;
    868.        }
    869.          #endregion
    870.  
    871.        else
    872.        {
    873.          return base.CanEquip(from);
    874.        }
    875.      }
    876.  
    877.      public virtual bool UseSkillMod { get { return !Core.AOS; } }
    878.  
    879.      public override bool OnEquip(Mobile from)
    880.      {
    881.        int strBonus = m_AosAttributes.BonusStr;
    882.        int dexBonus = m_AosAttributes.BonusDex;
    883.        int intBonus = m_AosAttributes.BonusInt;
    884.  
    885.        if ((strBonus != 0 || dexBonus != 0 || intBonus != 0))
    886.        {
    887.          Mobile m = from;
    888.  
    889.          string modName = Serial.ToString();
    890.  
    891.          if (strBonus != 0)
    892.          {
    893.            m.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero));
    894.          }
    895.  
    896.          if (dexBonus != 0)
    897.          {
    898.            m.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero));
    899.          }
    900.  
    901.          if (intBonus != 0)
    902.          {
    903.            m.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero));
    904.          }
    905.        }
    906.  
    907.        from.NextCombatTime = Core.TickCount + (int)GetDelay(from).TotalMilliseconds;
    908.  
    909.        if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular)
    910.        {
    911.          if (m_SkillMod != null)
    912.          {
    913.            m_SkillMod.Remove();
    914.          }
    915.  
    916.          m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5);
    917.          from.AddSkillMod(m_SkillMod);
    918.        }
    919.  
    920.        if (Core.AOS && m_AosWeaponAttributes.MageWeapon != 0 && m_AosWeaponAttributes.MageWeapon != 30)
    921.        {
    922.          if (m_MageMod != null)
    923.          {
    924.            m_MageMod.Remove();
    925.          }
    926.  
    927.          m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + m_AosWeaponAttributes.MageWeapon);
    928.          from.AddSkillMod(m_MageMod);
    929.        }
    930.  
    931.        XmlAttach.CheckOnEquip(this, from);
    932.  
    933.        return true;
    934.      }
    935.  
    936.      public override void OnAdded(object parent)
    937.      {
    938.        base.OnAdded(parent);
    939.  
    940.        if (parent is Mobile)
    941.        {
    942.          Mobile from = (Mobile)parent;
    943.  
    944.          if (Core.AOS)
    945.          {
    946.            m_AosSkillBonuses.AddTo(from);
    947.          }
    948.  
    949.          #region Mondain's Legacy Sets
    950.          if (IsSetItem)
    951.          {
    952.            m_SetEquipped = SetHelper.FullSetEquipped(from, SetID, Pieces);
    953.  
    954.            if (m_SetEquipped)
    955.            {
    956.              m_LastEquipped = true;
    957.              SetHelper.AddSetBonus(from, SetID);
    958.            }
    959.          }
    960.          #endregion
    961.  
    962.          from.CheckStatTimers();
    963.          from.Delta(MobileDelta.WeaponDamage);
    964.        }
    965.      }
    966.  
    967.      public override void OnRemoved(object parent)
    968.      {
    969.        if (parent is Mobile)
    970.        {
    971.          Mobile m = (Mobile)parent;
    972.          BaseWeapon weapon = m.Weapon as BaseWeapon;
    973.  
    974.          string modName = Serial.ToString();
    975.  
    976.          m.RemoveStatMod(modName + "Str");
    977.          m.RemoveStatMod(modName + "Dex");
    978.          m.RemoveStatMod(modName + "Int");
    979.  
    980.          if (weapon != null)
    981.          {
    982.            m.NextCombatTime = Core.TickCount + (int)weapon.GetDelay(m).TotalMilliseconds;
    983.          }
    984.  
    985.          if (UseSkillMod && m_SkillMod != null)
    986.          {
    987.            m_SkillMod.Remove();
    988.            m_SkillMod = null;
    989.          }
    990.  
    991.          if (m_MageMod != null)
    992.          {
    993.            m_MageMod.Remove();
    994.            m_MageMod = null;
    995.          }
    996.  
    997.          if (Core.AOS)
    998.          {
    999.            m_AosSkillBonuses.Remove();
    1000.          }
    1001.  
    1002.          ImmolatingWeaponSpell.StopImmolating(this);
    1003.  
    1004.          m.CheckStatTimers();
    1005.  
    1006.          m.Delta(MobileDelta.WeaponDamage);
    1007.  
    1008.          XmlAttach.CheckOnRemoved(this, parent);
    1009.  
    1010.          #region Mondain's Legacy Sets
    1011.          if (IsSetItem && m_SetEquipped)
    1012.          {
    1013.            SetHelper.RemoveSetBonus(m, SetID, this);
    1014.          }
    1015.          #endregion
    1016.        }
    1017.      }
    1018.  
    1019.      public virtual SkillName GetUsedSkill(Mobile m, bool checkSkillAttrs)
    1020.      {
    1021.        SkillName sk;
    1022.  
    1023.        if (checkSkillAttrs && m_AosWeaponAttributes.UseBestSkill != 0)
    1024.        {
    1025.          double swrd = m.Skills[SkillName.Swords].Value;
    1026.          double fenc = m.Skills[SkillName.Fencing].Value;
    1027.          double mcng = m.Skills[SkillName.Macing].Value;
    1028.          double val;
    1029.  
    1030.          sk = SkillName.Swords;
    1031.          val = swrd;
    1032.  
    1033.          if (fenc > val)
    1034.          {
    1035.            sk = SkillName.Fencing;
    1036.            val = fenc;
    1037.          }
    1038.          if (mcng > val)
    1039.          {
    1040.            sk = SkillName.Macing;
    1041.            val = mcng;
    1042.          }
    1043.        }
    1044.        else if (m_AosWeaponAttributes.MageWeapon != 0)
    1045.        {
    1046.          if (m.Skills[SkillName.Magery].Value > m.Skills[Skill].Value)
    1047.          {
    1048.            sk = SkillName.Magery;
    1049.          }
    1050.          else
    1051.          {
    1052.            sk = Skill;
    1053.          }
    1054.        }
    1055.        else
    1056.        {
    1057.          sk = Skill;
    1058.  
    1059.          if (sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman &&
    1060.            m.Skills[SkillName.Wrestling].Value > m.Skills[sk].Value)
    1061.          {
    1062.            sk = SkillName.Wrestling;
    1063.          }
    1064.        }
    1065.  
    1066.        return sk;
    1067.      }
    1068.  
    1069.      public virtual double GetAttackSkillValue(Mobile attacker, Mobile defender)
    1070.      {
    1071.        return attacker.Skills[GetUsedSkill(attacker, true)].Value;
    1072.      }
    1073.  
    1074.      public virtual double GetDefendSkillValue(Mobile attacker, Mobile defender)
    1075.      {
    1076.        return defender.Skills[GetUsedSkill(defender, true)].Value;
    1077.      }
    1078.  
    1079.      private static bool CheckAnimal(Mobile m, Type type)
    1080.      {
    1081.        return AnimalForm.UnderTransformation(m, type);
    1082.      }
    1083.  
    1084.      public virtual bool CheckHit(Mobile attacker, Mobile defender)
    1085.      {
    1086.        BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
    1087.        BaseWeapon defWeapon = defender.Weapon as BaseWeapon;
    1088.  
    1089.        Skill atkSkill = attacker.Skills[atkWeapon.Skill];
    1090.        Skill defSkill = defender.Skills[defWeapon.Skill];
    1091.  
    1092.        double atkValue = atkWeapon.GetAttackSkillValue(attacker, defender);
    1093.        double defValue = defWeapon.GetDefendSkillValue(attacker, defender);
    1094.  
    1095.        double ourValue, theirValue;
    1096.  
    1097.        int bonus = GetHitChanceBonus();
    1098.  
    1099.        #region Stygian Abyss
    1100.        if (atkWeapon is BaseThrown)
    1101.        {
    1102.          int min = ((BaseThrown)atkWeapon).MinThrowRange;
    1103.          int throwchances = 0;
    1104.  
    1105.          if (attacker.InRange(defender, 1))
    1106.          {
    1107.            throwchances -= 12 - (int)(attacker.Skills[SkillName.Swords].Value / 10);
    1108.          }
    1109.          else if (!attacker.InRange(defender, min - 1))
    1110.          {
    1111.            throwchances -= 12;
    1112.          }
    1113.  
    1114.          BaseShield shield = attacker.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
    1115.  
    1116.          if (shield != null)
    1117.          {
    1118.            throwchances -= 12 - (int)(attacker.Skills[SkillName.Parry].Value / 10);
    1119.            throwchances -= Math.Max(0, (10 - (attacker.Dex / 10)));
    1120.          }
    1121.  
    1122.          if (throwchances < 0)
    1123.          {
    1124.            throwchances = 0;
    1125.          }
    1126.  
    1127.          bonus += throwchances;
    1128.        }
    1129.        #endregion
    1130.  
    1131.        if (Core.AOS)
    1132.        {
    1133.          if (atkValue <= -20.0)
    1134.          {
    1135.            atkValue = -19.9;
    1136.          }
    1137.  
    1138.          if (defValue <= -20.0)
    1139.          {
    1140.            defValue = -19.9;
    1141.          }
    1142.  
    1143.          bonus += AosAttributes.GetValue(attacker, AosAttribute.AttackChance);
    1144.  
    1145.          if (DivineFurySpell.UnderEffect(attacker))
    1146.          {
    1147.            bonus += 10; // attacker gets 10% bonus when they're under divine fury
    1148.          }
    1149.  
    1150.          if (CheckAnimal(attacker, typeof(GreyWolf)) || CheckAnimal(attacker, typeof(BakeKitsune)))
    1151.          {
    1152.            bonus += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form
    1153.          }
    1154.  
    1155.          if (HitLower.IsUnderAttackEffect(attacker))
    1156.          {
    1157.            bonus -= 25; // Under Hit Lower Attack effect -> 25% malus
    1158.          }
    1159.  
    1160.          WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker);
    1161.  
    1162.          if (ability != null)
    1163.          {
    1164.            bonus += ability.AccuracyBonus;
    1165.          }
    1166.  
    1167.          SpecialMove move = SpecialMove.GetCurrentMove(attacker);
    1168.  
    1169.          if (move != null)
    1170.          {
    1171.            bonus += move.GetAccuracyBonus(attacker);
    1172.          }
    1173.  
    1174.          // Max Hit Chance Increase = 45%
    1175.          if (bonus > 45)
    1176.          {
    1177.            bonus = 45;
    1178.          }
    1179.  
    1180.          ourValue = (atkValue + 20.0) * (100 + bonus);
    1181.  
    1182.          bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance);
    1183.  
    1184.          if (DivineFurySpell.UnderEffect(defender))
    1185.          {
    1186.            bonus -= 20; // defender loses 20% bonus when they're under divine fury
    1187.          }
    1188.  
    1189.          if (HitLower.IsUnderDefenseEffect(defender))
    1190.          {
    1191.            bonus -= 25; // Under Hit Lower Defense effect -> 25% malus
    1192.          }
    1193.  
    1194.          int blockBonus = 0;
    1195.  
    1196.          if (Block.GetBonus(defender, ref blockBonus))
    1197.          {
    1198.            bonus += blockBonus;
    1199.          }
    1200.  
    1201.          int surpriseMalus = 0;
    1202.  
    1203.          if (SurpriseAttack.GetMalus(defender, ref surpriseMalus))
    1204.          {
    1205.            bonus -= surpriseMalus;
    1206.          }
    1207.  
    1208.          int discordanceEffect = 0;
    1209.  
    1210.          // Defender loses -0/-28% if under the effect of Discordance.
    1211.          if (Discordance.GetEffect(attacker, ref discordanceEffect))
    1212.          {
    1213.            bonus -= discordanceEffect;
    1214.          }
    1215.  
    1216.          // Defense Chance Increase = 45%
    1217.          if (bonus > 45)
    1218.          {
    1219.            bonus = 45;
    1220.          }
    1221.  
    1222.          theirValue = (defValue + 20.0) * (100 + bonus);
    1223.  
    1224.          bonus = 0;
    1225.        }
    1226.        else
    1227.        {
    1228.          if (atkValue <= -50.0)
    1229.          {
    1230.            atkValue = -49.9;
    1231.          }
    1232.  
    1233.          if (defValue <= -50.0)
    1234.          {
    1235.            defValue = -49.9;
    1236.          }
    1237.  
    1238.          ourValue = (atkValue + 50.0);
    1239.          theirValue = (defValue + 50.0);
    1240.        }
    1241.  
    1242.        double chance = ourValue / (theirValue * 2.0);
    1243.  
    1244.        chance *= 1.0 + ((double)bonus / 100);
    1245.  
    1246.        if (Core.AOS && chance < 0.02)
    1247.        {
    1248.          chance = 0.02;
    1249.        }
    1250.  
    1251.        return attacker.CheckSkill(atkSkill.SkillName, chance);
    1252.      }
    1253.  
    1254.      public virtual TimeSpan GetDelay(Mobile m)
    1255.      {
    1256.        double speed = Speed;
    1257.  
    1258.        if (speed == 0)
    1259.        {
    1260.          return TimeSpan.FromHours(1.0);
    1261.        }
    1262.  
    1263.        double delayInSeconds;
    1264.  
    1265.        if (Core.SE)
    1266.        {
    1267.          /*
    1268.   * This is likely true for Core.AOS as well... both guides report the same
    1269.   * formula, and both are wrong.
    1270.   * The old formula left in for AOS for legacy & because we aren't quite 100%
    1271.   * Sure that AOS has THIS formula
    1272.   */
    1273.          int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);
    1274.  
    1275.          if (DivineFurySpell.UnderEffect(m))
    1276.          {
    1277.            bonus += 10;
    1278.          }
    1279.  
    1280.          // Bonus granted by successful use of Honorable Execution.
    1281.          bonus += HonorableExecution.GetSwingBonus(m);
    1282.  
    1283.          if (DualWield.Registry.Contains(m))
    1284.          {
    1285.            bonus += ((DualWield.DualWieldTimer)DualWield.Registry[m]).BonusSwingSpeed;
    1286.          }
    1287.  
    1288.          if (Feint.Registry.Contains(m))
    1289.          {
    1290.            bonus -= ((Feint.FeintTimer)Feint.Registry[m]).SwingSpeedReduction;
    1291.          }
    1292.  
    1293.          TransformContext context = TransformationSpellHelper.GetContext(m);
    1294.  
    1295.          if (context != null && context.Spell is ReaperFormSpell)
    1296.          {
    1297.            bonus += ((ReaperFormSpell)context.Spell).SwingSpeedBonus;
    1298.          }
    1299.  
    1300.          int discordanceEffect = 0;
    1301.  
    1302.          // Discordance gives a malus of -0/-28% to swing speed.
    1303.          if (Discordance.GetEffect(m, ref discordanceEffect))
    1304.          {
    1305.            bonus -= discordanceEffect;
    1306.          }
    1307.  
    1308.          if (EssenceOfWindSpell.IsDebuffed(m))
    1309.          {
    1310.            bonus -= EssenceOfWindSpell.GetSSIMalus(m);
    1311.          }
    1312.  
    1313.          if (bonus > 60)
    1314.          {
    1315.            bonus = 60;
    1316.          }
    1317.  
    1318.          double ticks;
    1319.  
    1320.          if (Core.ML)
    1321.          {
    1322.            int stamTicks = m.Stam / 30;
    1323.  
    1324.            ticks = speed * 4;
    1325.            ticks = Math.Floor((ticks - stamTicks) * (100.0 / (100 + bonus)));
    1326.          }
    1327.          else
    1328.          {
    1329.            speed = Math.Floor(speed * (bonus + 100.0) / 100.0);
    1330.  
    1331.            if (speed <= 0)
    1332.            {
    1333.              speed = 1;
    1334.            }
    1335.  
    1336.            ticks = Math.Floor((80000.0 / ((m.Stam + 100) * speed)) - 2);
    1337.          }
    1338.  
    1339.          // Swing speed currently capped at one swing every 1.25 seconds (5 ticks).
    1340.          if (ticks < 5)
    1341.          {
    1342.            ticks = 5;
    1343.          }
    1344.  
    1345.          delayInSeconds = ticks * 0.25;
    1346.        }
    1347.        else if (Core.AOS)
    1348.        {
    1349.          int v = (m.Stam + 100) * (int)speed;
    1350.  
    1351.          int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed);
    1352.  
    1353.          if (DivineFurySpell.UnderEffect(m))
    1354.          {
    1355.            bonus += 10;
    1356.          }
    1357.  
    1358.          int discordanceEffect = 0;
    1359.  
    1360.          // Discordance gives a malus of -0/-28% to swing speed.
    1361.          if (Discordance.GetEffect(m, ref discordanceEffect))
    1362.          {
    1363.            bonus -= discordanceEffect;
    1364.          }
    1365.  
    1366.          v += AOS.Scale(v, bonus);
    1367.  
    1368.          if (v <= 0)
    1369.          {
    1370.            v = 1;
    1371.          }
    1372.  
    1373.          delayInSeconds = Math.Floor(40000.0 / v) * 0.5;
    1374.  
    1375.          // Maximum swing rate capped at one swing per second
    1376.          // OSI dev said that it has and is supposed to be 1.25
    1377.          if (delayInSeconds < 1.25)
    1378.          {
    1379.            delayInSeconds = 1.25;
    1380.          }
    1381.        }
    1382.        else
    1383.        {
    1384.          int v = (m.Stam + 100) * (int)speed;
    1385.  
    1386.          if (v <= 0)
    1387.          {
    1388.            v = 1;
    1389.          }
    1390.  
    1391.          delayInSeconds = 15000.0 / v;
    1392.        }
    1393.  
    1394.        return TimeSpan.FromSeconds(delayInSeconds);
    1395.      }
    1396.  
    1397.      public virtual void OnBeforeSwing(Mobile attacker, Mobile defender)
    1398.      {
    1399.        WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);
    1400.  
    1401.        if (a != null && !a.OnBeforeSwing(attacker, defender))
    1402.        {
    1403.          WeaponAbility.ClearCurrentAbility(attacker);
    1404.        }
    1405.  
    1406.        SpecialMove move = SpecialMove.GetCurrentMove(attacker);
    1407.  
    1408.        if (move != null && !move.OnBeforeSwing(attacker, defender))
    1409.        {
    1410.          SpecialMove.ClearCurrentMove(attacker);
    1411.        }
    1412.      }
    1413.  
    1414.      public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender)
    1415.      {
    1416.        return OnSwing(attacker, defender, 1.0);
    1417.      }
    1418.  
    1419.      public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus)
    1420.      {
    1421.        bool canSwing = true;
    1422.  
    1423.        if (Core.AOS)
    1424.        {
    1425.          canSwing = (!attacker.Paralyzed && !attacker.Frozen);
    1426.  
    1427.          if (canSwing)
    1428.          {
    1429.            Spell sp = attacker.Spell as Spell;
    1430.  
    1431.            canSwing = (sp == null || !sp.IsCasting || !sp.BlocksMovement);
    1432.          }
    1433.  
    1434.          if (canSwing)
    1435.          {
    1436.            PlayerMobile p = attacker as PlayerMobile;
    1437.  
    1438.            canSwing = (p == null || p.PeacedUntil <= DateTime.UtcNow);
    1439.          }
    1440.        }
    1441.  
    1442.        #region Dueling
    1443.        if (attacker is PlayerMobile)
    1444.        {
    1445.          PlayerMobile pm = (PlayerMobile)attacker;
    1446.  
    1447.          if (pm.DuelContext != null && !pm.DuelContext.CheckItemEquip(attacker, this))
    1448.          {
    1449.            canSwing = false;
    1450.          }
    1451.        }
    1452.        #endregion
    1453.  
    1454.        if (canSwing && attacker.HarmfulCheck(defender))
    1455.        {
    1456.          attacker.DisruptiveAction();
    1457.  
    1458.          if (attacker.NetState != null)
    1459.          {
    1460.            attacker.Send(new Swing(0, attacker, defender));
    1461.          }
    1462.  
    1463.          if (attacker is BaseCreature)
    1464.          {
    1465.            BaseCreature bc = (BaseCreature)attacker;
    1466.            WeaponAbility ab = bc.GetWeaponAbility();
    1467.  
    1468.            if (ab != null)
    1469.            {
    1470.              if (bc.WeaponAbilityChance > Utility.RandomDouble())
    1471.              {
    1472.                WeaponAbility.SetCurrentAbility(bc, ab);
    1473.              }
    1474.              else
    1475.              {
    1476.                WeaponAbility.ClearCurrentAbility(bc);
    1477.              }
    1478.            }
    1479.          }
    1480.  
    1481.          if (CheckHit(attacker, defender))
    1482.          {
    1483.            OnHit(attacker, defender, damageBonus);
    1484.          }
    1485.          else
    1486.          {
    1487.            OnMiss(attacker, defender);
    1488.          }
    1489.        }
    1490.  
    1491.        return GetDelay(attacker);
    1492.      }
    1493.  
    1494.      #region Sounds
    1495.      public virtual int GetHitAttackSound(Mobile attacker, Mobile defender)
    1496.      {
    1497.        int sound = attacker.GetAttackSound();
    1498.  
    1499.        if (sound == -1)
    1500.        {
    1501.          sound = HitSound;
    1502.        }
    1503.  
    1504.        return sound;
    1505.      }
    1506.  
    1507.      public virtual int GetHitDefendSound(Mobile attacker, Mobile defender)
    1508.      {
    1509.        return defender.GetHurtSound();
    1510.      }
    1511.  
    1512.      public virtual int GetMissAttackSound(Mobile attacker, Mobile defender)
    1513.      {
    1514.        if (attacker.GetAttackSound() == -1)
    1515.        {
    1516.          return MissSound;
    1517.        }
    1518.        else
    1519.        {
    1520.          return -1;
    1521.        }
    1522.      }
    1523.  
    1524.      public virtual int GetMissDefendSound(Mobile attacker, Mobile defender)
    1525.      {
    1526.        return -1;
    1527.      }
    1528.      #endregion
    1529.  
    1530.      public static bool CheckParry(Mobile defender)
    1531.      {
    1532.        if (defender == null)
    1533.        {
    1534.          return false;
    1535.        }
    1536.  
    1537.        BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
    1538.  
    1539.        double parry = defender.Skills[SkillName.Parry].Value;
    1540.        double bushidoNonRacial = defender.Skills[SkillName.Bushido].NonRacialValue;
    1541.        double bushido = defender.Skills[SkillName.Bushido].Value;
    1542.  
    1543.        if (shield != null)
    1544.        {
    1545.          double chance = (parry - bushidoNonRacial) / 400.0;
    1546.            // As per OSI, no negitive effect from the Racial stuffs, ie, 120 parry and '0' bushido with humans
    1547.  
    1548.          if (chance < 0) // chance shouldn't go below 0
    1549.          {
    1550.            chance = 0;
    1551.          }
    1552.  
    1553.          // Parry/Bushido over 100 grants a 5% bonus.
    1554.          if (parry >= 100.0 || bushido >= 100.0)
    1555.          {
    1556.            chance += 0.05;
    1557.          }
    1558.  
    1559.          // Evasion grants a variable bonus post ML. 50% prior.
    1560.          if (Evasion.IsEvading(defender))
    1561.          {
    1562.            chance *= Evasion.GetParryScalar(defender);
    1563.          }
    1564.  
    1565.          // Low dexterity lowers the chance.
    1566.          if (defender.Dex < 80)
    1567.          {
    1568.            chance = chance * (20 + defender.Dex) / 100;
    1569.          }
    1570.  
    1571.          return defender.CheckSkill(SkillName.Parry, chance);
    1572.        }
    1573.        else if (!(defender.Weapon is Fists) && !(defender.Weapon is BaseRanged))
    1574.        {
    1575.          BaseWeapon weapon = defender.Weapon as BaseWeapon;
    1576.  
    1577.          double divisor = (weapon.Layer == Layer.OneHanded) ? 48000.0 : 41140.0;
    1578.  
    1579.          double chance = (parry * bushido) / divisor;
    1580.  
    1581.          double aosChance = parry / 800.0;
    1582.  
    1583.          // Parry or Bushido over 100 grant a 5% bonus.
    1584.          if (parry >= 100.0)
    1585.          {
    1586.            chance += 0.05;
    1587.            aosChance += 0.05;
    1588.          }
    1589.          else if (bushido >= 100.0)
    1590.          {
    1591.            chance += 0.05;
    1592.          }
    1593.  
    1594.          // Evasion grants a variable bonus post ML. 50% prior.
    1595.          if (Evasion.IsEvading(defender))
    1596.          {
    1597.            chance *= Evasion.GetParryScalar(defender);
    1598.          }
    1599.  
    1600.          // Low dexterity lowers the chance.
    1601.          if (defender.Dex < 80)
    1602.          {
    1603.            chance = chance * (20 + defender.Dex) / 100;
    1604.          }
    1605.  
    1606.          if (chance > aosChance)
    1607.          {
    1608.            return defender.CheckSkill(SkillName.Parry, chance);
    1609.          }
    1610.          else
    1611.          {
    1612.            return (aosChance > Utility.RandomDouble());
    1613.              // Only skillcheck if wielding a shield & there's no effect from Bushido
    1614.          }
    1615.        }
    1616.  
    1617.        return false;
    1618.      }
    1619.  
    1620.      public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage)
    1621.      {
    1622.        int originalDamage = damage;
    1623.  
    1624.        bool blocked = false;
    1625.  
    1626.        if (defender.Player || defender.Body.IsHuman)
    1627.        {
    1628.          blocked = CheckParry(defender);
    1629.  
    1630.          if (blocked)
    1631.          {
    1632.            defender.FixedEffect(0x37B9, 10, 16);
    1633.            damage = 0;
    1634.  
    1635.            // Successful block removes the Honorable Execution penalty.
    1636.            HonorableExecution.RemovePenalty(defender);
    1637.  
    1638.            if (CounterAttack.IsCountering(defender))
    1639.            {
    1640.              BaseWeapon weapon = defender.Weapon as BaseWeapon;
    1641.  
    1642.              if (weapon != null)
    1643.              {
    1644.                defender.FixedParticles(0x3779, 1, 15, 0x158B, 0x0, 0x3, EffectLayer.Waist);
    1645.                weapon.OnSwing(defender, attacker);
    1646.              }
    1647.  
    1648.              CounterAttack.StopCountering(defender);
    1649.            }
    1650.  
    1651.            if (Confidence.IsConfident(defender))
    1652.            {
    1653.              defender.SendLocalizedMessage(1063117);
    1654.                // Your confidence reassures you as you successfully block your opponent's blow.
    1655.  
    1656.              double bushido = defender.Skills.Bushido.Value;
    1657.  
    1658.              defender.Hits += Utility.RandomMinMax(1, (int)(bushido / 12));
    1659.              defender.Stam += Utility.RandomMinMax(1, (int)(bushido / 5));
    1660.            }
    1661.  
    1662.            BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
    1663.  
    1664.            if (shield != null)
    1665.            {
    1666.              shield.OnHit(this, damage);
    1667.  
    1668.              XmlAttach.OnArmorHit(attacker, defender, shield, this, originalDamage);
    1669.            }
    1670.          }
    1671.        }
    1672.  
    1673.        if (!blocked)
    1674.        {
    1675.          double positionChance = Utility.RandomDouble();
    1676.  
    1677.          Item armorItem;
    1678.  
    1679.          if (positionChance < 0.07)
    1680.          {
    1681.            armorItem = defender.NeckArmor;
    1682.          }
    1683.          else if (positionChance < 0.14)
    1684.          {
    1685.            armorItem = defender.HandArmor;
    1686.          }
    1687.          else if (positionChance < 0.28)
    1688.          {
    1689.            armorItem = defender.ArmsArmor;
    1690.          }
    1691.          else if (positionChance < 0.43)
    1692.          {
    1693.            armorItem = defender.HeadArmor;
    1694.          }
    1695.          else if (positionChance < 0.65)
    1696.          {
    1697.            armorItem = defender.LegsArmor;
    1698.          }
    1699.          else
    1700.          {
    1701.            armorItem = defender.ChestArmor;
    1702.          }
    1703.  
    1704.          IWearableDurability armor = armorItem as IWearableDurability;
    1705.  
    1706.          if (armor != null)
    1707.          {
    1708.            armor.OnHit(this, damage); // call OnHit to lose durability
    1709.            damage -= XmlAttach.OnArmorHit(attacker, defender, armorItem, this, originalDamage);
    1710.          }
    1711.        }
    1712.  
    1713.        return damage;
    1714.      }
    1715.  
    1716.      public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage)
    1717.      {
    1718.        if (Core.AOS)
    1719.        {
    1720.          return AbsorbDamageAOS(attacker, defender, damage);
    1721.        }
    1722.  
    1723.        BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield;
    1724.        if (shield != null)
    1725.        {
    1726.          damage = shield.OnHit(this, damage);
    1727.        }
    1728.  
    1729.        double chance = Utility.RandomDouble();
    1730.  
    1731.        Item armorItem;
    1732.  
    1733.        if (chance < 0.07)
    1734.        {
    1735.          armorItem = defender.NeckArmor;
    1736.        }
    1737.        else if (chance < 0.14)
    1738.        {
    1739.          armorItem = defender.HandArmor;
    1740.        }
    1741.        else if (chance < 0.28)
    1742.        {
    1743.          armorItem = defender.ArmsArmor;
    1744.        }
    1745.        else if (chance < 0.43)
    1746.        {
    1747.          armorItem = defender.HeadArmor;
    1748.        }
    1749.        else if (chance < 0.65)
    1750.        {
    1751.          armorItem = defender.LegsArmor;
    1752.        }
    1753.        else
    1754.        {
    1755.          armorItem = defender.ChestArmor;
    1756.        }
    1757.  
    1758.        IWearableDurability armor = armorItem as IWearableDurability;
    1759.  
    1760.        if (armor != null)
    1761.        {
    1762.          damage = armor.OnHit(this, damage);
    1763.        }
    1764.  
    1765.        int virtualArmor = defender.VirtualArmor + defender.VirtualArmorMod;
    1766.  
    1767.        damage -= XmlAttach.OnArmorHit(attacker, defender, armorItem, this, damage);
    1768.        damage -= XmlAttach.OnArmorHit(attacker, defender, shield, this, damage);
    1769.  
    1770.        if (virtualArmor > 0)
    1771.        {
    1772.          double scalar;
    1773.  
    1774.          if (chance < 0.14)
    1775.          {
    1776.            scalar = 0.07;
    1777.          }
    1778.          else if (chance < 0.28)
    1779.          {
    1780.            scalar = 0.14;
    1781.          }
    1782.          else if (chance < 0.43)
    1783.          {
    1784.            scalar = 0.15;
    1785.          }
    1786.          else if (chance < 0.65)
    1787.          {
    1788.            scalar = 0.22;
    1789.          }
    1790.          else
    1791.          {
    1792.            scalar = 0.35;
    1793.          }
    1794.  
    1795.          int from = (int)(virtualArmor * scalar) / 2;
    1796.          int to = (int)(virtualArmor * scalar);
    1797.  
    1798.          damage -= Utility.Random(from, (to - from) + 1);
    1799.        }
    1800.  
    1801.        return damage;
    1802.      }
    1803.  
    1804.      public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender)
    1805.      {
    1806.        if (attacker.Player || defender.Player)
    1807.        {
    1808.          return 0;
    1809.        }
    1810.  
    1811.        BaseCreature bc = attacker as BaseCreature;
    1812.  
    1813.        if (bc == null || bc.PackInstinct == PackInstinct.None || (!bc.Controlled && !bc.Summoned))
    1814.        {
    1815.          return 0;
    1816.        }
    1817.  
    1818.        Mobile master = bc.ControlMaster;
    1819.  
    1820.        if (master == null)
    1821.        {
    1822.          master = bc.SummonMaster;
    1823.        }
    1824.  
    1825.        if (master == null)
    1826.        {
    1827.          return 0;
    1828.        }
    1829.  
    1830.        int inPack = 1;
    1831.  
    1832.        foreach (Mobile m in defender.GetMobilesInRange(1))
    1833.        {
    1834.          if (m != attacker && m is BaseCreature)
    1835.          {
    1836.            BaseCreature tc = (BaseCreature)m;
    1837.  
    1838.            if ((tc.PackInstinct & bc.PackInstinct) == 0 || (!tc.Controlled && !tc.Summoned))
    1839.            {
    1840.              continue;
    1841.            }
    1842.  
    1843.            Mobile theirMaster = tc.ControlMaster;
    1844.  
    1845.            if (theirMaster == null)
    1846.            {
    1847.              theirMaster = tc.SummonMaster;
    1848.            }
    1849.  
    1850.            if (master == theirMaster && tc.Combatant == defender)
    1851.            {
    1852.              ++inPack;
    1853.            }
    1854.          }
    1855.        }
    1856.  
    1857.        if (inPack >= 5)
    1858.        {
    1859.          return 100;
    1860.        }
    1861.        else if (inPack >= 4)
    1862.        {
    1863.          return 75;
    1864.        }
    1865.        else if (inPack >= 3)
    1866.        {
    1867.          return 50;
    1868.        }
    1869.        else if (inPack >= 2)
    1870.        {
    1871.          return 25;
    1872.        }
    1873.  
    1874.        return 0;
    1875.      }
    1876.  
    1877.      private static bool m_InDoubleStrike;
    1878.  
    1879.      public static bool InDoubleStrike { get { return m_InDoubleStrike; } set { m_InDoubleStrike = value; } }
    1880.  
    1881.      public void OnHit(Mobile attacker, Mobile defender)
    1882.      {
    1883.        OnHit(attacker, defender, 1.0);
    1884.      }
    1885.  
    1886.      public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus)
    1887.      {
    1888.        if (MirrorImage.HasClone(defender) && (defender.Skills.Ninjitsu.Value / 150.0) > Utility.RandomDouble())
    1889.        {
    1890.          Clone bc;
    1891.  
    1892.          foreach (Mobile m in defender.GetMobilesInRange(4))
    1893.          {
    1894.            bc = m as Clone;
    1895.  
    1896.            if (bc != null && bc.Summoned && bc.SummonMaster == defender)
    1897.            {
    1898.              attacker.SendLocalizedMessage(1063141); // Your attack has been diverted to a nearby mirror image of your target!
    1899.              defender.SendLocalizedMessage(1063140); // You manage to divert the attack onto one of your nearby mirror images.
    1900.  
    1901.              /*
    1902.   * TODO: What happens if the Clone parries a blow?
    1903.   * And what about if the attacker is using Honorable Execution
    1904.   * and kills it?
    1905.   */
    1906.  
    1907.              defender = m;
    1908.              break;
    1909.            }
    1910.          }
    1911.        }
    1912.  
    1913.        PlaySwingAnimation(attacker);
    1914.        PlayHurtAnimation(defender);
    1915.  
    1916.        attacker.PlaySound(GetHitAttackSound(attacker, defender));
    1917.        defender.PlaySound(GetHitDefendSound(attacker, defender));
    1918.  
    1919.        int damage = ComputeDamage(attacker, defender);
    1920.  
    1921.        #region Damage Multipliers
    1922.        /*
    1923.   * The following damage bonuses multiply damage by a factor.
    1924.   * Capped at x3 (300%).
    1925.   */
    1926.        int percentageBonus = 0;
    1927.  
    1928.        WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker);
    1929.        SpecialMove move = SpecialMove.GetCurrentMove(attacker);
    1930.  
    1931.        if (a != null)
    1932.        {
    1933.          percentageBonus += (int)(a.DamageScalar * 100) - 100;
    1934.        }
    1935.  
    1936.        if (move != null)
    1937.        {
    1938.          percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100;
    1939.        }
    1940.  
    1941.        percentageBonus += (int)(damageBonus * 100) - 100;
    1942.  
    1943.        CheckSlayerResult cs = CheckSlayers(attacker, defender);
    1944.  
    1945.        if (cs != CheckSlayerResult.None)
    1946.        {
    1947.          if (cs == CheckSlayerResult.Slayer)
    1948.          {
    1949.            defender.FixedEffect(0x37B9, 10, 5);
    1950.          }
    1951.  
    1952.          percentageBonus += 100;
    1953.        }
    1954.  
    1955.        if (!attacker.Player)
    1956.        {
    1957.          if (defender is PlayerMobile)
    1958.          {
    1959.            PlayerMobile pm = (PlayerMobile)defender;
    1960.  
    1961.            if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType())
    1962.            {
    1963.              percentageBonus += 100;
    1964.            }
    1965.          }
    1966.        }
    1967.        else if (!defender.Player)
    1968.        {
    1969.          if (attacker is PlayerMobile)
    1970.          {
    1971.            PlayerMobile pm = (PlayerMobile)attacker;
    1972.  
    1973.            if (pm.WaitingForEnemy)
    1974.            {
    1975.              pm.EnemyOfOneType = defender.GetType();
    1976.              pm.WaitingForEnemy = false;
    1977.            }
    1978.  
    1979.            if (pm.EnemyOfOneType == defender.GetType())
    1980.            {
    1981.              defender.FixedEffect(0x37B9, 10, 5, 1160, 0);
    1982.  
    1983.              percentageBonus += 50;
    1984.            }
    1985.          }
    1986.        }
    1987.  
    1988.        int packInstinctBonus = GetPackInstinctBonus(attacker, defender);
    1989.  
    1990.        if (packInstinctBonus != 0)
    1991.        {
    1992.          percentageBonus += packInstinctBonus;
    1993.        }
    1994.  
    1995.        if (m_InDoubleStrike)
    1996.        {
    1997.          percentageBonus -= 10;
    1998.        }
    1999.  
    2000.        TransformContext context = TransformationSpellHelper.GetContext(defender);
    2001.  
    2002.        if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver) && context != null &&
    2003.          context.Spell is NecromancerSpell && context.Type != typeof(HorrificBeastSpell))
    2004.        {
    2005.          // Every necromancer transformation other than horrific beast takes an additional 25% damage
    2006.          percentageBonus += 25;
    2007.        }
    2008.  
    2009.        if (attacker is PlayerMobile && !(Core.ML && defender is PlayerMobile))
    2010.        {
    2011.          PlayerMobile pmAttacker = (PlayerMobile)attacker;
    2012.  
    2013.          if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1))
    2014.          {
    2015.            percentageBonus += 25;
    2016.          }
    2017.  
    2018.          if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender)
    2019.          {
    2020.            percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus;
    2021.          }
    2022.        }
    2023.  
    2024.        #region Stygian Abyss
    2025.        percentageBonus += BattleLust.GetBonus(attacker, defender);
    2026.  
    2027.        if (this is BaseThrown)
    2028.        {
    2029.          int max = ((BaseThrown)this).MaxThrowRange;
    2030.  
    2031.          if (attacker.InRange(defender, max))
    2032.          {
    2033.            percentageBonus += -47;
    2034.          }
    2035.        }
    2036.        #endregion
    2037.  
    2038.        #region Mondain's Legacy
    2039.        if (Core.ML)
    2040.        {
    2041.          BaseTalisman talisman = attacker.Talisman as BaseTalisman;
    2042.  
    2043.          if (talisman != null && talisman.Killer != null)
    2044.          {
    2045.            percentageBonus += talisman.Killer.DamageBonus(defender);
    2046.          }
    2047.  
    2048.          if (this is ButchersWarCleaver)
    2049.          {
    2050.            if (defender is Bull || defender is Cow || defender is Gaman)
    2051.            {
    2052.              percentageBonus += 100;
    2053.            }
    2054.          }
    2055.        }
    2056.        #endregion
    2057.  
    2058.        percentageBonus = Math.Min(percentageBonus, 300);
    2059.  
    2060.        damage = AOS.Scale(damage, 100 + percentageBonus);
    2061.        #endregion
    2062.  
    2063.        if (attacker is BaseCreature)
    2064.        {
    2065.          ((BaseCreature)attacker).AlterMeleeDamageTo(defender, ref damage);
    2066.        }
    2067.  
    2068.        if (defender is BaseCreature)
    2069.        {
    2070.          ((BaseCreature)defender).AlterMeleeDamageFrom(attacker, ref damage);
    2071.        }
    2072.  
    2073.        damage = AbsorbDamage(attacker, defender, damage);
    2074.  
    2075.        if (!Core.AOS && damage < 1)
    2076.        {
    2077.          damage = 1;
    2078.        }
    2079.        else if (Core.AOS && damage == 0) // parried
    2080.        {
    2081.          if (a != null && a.Validate(attacker) /*&& a.CheckMana( attacker, true )*/)
    2082.            // Parried special moves have no mana cost
    2083.          {
    2084.            a = null;
    2085.            WeaponAbility.ClearCurrentAbility(attacker);
    2086.  
    2087.            attacker.SendLocalizedMessage(1061140); // Your attack was parried!
    2088.          }
    2089.  
    2090.          #region Stygian Abyss
    2091.          if (AosArmorAttributes.GetValue(defender, AosArmorAttribute.ReactiveParalyze) > Utility.RandomMinMax(1, 100))
    2092.          {
    2093.            attacker.Paralyze(TimeSpan.FromSeconds(3));
    2094.          }
    2095.          #endregion
    2096.        }
    2097.  
    2098.        #region Mondain's Legacy
    2099.        if (m_Immolating)
    2100.        {
    2101.          int d = ImmolatingWeaponSpell.GetImmolatingDamage(this);
    2102.          d = AOS.Damage(defender, attacker, d, 0, 100, 0, 0, 0);
    2103.  
    2104.          AttuneWeaponSpell.TryAbsorb(defender, ref d);
    2105.  
    2106.          if (d > 0)
    2107.          {
    2108.            defender.Damage(d);
    2109.          }
    2110.        }
    2111.        #endregion
    2112.  
    2113.        AddBlood(attacker, defender, damage);
    2114.  
    2115.        int phys, fire, cold, pois, nrgy, chaos, direct;
    2116.  
    2117.        GetDamageTypes(attacker, out phys, out fire, out cold, out pois, out nrgy, out chaos, out direct);
    2118.  
    2119.        if (Core.ML && this is BaseRanged)
    2120.        {
    2121.          BaseQuiver quiver = attacker.FindItemOnLayer(Layer.Cloak) as BaseQuiver;
    2122.  
    2123.          if (quiver != null)
    2124.          {
    2125.            quiver.AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct);
    2126.          }
    2127.        }
    2128.  
    2129.        if (m_Consecrated)
    2130.        {
    2131.          phys = defender.PhysicalResistance;
    2132.          fire = defender.FireResistance;
    2133.          cold = defender.ColdResistance;
    2134.          pois = defender.PoisonResistance;
    2135.          nrgy = defender.EnergyResistance;
    2136.  
    2137.          int low = phys, type = 0;
    2138.  
    2139.          if (fire < low)
    2140.          {
    2141.            low = fire;
    2142.            type = 1;
    2143.          }
    2144.          if (cold < low)
    2145.          {
    2146.            low = cold;
    2147.            type = 2;
    2148.          }
    2149.          if (pois < low)
    2150.          {
    2151.            low = pois;
    2152.            type = 3;
    2153.          }
    2154.          if (nrgy < low)
    2155.          {
    2156.            low = nrgy;
    2157.            type = 4;
    2158.          }
    2159.  
    2160.          phys = fire = cold = pois = nrgy = chaos = direct = 0;
    2161.  
    2162.          if (type == 0)
    2163.          {
    2164.            phys = 100;
    2165.          }
    2166.          else if (type == 1)
    2167.          {
    2168.            fire = 100;
    2169.          }
    2170.          else if (type == 2)
    2171.          {
    2172.            cold = 100;
    2173.          }
    2174.          else if (type == 3)
    2175.          {
    2176.            pois = 100;
    2177.          }
    2178.          else if (type == 4)
    2179.          {
    2180.            nrgy = 100;
    2181.          }
    2182.        }
    2183.  
    2184.        // TODO: Scale damage, alongside the leech effects below, to weapon speed.
    2185.        if (ImmolatingWeaponSpell.IsImmolating(this) && damage > 0)
    2186.        {
    2187.          ImmolatingWeaponSpell.DoEffect(this, defender);
    2188.        }
    2189.  
    2190.        int damageGiven = damage;
    2191.  
    2192.        if (a != null && !a.OnBeforeDamage(attacker, defender))
    2193.        {
    2194.          WeaponAbility.ClearCurrentAbility(attacker);
    2195.          a = null;
    2196.        }
    2197.  
    2198.        if (move != null && !move.OnBeforeDamage(attacker, defender))
    2199.        {
    2200.          SpecialMove.ClearCurrentMove(attacker);
    2201.          move = null;
    2202.        }
    2203.  
    2204.        bool ignoreArmor = (a is ArmorIgnore || (move != null && move.IgnoreArmor(attacker)));
    2205.  
    2206.        damageGiven = AOS.Damage(
    2207.          defender,
    2208.          attacker,
    2209.          damage,
    2210.          ignoreArmor,
    2211.          phys,
    2212.          fire,
    2213.          cold,
    2214.          pois,
    2215.          nrgy,
    2216.          chaos,
    2217.          direct,
    2218.          false,
    2219.          this is BaseRanged,
    2220.          false);
    2221.  
    2222.        double propertyBonus = (move == null) ? 1.0 : move.GetPropertyBonus(attacker);
    2223.  
    2224.        if (Core.AOS)
    2225.        {
    2226.          int lifeLeech = 0;
    2227.          int stamLeech = 0;
    2228.          int manaLeech = 0;
    2229.          int wraithLeech = 0;
    2230.  
    2231.          if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) >
    2232.            Utility.Random(100))
    2233.          {
    2234.            lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points
    2235.          }
    2236.  
    2237.          if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) >
    2238.            Utility.Random(100))
    2239.          {
    2240.            stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina
    2241.          }
    2242.  
    2243.          if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) >
    2244.            Utility.Random(100))
    2245.          {
    2246.            manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana
    2247.          }
    2248.  
    2249.          if (m_Cursed)
    2250.          {
    2251.            lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell)
    2252.          }
    2253.  
    2254.          context = TransformationSpellHelper.GetContext(attacker);
    2255.  
    2256.          if (context != null && context.Type == typeof(VampiricEmbraceSpell))
    2257.          {
    2258.            lifeLeech += 20; // Vampiric embrace gives an additional 20% life leech
    2259.          }
    2260.  
    2261.          if (context != null && context.Type == typeof(WraithFormSpell))
    2262.          {
    2263.            wraithLeech = (5 + (int)((15 * attacker.Skills.SpiritSpeak.Value) / 100));
    2264.              // Wraith form gives an additional 5-20% mana leech
    2265.  
    2266.            // Mana leeched by the Wraith Form spell is actually stolen, not just leeched.
    2267.            defender.Mana -= AOS.Scale(damageGiven, wraithLeech);
    2268.  
    2269.            manaLeech += wraithLeech;
    2270.          }
    2271.  
    2272.          if (lifeLeech != 0)
    2273.          {
    2274.            attacker.Hits += AOS.Scale(damageGiven, lifeLeech);
    2275.          }
    2276.  
    2277.          if (stamLeech != 0)
    2278.          {
    2279.            attacker.Stam += AOS.Scale(damageGiven, stamLeech);
    2280.          }
    2281.  
    2282.          if (manaLeech != 0)
    2283.          {
    2284.            attacker.Mana += AOS.Scale(damageGiven, manaLeech);
    2285.          }
    2286.  
    2287.          if (lifeLeech != 0 || stamLeech != 0 || manaLeech != 0)
    2288.          {
    2289.            attacker.PlaySound(0x44D);
    2290.          }
    2291.        }
    2292.  
    2293.        if (m_MaxHits > 0 &&
    2294.          ((MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime)) ||
    2295.           Utility.Random(25) == 0)) // Stratics says 50% chance, seems more like 4%..
    2296.        {
    2297.          if (MaxRange <= 1 && (defender is Slime || defender is ToxicElemental || defender is CorrosiveSlime))
    2298.          {
    2299.            attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!*
    2300.          }
    2301.  
    2302.          if (Core.AOS &&
    2303.            m_AosWeaponAttributes.SelfRepair + (IsSetItem && m_SetEquipped ? m_SetSelfRepair : 0) > Utility.Random(10))
    2304.          {
    2305.            HitPoints += 2;
    2306.          }
    2307.          else
    2308.          {
    2309.            if (m_Hits > 0)
    2310.            {
    2311.              --HitPoints;
    2312.            }
    2313.            else if (m_MaxHits > 1)
    2314.            {
    2315.              --MaxHitPoints;
    2316.  
    2317.              if (Parent is Mobile)
    2318.              {
    2319.                ((Mobile)Parent).LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121);
    2320.                  // Your equipment is severely damaged.
    2321.              }
    2322.            }
    2323.            else
    2324.            {
    2325.              Delete();
    2326.            }
    2327.          }
    2328.        }
    2329.  
    2330.        if (attacker is VampireBatFamiliar)
    2331.        {
    2332.          BaseCreature bc = (BaseCreature)attacker;
    2333.          Mobile caster = bc.ControlMaster;
    2334.  
    2335.          if (caster == null)
    2336.          {
    2337.            caster = bc.SummonMaster;
    2338.          }
    2339.  
    2340.          if (caster != null && caster.Map == bc.Map && caster.InRange(bc, 2))
    2341.          {
    2342.            caster.Hits += damage;
    2343.          }
    2344.          else
    2345.          {
    2346.            bc.Hits += damage;
    2347.          }
    2348.        }
    2349.  
    2350.        if (Core.AOS)
    2351.        {
    2352.          int physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * propertyBonus);
    2353.          int fireChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus);
    2354.          int coldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus);
    2355.          int poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * propertyBonus);
    2356.          int nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * propertyBonus);
    2357.  
    2358.          if (physChance != 0 && physChance > Utility.Random(100))
    2359.          {
    2360.            DoAreaAttack(attacker, defender, 0x10E, 50, 100, 0, 0, 0, 0);
    2361.          }
    2362.  
    2363.          if (fireChance != 0 && fireChance > Utility.Random(100))
    2364.          {
    2365.            DoAreaAttack(attacker, defender, 0x11D, 1160, 0, 100, 0, 0, 0);
    2366.          }
    2367.  
    2368.          if (coldChance != 0 && coldChance > Utility.Random(100))
    2369.          {
    2370.            DoAreaAttack(attacker, defender, 0x0FC, 2100, 0, 0, 100, 0, 0);
    2371.          }
    2372.  
    2373.          if (poisChance != 0 && poisChance > Utility.Random(100))
    2374.          {
    2375.            DoAreaAttack(attacker, defender, 0x205, 1166, 0, 0, 0, 100, 0);
    2376.          }
    2377.  
    2378.          if (nrgyChance != 0 && nrgyChance > Utility.Random(100))
    2379.          {
    2380.            DoAreaAttack(attacker, defender, 0x1F1, 120, 0, 0, 0, 0, 100);
    2381.          }
    2382.  
    2383.          int maChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus);
    2384.          int harmChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitHarm) * propertyBonus);
    2385.          int fireballChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireball) * propertyBonus);
    2386.          int lightningChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLightning) * propertyBonus);
    2387.          int dispelChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus);
    2388.  
    2389.          #region Stygian Abyss
    2390.          int curseChance = (int)(m_AosWeaponAttributes.HitCurse * propertyBonus);
    2391.          int fatigueChance = (int)(m_AosWeaponAttributes.HitFatigue * propertyBonus);
    2392.          int manadrainChance = (int)(m_AosWeaponAttributes.HitManaDrain * propertyBonus);
    2393.          #endregion
    2394.  
    2395.          if (maChance != 0 && maChance > Utility.Random(100))
    2396.          {
    2397.            DoMagicArrow(attacker, defender);
    2398.          }
    2399.  
    2400.          if (harmChance != 0 && harmChance > Utility.Random(100))
    2401.          {
    2402.            DoHarm(attacker, defender);
    2403.          }
    2404.  
    2405.          if (fireballChance != 0 && fireballChance > Utility.Random(100))
    2406.          {
    2407.            DoFireball(attacker, defender);
    2408.          }
    2409.  
    2410.          if (lightningChance != 0 && lightningChance > Utility.Random(100))
    2411.          {
    2412.            DoLightning(attacker, defender);
    2413.          }
    2414.  
    2415.          if (dispelChance != 0 && dispelChance > Utility.Random(100))
    2416.          {
    2417.            DoDispel(attacker, defender);
    2418.          }
    2419.  
    2420.          #region Stygian Abyss
    2421.          if (curseChance != 0 && curseChance > Utility.Random(100))
    2422.          {
    2423.            DoCurse(attacker, defender);
    2424.          }
    2425.  
    2426.          if (fatigueChance != 0 && fatigueChance > Utility.Random(100))
    2427.          {
    2428.            DoFatigue(attacker, defender, damageGiven);
    2429.          }
    2430.  
    2431.          if (manadrainChance != 0 && manadrainChance > Utility.Random(100))
    2432.          {
    2433.            DoManaDrain(attacker, defender, damageGiven);
    2434.          }
    2435.          #endregion
    2436.  
    2437.          int laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * propertyBonus);
    2438.          int ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * propertyBonus);
    2439.  
    2440.          if (laChance != 0 && laChance > Utility.Random(100))
    2441.          {
    2442.            DoLowerAttack(attacker, defender);
    2443.          }
    2444.  
    2445.          if (ldChance != 0 && ldChance > Utility.Random(100))
    2446.          {
    2447.            DoLowerDefense(attacker, defender);
    2448.          }
    2449.        }
    2450.  
    2451.        if (attacker is BaseCreature)
    2452.        {
    2453.          ((BaseCreature)attacker).OnGaveMeleeAttack(defender);
    2454.        }
    2455.  
    2456.        if (defender is BaseCreature)
    2457.        {
    2458.          ((BaseCreature)defender).OnGotMeleeAttack(attacker);
    2459.        }
    2460.  
    2461.        if (a != null)
    2462.        {
    2463.          a.OnHit(attacker, defender, damage);
    2464.        }
    2465.  
    2466.        if (move != null)
    2467.        {
    2468.          move.OnHit(attacker, defender, damage);
    2469.        }
    2470.  
    2471.        if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
    2472.        {
    2473.          ((IHonorTarget)defender).ReceivedHonorContext.OnTargetHit(attacker);
    2474.        }
    2475.  
    2476.        if (!(this is BaseRanged))
    2477.        {
    2478.          if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent)))
    2479.          {
    2480.            defender.ApplyPoison(attacker, Poison.Lesser);
    2481.          }
    2482.  
    2483.          if (AnimalForm.UnderTransformation(defender, typeof(BullFrog)))
    2484.          {
    2485.            attacker.ApplyPoison(defender, Poison.Regular);
    2486.          }
    2487.        }
    2488.  
    2489.        XmlAttach.OnWeaponHit(this, attacker, defender, damageGiven);
    2490.      }
    2491.  
    2492.      public virtual double GetAosDamage(Mobile attacker, int bonus, int dice, int sides)
    2493.      {
    2494.        int damage = Utility.Dice(dice, sides, bonus) * 100;
    2495.        int damageBonus = 0;
    2496.  
    2497.        // Inscription bonus
    2498.        int inscribeSkill = attacker.Skills[SkillName.Inscribe].Fixed;
    2499.  
    2500.        damageBonus += inscribeSkill / 200;
    2501.  
    2502.        if (inscribeSkill >= 1000)
    2503.        {
    2504.          damageBonus += 5;
    2505.        }
    2506.  
    2507.        if (attacker.Player)
    2508.        {
    2509.          // Int bonus
    2510.          damageBonus += (attacker.Int / 10);
    2511.  
    2512.          // SDI bonus
    2513.          damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage);
    2514.  
    2515.          TransformContext context = TransformationSpellHelper.GetContext(attacker);
    2516.  
    2517.          if (context != null && context.Spell is ReaperFormSpell)
    2518.          {
    2519.            damageBonus += ((ReaperFormSpell)context.Spell).SpellDamageBonus;
    2520.          }
    2521.        }
    2522.  
    2523.        damage = AOS.Scale(damage, 100 + damageBonus);
    2524.  
    2525.        return damage / 100;
    2526.      }
    2527.  
    2528.      #region Do<AoSEffect>
    2529.      public virtual void DoMagicArrow(Mobile attacker, Mobile defender)
    2530.      {
    2531.        if (!attacker.CanBeHarmful(defender, false))
    2532.        {
    2533.          return;
    2534.        }
    2535.  
    2536.        attacker.DoHarmful(defender);
    2537.  
    2538.        double damage = GetAosDamage(attacker, 10, 1, 4);
    2539.  
    2540.        attacker.MovingParticles(defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0);
    2541.        attacker.PlaySound(0x1E5);
    2542.  
    2543.        SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0);
    2544.      }
    2545.  
    2546.      public virtual void DoHarm(Mobile attacker, Mobile defender)
    2547.      {
    2548.        if (!attacker.CanBeHarmful(defender, false))
    2549.        {
    2550.          return;
    2551.        }
    2552.  
    2553.        attacker.DoHarmful(defender);
    2554.  
    2555.        double damage = GetAosDamage(attacker, 17, 1, 5);
    2556.  
    2557.        if (!defender.InRange(attacker, 2))
    2558.        {
    2559.          damage *= 0.25; // 1/4 damage at > 2 tile range
    2560.        }
    2561.        else if (!defender.InRange(attacker, 1))
    2562.        {
    2563.          damage *= 0.50; // 1/2 damage at 2 tile range
    2564.        }
    2565.  
    2566.        defender.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist);
    2567.        defender.PlaySound(0x0FC);
    2568.  
    2569.        SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 100, 0, 0);
    2570.      }
    2571.  
    2572.      public virtual void DoFireball(Mobile attacker, Mobile defender)
    2573.      {
    2574.        if (!attacker.CanBeHarmful(defender, false))
    2575.        {
    2576.          return;
    2577.        }
    2578.  
    2579.        attacker.DoHarmful(defender);
    2580.  
    2581.        double damage = GetAosDamage(attacker, 19, 1, 5);
    2582.  
    2583.        attacker.MovingParticles(defender, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160);
    2584.        attacker.PlaySound(0x15E);
    2585.  
    2586.        SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0);
    2587.      }
    2588.  
    2589.      public virtual void DoLightning(Mobile attacker, Mobile defender)
    2590.      {
    2591.        if (!attacker.CanBeHarmful(defender, false))
    2592.        {
    2593.          return;
    2594.        }
    2595.  
    2596.        attacker.DoHarmful(defender);
    2597.  
    2598.        double damage = GetAosDamage(attacker, 23, 1, 4);
    2599.  
    2600.        defender.BoltEffect(0);
    2601.  
    2602.        SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 0, 0, 100);
    2603.      }
    2604.  
    2605.      public virtual void DoDispel(Mobile attacker, Mobile defender)
    2606.      {
    2607.        bool dispellable = false;
    2608.  
    2609.        if (defender is BaseCreature)
    2610.        {
    2611.          dispellable = ((BaseCreature)defender).Summoned && !((BaseCreature)defender).IsAnimatedDead;
    2612.        }
    2613.  
    2614.        if (!dispellable)
    2615.        {
    2616.          return;
    2617.        }
    2618.  
    2619.        if (!attacker.CanBeHarmful(defender, false))
    2620.        {
    2621.          return;
    2622.        }
    2623.  
    2624.        attacker.DoHarmful(defender);
    2625.  
    2626.        MagerySpell sp = new DispelSpell(attacker, null);
    2627.  
    2628.        if (sp.CheckResisted(defender))
    2629.        {
    2630.          defender.FixedEffect(0x3779, 10, 20);
    2631.        }
    2632.        else
    2633.        {
    2634.          Effects.SendLocationParticles(
    2635.            EffectItem.Create(defender.Location, defender.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
    2636.          Effects.PlaySound(defender, defender.Map, 0x201);
    2637.  
    2638.          defender.Delete();
    2639.        }
    2640.      }
    2641.  
    2642.      #region Stygian Abyss
    2643.      public virtual void DoCurse(Mobile attacker, Mobile defender)
    2644.      {
    2645.        attacker.SendLocalizedMessage(1113717); // You have hit your target with a curse effect.
    2646.        defender.SendLocalizedMessage(1113718); // You have been hit with a curse effect.
    2647.        defender.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist);
    2648.        defender.PlaySound(0x1EA);
    2649.        defender.AddStatMod(
    2650.          new StatMod(StatType.Str, String.Format("[Magic] {0} Offset", StatType.Str), -10, TimeSpan.FromSeconds(30)));
    2651.        defender.AddStatMod(
    2652.          new StatMod(StatType.Dex, String.Format("[Magic] {0} Offset", StatType.Dex), -10, TimeSpan.FromSeconds(30)));
    2653.        defender.AddStatMod(
    2654.          new StatMod(StatType.Int, String.Format("[Magic] {0} Offset", StatType.Int), -10, TimeSpan.FromSeconds(30)));
    2655.  
    2656.        int percentage = -10; //(int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100);
    2657.        string args = String.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", percentage, percentage, percentage, 10, 10, 10, 10);
    2658.  
    2659.        BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, TimeSpan.FromSeconds(30), defender, args));
    2660.      }
    2661.  
    2662.      public virtual void DoFatigue(Mobile attacker, Mobile defender, int damagegiven)
    2663.      {
    2664.        // Message?
    2665.        // Effects?
    2666.        defender.Stam -= (damagegiven * (100 - m_AosWeaponAttributes.HitFatigue)) / 100;
    2667.      }
    2668.  
    2669.      public virtual void DoManaDrain(Mobile attacker, Mobile defender, int damagegiven)
    2670.      {
    2671.        // Message?
    2672.        defender.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head);
    2673.        defender.PlaySound(0x1F8);
    2674.        defender.Mana -= (damagegiven * (100 - m_AosWeaponAttributes.HitManaDrain)) / 100;
    2675.      }
    2676.      #endregion
    2677.  
    2678.      public virtual void DoLowerAttack(Mobile from, Mobile defender)
    2679.      {
    2680.        if (HitLower.ApplyAttack(defender))
    2681.        {
    2682.          defender.PlaySound(0x28E);
    2683.          Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0xA, 3);
    2684.        }
    2685.      }
    2686.  
    2687.      public virtual void DoLowerDefense(Mobile from, Mobile defender)
    2688.      {
    2689.        if (HitLower.ApplyDefense(defender))
    2690.        {
    2691.          defender.PlaySound(0x28E);
    2692.          Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0x23, 3);
    2693.        }
    2694.      }
    2695.  
    2696.      public virtual void DoAreaAttack(
    2697.        Mobile from, Mobile defender, int sound, int hue, int phys, int fire, int cold, int pois, int nrgy)
    2698.      {
    2699.        Map map = from.Map;
    2700.  
    2701.        if (map == null)
    2702.        {
    2703.          return;
    2704.        }
    2705.  
    2706.        var list = new List<Mobile>();
    2707.  
    2708.        foreach (Mobile m in from.GetMobilesInRange(10))
    2709.        {
    2710.          if (from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m) && from.CanBeHarmful(m, false) &&
    2711.            (!Core.ML || from.InLOS(m)))
    2712.          {
    2713.            list.Add(m);
    2714.          }
    2715.        }
    2716.  
    2717.        if (list.Count == 0)
    2718.        {
    2719.          return;
    2720.        }
    2721.  
    2722.        Effects.PlaySound(from.Location, map, sound);
    2723.  
    2724.        // TODO: What is the damage calculation?
    2725.  
    2726.        for (int i = 0; i < list.Count; ++i)
    2727.        {
    2728.          Mobile m = list[i];
    2729.  
    2730.          double scalar = (11 - from.GetDistanceToSqrt(m)) / 10;
    2731.  
    2732.          if (scalar > 1.0)
    2733.          {
    2734.            scalar = 1.0;
    2735.          }
    2736.          else if (scalar < 0.0)
    2737.          {
    2738.            continue;
    2739.          }
    2740.  
    2741.          from.DoHarmful(m, true);
    2742.          m.FixedEffect(0x3779, 1, 15, hue, 0);
    2743.          AOS.Damage(m, from, (int)(GetBaseDamage(from) * scalar), phys, fire, cold, pois, nrgy);
    2744.        }
    2745.      }
    2746.      #endregion
    2747.  
    2748.      public virtual CheckSlayerResult CheckSlayers(Mobile attacker, Mobile defender)
    2749.      {
    2750.        BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon;
    2751.        SlayerEntry atkSlayer = SlayerGroup.GetEntryByName(atkWeapon.Slayer);
    2752.        SlayerEntry atkSlayer2 = SlayerGroup.GetEntryByName(atkWeapon.Slayer2);
    2753.  
    2754.   if (atkSlayer != null && atkSlayer.Slays(defender) || atkSlayer2 != null && atkSlayer2.Slays(defender))
    2755.        {
    2756.          return CheckSlayerResult.Slayer;
    2757.        }
    2758.  
    2759.        BaseTalisman talisman = attacker.Talisman as BaseTalisman;
    2760.  
    2761.        if (talisman != null && TalismanSlayer.Slays(talisman.Slayer, defender))
    2762.        {
    2763.          return CheckSlayerResult.Slayer;
    2764.        }
    2765.  
    2766.        if (!Core.SE)
    2767.        {
    2768.          ISlayer defISlayer = Spellbook.FindEquippedSpellbook(defender);
    2769.  
    2770.          if (defISlayer == null)
    2771.          {
    2772.            defISlayer = defender.Weapon as ISlayer;
    2773.          }
    2774.  
    2775.          if (defISlayer != null)
    2776.          {
    2777.            SlayerEntry defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer);
    2778.            SlayerEntry defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2);
    2779.  
    2780.            if (defSlayer != null && defSlayer.Group.OppositionSuperSlays(attacker) ||
    2781.              defSlayer2 != null && defSlayer2.Group.OppositionSuperSlays(attacker))
    2782.            {
    2783.              return CheckSlayerResult.Opposition;
    2784.            }
    2785.          }
    2786.        }
    2787.  
    2788.        return CheckSlayerResult.None;
    2789.      }
    2790.  
    2791.      public virtual void AddBlood(Mobile attacker, Mobile defender, int damage)
    2792.      {
    2793.        if (damage > 0)
    2794.        {
    2795.          new Blood().MoveToWorld(defender.Location, defender.Map);
    2796.  
    2797.          int extraBlood = (Core.SE ? Utility.RandomMinMax(3, 4) : Utility.RandomMinMax(0, 1));
    2798.  
    2799.          for (int i = 0; i < extraBlood; i++)
    2800.          {
    2801.            new Blood().MoveToWorld(
    2802.              new Point3D(defender.X + Utility.RandomMinMax(-1, 1), defender.Y + Utility.RandomMinMax(-1, 1), defender.Z),
    2803.              defender.Map);
    2804.          }
    2805.        }
    2806.      }
    2807.  
    2808.      public virtual void GetDamageTypes(
    2809.        Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct)
    2810.      {
    2811.        if (wielder is BaseCreature)
    2812.        {
    2813.          BaseCreature bc = (BaseCreature)wielder;
    2814.  
    2815.          phys = bc.PhysicalDamage;
    2816.          fire = bc.FireDamage;
    2817.          cold = bc.ColdDamage;
    2818.          pois = bc.PoisonDamage;
    2819.          nrgy = bc.EnergyDamage;
    2820.          chaos = bc.ChaosDamage;
    2821.          direct = bc.DirectDamage;
    2822.        }
    2823.        else
    2824.        {
    2825.          fire = m_AosElementDamages.Fire;
    2826.          cold = m_AosElementDamages.Cold;
    2827.          pois = m_AosElementDamages.Poison;
    2828.          nrgy = m_AosElementDamages.Energy;
    2829.          chaos = m_AosElementDamages.Chaos;
    2830.          direct = m_AosElementDamages.Direct;
    2831.  
    2832.          phys = 100 - fire - cold - pois - nrgy - chaos - direct;
    2833.  
    2834.          CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource);
    2835.  
    2836.          if (resInfo != null)
    2837.          {
    2838.            CraftAttributeInfo attrInfo = resInfo.AttributeInfo;
    2839.  
    2840.            if (attrInfo != null)
    2841.            {
    2842.              int left = phys;
    2843.  
    2844.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponColdDamage, ref cold, left);
    2845.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponEnergyDamage, ref nrgy, left);
    2846.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponFireDamage, ref fire, left);
    2847.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponPoisonDamage, ref pois, left);
    2848.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponChaosDamage, ref chaos, left);
    2849.              left = ApplyCraftAttributeElementDamage(attrInfo.WeaponDirectDamage, ref direct, left);
    2850.  
    2851.              phys = left;
    2852.            }
    2853.          }
    2854.        }
    2855.      }
    2856.  
    2857.      private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining)
    2858.      {
    2859.        if (totalRemaining <= 0)
    2860.        {
    2861.          return 0;
    2862.        }
    2863.  
    2864.        if (attrDamage <= 0)
    2865.        {
    2866.          return totalRemaining;
    2867.        }
    2868.  
    2869.        int appliedDamage = attrDamage;
    2870.  
    2871.        if ((appliedDamage + element) > 100)
    2872.        {
    2873.          appliedDamage = 100 - element;
    2874.        }
    2875.  
    2876.        if (appliedDamage > totalRemaining)
    2877.        {
    2878.          appliedDamage = totalRemaining;
    2879.        }
    2880.  
    2881.        element += appliedDamage;
    2882.  
    2883.        return totalRemaining - appliedDamage;
    2884.      }
    2885.  
    2886.      public virtual void OnMiss(Mobile attacker, Mobile defender)
    2887.      {
    2888.        PlaySwingAnimation(attacker);
    2889.        attacker.PlaySound(GetMissAttackSound(attacker, defender));
    2890.        defender.PlaySound(GetMissDefendSound(attacker, defender));
    2891.  
    2892.        WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker);
    2893.  
    2894.        if (ability != null)
    2895.        {
    2896.          ability.OnMiss(attacker, defender);
    2897.        }
    2898.  
    2899.        SpecialMove move = SpecialMove.GetCurrentMove(attacker);
    2900.  
    2901.        if (move != null)
    2902.        {
    2903.          move.OnMiss(attacker, defender);
    2904.        }
    2905.  
    2906.        if (defender is IHonorTarget && ((IHonorTarget)defender).ReceivedHonorContext != null)
    2907.        {
    2908.          ((IHonorTarget)defender).ReceivedHonorContext.OnTargetMissed(attacker);
    2909.        }
    2910.      }
    2911.  
    2912.      public virtual void GetBaseDamageRange(Mobile attacker, out int min, out int max)
    2913.      {
    2914.        if (attacker is BaseCreature)
    2915.        {
    2916.          BaseCreature c = (BaseCreature)attacker;
    2917.  
    2918.          if (c.DamageMin >= 0)
    2919.          {
    2920.            min = c.DamageMin;
    2921.            max = c.DamageMax;
    2922.            return;
    2923.          }
    2924.  
    2925.          if (this is Fists && !attacker.Body.IsHuman)
    2926.          {
    2927.            min = attacker.Str / 28;
    2928.            max = attacker.Str / 28;
    2929.            return;
    2930.          }
    2931.        }
    2932.  
    2933.        min = MinDamage;
    2934.        max = MaxDamage;
    2935.      }
    2936.  
    2937.      public virtual double GetBaseDamage(Mobile attacker)
    2938.      {
    2939.        int min, max;
    2940.  
    2941.        GetBaseDamageRange(attacker, out min, out max);
    2942.  
    2943.        int damage = Utility.RandomMinMax(min, max);
    2944.  
    2945.        if (Core.AOS)
    2946.        {
    2947.          return damage;
    2948.        }
    2949.  
    2950.        /* Apply damage level offset
    2951.   * : Regular : 0
    2952.   * : Ruin  : 1
    2953.   * : Might  : 3
    2954.   * : Force  : 5
    2955.   * : Power  : 7
    2956.   * : Vanq  : 9
    2957.   */
    2958.        if (m_DamageLevel != WeaponDamageLevel.Regular)
    2959.        {
    2960.          damage += (2 * (int)m_DamageLevel) - 1;
    2961.        }
    2962.  
    2963.        return damage;
    2964.      }
    2965.  
    2966.      public virtual double GetBonus(double value, double scalar, double threshold, double offset)
    2967.      {
    2968.        double bonus = value * scalar;
    2969.  
    2970.        if (value >= threshold)
    2971.        {
    2972.          bonus += offset;
    2973.        }
    2974.  
    2975.        return bonus / 100;
    2976.      }
    2977.  
    2978.      public virtual int GetHitChanceBonus()
    2979.      {
    2980.        if (!Core.AOS)
    2981.        {
    2982.          return 0;
    2983.        }
    2984.  
    2985.        int bonus = 0;
    2986.  
    2987.        switch (m_AccuracyLevel)
    2988.        {
    2989.          case WeaponAccuracyLevel.Accurate:
    2990.            bonus += 02;
    2991.            break;
    2992.          case WeaponAccuracyLevel.Surpassingly:
    2993.            bonus += 04;
    2994.            break;
    2995.          case WeaponAccuracyLevel.Eminently:
    2996.            bonus += 06;
    2997.            break;
    2998.          case WeaponAccuracyLevel.Exceedingly:
    2999.            bonus += 08;
    3000.            break;
    3001.          case WeaponAccuracyLevel.Supremely:
    3002.            bonus += 10;
    3003.            break;
    3004.        }
    3005.  
    3006.        return bonus;
    3007.      }
    3008.  
    3009.      public virtual int GetDamageBonus()
    3010.      {
    3011.        int bonus = VirtualDamageBonus;
    3012.  
    3013.        switch (m_Quality)
    3014.        {
    3015.          case WeaponQuality.Low:
    3016.            bonus -= 20;
    3017.            break;
    3018.          case WeaponQuality.Exceptional:
    3019.            bonus += 20;
    3020.            break;
    3021.        }
    3022.  
    3023.        switch (m_DamageLevel)
    3024.        {
    3025.          case WeaponDamageLevel.Ruin:
    3026.            bonus += 15;
    3027.            break;
    3028.          case WeaponDamageLevel.Might:
    3029.            bonus += 20;
    3030.            break;
    3031.          case WeaponDamageLevel.Force:
    3032.            bonus += 25;
    3033.            break;
    3034.          case WeaponDamageLevel.Power:
    3035.            bonus += 30;
    3036.            break;
    3037.          case WeaponDamageLevel.Vanq:
    3038.            bonus += 35;
    3039.            break;
    3040.        }
    3041.  
    3042.        return bonus;
    3043.      }
    3044.  
    3045.      public virtual void GetStatusDamage(Mobile from, out int min, out int max)
    3046.      {
    3047.        int baseMin, baseMax;
    3048.  
    3049.        GetBaseDamageRange(from, out baseMin, out baseMax);
    3050.  
    3051.        if (Core.AOS)
    3052.        {
    3053.          min = Math.Max((int)ScaleDamageAOS(from, baseMin, false), 1);
    3054.          max = Math.Max((int)ScaleDamageAOS(from, baseMax, false), 1);
    3055.        }
    3056.        else
    3057.        {
    3058.          min = Math.Max((int)ScaleDamageOld(from, baseMin, false), 1);
    3059.          max = Math.Max((int)ScaleDamageOld(from, baseMax, false), 1);
    3060.        }
    3061.      }
    3062.  
    3063.      public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills)
    3064.      {
    3065.        if (checkSkills)
    3066.        {
    3067.          attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap);
    3068.            // Passively check tactics for gain
    3069.          attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap);
    3070.            // Passively check Anatomy for gain
    3071.  
    3072.          if (Type == WeaponType.Axe)
    3073.          {
    3074.            attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
    3075.          }
    3076.        }
    3077.  
    3078.        #region Physical bonuses
    3079.        /*
    3080.   * These are the bonuses given by the physical characteristics of the mobile.
    3081.   * No caps apply.
    3082.   */
    3083.        double strengthBonus = GetBonus(attacker.Str, 0.300, 100.0, 5.00);
    3084.        double anatomyBonus = GetBonus(attacker.Skills[SkillName.Anatomy].Value, 0.500, 100.0, 5.00);
    3085.        double tacticsBonus = GetBonus(attacker.Skills[SkillName.Tactics].Value, 0.625, 100.0, 6.25);
    3086.        double lumberBonus = GetBonus(attacker.Skills[SkillName.Lumberjacking].Value, 0.200, 100.0, 10.00);
    3087.  
    3088.        if (Type != WeaponType.Axe)
    3089.        {
    3090.          lumberBonus = 0.0;
    3091.        }
    3092.        #endregion
    3093.  
    3094.        #region Modifiers
    3095.        /*
    3096.   * The following are damage modifiers whose effect shows on the status bar.
    3097.   * Capped at 100% total.
    3098.   */
    3099.        int damageBonus = AosAttributes.GetValue(attacker, AosAttribute.WeaponDamage);
    3100.  
    3101.        // Horrific Beast transformation gives a +25% bonus to damage.
    3102.        if (TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell)))
    3103.        {
    3104.          damageBonus += 25;
    3105.        }
    3106.  
    3107.        // Divine Fury gives a +10% bonus to damage.
    3108.        if (DivineFurySpell.UnderEffect(attacker))
    3109.        {
    3110.          damageBonus += 10;
    3111.        }
    3112.  
    3113.        int defenseMasteryMalus = 0;
    3114.  
    3115.        // Defense Mastery gives a -50%/-80% malus to damage.
    3116.        if (DefenseMastery.GetMalus(attacker, ref defenseMasteryMalus))
    3117.        {
    3118.          damageBonus -= defenseMasteryMalus;
    3119.        }
    3120.  
    3121.        int discordanceEffect = 0;
    3122.  
    3123.        // Discordance gives a -2%/-48% malus to damage.
    3124.        if (Discordance.GetEffect(attacker, ref discordanceEffect))
    3125.        {
    3126.          damageBonus -= discordanceEffect * 2;
    3127.        }
    3128.  
    3129.        if (damageBonus > 100)
    3130.        {
    3131.          damageBonus = 100;
    3132.        }
    3133.        #endregion
    3134.  
    3135.        double totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus +
    3136.                  ((GetDamageBonus() + damageBonus) / 100.0);
    3137.  
    3138.        return damage + (int)(damage * totalBonus);
    3139.      }
    3140.  
    3141.      public virtual int VirtualDamageBonus { get { return 0; } }
    3142.  
    3143.      public virtual int ComputeDamageAOS(Mobile attacker, Mobile defender)
    3144.      {
    3145.        return (int)ScaleDamageAOS(attacker, GetBaseDamage(attacker), true);
    3146.      }
    3147.  
    3148.      public virtual double ScaleDamageOld(Mobile attacker, double damage, bool checkSkills)
    3149.      {
    3150.        if (checkSkills)
    3151.        {
    3152.          attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills[SkillName.Tactics].Cap);
    3153.            // Passively check tactics for gain
    3154.          attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills[SkillName.Anatomy].Cap);
    3155.            // Passively check Anatomy for gain
    3156.  
    3157.          if (Type == WeaponType.Axe)
    3158.          {
    3159.            attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
    3160.          }
    3161.        }
    3162.  
    3163.        /* Compute tactics modifier