//Created by Peoharen for the Mobile Abilities Package.
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Network;

namespace Server
{
    public class Ability
    {
        public static void Aura(Mobile from, int min, int max, int type, int range, int poisons, string text)
        {       //Adds the range scaler
            Aura(from, min, max, type, range, poisons, text, false);
        }

        public static void Aura(Mobile from, int min, int max, int type, int range, int poisons, string text, bool scales)
        {
            ArrayList targets = new ArrayList();

            foreach (Mobile m in from.GetMobilesInRange(range))
            {
                if (m == from || m == null)
                    continue;

                if ((from is BaseCreature && ((BaseCreature)from).Controlled) || from is PlayerMobile)
                {
                    if (m is BaseCreature && !(((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned))
                        targets.Add(m);
                    else if (m.Player && m.AccessLevel == AccessLevel.Player && m.Alive && m.Kills >= 5)
                        targets.Add(m);
                }
                else
                {
                    if (m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned))
                        targets.Add(m);
                    else if (m.Player && m.AccessLevel == AccessLevel.Player && m.Alive)
                        targets.Add(m);
                }
            }

            for (int i = 0; i < targets.Count; ++i)
            {
                Mobile m = (Mobile)targets[i];
                m.RevealingAction();
                m.SendMessage(89, text);

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

                if (scales)
                {
                    int scalebyrange;

                    if (m.InRange(from.Location, (range / 4)))
                        scalebyrange = 1;
                    else if (m.InRange(from.Location, (range / 2)))
                        scalebyrange = 2;
                    else
                        scalebyrange = 4;

                    auradamage /= scalebyrange;
                }

                if (type == 1)
                {
                    AOS.Damage(m, from, auradamage, 0, 100, 0, 0, 0);
                }
                else if (type == 2)
                {
                    AOS.Damage(m, from, auradamage, 0, 0, 100, 0, 0);
                }
                else if (type == 3)
                {
                    AOS.Damage(m, from, auradamage, 0, 0, 0, 100, 0);
                    m.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist);
                }
                else if (type == 4)
                {
                    AOS.Damage(m, from, auradamage, 0, 0, 0, 0, 100);
                }
                else
                {
                    AOS.Damage(m, from, auradamage, 100, 0, 0, 0, 0);
                }

                if (poisons == 1)
                    m.ApplyPoison(from, Poison.Lesser);
                else if (poisons == 2)
                    m.ApplyPoison(from, Poison.Regular);
                else if (poisons == 3)
                    m.ApplyPoison(from, Poison.Greater);
                else if (poisons == 4)
                    m.ApplyPoison(from, Poison.Deadly);
                else if (poisons == 5)
                    m.ApplyPoison(from, Poison.Lethal);
                else
                { }; //TODO Make this varable: m.FixedParticles( 0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255 );
            }

        }

        public static void DamageArmor(Mobile to, int min, int max)
        {
            double positionChance = Utility.RandomDouble();
            BaseArmor armor;

            if (positionChance < 0.07)
                armor = to.NeckArmor as BaseArmor;
            else if (positionChance < 0.14)
                armor = to.HandArmor as BaseArmor;
            else if (positionChance < 0.28)
                armor = to.ArmsArmor as BaseArmor;
            else if (positionChance < 0.43)
                armor = to.HeadArmor as BaseArmor;
            else if (positionChance < 0.65)
                armor = to.LegsArmor as BaseArmor;
            else
                armor = to.ChestArmor as BaseArmor;

            if (armor != null)
            {
                int ruin = Utility.RandomMinMax(min, max);

                if (armor.HitPoints > ruin)
                    armor.HitPoints -= ruin;
                else if (armor.MaxHitPoints > ruin)
                    armor.MaxHitPoints -= ruin;
            }
        }

        public static void TurnPet(Mobile target)
        {
            if (target is BaseCreature)
            {
                BaseCreature c = (BaseCreature)target;

                if (c.Controlled && c.ControlMaster != null)
                {
                    c.ControlTarget = c.ControlMaster;
                    c.ControlOrder = OrderType.Attack;
                    c.Combatant = c.ControlMaster;
                }
            }
        }

