/// <summary>
        /// Handles movement by a monster.
        /// </summary>
        /// <param name="monster">The monster to handle.</param>
        private static void HandleMovement(Models.Entities.Monster monster)
        {
            if (!monster.Alive)
            {
                return;
            }

            var target = monster.Target as Models.Maps.IMapObject;

            if (monster.IsGuard || monster.Behaviour == Enums.MonsterBehaviour.Peaceful || target != null)
            {
                if (DateTime.UtcNow >= monster.NextMoveTime)
                {
                    byte dir           = 0;
                    int  nextMoveSpeed = 0;

                    if (monster.IsGuard || monster.Behaviour == Enums.MonsterBehaviour.Peaceful && target == null || Tools.RangeTools.GetDistance(monster.X, monster.Y, target.X, target.Y) >= monster.ViewRange)
                    {
                        dir           = (byte)Drivers.Repositories.Safe.Random.Next(8);
                        nextMoveSpeed = Drivers.Repositories.Safe.Random.Next(monster.MoveSpeed * 4, monster.MoveSpeed * 6);
                    }
                    else
                    {
                        dir = (byte)Tools.RangeTools.GetFacing(
                            Tools.RangeTools.GetAngle(monster.X, monster.Y, target.X, target.Y));
                        nextMoveSpeed = Drivers.Repositories.Safe.Random.Next(monster.MoveSpeed, monster.MoveSpeed * 2);
                    }

                    monster.NextMoveTime = DateTime.UtcNow.AddMilliseconds(nextMoveSpeed);
                    var location = Controllers.Maps.MapController.CreateDirectionPoint(monster.X, monster.Y, dir);

                    if (monster.ValidMoveCoord <Models.Entities.Monster>(location.X, location.Y))
                    {
                        monster.Direction = (Enums.Direction)dir;
                        monster.X         = location.X;
                        monster.Y         = location.Y;

                        monster.UpdateScreen(false, new Models.Packets.Location.WalkPacket
                        {
                            Direction = monster.Direction,
                            ClientId  = monster.ClientId,
                            Mode      = Enums.WalkMode.Run,
                            Timestamp = Drivers.Time.GetSystemTime()
                        });
                    }
                }
            }
        }
        /// <summary>
        /// Handles guards.
        /// </summary>
        /// <param name="guard">The guard to handle.</param>
        private static void HandleGuard(Models.Entities.Monster guard)
        {
            switch (guard.Behaviour)
            {
                #region Magic Guard
            case Enums.MonsterBehaviour.MagicGuard:
            {
                var target = guard.FindInScreen <Controllers.Entities.AttackableEntityController>(
                    entity =>
                    {
                        if (entity != null)
                        {
                            var player = entity as Models.Entities.Player;
                            if (player != null)
                            {
                                return(player.ContainsStatusFlag(Enums.StatusFlag.BlueName) &&
                                       player.Alive &&
                                       Tools.RangeTools.GetDistance(player.X, player.Y, guard.X, guard.Y) <= guard.AttackRange);
                            }

                            var monster = entity as Models.Entities.Monster;
                            if (monster != null)
                            {
                                return(monster.Alive &&
                                       !monster.IsGuard &&
                                       Tools.RangeTools.GetDistance(monster.X, monster.Y, guard.X, guard.Y) <= guard.AttackRange);
                            }
                        }

                        return(false);
                    }
                    );

                if (target != null)
                {
                    Helpers.Packets.Interaction.Battle.Magic
                    .Handle(guard,
                            new Models.Packets.Entities.InteractionPacket
                        {
                            Action         = Enums.InteractionAction.MagicAttack,
                            MagicType      = 1002,
                            ClientId       = guard.ClientId,
                            TargetClientId = target.AttackableEntity.ClientId,
                            X = target.MapObject.X,
                            Y = target.MapObject.Y
                        });
                }
                break;
            }
                #endregion

                #region Physical Guard
            case Enums.MonsterBehaviour.PhysicalGuard:
            {
                var target = guard.FindInScreen <Models.Entities.Player>(
                    player =>
                    {
                        if (player != null)
                        {
                            return((player.ContainsStatusFlag(Enums.StatusFlag.BlueName) ||
                                    player.PKPoints >= 100) &&
                                   player.Alive &&
                                   Tools.RangeTools.GetDistance(player.X, player.Y, guard.X, guard.Y) <= guard.ViewRange);
                        }

                        return(false);
                    }
                    );

                if (Tools.RangeTools.GetDistanceU(guard.X, guard.Y, guard.OriginalX, guard.OriginalY) >= (ulong)(guard.ViewRange * 2))
                {
                    if (target != null)
                    {
                        target.ClientSocket.Send(guard.GetRemoveSpawnPacket());
                    }

                    guard.Teleport(guard.MapId, guard.OriginalX, guard.OriginalY);

                    target = null;
                }

                if (target != null)
                {
                    if (Tools.RangeTools.GetDistanceU(guard.X, guard.Y, target.X, target.Y) > 1)
                    {
                        var nearest = target.NearBy();
                        guard.X = nearest.X;
                        guard.Y = nearest.Y;

                        guard.UpdateScreen(false, new Models.Packets.Client.DataExchangePacket
                            {
                                ExchangeType = Enums.ExchangeType.Jump,
                                Data1Low     = nearest.X,
                                Data1High    = nearest.Y,
                                ClientId     = guard.ClientId,
                                Timestamp    = Drivers.Time.GetSystemTime()
                            });
                    }

                    if (Tools.CalculationTools.ChanceSuccess(33))
                    {
                        Helpers.Packets.Interaction.Battle.Physical
                        .Handle(guard,
                                new Models.Packets.Entities.InteractionPacket
                            {
                                Action         = Enums.InteractionAction.Attack,
                                ClientId       = guard.ClientId,
                                TargetClientId = target.ClientId,
                                X = target.X,
                                Y = target.Y
                            });
                    }
                }
                break;
            }
                #endregion

                #region Death Guard
            case Enums.MonsterBehaviour.DeathGuard:
            {
                var target = guard.FindInScreen <Controllers.Entities.AttackableEntityController>(
                    entity =>
                    {
                        if (entity != null)
                        {
                            var player = entity as Models.Entities.Player;
                            if (player != null)
                            {
                                return((player.ContainsStatusFlag(Enums.StatusFlag.BlueName) ||
                                        player.PKPoints >= 100) &&
                                       player.Alive &&
                                       Tools.RangeTools.GetDistance(player.X, player.Y, guard.X, guard.Y) <= guard.ViewRange);
                            }

                            var monster = entity as Models.Entities.Monster;
                            if (monster != null)
                            {
                                return(monster.Alive &&
                                       !monster.IsGuard &&
                                       Tools.RangeTools.GetDistance(monster.X, monster.Y, guard.X, guard.Y) <= guard.AttackRange);
                            }
                        }

                        return(false);
                    }
                    );

                if (target != null)
                {
                    Helpers.Packets.Interaction.Battle.Magic
                    .Handle(guard,
                            new Models.Packets.Entities.InteractionPacket
                        {
                            Action         = Enums.InteractionAction.MagicAttack,
                            MagicType      = 1002,
                            ClientId       = guard.ClientId,
                            TargetClientId = target.AttackableEntity.ClientId,
                            X = target.MapObject.X,
                            Y = target.MapObject.Y
                        });
                }
                break;
            }
                #endregion

                #region Revive Guard
            case Enums.MonsterBehaviour.ReviverGuard1:
            case Enums.MonsterBehaviour.ReviverGuard2:
            {
                if (guard.HP < guard.MaxHP)
                {
                    Helpers.Packets.Interaction.Battle.Magic
                    .Handle(guard,
                            new Models.Packets.Entities.InteractionPacket
                        {
                            Action         = Enums.InteractionAction.MagicAttack,
                            MagicType      = 1190,
                            ClientId       = guard.ClientId,
                            TargetClientId = guard.ClientId,
                            X = guard.X,
                            Y = guard.Y
                        });
                }

                var target = guard.FindInScreen <Models.Entities.Player>(
                    player =>
                    {
                        if (player != null)
                        {
                            return(!player.Alive &&
                                   Tools.RangeTools.GetDistance(player.X, player.Y, guard.X, guard.Y) <= guard.ViewRange);
                        }

                        return(false);
                    }
                    );

                if (target != null)
                {
                    Helpers.Packets.Interaction.Battle.Magic
                    .Handle(guard,
                            new Models.Packets.Entities.InteractionPacket
                        {
                            Action         = Enums.InteractionAction.MagicAttack,
                            MagicType      = 1100,
                            ClientId       = guard.ClientId,
                            TargetClientId = target.ClientId,
                            X = target.X,
                            Y = target.Y
                        });

                    if (guard.Behaviour == Enums.MonsterBehaviour.ReviverGuard1)
                    {
                        target.Teleport(target.MapId);
                    }
                }
                break;
            }
                #endregion
            }
        }
 /// <summary>
 /// Handles a monster by the thread.
 /// </summary>
 /// <param name="monster">The monster to handle.</param>
 public static void HandleMonster(Models.Entities.Monster monster)
 {
     _monsters.TryAdd(monster.ClientId, monster);
 }
        /// <summary>
        /// Handles attack for a monster.
        /// </summary>
        /// <param name="monster">The monster to handle attack for.</param>
        private static void HandleAttack(Models.Entities.Monster monster)
        {
            if (!monster.Alive)
            {
                return;
            }

            #region Poison
            if (monster.ContainsStatusFlag(Enums.StatusFlag.Poisoned))
            {
                if (DateTime.UtcNow >= monster.NextPoison)
                {
                    monster.NextPoison = DateTime.UtcNow.AddMilliseconds(3000);

                    if (monster.PoisonEffect > 0)
                    {
                        uint damage = (uint)Math.Max(1, (monster.HP / 100) * monster.PoisonEffect);

                        if (monster.HP > damage)
                        {
                            Helpers.Packets.Interaction.Battle.Damage.Hit(null, monster, damage);

                            var poisonPacket = new Models.Packets.Entities.InteractionPacket
                            {
                                Action         = Enums.InteractionAction.Attack,
                                ClientId       = monster.ClientId,
                                TargetClientId = monster.ClientId,
                                X    = monster.X,
                                Y    = monster.Y,
                                Data = damage
                            };

                            monster.UpdateScreen(false, poisonPacket);
                        }
                        else
                        {
                            monster.PoisonEffect = 0;
                            monster.RemoveStatusFlag(Enums.StatusFlag.Poisoned);
                        }
                    }
                    else
                    {
                        monster.RemoveStatusFlag(Enums.StatusFlag.Poisoned);
                    }
                }
            }
            #endregion

            var target = monster.Target as Models.Maps.IMapObject;

            if (target != null && target.Alive)
            {
                if (Tools.RangeTools.GetDistance(monster.X, monster.Y, target.X, target.Y) <= monster.AttackRange &&
                    monster.ContainsInScreen(target.ClientId) && DateTime.UtcNow >= monster.NextAttackTime)
                {
                    monster.NextAttackTime = DateTime.UtcNow.AddMilliseconds(
                        Drivers.Repositories.Safe.Random.Next(monster.AttackSpeed, monster.AttackSpeed * 3));

                    Helpers.Packets.Interaction.Battle.Physical.Handle(monster, new Models.Packets.Entities.InteractionPacket
                    {
                        Action         = Enums.InteractionAction.Attack,
                        ClientId       = monster.ClientId,
                        TargetClientId = target.ClientId,
                        X = target.X,
                        Y = target.Y
                    });
                    return;
                }
            }

            var possibleTarget = monster.FindClosest <Models.Entities.Player>();
            if (possibleTarget != null &&
                possibleTarget.Alive &&
                !possibleTarget.ContainsStatusFlag(Enums.StatusFlag.PartiallyInvisible))
            {
                if (monster.Behaviour == Enums.MonsterBehaviour.Peaceful &&
                    (possibleTarget.Target == null || possibleTarget.Target.ClientId != monster.ClientId))
                {
                    monster.Target = null;
                }
                else
                {
                    monster.Target = possibleTarget;
                }
            }
            else
            {
                monster.Target = null;
            }

            monster.Idle = possibleTarget == null;
        }