context: using System;
  using System.Collections.Generic;
  using Server.Engines.XmlSpawner2;
  using Server.Items;
  using Server.Mobiles;
  using Server.Spells;
  using Server.Spells.Second;
  using Server.Spells.Fifth;
  using Server.Spells.Bushido;
  using Server.Spells.Ninjitsu;
  using Server.Spells.Seventh;
  using Server.Spells.Chivalry;
  using Server.Spells.Necromancy;
  using Server.Spells.Spellweaving;
  using Server.SkillHandlers;
  
  namespace Server
  {
      public class AOS
      {
          public static void DisableStatInfluences()
          {
              for (int i = 0; i < SkillInfo.Table.Length; ++i)
              {
                  SkillInfo info = SkillInfo.Table[i];
  
                  info.StrScale = 0.0;
                  info.DexScale = 0.0;
                  info.IntScale = 0.0;
                  info.StatTotal = 0.0;
              }
          }
  
          public static int Damage(Mobile m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
          {
              return Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy);
          }
  
          public static int Damage(Mobile m, int damage, int phys, int fire, int cold, int pois, int nrgy)
          {
              return Damage(m, null, damage, phys, fire, cold, pois, nrgy);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy)
          {
              return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, false, false, false);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos)
          {
              return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, 0, false, false, false);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct)
          {
              return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos, direct, false, false, false);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy)
          {
              return Damage(m, from, damage, ignoreArmor, phys, fire, cold, pois, nrgy, 0, 0, false, false, false);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, bool keepAlive)
          {
              return Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive, false, false);
          }
  
          public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy, int chaos, int direct, bool keepAlive, bool archer, bool deathStrike)
          {
              if (m == null || m.Deleted || !m.Alive || damage <= 0)
                  return 0;
  
              if (phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0)
                  Mobiles.MeerMage.StopEffect(m, true);
  
              if (!Core.AOS)
              {
                  m.Damage(damage, from);
                  return damage;
              }
  
              Fix(ref phys);
              Fix(ref fire);
              Fix(ref cold);
              Fix(ref pois);
              Fix(ref nrgy);
              Fix(ref chaos);
              Fix(ref direct);
  
              if (Core.ML && chaos > 0)
              {
                  switch (Utility.Random(5))
                  {
                      case 0:
                          phys += chaos;
                          break;
                      case 1:
                          fire += chaos;
                          break;
                      case 2:
                          cold += chaos;
                          break;
                      case 3:
                          pois += chaos;
                          break;
                      case 4:
                          nrgy += chaos;
                          break;
                  }
              }
  
              BaseQuiver quiver = null;
  
              if (archer && from != null)
                  quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver;
  
              int totalDamage;
  
              if (!ignoreArmor)
              {
                  // Armor Ignore on OSI ignores all defenses, not just physical.
                  int resPhys = m.PhysicalResistance;
  
                  #region SA
                  int physDamage = damage * phys * (100 - m.PhysicalResistance);
                  int fireDamage = damage * fire * (100 - m.FireResistance);
                  int coldDamage = damage * cold * (100 - m.ColdResistance);
                  int poisonDamage = damage * pois * (100 - m.PoisonResistance);
                  int energyDamage = damage * nrgy * (100 - m.EnergyResistance);
  
                  int[] amounts = new int[] { physDamage, fireDamage, coldDamage, poisonDamage, energyDamage };
  
                  totalDamage = physDamage + fireDamage + coldDamage + poisonDamage + energyDamage;
                  totalDamage /= 10000;
  
                  
                  #endregion
  
                  if (Core.ML)
                  {
                      totalDamage += damage * direct / 100;
  
                      if (quiver != null)
                          totalDamage += totalDamage * quiver.DamageIncrease / 100;
                  }
  
                  BaseFishPie.ScaleDamage(m, ref totalDamage, phys, fire, cold, pois, nrgy, direct);
  
                  if (totalDamage < 1)
                      totalDamage = 1;
              }
              else if (Core.ML && m is PlayerMobile && from is PlayerMobile)
              {
                  if (quiver != null)
                      damage += damage * quiver.DamageIncrease / 100;
  
                  if (!deathStrike)
                      totalDamage = Math.Min(damage, 35);	// Direct Damage cap of 35
                  else
                      totalDamage = Math.Min(damage, 70);	// Direct Damage cap of 70
              }
              else
              {
                  totalDamage = damage;
  
                  if (Core.ML && quiver != null)
                      totalDamage += totalDamage * quiver.DamageIncrease / 100;
              }
  
              #region Dragon Barding
              if ((from == null || !from.Player) && m.Player && m.Mount is SwampDragon)
              {
                  SwampDragon pet = m.Mount as SwampDragon;
  
                  if (pet != null && pet.HasBarding)
                  {
                      int percent = (pet.BardingExceptional ? 20 : 10);
                      int absorbed = Scale(totalDamage, percent);
  
                      totalDamage -= absorbed;
  					
                      // Mondain's Legacy mod
                      if (!(pet is ParoxysmusSwampDragon))
                          pet.BardingHP -= absorbed;
  
                      if (pet.BardingHP < 0)
                      {
                          pet.HasBarding = false;
                          pet.BardingHP = 0;
  
                          m.SendLocalizedMessage(1053031); // Your dragon's barding has been destroyed!
                      }
                  }
              }
              #endregion
  
              #region Stygian Abyss
              //SHould this go in after or before dragon barding absorb?
              if (ignoreArmor)
                  DamageEaterContext.CheckDamage(m, totalDamage, 0, 0, 0, 0, 0, 100);
              else
                  DamageEaterContext.CheckDamage(m, totalDamage, phys, fire, cold, pois, nrgy, direct);
  
              if(totalDamage > 0)
                  Spells.Mystic.SpellPlagueSpell.OnMobileDamaged(m);
              #endregion 
  
              if (keepAlive && totalDamage > m.Hits)
                  totalDamage = m.Hits;
  
              if (from != null && !from.Deleted && from.Alive)
              {
                  int reflectPhys = AosAttributes.GetValue(m, AosAttribute.ReflectPhysical);
  
                  if (reflectPhys != 0)
                  {
                      if (from is ExodusMinion && ((ExodusMinion)from).FieldActive || from is ExodusOverseer && ((ExodusOverseer)from).FieldActive)
                      {
                          from.FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist);
                          from.PlaySound(0x2F4);
                          m.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier");
                      }
                      else
                      {
                          from.Damage(Scale((damage * phys * (100 - (ignoreArmor ? 0 : m.PhysicalResistance))) / 10000, reflectPhys), m);
                      }
                  }
              }
  
              m.Damage(totalDamage, from, true, false);
  
              #region Stygian Abyss
              if (m.Spell != null)
                  ((Spell)m.Spell).CheckCasterDisruption(true, phys, fire, cold, pois, nrgy);
  
              BattleLust.IncreaseBattleLust(m, totalDamage);
  
              if (ManaPhasingOrb.IsInManaPhase(m))
                  ManaPhasingOrb.RemoveFromTable(m);
              #endregion
  
              return totalDamage;
          }
  
          public static void Fix(ref int val)
          {
              if (val < 0)
                  val = 0;
          }
  
          public static int Scale(int input, int percent)
          {
              return (input * percent) / 100;
          }
  
  		public static int GetStatus( Mobile from, int index )
  		{
  			switch ( index )
  			{
  				// TODO: Account for buffs/debuffs
  				case 0: return from.GetMaxResistance( ResistanceType.Physical );
  				case 1: return from.GetMaxResistance( ResistanceType.Fire );
  				case 2: return from.GetMaxResistance( ResistanceType.Cold );
  				case 3: return from.GetMaxResistance( ResistanceType.Poison );
  				case 4: return from.GetMaxResistance( ResistanceType.Energy );
                  case 5: return Math.Min(45 + BaseArmor.GetRefinedDefenseChance(from), AosAttributes.GetValue(from, AosAttribute.DefendChance));
                  case 6: return 45 + BaseArmor.GetRefinedDefenseChance(from);
                  case 7: return Math.Min(from.Race == Race.Gargoyle ? 50 : 45, AosAttributes.GetValue(from, AosAttribute.AttackChance));
                  case 8: return Math.Min(60, AosAttributes.GetValue(from, AosAttribute.WeaponSpeed));
                  case 9: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.WeaponDamage));
                  case 10: return Math.Min(100, AosAttributes.GetValue(from, AosAttribute.LowerRegCost));
                  case 11: return AosAttributes.GetValue(from, AosAttribute.SpellDamage);
                  case 12: return Math.Min(6, AosAttributes.GetValue(from, AosAttribute.CastRecovery));
                  case 13:
                      int max = from.Skills[SkillName.Chivalry].Value < 70.0 ? 4 : 2;
                      if (ProtectionSpell.Registry.ContainsKey(from) /*|| EodonianPotion.IsUnderEffects(m, PotionEffect.Urali)*/)
                      {
                          return Math.Min(max - 2, AosAttributes.GetValue(from, AosAttribute.CastSpeed) - 2);
                      }
                      return Math.Min(max, AosAttributes.GetValue(from, AosAttribute.CastSpeed));
                  case 14: return Math.Min(40, AosAttributes.GetValue(from, AosAttribute.LowerManaCost)) + BaseArmor.GetInherentLowerManaCost(from);
  				default: return 0;
  			}
  		}
      }
  
      [Flags]
      public enum AosAttribute
      {
          RegenHits = 0x00000001,
          RegenStam = 0x00000002,
          RegenMana = 0x00000004,
          DefendChance = 0x00000008,
          AttackChance = 0x00000010,
          BonusStr = 0x00000020,
          BonusDex = 0x00000040,
          BonusInt = 0x00000080,
          BonusHits = 0x00000100,
          BonusStam = 0x00000200,
          BonusMana = 0x00000400,
          WeaponDamage = 0x00000800,
          WeaponSpeed = 0x00001000,
          SpellDamage = 0x00002000,
          CastRecovery = 0x00004000,
          CastSpeed = 0x00008000,
          LowerManaCost = 0x00010000,
          LowerRegCost = 0x00020000,
          ReflectPhysical = 0x00040000,
          EnhancePotions = 0x00080000,
          Luck = 0x00100000,
          SpellChanneling = 0x00200000,
          NightSight = 0x00400000,
          IncreasedKarmaLoss = 0x00800000,
          Brittle = 0x01000000,
          LowerAmmoCost = 0x02000000
      }
  
      public sealed class AosAttributes : BaseAttributes
      {
          public AosAttributes(Item owner)
              : base(owner)
          {
          }
  
          public AosAttributes(Item owner, AosAttributes other)
              : base(owner, other)
          {
          }
  
          public AosAttributes(Item owner, GenericReader reader)
              : base(owner, reader)
          {
          }
  
          public static int GetValue(Mobile m, AosAttribute attribute)
          {
              if (!Core.AOS)
                  return 0;
  
              List<Item> items = m.Items;
              int value = 0;
  
              #region Enhancement
              value += Enhancement.GetValue(m, attribute);
              #endregion
  
              for (int i = 0; i < items.Count; ++i)
              {
                  Item obj = items[i];
  
                  if (obj is BaseWeapon)
                  {
                      AosAttributes attrs = ((BaseWeapon)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
  
                      if (attribute == AosAttribute.Luck)
                          value += ((BaseWeapon)obj).GetLuckBonus();
                  }
                  else if (obj is BaseArmor)
                  {
                      AosAttributes attrs = ((BaseArmor)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
  
                      if (attribute == AosAttribute.Luck)
                          value += ((BaseArmor)obj).GetLuckBonus();
                  }
                  else if (obj is BaseJewel)
                  {
                      AosAttributes attrs = ((BaseJewel)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
                  }
                  else if (obj is BaseClothing)
                  {
                      AosAttributes attrs = ((BaseClothing)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
                  }
                  else if (obj is Spellbook)
                  {
                      AosAttributes attrs = ((Spellbook)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
                  }
                  else if (obj is BaseQuiver)
                  {
                      AosAttributes attrs = ((BaseQuiver)obj).Attributes;
  
                      if (attrs != null)
                          value += attrs[attribute];
                  }
                  else if (obj is BaseTalisman)
                  {
  
gt:                     AosAttributes attrs = ((BaseTalisman)obj).Attributes;