        public static int UseBandage(BaseCreature from)
        {
            return UseBandage(from, false);
        }

        public static int UseBandage(BaseCreature from, bool healmaster)
        {
            if (from == null || from.IsDeadPet)
                return 12;

            Bandage band;
            Mobile m = from.ControlMaster;

            if (from.Controlled && m != null && from.InRange(m.Location, 3) && from.Hits >= 2 && m.Alive && (m.Hits < (m.HitsMax - m.HitsMax / 3)) && healmaster)
            {

                band = new Bandage();
                from.AddToBackpack(band);

                band.OnDoubleClick(from);

                if (from.Target != null)
                {
                    from.Target.Invoke(from, m);
                    return 8;
                }
                else
                {
                    band.Delete();
                    return 7;
                }

                return 7;
            }
            else if (from.Hits < (from.HitsMax - (from.HitsMax / 3)))
            {
                band = new Bandage();
                from.AddToBackpack(band);

                band.OnDoubleClick(from);

                if (from.Target != null)
                {
                    from.Target.Invoke(from, from);
                    return 8;
                }
                else
                {
                    band.Delete();
                    return 5;
                }
            }
            else
                return 12;
        }

        //hidding
        public static DateTime HideSelf(Mobile from, DateTime delay, int nexttime, int range)
        {
            Mobile m = null;

            foreach (Mobile mob in from.GetMobilesInRange(range))
            {
                if (mob.Player && mob.AccessLevel == AccessLevel.Player && mob.Alive && !mob.Hidden && !mob.Blessed && from.CanSee(mob) && from.InLOS(mob))
                {
                    m = mob;
                    break;
                }
            }

            if (from.Hidden)
            {
                if (m != null)
                {
                    from.Frozen = false;
                    from.Combatant = m;
                    from.RevealingAction();
                    Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0x375A, 10, 15, 5045);
                    from.PlaySound(0x1FD);
                }

                return delay;
            }
            else
            {
                if (m != null && from.Combatant == null)
                {
                    from.Frozen = false;
                    from.Combatant = m;
                }
                else if (m == null && from.Combatant == null && DateTime.Now >= delay)
                {
                    Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0x376A, 10, 15, 5045);
                    from.PlaySound(0x3C4);
                    from.Frozen = true;
                    from.Hidden = true;
                    //                from.UseSkill( SkillName.Stealth );
                    return DateTime.Now + TimeSpan.FromSeconds(nexttime);
                }
                return delay;
            }
        }

        //critical hit
        public static void CriticalHit(Mobile mob)
        {
            if (mob != null)
            {
                int dmg = (mob.Hits / 2);
                mob.Hits /= 2;
                mob.Mana /= 2;
                mob.Stam /= 2;
                mob.PlaySound(0x3B9);

                if (mob is PlayerMobile)
                {
                    mob.LocalOverheadMessage(MessageType.Regular, 0x21, 1072220); // You have been hit by a critical strike!
                    ISTile5.SendDmgPacket(mob, dmg);
                }
            }
        }

        //Color Spray
        //use this method for weapons in OnHit
        public static void FlameSpray(int dist, int level, Mobile attacker, Mobile victim, bool animate)
        {
            Direction dir = Utility.GetDirection(attacker.Location, victim.Location);
            FlameSpray(dist, level, attacker, victim.Location, dir, animate);
        }

        //use this method for basic things
        public static void FlameSpray(int dist, int level, Mobile mobile, bool animate)
        {
            FlameSpray(dist, level, mobile, mobile.Location, mobile.Direction, animate);
        }

        //core method
        public static void FlameSpray(int dist, int level, Mobile mobile, Point3D start, Direction direction, bool animate)
        {
            if (mobile == null || mobile.Deleted || !mobile.Alive)
                return;

            Point3DList path = new Point3DList();

            if (animate)
            {
                mobile.PublicOverheadMessage(Network.MessageType.Spell, mobile.SpeechHue, true, "Vas Flam Cul Ylem", false);
                mobile.Animate(212, 7, 1, true, false, 0);
            }

            for (int i = 0; i < dist + 1; i++)
            {
                int x = 0, y = 0;
                switch ((int)direction)
                {
                    case (int)Direction.Running: case (int)Direction.North: { y -= i; break; }
                    case 129: case (int)Direction.Right: { y -= i; x += i; break; }
                    case 130: case (int)Direction.East: { x += i; break; }
                    case 131: case (int)Direction.Down: { x += i; y += i; break; }
                    case 132: case (int)Direction.South: { y += i; break; }
                    case 133: case (int)Direction.Left: { y += i; x -= i; break; }
                    case 134: case (int)Direction.West: { x -= i; break; }
                    case (int)Direction.ValueMask: case (int)Direction.Up: { x -= i; y -= i; break; }
                }
                path.Add(start.X + x, start.Y + y, start.Z);
            }
            new SprayTimer(mobile, path, direction, 1, dist + 2, level).Start();
        }

        private static void doSpray(Mobile sprayer, Point3DList path, Direction dir, int i, int level)
        {
            if (path.Count > i && sprayer != null && !sprayer.Deleted && sprayer.Alive)
            { //please to not crashing!
                Point3D point = path[i];
                int o = i - 1;
                Server.Effects.PlaySound(point, sprayer.Map, 0x5CF);
                Server.Effects.PlaySound(point, sprayer.Map, 477);
                for (int rn = 0; rn < (o * 2) + 1; rn++)
                {
                    int y = 0, x = 0, y2 = 0, x2 = 0;
                    bool diag = false;
                    switch ((int)dir)
                    {
                        case (int)Direction.Running: case (int)Direction.North: { x = x - o + rn; break; }
                        case 129: case (int)Direction.Right: { x = x - o + rn; y = y - o + rn; break; }
                        case 130: case (int)Direction.East: { y = y - o + rn; break; }
                        case 131: case (int)Direction.Down: { y = y - o + rn; x = x + o - rn; break; }
                        case 132: case (int)Direction.South: { x = x + o - rn; break; }
                        case 133: case (int)Direction.Left: { x = x + o - rn; y = y + o - rn; break; }
                        case 134: case (int)Direction.West: { y = y + o - rn; break; }
                        case (int)Direction.ValueMask: case (int)Direction.Up: { y = y + o - rn; x = x - o + rn; break; }
                    }
                    switch ((int)dir)
                    {
                        case 129: case (int)Direction.Right: { y2++; diag = true; break; }
                        case 131: case (int)Direction.Down: { x2--; diag = true; break; }
                        case 133: case (int)Direction.Left: { y2--; diag = true; break; }
                        case (int)Direction.ValueMask: case (int)Direction.Up: { x2++; diag = true; break; }
                        default: { break; }
                    }
                    Point3D ep = new Point3D(point.X + x, point.Y + y, point.Z);
                    Point3D ep2 = new Point3D(ep.X + x2, ep.Y + y2, ep.Z);

                    if (diag && i >= ((2 * path.Count) / 3))
                        return;

                    if (diag && rn < (o * 2) && sprayer.InLOS(ep2))
                        Effects.SendLocationEffect(ep2, sprayer.Map, 6581, 15, 0, 0);

                    if (sprayer.InLOS(ep))
                        Effects.SendLocationEffect(ep, sprayer.Map, 6581, 15, 0, 0);

                    List<Mobile> die = new List<Mobile>();

                    foreach (Mobile sprayed in sprayer.Map.GetMobilesInRange(ep, 0))
                    {
                        if (ValidSprayed(sprayer, sprayed))
                            die.Add(sprayed);
                    }

                    foreach (Mobile sprayed in sprayer.Map.GetMobilesInRange(ep2, 0))
                    {
                        if (ValidSprayed(sprayer, sprayed))
                            die.Add(sprayed);
                    }
                    for (int k = 0; k < die.Count; k++)
                    {
                        Mobile died = die[k];
                        if (!died.Deleted && died != null)
                        {
                            if (level == 666)
                            {
                                died.Kill();
                            }
                            else
                            {
                                AOS.Damage(died, sprayer, Utility.RandomMinMax(level, level * 10), 0, 0, 0, 0, 100);
                            }
                        }
                    }
                }
            }
        }

        private static bool ValidSprayed(Mobile sprayer, Mobile sprayed)
        {
            if (sprayed != sprayer && sprayed != null && !sprayer.Deleted && !sprayed.Deleted && !sprayed.Blessed && sprayed.Alive && sprayed.InLOS(sprayer) && !sprayed.IsDeadBondedPet)
            {
                //MONSTRUM
                if (sprayer is BaseCreature && !(((BaseCreature)sprayer).Controlled || ((BaseCreature)sprayer).Summoned))
                {
                    if (sprayed is BaseCreature && (((BaseCreature)sprayed).Controlled || ((BaseCreature)sprayed).Summoned))
                        return true;
                    else if (sprayed.Player && sprayed.AccessLevel == AccessLevel.Player)
                        return true;
                    else
                        return false;
                }
                else //PLAYER
                {
                    if (sprayed is BaseCreature && !(((BaseCreature)sprayed).Controlled || ((BaseCreature)sprayed).Summoned))
                        return true;
                    else
                        return false;
                }
            }
            else
                return false;
        }

        /*private static int RandomHue() {
			switch (Utility.Random(5)) {
				default:
					case 0: return Utility.RandomBlueHue();
					case 1: return Utility.RandomGreenHue();
					case 2: return Utility.RandomRedHue();
					case 3: return Utility.RandomYellowHue();
					case 4: return Utility.RandomNeutralHue();
			}
		}*/

        private class SprayTimer : Timer
        {
            private Direction m_Dir;
            private int m_I, m_IMax, m_Level;
            private Point3DList m_Path;
            private Mobile m_Sprayer;

            public SprayTimer(Mobile sprayer, Point3DList path, Direction dir, int i, int imax, int level) : base(TimeSpan.FromTicks(4))
            {
                m_Dir = dir;
                m_I = i;
                m_IMax = imax;
                m_Path = path;
                m_Sprayer = sprayer;
                m_Level = level;
                Priority = TimerPriority.FiftyMS;
            }

            protected override void OnTick()
            {
                doSpray(m_Sprayer, m_Path, m_Dir, m_I, m_Level);
                if (m_I < m_IMax)
                    new SprayTimer(m_Sprayer, m_Path, m_Dir, m_I + 1, m_IMax, m_Level).Start();
                Stop();
            }
        }

        #region ColdBlood

        private static Hashtable m_ColdBloodTable = new Hashtable();

        private class ColdBloodExpireTimer : Timer
        {
            private Mobile m_Mobile;
            private Mobile m_From;

            public ColdBloodExpireTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(38.0))
            {
                m_Mobile = m;
                m_From = from;
                Priority = TimerPriority.OneSecond;
            }

            protected override void OnTick()
            {
                Stop();
                m_ColdBloodTable.Remove(m_Mobile);
                m_Mobile.SolidHueOverride = -1;

                if (m_Mobile.Alive)
                {
                    m_Mobile.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist);
                    m_Mobile.PlaySound(0x1E0);
                }

                m_Mobile.SendMessage("Tva krev se vratila do normalu");
            }
        }

        public static bool UnderColdBlood(Mobile mobile)
        {
            if (mobile == null) return false;

            if (mobile.Region != null && ((Server.Regions.IceRegion)Region.Find(mobile.Location, mobile.Map).GetRegion(typeof(Server.Regions.IceRegion)) != null))
                return true;

            ColdBloodExpireTimer timer = (ColdBloodExpireTimer)m_ColdBloodTable[mobile];

            if (timer == null)
                return false;

            return true;
        }

        public static void ColdBlood(Mobile mob)
        {
            if (mob == null || mob.Deleted || !mob.Alive)
                return;

            mob.PublicOverheadMessage(MessageType.Regular, 193, true, "Stone Cold Blood");

            ArrayList targets = Utilitky.GetTargets(mob, 15, false);

            for (int i = 0; i < targets.Count; ++i)
            {
                Mobile m = (Mobile)targets[i];

                if (m == null || m.Deleted || SoutezeLog.IsAbilityImmune(m))
                    continue;

                m.RevealingAction();
                mob.DoHarmful(m);

                //FixedParticles( int itemID, int speed, int duration, int effect, int hue, int renderMode, EffectLayer layer )
                m.FixedParticles(0x36BD, 1, 40, 0x1F78, 1401, 0, (EffectLayer)255);
                m.PlaySound(0x231);
                m.SolidHueOverride = 1401;
                m.SendMessage("Tva krev je chladna jako kamen");
                m.Hits /= 2;
                m.Mana /= 2;
                m.Stam /= 2;
                ISTile5.SendDmgPacket(m, m.Hits / 2);

                if (UnderColdBlood(m))
                    continue;

                ColdBloodExpireTimer timer = new ColdBloodExpireTimer(m, mob);

                timer.Start();
                m_ColdBloodTable[m] = timer;
            }
        }
        #endregion

        #region DoT      

        private static Hashtable m_DoTTable = new Hashtable();

        public static bool IsDoTted(Mobile m)
        {
            return m_DoTTable.Contains(m);
        }

        public static void BeginDoT(Mobile m, Mobile from, int damage)
        {
            Timer t = (Timer)m_DoTTable[m];

            if (t != null)
                t.Stop();

            t = new DotTimer(from, m, damage);
            m_DoTTable[m] = t;

            t.Start();

            // 			BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.Bleed, 1075829, "5\t25\t2" ) );
        }

        public static void DoDoT(Mobile m, Mobile from, int damage)
        {
            if (m.Alive)
            {
                if (from != null && from.Alive)
                    m.Damage(damage, from, 1);
                else
                    m.Damage(damage, null, 1);

                m.PlaySound(0x133);

                Blood blood = new Blood();

                blood.ItemID = Utility.Random(0x122A, 5);

                blood.MoveToWorld(m.Location, m.Map);
            }
            else
            {
                EndDoT(m);
            }
        }

        public static void EndDoT(Mobile m)
        {
            Timer t = (Timer)m_DoTTable[m];

            if (t == null)
                return;

            t.Stop();
            m_DoTTable.Remove(m);

            // 			m.SendLocalizedMessage( 1060167 ); // The bleeding wounds have healed, you are no longer bleeding!
            // 			BuffInfo.RemoveBuff( m, BuffIcon.Bleed );
        }

        private class DotTimer : Timer
        {
            private Mobile m_From;
            private Mobile m_Mobile;
            private int m_Count;
            private int m_Damage;

            public DotTimer(Mobile from, Mobile m, int damage) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0))
            {
                m_From = from;
                m_Mobile = m;
                m_Damage = damage;
                Priority = TimerPriority.TwoFiftyMS;
            }

            protected override void OnTick()
            {
                DoDoT(m_Mobile, m_From, m_Damage);

                if (++m_Count == 5)
                    EndDoT(m_Mobile);
            }
        }

        #endregion

        #region JaggedFire
        public static void JaggedLineEffect(Mobile from, int range, int speed)
        {
            if (from == null || from.Deleted || from.Map == null || from.Map == Map.Internal || !from.Alive)
            {
                return;
            }
            else
            {
                //from.Freeze(TimeSpan.FromSeconds(2.0));
                new JaggedLineTimer(from, range, speed).Start();
            }
        }

        public static Direction JaggedLine(Direction d)
        {
            int number = (int)d + Utility.RandomMinMax(-1, 1);

            if (number < 0)
                number = 8;

            number %= 8;

            return (Direction)number;
        }

        public class JaggedLineTimer : Timer
        {
            private Mobile m_From;
            private Direction m_D;
            private Point3D m_Point;
            private Map m_Map;
            private int m_Count;
            private int m_MaxCount;

            public JaggedLineTimer(Mobile from, int range, int speed)
                : base(TimeSpan.FromMilliseconds(speed), TimeSpan.FromMilliseconds(speed))
            {
                this.m_From = from;
                this.m_D = from.Direction;
                this.m_Point = new Point3D(from.Location);
                this.m_Map = from.Map;
                this.m_Count = 0;
                this.m_MaxCount = range;
            }

            protected override void OnTick()
            {
                if (this.m_From == null || this.m_From.Deleted)
                {
                    this.Stop();
                    return;
                }

                this.m_Count++;

                if (this.m_Count == 0)
                    Utilitky.IncreaseByDirection(ref this.m_Point, this.m_D);
                else
                    Utilitky.IncreaseByDirection(ref this.m_Point, JaggedLine(this.m_D));

                Point3D p = new Point3D(this.m_Point.X, this.m_Point.Y, this.m_Map.GetAverageZ(this.m_Point.X, this.m_Point.Y));

                if (this.m_Map.CanFit(p, 16, false, false) && m_From.InLOS(p))
                {
                    bool canplace = true;

                    foreach (Item item in this.m_Map.GetItemsInRange(p, 0))
                    {
                        if (item != null)
                        {
                            if (item is FireField && item.Visible == false)
                            {
                                canplace = false;
                                break;
                            }
                        }
                    }

                    if (canplace)
                    {
                        new FireField(this.m_From, 15, 20, 35, false, new Point3D(p.X, p.Y, p.Z), this.m_Map).Visible = false;
                        new FireField(this.m_From, 15, 0, 0, true, new Point3D(p.X, p.Y + 1, p.Z), this.m_Map);
                        new FireField(this.m_From, 15, 0, 0, false, new Point3D(p.X + 1, p.Y, p.Z), this.m_Map);
                    }
                }
                else
                    this.m_Count = 999;

                if (this.m_Count > this.m_MaxCount)
                {
                    this.Stop();
                }
            }
        }
        #endregion

        #region FireField
        public class FireField : Item
        {
            private Mobile m_Owner;
            private int m_MinDamage;
            private int m_MaxDamage;
            private DateTime m_Destroy;
            private Point3D m_MoveToPoint;
            private Map m_MoveToMap;
            private Timer m_Timer;
            private List<Mobile> m_List;

            [Constructable]
            public FireField(int duration, int min, int max, bool south, Point3D point, Map map)
                : this(null, duration, min, max, south, point, map)
            {
            }

            [Constructable]
            public FireField(Mobile owner, int duration, int min, int max, bool south, Point3D point, Map map)
                : base(GetItemID(south))
            {
                this.Movable = false;
                this.Light = LightType.Circle225;

                this.m_Owner = owner;
                this.m_MinDamage = min;
                this.m_MaxDamage = max;
                this.m_Destroy = DateTime.Now + TimeSpan.FromSeconds((double)duration + 1.5);
                this.m_MoveToPoint = point;
                this.m_MoveToMap = map;
                this.m_List = new List<Mobile>();
                this.m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), new TimerCallback(OnTick));
                Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1.5), new TimerCallback(Move));
            }

            private static int GetItemID(bool south)
            {
                if (south)
                    return 0x398C;
                else
                    return 0x3996;
            }

            public override void OnAfterDelete()
            {
                if (this.m_Timer != null)
                    this.m_Timer.Stop();
            }

            private void Move()
            {
                if (!this.Visible)
                    this.ItemID = 0x36FE;

                this.MoveToWorld(this.m_MoveToPoint, this.m_MoveToMap);
            }

            private void OnTick()
            {
                if (DateTime.Now > this.m_Destroy)
                    this.Delete();
                else if (this.m_MinDamage != 0)
                {
                    foreach (Mobile m in this.GetMobilesInRange(0))
                    {
                        if (m == null)
                            continue;
                        else
                        {
                            if (m_Owner == null || m == m_Owner || !m_Owner.CanBeHarmful(m))
                                continue;

                            if (Utilitky.IsPlayersPet(m))
                            {
                                m_List.Add(m);
                            }
                            else if (m.Player && m.AccessLevel == AccessLevel.Player)
                                m_List.Add(m);
                        }
                    }

                    for (int i = 0; i < this.m_List.Count; i++)
                    {
                        if (this.m_List[i] != null)
                            this.DealDamage(this.m_List[i]);
                    }

                    this.m_List.Clear();
                    this.m_List = new List<Mobile>();
                }
            }

            public override bool OnMoveOver(Mobile m)
            {
                if (this.m_MinDamage != 0)
                {
                    if (m_Owner == null || m == m_Owner || !m_Owner.CanBeHarmful(m))
                        return true;

                    if (Utilitky.IsPlayersPet(m))
                    {
                        this.DealDamage(m);
                    }
                    else if (m.Player && m.AccessLevel == AccessLevel.Player)
                        this.DealDamage(m);
                }

                return true;
            }

            public void DealDamage(Mobile m)
            {
                m.RevealingAction();

                if (m_Owner != null)
                    m_Owner.DoHarmful(m);

                int auradamage = AOS.Scale(m.HitsMax, Utility.RandomMinMax(m_MinDamage, m_MaxDamage));

                m.Hits -= auradamage;
                ISTile5.SendDmgPacket(m, auradamage);

                if (m.Hits < 2)
                    m.Kill();
            }

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

            public override void Serialize(GenericWriter writer)
            {
                // Unsaved.
            }

            public override void Deserialize(GenericReader reader)
            {
            }
        }
        #endregion

        #region CrimsonMeteor
        public static void CrimsonMeteor(Mobile from, int damage)
        {
            from.PublicOverheadMessage(MessageType.Regular, 193, true, "*Shooting Meteor*");

            new CrimsonMeteorTimer(from, damage).Start();
        }

        public class CrimsonMeteorTimer : Timer
        {
            private Mobile m_From;
            private int m_Damage;
            private int m_Count;
            private int m_MaxCount;
            private Point3D m_LastTarget;
            private Point3D m_ShowerLocation;

            public CrimsonMeteorTimer(Mobile from, int damage)
                : base(TimeSpan.FromMilliseconds(300.0), TimeSpan.FromMilliseconds(300.0))
            {
                this.m_From = from;
                this.m_Damage = damage;
                this.m_Count = 0;
                this.m_MaxCount = 30;
                this.m_LastTarget = new Point3D(0, 0, 0);
                this.m_ShowerLocation = new Point3D(from.Location);
            }

            protected override void OnTick()
            {
                if (this.m_From == null || this.m_From.Deleted)
                {
                    this.Stop();
                    return;
                }

                new FireField(this.m_From, 40, this.m_Damage, this.m_Damage, Utility.RandomBool(), this.m_LastTarget, this.m_From.Map);

                Point3D point = new Point3D();
                int tries = 0;

                while (tries < 5)
                {
                    point.X = this.m_ShowerLocation.X += Utility.RandomMinMax(-5, 5);
                    point.Y = this.m_ShowerLocation.Y += Utility.RandomMinMax(-5, 5);
                    point.Z = this.m_From.Map.GetAverageZ(point.X, point.Y);

                    if (this.m_From.CanSee(point))
                        break;

                    tries++;
                }

                Effects.SendMovingParticles(
                    new Entity(Serial.Zero, new Point3D(point.X, point.Y, point.Z + 30), this.m_From.Map),
                    new Entity(Serial.Zero, point, this.m_From.Map),
                    0x36D4, 5, 0, false, false, 0, 0, 9502, 1, 0, (EffectLayer)255, 0x100);

                Effects.PlaySound(point, this.m_From.Map, 0x11D);

                this.m_LastTarget = point;
                this.m_Count++;

                if (this.m_Count >= this.m_MaxCount)
                {
                    this.Stop();
                    return;
                }
            }
        }
        #endregion
    }
}
