context: // Created by Peoharen for the Mobile Abilities Package.
  // #define ML // Used for the Bardic Peace ability
  using System;
  using System.Collections.Generic;
  using Server.Engines.PartySystem;
  using Server.Guilds;
  using Server.Items;
  using Server.Mobiles;
  using Server.Network;
  
  namespace Server
  {
      public partial class Ability
      {
          public static bool CanUse(Mobile from)
          {
              if (from == null)
                  return false;
  
              return !(from.Frozen || from.Paralyzed || from.Map == null || from.Map == Map.Internal || !from.Alive);
          }
  
          public static bool CanUse(Mobile from, Mobile target)
          {
              return CanUse(from) && CanUse(from, target, true);
          }
  
          public static bool CanUse(Mobile from, Mobile target, bool harm)
          {
              if (!CanUse(from) || target == null)
                  return false;
              else if (!from.CanSee(target))
                  return false;
              else
                  return CanTarget(from, target, harm);
          }
  
          #region Aura
          // Support for the old Aura permaiters
          public static void Aura(Mobile from, int min, int max, int type, int range, int poisons, string text)
          {
              ResistanceType rt = ResistanceType.Physical;
              Poison p = null;
  
              switch (type)
              {
                  case 1:
                      rt = ResistanceType.Fire;
                      break;
                  case 2:
                      rt = ResistanceType.Cold;
                      break;
                  case 3:
                      rt = ResistanceType.Poison;
                      break;
                  case 4:
                      rt = ResistanceType.Energy;
                      break;
              }
  
              switch (poisons)
              {
                  case 1:
                      p = Poison.Lesser;
                      break;
                  case 2:
                      p = Poison.Regular;
                      break;
                  case 3:
                      p = Poison.Greater;
                      break;
                  case 4:
                      p = Poison.Deadly;
                      break;
                  case 5:
                      p = Poison.Lethal;
                      break;
              }
  
              Aura(from.Location, from.Map, from, min, max, rt, range, p, text, true, false, false, 0, 0);
          }
  
          // Mobile based Aura
          public static void Aura(Mobile from, int min, int max, ResistanceType type, int range, Poison poison, string text)
          {
              Aura(from.Location, from.Map, from, min, max, type, range, poison, text, true, false, false, 0, 0);
          }
  
          // Null based Aura
          public static void Aura(Point3D location, Map map, Mobile from, int min, int max, ResistanceType type, int range, Poison poison, string text)
          {
              Aura(location, map, from, min, max, type, range, poison, text, true, false, false, 0, 0);
          }
  
          // No Effects
          public static void Aura(Point3D location, Map map, Mobile from, int min, int max, ResistanceType type, int range, Poison poison, string text, bool scales, bool allownull)
          {
              Aura(location, map, from, min, max, type, range, poison, text, scales, allownull, false, 0, 0);
          }
  
          // Main Aura Method
          public static void Aura(Point3D location, Map map, Mobile from, int min, int max, ResistanceType type, int range, Poison poison, string text, bool scales, bool allownull, bool effects, int itemid, int hue)
          {
              if (from == null && !allownull)
                  return;
  
              List<Mobile> targets = new List<Mobile>();
  
              foreach (Mobile m in Map.AllMaps[map.MapID].GetMobilesInRange(location, range))
              {
                  if (CanTarget(from, m, true, false, allownull))
                      targets.Add(m);
              }
  
              if (effects && from != null)
                  from.Animate(12, 5, 1, true, false, 0);
  
              for (int i = 0; i < targets.Count; i++)
              {
                  Mobile m = (Mobile)targets[i];
                  m.RevealingAction();
  
                  if (text != "")
                      m.SendMessage(text);
  
                  int auradamage = Utility.RandomMinMax(min, max);
  
                  if (scales)
                      auradamage = (int)((auradamage / GetDist(location, m.Location)) * range);
  
                  if (poison != null)
                      m.ApplyPoison((from == null) ? m : from, poison);
  
                  if (effects)
                      m.FixedParticles(itemid, 10, 15, 5030/*what the hell does this number do?*/, hue, 0, EffectLayer.Waist);
  
                  switch (type)
                  {
                      case ResistanceType.Physical:
                          AOS.Damage(m, (from == null) ? m : from, auradamage, 100, 0, 0, 0, 0);
                          break;
                      case ResistanceType.Fire:
                          AOS.Damage(m, (from == null) ? m : from, auradamage, 0, 100, 0, 0, 0);
                          break;
                      case ResistanceType.Cold:
                          AOS.Damage(m, (from == null) ? m : from, auradamage, 0, 0, 100, 0, 0);
                          break;
                      case ResistanceType.Poison:
                          AOS.Damage(m, (from == null) ? m : from, auradamage, 0, 0, 0, 100, 0);
                          break;
                      case ResistanceType.Energy:
                          AOS.Damage(m, (from == null) ? m : from, auradamage, 0, 0, 0, 0, 100);
                          break;
                  }
              }
  
              targets.Clear();
          }
  
          #endregion
  
          #region UseBandage
          public static int UseBandage(BaseCreature from)
          {
              return UseBandage(from, false);
          }
  
          public static int UseBandage(BaseCreature from, bool healmaster)
          {
              if (from.IsDeadPet)
                  return 12;
  
              int delay = (500 + (50 * ((120 - from.Dex) / 10))) / 100;
  
              if (delay < 3)
                  delay = 3;
  
              if (from.Controlled && from.ControlMaster != null && from.Hits >= (from.Hits / 2) && healmaster)
              {
                  if (from.InRange(from.ControlMaster, 2) && from.ControlMaster.Alive && from.ControlMaster.Hits < from.ControlMaster.HitsMax)
                      BandageContext.BeginHeal(from, from.ControlMaster);
              }
              else if (from.Hits < from.HitsMax)
              {
                  BandageContext.BeginHeal(from, from);
              }
  
              return delay + 3;
          }
  
          #endregion
  
          #region Bard Skills
          // Warning: Untested
          public static bool CheckBarding(BaseCreature from)
          {
              BaseInstrument inst = BaseInstrument.GetInstrument(from);
  
              if (inst == null)
              {
                  if (from.Backpack == null)
                      return false;
  
                  inst = (BaseInstrument)from.Backpack.FindItemByType(typeof(BaseInstrument));
  
                  if (inst == null)
                  {
                      inst = new Harp();
                      inst.SuccessSound = 0x58B;
                      // inst.DiscordSound = inst.PeaceSound = 0x58B;
                      // inst.ProvocationSound = 0x58A;
                      inst.FailureSound = 0x58C;
                  }
              }
  
              BaseInstrument.SetInstrument(from, inst);
  
              if (from.Skills[SkillName.Discordance].Base == 0)
                  from.Skills[SkillName.Discordance].Base = 100.0;
  
              if (from.Skills[SkillName.Peacemaking].Base == 0)
                  from.Skills[SkillName.Peacemaking].Base = 100.0;
  
              if (from.Skills[SkillName.Provocation].Base == 0)
                  from.Skills[SkillName.Provocation].Base = 100.0;
  
              return true;
          }
  
          public static void UseDiscord(BaseCreature from)
          {
              if (from.Combatant == null || !CanUse(from) || !CheckBarding(from))
                  return;
  
              //int effect = 0.0;
  
              //if ( SkillHandlers.Discordance.GetEffect( from.Combatant, ref effect ) )
              //return;
  
              if (!from.UseSkill(SkillName.Discordance))
                  return;
  
              if (from.Combatant is BaseCreature)
                  if (from.Target != null)
                      from.Target.Invoke(from, from.Combatant);
                  else
                  {
                      double effect = -(from.Skills[SkillName.Discordance].Value / 5.0);
                      TimeSpan duration = TimeSpan.FromSeconds(from.Skills[SkillName.Discordance].Value * 2);
  
                      ResistanceMod[] mods = 
                      {
                          new ResistanceMod(ResistanceType.Physical, (int)(effect * 0.01)),
                          new ResistanceMod(ResistanceType.Fire, (int)(effect * 0.01)),
                          new ResistanceMod(ResistanceType.Cold, (int)(effect * 0.01)),
                          new ResistanceMod(ResistanceType.Poison, (int)(effect * 0.01)),
                          new ResistanceMod(ResistanceType.Energy, (int)(effect * 0.01))
                      };
  
                      TimedResistanceMod.AddMod(from.Combatant, "Discordance", mods, duration);
                      from.Combatant.AddStatMod(new StatMod(StatType.Str, "DiscordanceStr", (int)(from.Combatant.RawStr * effect), duration));
                      from.Combatant.AddStatMod(new StatMod(StatType.Int, "DiscordanceInt", (int)(from.Combatant.RawInt * effect), duration));
                      from.Combatant.AddStatMod(new StatMod(StatType.Dex, "DiscordanceDex", (int)(from.Combatant.RawDex * effect), duration));
                  }
          }
  
          public class DiscordEffectTimer : Timer
          {
              public Mobile Mob;
              public int Count;
              public int MaxCount;
  
              public DiscordEffectTimer(Mobile mob, TimeSpan duration)
                  : base(TimeSpan.FromSeconds(1.25), TimeSpan.FromSeconds(1.25))
              {
                  this.Mob = mob;
                  this.Count = 0;
                  this.MaxCount = (int)((double)duration.TotalSeconds / 1.25);
              }
  
              protected override void OnTick()
              {
                  if (this.Count >= this.MaxCount)
                      this.Stop();
                  else
                  {
                      this.Mob.FixedEffect(0x376A, 1, 32);
                      this.Count++;
                  }
              }
          }
  
          public static void UsePeace(BaseCreature from)
          {
              if (from.Combatant == null || !CanUse(from) || !CheckBarding(from))
                  return;
  
              if (!from.UseSkill(SkillName.Peacemaking))
                  return;
  
              if (from.Combatant is PlayerMobile)
              {
                  #if ML
                                  PlayerMobile pm = (PlayerMobile)from.Combatant;
                                  if ( pm.PeacedUntil <= DateTime.UtcNow )
                                  {
                                          pm.PeacedUntil = DateTime.UtcNow + TimeSpan.FromSeconds( (int)(from.Skills[SkillName.Peacemaking].Value / 5) );
                                          pm.SendLocalizedMessage( 500616 ); // You hear lovely music, and forget to continue battling!                                   
                                  }
                  #endif
              }
              else if (from.Target != null)
                  from.Target.Invoke(from, from.Combatant);
          }
  
          public static void UseProvo(BaseCreature from, bool randomly)
          {
              if (from.Combatant == null && randomly || !CheckBarding(from))
                  return;
  
              if (!CanUse(from))
                  return;
  
              if (!from.UseSkill(SkillName.Provocation))
                  return;
  
              Mobile targetone = FindRandomTarget(from, randomly);
  
              if (targetone == null)
                  return;
  
              if (from.Target != null)
                  from.Target.Invoke(from, targetone);
  
              Mobile targettwo = randomly ? FindRandomTarget(from, randomly) : from.Combatant;
  
              if (targettwo == null)
                  return;
  
              if (from.Target != null)
                  from.Target.Invoke(from, targettwo);
          }
  
          #endregion
  
          #region MimicThem
          public static void MimicThem(BaseCreature from)
          {
              Mobile targ = from.Combatant;
              MimicThem(from, false, false);
          }
  
          public static void MimicThem(BaseCreature from, bool allowskillchanges, bool allowAIchanges)
          {
              Mobile targ = from.Combatant;
              MimicThem(from, targ, allowskillchanges, allowAIchanges);
          }
  
          public static void MimicThem(BaseCreature from, Mobile targ, bool allowskillchanges, bool allowAIchanges)
          {
              if (targ == null)
                  return;
  
              if (from.BodyMod == 0)
              {
                  from.BodyMod = targ.Body;
                  from.Hue = targ.Hue;
  
                  from.NameMod = targ.Name;
                  from.Title = targ.Title;
  
                  from.HairItemID = targ.HairItemID;
                  from.FacialHairItemID = targ.FacialHairItemID;
  
                  from.VirtualArmor = targ.VirtualArmor;
  
                  foreach (Item item in targ.Items)
                  {
                      if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount)
                      {
                          /*
                          We don't dupe armor because the creatures base seed stacks with armor
                          By duping a high resistance player we shoot the creature up into the 100's in res
                          Imagine being the player facing your 400+ HP creature and EVERY attack & spell only deals 1 damage to them.
                          */
                          if (item is BaseShield)
                          {
                              Buckler shieldtomake = new Buckler();
                              shieldtomake.PoisonBonus = 0;
                              shieldtomake.ItemID = item.ItemID;
                              shieldtomake.Hue = item.Hue;
                              shieldtomake.Layer = item.Layer;
                              shieldtomake.Movable = false;
                              shieldtomake.Name = item.Name;
                              from.EquipItem(shieldtomake);
                          }
                          else if (item is BaseWeapon)
                          {
                              Broadsword weapontomake = new Broadsword();
                              weapontomake.ItemID = item.ItemID;
                              weapontomake.Hue = item.Hue;
                              weapontomake.Layer = item.Layer;
                              weapontomake.Movable = false;
                              weapontomake.Name = item.Name;
  
                              BaseWeapon weapon = item as BaseWeapon;
                              weapontomake.Animation = weapon.Animation;
                              weapontomake.HitSound = weapon.HitSound;
                              weapontomake.MissSound = weapon.MissSound;
                              //weapontomake.MinDamage = weapon.MinDamage;
                              //weapontomake.MaxDamage = weapon.MaxDamage;
                              weapontomake.Speed = weapon.Speed;
                              from.EquipItem(weapontomake);
                          }
                          else
                          {
                              Item itemtomake = new Item(item.ItemID);
                              itemtomake.Hue = item.Hue;
                              itemtomake.Layer = item.Layer;
                              itemtomake.Movable = false;
                              itemtomake.Name = item.Name;
                              from.EquipItem(itemtomake);
                          }
                      }
                  }
  
                  /*
                  Duping skills can mess up the AI.
                  What good is trying to melee when you have 0 tactics?
                  On the other side, What good is stopping it's attack to try and cast something it can't do?
                  The bool allows you to use it as a staff command or spell or make clone creatures that don't run around with the same exact skills as the others.
                  */
  
                  if (allowskillchanges)
                      for (int i = 0; i < targ.Skills.Length && i < from.Skills.Length; i++)
                          from.Skills[i].Base = targ.Skills[i].Base;
              }
              else
              {
                  from.BodyMod = 0;
                  from.Hue = 0;
  
                  from.NameMod = null;
                  from.Title = null;
  
                  from.HairItemID = 0;
                  from.FacialHairItemID = 0;
  
                  from.VirtualArmor = 0;
  
                  List<Item> list = new List<Item>(from.Items);
  
                  foreach (Item item in list)
                  {
                      if (item != null)
                          item.Delete();
                  }
  
                  if (allowskillchanges)
                  {
                      for (int i = 0; i < targ.Skills.Length; ++i)
                          from.Skills[i].Base = 50.0;
                  }
              }
  
              return;
          }
  
          #endregion
  
          #region DarkKnightAbilities
          /* Bull Rush
          He gathers energy and then slams into you from a
          distance, dealing heavy damage and physically knocking
          you back, stunning you.
          */
  
          public static void BullRush(Mobile from)
          {
              BullRush(from, "", 7);
          }
  
          public static void BullRush(Mobile from, string text, int duration)
          {
              Mobile target = from.Combatant;
  
              if (target == null || CanUse(from, target))
                  return;
  
              int dist = from.Str / 20;
              SlideAway(target, from.Location, (dist > 12) ? 12 : dist);
  
  
gt:             if (text != "")