GetDistance() public static method

public static GetDistance ( Character character1, Character character2 ) : int
character1 Character
character2 Character
return int
Beispiel #1
0
        private void Move()
        {
            // Normal Move Mode
            if (Monster == null || !IsAlive)
            {
                return;
            }

            if (IsMoving && Monster.Speed > 0)
            {
                double time = (DateTime.Now - LastMove).TotalMilliseconds;

                if (Path.Any(s => s != null)) // move back to initial position after following target
                {
                    int timetowalk = 2000 / Monster.Speed;
                    if (time > timetowalk)
                    {
                        int mapX = Path.ElementAt(0).X;
                        int mapY = Path.ElementAt(0).Y;
                        Path.RemoveAt(0);
                        Observable.Timer(TimeSpan.FromMilliseconds(timetowalk))
                        .Subscribe(
                            x =>
                        {
                            MapX = (short)mapX;
                            MapY = (short)mapY;
                        });

                        LastMove = DateTime.Now;
                        MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                        return;
                    }
                }
                else if (time > _movetime)
                {
                    short mapX = FirstX, mapY = FirstY;
                    if (MapInstance.Map?.GetFreePosition(ref mapX, ref mapY, (byte)ServerManager.Instance.RandomNumber(0, 2), (byte)_random.Next(0, 2)) ?? false)
                    {
                        int distance = Map.GetDistance(new MapCell {
                            X = mapX, Y = mapY
                        }, new MapCell {
                            X = MapX, Y = MapY
                        });

                        double value = 1000d * distance / (2 * Monster.Speed);
                        Observable.Timer(TimeSpan.FromMilliseconds(value))
                        .Subscribe(
                            x =>
                        {
                            MapX = mapX;
                            MapY = mapY;
                        });

                        LastMove = DateTime.Now.AddMilliseconds(value);
                        MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.All));
                    }
                }
            }
            HostilityTarget();
        }
Beispiel #2
0
        internal IEnumerable <Character> GetCharactersInRange(short mapX, short mapY, byte distance, bool attackGreaterDistance = false)
        {
            List <Character>            characters     = new List <Character>();
            IEnumerable <ClientSession> cl             = Sessions.Where(s => s.HasSelectedCharacter && s.Character.Hp > 0);
            IEnumerable <ClientSession> clientSessions = cl as IList <ClientSession> ?? cl.ToList();

            for (int i = clientSessions.Count() - 1; i >= 0; i--)
            {
                if (!attackGreaterDistance)
                {
                    if (Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY
                    }, new MapCell {
                        X = clientSessions.ElementAt(i).Character.PositionX, Y = clientSessions.ElementAt(i).Character.PositionY
                    }) <= distance + 1)
                    {
                        characters.Add(clientSessions.ElementAt(i).Character);
                    }
                }
                else
                {
                    if (Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY
                    }, new MapCell {
                        X = clientSessions.ElementAt(i).Character.PositionX, Y = clientSessions.ElementAt(i).Character.PositionY
                    }) > distance)
                    {
                        characters.Add(clientSessions.ElementAt(i).Character);
                    }
                }
            }
            return(characters);
        }
Beispiel #3
0
        public long OrderedCharacterId(Character Character)
        {
            order++;
            IEnumerable <ClientSession> lst = Characters.Where(s => Map.GetDistance(s.Character, Character) < 50);

            if (order > lst.Count() - 1)
            {
                order = 0;
            }
            return(lst.ElementAt(order).Character.CharacterId);
        }
Beispiel #4
0
 /// <summary>
 /// Check if the Monster is in the given Range.
 /// </summary>
 /// <param name="mapX">The X coordinate on the Map of the object to check.</param>
 /// <param name="mapY">The Y coordinate on the Map of the object to check.</param>
 /// <param name="distance">The maximum distance of the object to check.</param>
 /// <returns>True if the Monster is in range, False if not.</returns>
 public bool IsInRange(short mapX, short mapY, byte distance)
 {
     return(Map.GetDistance(new MapCell
     {
         X = mapX,
         Y = mapY
     }, new MapCell
     {
         X = MapX,
         Y = MapY
     }) <= distance);
 }
Beispiel #5
0
        /// <summary>
        /// Follow the Monsters target to it's position.
        /// </summary>
        /// <param name="targetSession">The TargetSession to follow</param>
        private void FollowTarget(ClientSession targetSession)
        {
            if (IsMoving)
            {
                short maxDistance = 22;
                int   distance    = 0;
                if (!Path.Any() && targetSession != null)
                {
                    short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                    short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                    try
                    {
                        List <Node> list = BestFirstSearch.TracePath(new Node()
                        {
                            X = MapX, Y = MapY
                        }, targetSession.Character.BrushFire, targetSession.Character.MapInstance.Map.Grid);
                        Path = list;
                    }
                    catch (Exception ex)
                    {
                        Logger.Log.Error($"Pathfinding using Pathfinder failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.PositionX + xoffset)} TargetY: {(short)(targetSession.Character.PositionY + yoffset)}", ex);
                        RemoveTarget();
                    }
                }
                if (Monster != null && DateTime.Now > LastMove && Monster.Speed > 0 && Path.Any())
                {
                    int    maxindex    = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                    short  mapX        = Path.ElementAt(maxindex - 1).X;
                    short  mapY        = Path.ElementAt(maxindex - 1).Y;
                    double waitingtime = Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY
                    }, new MapCell {
                        X = MapX, Y = MapY
                    }) / (double)Monster.Speed;
                    MapInstance.Broadcast(new BroadcastPacket(null, $"mv 3 {MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                    LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                    Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });
                    distance = (int)Path.First().F;
                    Path.RemoveRange(0, maxindex);
                }

                if (targetSession == null || MapId != targetSession.Character.MapInstance.Map.MapId || distance > maxDistance)
                {
                    RemoveTarget();
                }
            }
        }
Beispiel #6
0
        public long?GetNextOrderedCharacterId(Character character)
        {
            _order++;
            List <ClientSession> sessions = Characters.Where(s => Map.GetDistance(s.Character, character) < 50).ToList();

            if (_order > sessions.Count() - 1) // if order wents out of amount of ppl, reset it -> zero based index
            {
                _order = 0;
            }

            if (!sessions.Any()) // group seems to be empty
            {
                return(null);
            }

            return(sessions[_order].Character.CharacterId);
        }
Beispiel #7
0
 internal void GetNearestOponent()
 {
     if (Target == -1)
     {
         const int            maxDistance = 100;
         int                  distance    = 100;
         List <ClientSession> sess        = new List <ClientSession>();
         DamageList.Keys.ToList().ForEach(s => sess.Add(MapInstance.GetSessionByCharacterId(s)));
         ClientSession session = sess.OrderBy(s => distance = Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         })).FirstOrDefault();
         if (distance < maxDistance)
         {
             if (session != null)
             {
                 Target = session.Character.CharacterId;
             }
         }
     }
 }
Beispiel #8
0
 internal void GetNearestOponent()
 {
     if (Target == -1)
     {
         const int            maxDistance = 22;
         int                  distance    = 100;
         List <ClientSession> sess        = new List <ClientSession>();
         DamageList.Keys.ToList().ForEach(s => sess.Add(MapInstance.GetSessionByCharacterId(s)));
         //ClientSession session = sess.OrderBy(s => distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY })).FirstOrDefault();
         Character character = sess.Where(s => s?.Character != null && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)s.Character.Faction != 678) && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapInstance == MapInstance && Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         }) < Monster.NoticeRange).OrderBy(s => distance = Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         })).FirstOrDefault()?.Character;
         if (distance < maxDistance && character != null)
         {
             Target = character.CharacterId;
         }
     }
 }
Beispiel #9
0
        /// <summary>
        /// Remove the current Target from Monster.
        /// </summary>
        internal void RemoveTarget()
        {
            Path = MapInstance.Map.StraightPath(new GridPos {
                x = MapX, y = MapY
            }, new GridPos {
                x = FirstX, y = FirstY
            });
            if (!Path.Any())
            {
                Path = Map.JPSPlus(JumpPointParameters, new GridPos {
                    x = MapX, y = MapY
                }, new GridPos {
                    x = FirstX, y = FirstY
                });
            }
            Target = -1;
            int nearestDistance = 100;

            foreach (KeyValuePair <long, long> kvp in DamageList)
            {
                ClientSession session = MapInstance.GetSessionByCharacterId(kvp.Key);
                if (session != null)
                {
                    int distance = Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = session.Character.PositionX, Y = session.Character.PositionY
                    });
                    if (distance < nearestDistance)
                    {
                        nearestDistance = distance;
                        Target          = session.Character.CharacterId;
                    }
                }
            }
        }
Beispiel #10
0
        internal void NpcLife()
        {
            double time = (DateTime.Now - LastEffect).TotalMilliseconds;

            if (Effect > 0 && time > EffectDelay)
            {
                Map.Broadcast(GenerateEff(), MapX, MapY);
                LastEffect = DateTime.Now;
            }

            time = (DateTime.Now - LastMove).TotalMilliseconds;
            if (IsMoving && Npc.Speed > 0 && time > _movetime)
            {
                _movetime = _random.Next(500, 3000);
                byte point  = (byte)_random.Next(2, 4);
                byte fpoint = (byte)_random.Next(0, 2);

                byte xpoint = (byte)_random.Next(fpoint, point);
                byte ypoint = (byte)(point - xpoint);

                short mapX = FirstX;
                short mapY = FirstY;

                if (Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                {
                    Observable.Timer(TimeSpan.FromMilliseconds(1000 * (xpoint + ypoint) / (2 * Npc.Speed)))
                    .Subscribe(
                        x =>
                    {
                        this.MapX = mapX;
                        this.MapY = mapY;
                    });

                    LastMove = DateTime.Now.AddSeconds((xpoint + ypoint) / (2 * Npc.Speed));
                    Map.Broadcast(new BroadcastPacket(null, GenerateMv2(), ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                }
            }
            if (Target == -1)
            {
                if (this.Npc.IsHostile && this.Shop == null)
                {
                    MapMonster monster = this.Map.Monsters.FirstOrDefault(s => MapId == s.MapId && Map.GetDistance(new MapCell()
                    {
                        X = MapX, Y = MapY
                    }, new MapCell()
                    {
                        X = s.MapX, Y = s.MapY
                    }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange));
                    ClientSession session = this.Map.Sessions.FirstOrDefault(s => MapId == s.Character.MapId && Map.GetDistance(new MapCell()
                    {
                        X = MapX, Y = MapY
                    }, new MapCell()
                    {
                        X = s.Character.MapX, Y = s.Character.MapY
                    }) < Npc.NoticeRange);

                    if (monster != null && session != null)
                    {
                        Target = monster.MapMonsterId;
                    }
                }
            }
            else if (Target != -1)
            {
                MapMonster monster = this.Map.Monsters.FirstOrDefault(s => s.MapMonsterId == Target);
                if (monster == null || monster.CurrentHp < 1)
                {
                    Target = -1;
                    return;
                }
                NpcMonsterSkill npcMonsterSkill = null;
                if (_random.Next(10) > 8)
                {
                    npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                }

                short damage   = 100;
                int   distance = Map.GetDistance(new MapCell()
                {
                    X = MapX, Y = MapY
                }, new MapCell()
                {
                    X = monster.MapX, Y = monster.MapY
                });
                if (monster != null && monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || (distance <= Npc.BasicRange)))
                {
                    if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + Npc.BasicCooldown * 200 && !Npc.Skills.Any()) || npcMonsterSkill != null)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastSkillUse = DateTime.Now;
                            Map.Broadcast($"ct 2 {MapNpcId} 3 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}");
                        }

                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            Map.Broadcast(GenerateEff());
                        }

                        monster.CurrentHp -= damage;

                        if (npcMonsterSkill != null)
                        {
                            Map.Broadcast($"su 2 {MapNpcId} 3 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} { (int)(monster.CurrentHp / monster.Monster.MaxHP * 100) } {damage} 0 0");
                        }
                        else
                        {
                            Map.Broadcast($"su 2 {MapNpcId} 3 {Target} 0 {Npc.BasicCooldown} 11 {Npc.BasicSkill} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} { (int)(monster.CurrentHp / monster.Monster.MaxHP * 100) } {damage} 0 0");
                        }

                        LastEffect = DateTime.Now;
                        if (monster.CurrentHp < 1)
                        {
                            if (IsMoving)
                            {
                                Path = Map.StraightPath(new GridPos()
                                {
                                    x = this.MapX, y = this.MapY
                                }, new GridPos()
                                {
                                    x = FirstX, y = FirstY
                                });
                                if (!Path.Any())
                                {
                                    Path = Map.JPSPlus(JumpPointParameters, new GridPos()
                                    {
                                        x = this.MapX, y = this.MapY
                                    }, new GridPos()
                                    {
                                        x = FirstX, y = FirstY
                                    });
                                }
                            }

                            monster.IsAlive   = false;
                            monster.LastMove  = DateTime.Now;
                            monster.CurrentHp = 0;
                            monster.CurrentMp = 0;
                            monster.Death     = DateTime.Now;
                            Target            = -1;
                        }
                    }
                }
                else
                {
                    int maxdistance = (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange);
                    if (IsMoving)
                    {
                        short maxDistance = 5;
                        if (Path.Count() == 0 && monster != null && distance > 1 && distance < maxDistance)
                        {
                            short xoffset = (short)_random.Next(-1, 1);
                            short yoffset = (short)_random.Next(-1, 1);

                            Path = Map.StraightPath(new GridPos()
                            {
                                x = this.MapX, y = this.MapY
                            }, new GridPos()
                            {
                                x = (short)(monster.MapX + xoffset), y = (short)(monster.MapY + yoffset)
                            });
                            if (!Path.Any())
                            {
                                Path = Map.JPSPlus(JumpPointParameters, new GridPos()
                                {
                                    x = this.MapX, y = this.MapY
                                }, new GridPos()
                                {
                                    x = (short)(monster.MapX + xoffset), y = (short)(monster.MapY + yoffset)
                                });
                            }
                        }
                        if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Any())
                        {
                            short mapX;
                            short mapY;
                            int   maxindex = (Path.Count > Npc.Speed / 2 && Npc.Speed > 1) ? Npc.Speed / 2 : Path.Count;
                            mapX = (short)Path.ElementAt(maxindex - 1).x;
                            mapY = (short)Path.ElementAt(maxindex - 1).y;
                            double waitingtime = (double)(Map.GetDistance(new MapCell()
                            {
                                X = mapX, Y = mapY, MapId = MapId
                            }, new MapCell()
                            {
                                X = MapX, Y = MapY, MapId = MapId
                            })) / (double)(Npc.Speed);
                            Map.Broadcast(new BroadcastPacket(null, $"mv 2 {this.MapNpcId} {mapX} {mapY} {Npc.Speed}", ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                            LastMove = DateTime.Now.AddSeconds((waitingtime > 1 ? 1 : waitingtime));

                            Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000)))
                            .Subscribe(
                                x =>
                            {
                                this.MapX = mapX;
                                this.MapY = mapY;
                            });

                            for (int j = maxindex; j > 0; j--)
                            {
                                Path.RemoveAt(0);
                            }
                        }
                        if (Path.Count() == 0 && (monster == null || MapId != monster.MapId || distance > maxDistance))
                        {
                            Path = Map.StraightPath(new GridPos()
                            {
                                x = this.MapX, y = this.MapY
                            }, new GridPos()
                            {
                                x = FirstX, y = FirstY
                            });
                            if (!Path.Any())
                            {
                                Path = Map.JPSPlus(JumpPointParameters, new GridPos()
                                {
                                    x = this.MapX, y = this.MapY
                                }, new GridPos()
                                {
                                    x = FirstX, y = FirstY
                                });
                            }
                            Target = -1;
                        }
                    }
                    else
                    {
                        if (distance > maxdistance)
                        {
                            Target = -1;
                        }
                    }
                }
            }
        }
Beispiel #11
0
        private void Move()
        {
            // Normal Move Mode
            if (Monster == null || !IsAlive)
            {
                return;
            }

            if (IsMoving && Monster.Speed > 0)
            {
                double time = (DateTime.Now - LastMove).TotalMilliseconds;

                if (Path.Where(s => s != null).Any())
                {
                    int timetowalk = 2000 / (Monster.Speed);
                    if (time > timetowalk)
                    {
                        int mapX = Path.ElementAt(0).x;
                        int mapY = Path.ElementAt(0).y;
                        Path.RemoveAt(0);
                        Observable.Timer(TimeSpan.FromMilliseconds(timetowalk))
                        .Subscribe(
                            x =>
                        {
                            MapX = (short)mapX;
                            MapY = (short)mapY;
                        });

                        LastMove = DateTime.Now;
                        Map.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                        return;
                    }
                }
                else if (time > _movetime)
                {
                    _movetime = _random.Next(600, 3000);
                    byte point  = (byte)_random.Next(2, 4);
                    byte fpoint = (byte)_random.Next(0, 2);

                    byte xpoint = (byte)_random.Next(fpoint, point);
                    byte ypoint = (byte)(point - xpoint);

                    short mapX = FirstX;
                    short mapY = FirstY;
                    if (Map?.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint) ?? false)
                    {
                        Observable.Timer(TimeSpan.FromMilliseconds(1000 * (xpoint + ypoint) / (2 * Monster.Speed)))
                        .Subscribe(
                            x =>
                        {
                            this.MapX = mapX;
                            this.MapY = mapY;
                        });

                        LastMove = DateTime.Now.AddSeconds((xpoint + ypoint) / (2 * Monster.Speed));
                        Map.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                    }
                }
            }

            if (Monster.IsHostile)
            {
                Character character = ServerManager.Instance.Sessions.FirstOrDefault(s => s != null && s.Character != null && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapId == MapId && Map.GetDistance(new MapCell()
                {
                    X = MapX, Y = MapY
                }, new MapCell()
                {
                    X = s.Character.MapX, Y = s.Character.MapY
                }) < Monster.NoticeRange)?.Character;
                if (character != null)
                {
                    Target = character.CharacterId;
                    if (!Monster.NoAggresiveIcon)
                    {
                        character.Session.SendPacket(GenerateEff(5000));
                    }
                }
            }
        }
Beispiel #12
0
        private void npcLife()
        {
            // Respawn
            if (CurrentHp <= 0 && ShouldRespawn != null && !ShouldRespawn.Value)
            {
                MapInstance.RemoveNpc(this);
                MapInstance.Broadcast(GenerateOut());
            }

            if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= Npc.RespawnTime / 10d)
                {
                    Respawn();
                }
            }

            if (LastProtectedEffect.AddMilliseconds(6000) <= DateTime.Now)
            {
                LastProtectedEffect = DateTime.Now;
                if (IsMate || IsProtected)
                {
                    MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY);
                }
            }

            double time = (DateTime.Now - LastEffect).TotalMilliseconds;

            if (EffectDelay > 0)
            {
                if (time > EffectDelay)
                {
                    if (Effect > 0 && EffectActivated)
                    {
                        MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY);
                    }

                    LastEffect = DateTime.Now;
                }
            }

            time = (DateTime.Now - LastMove).TotalMilliseconds;
            if (Target == -1 && IsMoving && Npc.Speed > 0 && time > _movetime && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible))
            {
                _movetime = ServerManager.RandomNumber(500, 3000);
                int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                if (maxindex < 1)
                {
                    maxindex = 1;
                }
                if (Path.Count == 0 || Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null)
                {
                    short xoffset = (short)ServerManager.RandomNumber(-1, 1);
                    short yoffset = (short)ServerManager.RandomNumber(-1, 1);

                    MapCell moveToPosition = new MapCell {
                        X = FirstX, Y = FirstY
                    };
                    if (RunToX != 0 || RunToY != 0)
                    {
                        moveToPosition = new MapCell {
                            X = RunToX, Y = RunToY
                        };
                        _movetime = ServerManager.RandomNumber(300, 1200);
                    }
                    Path = BestFirstSearch.FindPathJagged(new GridPos {
                        X = MapX, Y = MapY
                    }, new GridPos {
                        X = (short)ServerManager.RandomNumber(moveToPosition.X - 3, moveToPosition.X + 3), Y = (short)ServerManager.RandomNumber(moveToPosition.Y - 3, moveToPosition.Y + 3)
                    }, MapInstance.Map.JaggedGrid);
                    maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                }
                if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0)
                {
                    byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5);
                    maxindex = Path.Count > speedIndex ? speedIndex : Path.Count;
                    short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1);
                    short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1);

                    //short mapX = Path[maxindex - 1].X;
                    //short mapY = Path[maxindex - 1].Y;
                    double waitingtime = Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY
                    }, new MapCell {
                        X = MapX, Y = MapY
                    }) / (double)Npc.Speed;
                    MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                    LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                    Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });

                    Path.RemoveRange(0, maxindex);
                }
            }
            if (Target == -1)
            {
                if (IsHostile && Shop == null)
                {
                    MapMonster    monster = MapInstance.GetMonsterInRangeList(MapX, MapY, (byte)(Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)).Where(s => BattleEntity.CanAttackEntity(s.BattleEntity)).FirstOrDefault();
                    ClientSession session = MapInstance.Sessions.FirstOrDefault(s => BattleEntity.CanAttackEntity(s.Character.BattleEntity) && MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = s.Character.PositionX, Y = s.Character.PositionY
                    }) < Npc.NoticeRange);

                    if (monster != null)
                    {
                        Target = monster.MapMonsterId;
                    }
                    if (session?.Character != null)
                    {
                        Target = session.Character.CharacterId;
                    }
                }
            }
            else if (Target != -1)
            {
                MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target);
                if (monster == null || monster.CurrentHp < 1)
                {
                    Target = -1;
                    return;
                }
                NpcMonsterSkill npcMonsterSkill = null;
                if (ServerManager.RandomNumber(0, 10) > 8)
                {
                    npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                }
                int  hitmode   = 0;
                bool onyxWings = false;
                int  damage    = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings);
                if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card)
                {
                    int reduce = damage / 100 * card.FirstData;
                    if (monster.CurrentMp < reduce)
                    {
                        reduce            = (int)monster.CurrentMp;
                        monster.CurrentMp = 0;
                    }
                    else
                    {
                        monster.DecreaseMp(reduce);
                    }
                    damage -= reduce;
                }
                int distance = Map.GetDistance(new MapCell {
                    X = MapX, Y = MapY
                }, new MapCell {
                    X = monster.MapX, Y = monster.MapY
                });
                if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange) && !HasBuff(CardType.SpecialAttack, (byte)AdditionalTypes.SpecialAttack.NoAttack))
                {
                    if (((DateTime.Now - LastSkill).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) /* && Skills.Count == 0*/) || npcMonsterSkill != null)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastSkillUse = DateTime.Now;
                            MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, UserType.Monster, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum));
                        }

                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect));
                        }
                        monster.BattleEntity.GetDamage(damage, BattleEntity);
                        lock (monster.DamageList)
                        {
                            if (!monster.DamageList.Any(s => s.Key.MapEntityId == MapNpcId))
                            {
                                monster.AddToAggroList(BattleEntity);
                            }
                        }
                        MapInstance.Broadcast(npcMonsterSkill != null
                            ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0)
                            : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0));
                        LastSkill = DateTime.Now;

                        if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 2)
                        {
                            IEnumerable <ClientSession> clientSessions =
                                MapInstance.Sessions?.Where(s =>
                                                            s.Character.IsInRange(MapX,
                                                                                  MapY, npcMonsterSkill.Skill.TargetRange));
                            IEnumerable <Mate> mates = MapInstance.GetListMateInRange(MapX, MapY, npcMonsterSkill.Skill.TargetRange);

                            foreach (BCard skillBcard in npcMonsterSkill.Skill.BCards)
                            {
                                if (skillBcard.Type == 25 && skillBcard.SubType == 1 && new Buff((short)skillBcard.SecondData, Npc.Level)?.Card?.BuffType == BuffType.Good)
                                {
                                    if (clientSessions != null)
                                    {
                                        foreach (ClientSession clientSession in clientSessions)
                                        {
                                            if (clientSession.Character != null)
                                            {
                                                if (!BattleEntity.CanAttackEntity(clientSession.Character.BattleEntity))
                                                {
                                                    skillBcard.ApplyBCards(clientSession.Character.BattleEntity, BattleEntity);
                                                }
                                            }
                                        }
                                    }
                                    if (mates != null)
                                    {
                                        foreach (Mate mate in mates)
                                        {
                                            if (!BattleEntity.CanAttackEntity(mate.BattleEntity))
                                            {
                                                skillBcard.ApplyBCards(mate.BattleEntity, BattleEntity);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (monster.CurrentHp < 1 && monster.SetDeathStatement())
                        {
                            monster.RunDeathEvent();
                            RemoveTarget();
                        }
                    }
                }
                else
                {
                    int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange;
                    if (IsMoving && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible))
                    {
                        const short maxDistance = 5;
                        int         maxindex    = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                        if (maxindex < 1)
                        {
                            maxindex = 1;
                        }
                        if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null))
                        {
                            short xoffset = (short)ServerManager.RandomNumber(-1, 1);
                            short yoffset = (short)ServerManager.RandomNumber(-1, 1);

                            //go to monster
                            Path = BestFirstSearch.FindPathJagged(new GridPos {
                                X = MapX, Y = MapY
                            }, new GridPos {
                                X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset)
                            }, MapInstance.Map.JaggedGrid);
                            maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                        }
                        if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0)
                        {
                            byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5);
                            maxindex = Path.Count > speedIndex ? speedIndex : Path.Count;
                            //short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1);
                            //short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1);

                            short  mapX        = Path[maxindex - 1].X;
                            short  mapY        = Path[maxindex - 1].Y;
                            double waitingtime = Map.GetDistance(new MapCell {
                                X = mapX, Y = mapY
                            }, new MapCell {
                                X = MapX, Y = MapY
                            }) / (double)Npc.Speed;
                            MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                            LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                            Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x =>
                            {
                                MapX = mapX;
                                MapY = mapY;
                            });

                            Path.RemoveRange(0, maxindex);
                        }
                        if (Target != -1 && (MapId != monster.MapId || distance > maxDistance))
                        {
                            RemoveTarget();
                        }
                    }
                }
            }
        }
Beispiel #13
0
        internal void MonsterLife()
        {
            //Respawn
            if (!Alive && Respawn)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= Monster.RespawnTime / 10)
                {
                    DamageList = new Dictionary <long, long>();
                    Alive      = true;
                    Target     = -1;
                    CurrentHp  = Monster.MaxHP;
                    CurrentMp  = Monster.MaxMP;
                    MapX       = firstX;
                    MapY       = firstY;
                    Path       = new List <MapCell>();
                    Map.Broadcast(GenerateIn3());
                    Map.Broadcast(GenerateEff(7));
                }
                return;
            }
            else if (Target == -1)
            {
                //Normal Move Mode
                if (Alive == false)
                {
                    return;
                }
                Random random       = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
                double time         = (DateTime.Now - LastMove).TotalSeconds;
                int    MoveFrequent = 5 - (int)Math.Round((double)(Monster.Speed / 5));
                if (MoveFrequent < 1)
                {
                    MoveFrequent = 1;
                }
                if (IsMoving)
                {
                    if (Path.Where(s => s != null).ToList().Count > 0)
                    {
                        if ((DateTime.Now - LastMove).TotalSeconds > 1.0 / Monster.Speed)
                        {
                            short mapX = Path.ElementAt(0).X;
                            short mapY = Path.ElementAt(0).Y;
                            Path.RemoveAt(0);
                            LastMove = DateTime.Now;
                            Map.Broadcast($"mv 3 {this.MapMonsterId} {this.MapX} {this.MapY} {Monster.Speed}");

                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(400);
                                this.MapX = mapX;
                                this.MapY = mapY;
                            });
                            return;
                        }
                    }
                    else if (time > 0.5 * random.Next(1, 3) * (0.5 + random.NextDouble()))
                    {
                        byte point  = (byte)random.Next(2, 4);
                        byte fpoint = (byte)random.Next(0, 2);

                        byte xpoint = (byte)random.Next(fpoint, point);
                        byte ypoint = (byte)(point - xpoint);

                        short mapX = firstX;
                        short mapY = firstY;
                        if (ServerManager.GetMap(MapId).GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                        {
                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(400);
                                this.MapX = mapX;
                                this.MapY = mapY;
                            });
                            LastMove = DateTime.Now;

                            string movePacket = $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}";
                            Map.Broadcast(movePacket);
                        }
                    }
                }
                if (Monster.IsHostile)
                {
                    Character character = ServerManager.Instance.Sessions.Where(s => s.Character != null && s.Character.Hp > 0).OrderBy(s => Map.GetDistance(new MapCell()
                    {
                        X = MapX, Y = MapY
                    }, new MapCell()
                    {
                        X = s.Character.MapX, Y = s.Character.MapY
                    })).FirstOrDefault(s => s.Character != null && !s.Character.Invisible && s.Character.MapId == MapId)?.Character;
                    if (character != null)
                    {
                        if (Map.GetDistance(new MapCell()
                        {
                            X = character.MapX, Y = character.MapY
                        }, new MapCell()
                        {
                            X = MapX, Y = MapY
                        }) < 10)
                        {
                            Target = character.CharacterId;
                            if (!Monster.NoAggresiveIcon)
                            {
                                character.Session.SendPacket(GenerateEff(5000));
                            }
                        }
                    }
                }
            }
            else
            {
                ClientSession targetSession = Map.Sessions.SingleOrDefault(s => s.Character.CharacterId == Target);

                if (targetSession == null || targetSession.Character.Invisible)
                {
                    Target = -1;
                    return;
                }
                Random          random          = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
                NpcMonsterSkill npcMonsterSkill = null;
                if (random.Next(10) > 8 || inWaiting)
                {
                    inWaiting = false;
                    if ((DateTime.Now - LastEffect).TotalMilliseconds < Monster.BasicCooldown * 200)
                    {
                        inWaiting = true;
                    }
                    npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => random.Next()).FirstOrDefault();
                }

                int damage = 100;

                if (targetSession != null && targetSession.Character.Hp > 0 && ((npcMonsterSkill != null && CurrentMp - npcMonsterSkill.Skill.MpCost >= 0 && Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                }) < npcMonsterSkill.Skill.Range) || (Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                }) <= Monster.BasicRange)))
                {
                    if ((DateTime.Now - LastEffect).TotalMilliseconds >= Monster.BasicCooldown * 200 && !inWaiting)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastUse = DateTime.Now;
                            CurrentMp -= npcMonsterSkill.Skill.MpCost;
                            Map.Broadcast($"ct 3 {MapMonsterId} 1 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}");
                        }
                        LastMove = DateTime.Now;

                        // deal 0 damage to GM with GodMode
                        damage = targetSession.Character.HasGodMode ? 0 : 100;
                        if (targetSession.Character.IsSitting)
                        {
                            targetSession.Character.IsSitting = false;
                            Map.Broadcast(null, targetSession.Character.GenerateRest(), ReceiverType.OnlySomeone, "", targetSession.Character.CharacterId);
                        }
                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            Map.Broadcast(GenerateEff(npcMonsterSkill.Skill.CastEffect));
                            Thread.Sleep(npcMonsterSkill.Skill.CastTime * 100);
                        }
                        Path = new List <MapCell>();
                        targetSession.Character.LastDefence = DateTime.Now;
                        targetSession.Character.GetDamage(damage);

                        Map.Broadcast(null, ServerManager.Instance.GetUserMethod <string>(Target, "GenerateStat"), ReceiverType.OnlySomeone, "", Target);

                        if (npcMonsterSkill != null)
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} {this.MapX} {this.MapY} {(targetSession.Character.Hp > 0 ? 1 : 0)} { (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100) } {damage} 0 0");
                        }
                        else
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(targetSession.Character.Hp > 0 ? 1 : 0)} { (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100) } {damage} 0 0");
                        }


                        LastEffect = DateTime.Now;
                        if (targetSession.Character.Hp <= 0)
                        {
                            Thread.Sleep(1000);
                            ServerManager.Instance.AskRevive(targetSession.Character.CharacterId);
                            Target = -1;
                        }
                        if (npcMonsterSkill != null && (npcMonsterSkill.Skill.Range > 0 || npcMonsterSkill.Skill.TargetRange > 0))
                        {
                            foreach (Character chara in ServerManager.GetMap(MapId).GetListPeopleInRange(npcMonsterSkill.Skill.TargetRange == 0 ? this.MapX : targetSession.Character.MapX, npcMonsterSkill.Skill.TargetRange == 0 ? this.MapY : targetSession.Character.MapY, (byte)(npcMonsterSkill.Skill.TargetRange + npcMonsterSkill.Skill.Range)).Where(s => s.CharacterId != Target && s.Hp > 0))
                            {
                                if (chara.IsSitting)
                                {
                                    chara.IsSitting = false;
                                    Map.Broadcast(null, chara.GenerateRest(), ReceiverType.OnlySomeone, "", chara.CharacterId);
                                }
                                damage = chara.HasGodMode ? 0 : 100;
                                bool AlreadyDead2 = chara.Hp <= 0;
                                chara.GetDamage(damage);
                                chara.LastDefence = DateTime.Now;
                                Map.Broadcast(null, chara.GenerateStat(), ReceiverType.OnlySomeone, "", chara.CharacterId);
                                Map.Broadcast($"su 3 {MapMonsterId} 1 {chara.CharacterId} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(chara.Hp > 0 ? 1 : 0)} { (int)(chara.Hp / chara.HPLoad() * 100) } {damage} 0 0");
                                if (chara.Hp <= 0 && !AlreadyDead2)
                                {
                                    Thread.Sleep(1000);
                                    ServerManager.Instance.AskRevive(chara.CharacterId);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (IsMoving == true)
                    {
                        short maxDistance = 22;

                        if (Path.Count() == 0 && targetSession != null && (Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY
                        }, new MapCell()
                        {
                            X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                        }) < maxDistance))
                        {
                            Path = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = targetSession.Character.MapX, Y = targetSession.Character.MapY, MapId = this.MapId
                            });
                            if (!Path.Any())
                            {
                                Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY, MapId = this.MapId
                                });
                            }
                        }
                        if (Path.Count > 0 && Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY, MapId = this.MapId
                        }, new MapCell()
                        {
                            X = targetSession.Character.MapX, Y = targetSession.Character.MapY, MapId = this.MapId
                        }) > 1)
                        {
                            this.MapX = Path.ElementAt(0).X;
                            this.MapY = Path.ElementAt(0).Y;
                            Path.RemoveAt(0);
                        }
                        if (targetSession == null || MapId != targetSession.Character.MapId || (Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY
                        }, new MapCell()
                        {
                            X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                        }) > maxDistance))
                        {
                            Path = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = firstX, Y = firstY, MapId = this.MapId
                            });
                            if (!Path.Any())
                            {
                                Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = firstX, Y = firstY, MapId = this.MapId
                                });
                            }
                            Target = -1;
                        }
                        else
                        {
                            if ((DateTime.Now - LastMove).TotalSeconds > 1.0 / Monster.Speed)
                            {
                                LastMove = DateTime.Now;
                                Map.Broadcast($"mv 3 {this.MapMonsterId} {this.MapX} {this.MapY} {Monster.Speed}");
                            }
                        }
                    }
                }
            }
        }
Beispiel #14
0
        public void Initialize()
        {
            if (MapInstance.MapInstanceType == MapInstanceType.BaseMapInstance && ServerManager.Instance.MapBossVNums.Contains(NpcVNum))
            {
                MapCell randomCell = MapInstance.Map.GetRandomPosition();
                if (randomCell != null)
                {
                    if (MapInstance.Portals.Any(s => Map.GetDistance(new MapCell {
                        X = s.SourceX, Y = s.SourceY
                    }, new MapCell {
                        X = randomCell.X, Y = randomCell.Y
                    }) < 5))
                    {
                        randomCell = MapInstance.Map.GetRandomPosition();
                    }
                    MapX = randomCell.X;
                    MapY = randomCell.Y;
                }
            }

            _random = new Random(MapNpcId);
            Npc     = ServerManager.GetNpcMonster(NpcVNum);
            MaxHp   = Npc.MaxHP;
            MaxMp   = Npc.MaxMP;

            if (MapInstance?.MapInstanceType == MapInstanceType.TimeSpaceInstance)
            {
                if (IsProtected)
                {
                    MaxHp *= 8;
                    MaxMp *= 8;
                }
            }
            IsAlive             = true;
            CurrentHp           = MaxHp;
            CurrentMp           = MaxMp;
            LastEffect          = DateTime.Now;
            LastProtectedEffect = DateTime.Now;
            LastMove            = DateTime.Now;
            LastSkill           = DateTime.Now;
            IsHostile           = Npc.IsHostile;
            ShouldRespawn       = ShouldRespawn ?? true;
            FirstX          = MapX;
            FirstY          = MapY;
            EffectActivated = true;
            _movetime       = ServerManager.RandomNumber(500, 3000);
            Path            = new List <Node>();
            Recipes         = ServerManager.Instance.GetRecipesByMapNpcId(MapNpcId);
            Target          = -1;
            Teleporters     = ServerManager.Instance.GetTeleportersByNpcVNum(MapNpcId);
            Shop shop = ServerManager.Instance.GetShopByMapNpcId(MapNpcId);

            if (shop != null)
            {
                shop.Initialize();
                Shop = shop;
            }
            Skills = new List <NpcMonsterSkill>();
            foreach (NpcMonsterSkill ski in Npc.Skills)
            {
                Skills.Add(new NpcMonsterSkill {
                    SkillVNum = ski.SkillVNum, Rate = ski.Rate
                });
            }
            BattleEntity = new BattleEntity(this);

            if (AliveTime > 0)
            {
                Thread AliveTimeThread = new Thread(() => AliveTimeCheck());
                AliveTimeThread.Start();
            }

            if (NpcVNum == 1408)
            {
                OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(621, new MapCell {
                    X = MapX, Y = MapY
                }, null, move: true)));
            }
            if (NpcVNum == 1409)
            {
                OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(622, new MapCell {
                    X = MapX, Y = MapY
                }, null, move: true)));
            }
            if (NpcVNum == 1410)
            {
                OnDeathEvents.Add(new EventContainer(MapInstance, EventActionType.SPAWNMONSTER, new MonsterToSummon(623, new MapCell {
                    X = MapX, Y = MapY
                }, null, move: true)));
            }

            if (OnSpawnEvents.Any())
            {
                OnSpawnEvents.ToList().ForEach(e => { EventHelper.Instance.RunEvent(e, npc: this); });
                OnSpawnEvents.Clear();
            }
        }
Beispiel #15
0
        private void NpcLife()
        {
            double time = (DateTime.Now - LastEffect).TotalMilliseconds;

            if (time > EffectDelay)
            {
                if (IsMate || IsProtected)
                {
                    MapInstance.Broadcast(GenerateEff(825), MapX, MapY);
                }
                if (Effect > 0 && EffectActivated)
                {
                    MapInstance.Broadcast(GenerateEff(Effect), MapX, MapY);
                }
                LastEffect = DateTime.Now;
            }

            time = (DateTime.Now - LastMove).TotalMilliseconds;
            if (IsMoving && Npc.Speed > 0 && time > _movetime)
            {
                _movetime = ServerManager.Instance.RandomNumber(500, 3000);
                byte point  = (byte)ServerManager.Instance.RandomNumber(2, 4);
                byte fpoint = (byte)ServerManager.Instance.RandomNumber(0, 2);

                byte xpoint = (byte)ServerManager.Instance.RandomNumber(fpoint, point);
                byte ypoint = (byte)(point - xpoint);

                short mapX = FirstX;
                short mapY = FirstY;

                if (MapInstance.Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                {
                    double value = (xpoint + ypoint) / (double)(2 * Npc.Speed);
                    Observable.Timer(TimeSpan.FromMilliseconds(1000 * value))
                    .Subscribe(
                        x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });

                    LastMove = DateTime.Now.AddSeconds(value);
                    MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv2(), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                }
            }
            if (Target == -1)
            {
                if (IsHostile && Shop == null)
                {
                    MapMonster monster = MapInstance.Monsters.FirstOrDefault(s => MapInstance == s.MapInstance && Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = s.MapX, Y = s.MapY
                    }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange));
                    ClientSession session = MapInstance.Sessions.FirstOrDefault(s => MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = s.Character.PositionX, Y = s.Character.PositionY
                    }) < Npc.NoticeRange);

                    if (monster != null && session != null)
                    {
                        Target = monster.MapMonsterId;
                    }
                }
            }
            else if (Target != -1)
            {
                MapMonster monster = MapInstance.Monsters.FirstOrDefault(s => s.MapMonsterId == Target);
                if (monster == null || monster.CurrentHp < 1)
                {
                    Target = -1;
                    return;
                }
                NpcMonsterSkill npcMonsterSkill = null;
                if (ServerManager.Instance.RandomNumber(0, 10) > 8)
                {
                    npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                }

                const short damage   = 100;
                int         distance = Map.GetDistance(new MapCell {
                    X = MapX, Y = MapY
                }, new MapCell {
                    X = monster.MapX, Y = monster.MapY
                });
                if (monster.CurrentHp > 0 && (npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range || distance <= Npc.BasicRange))
                {
                    if ((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + Npc.BasicCooldown * 200 && !Npc.Skills.Any() || npcMonsterSkill != null)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastSkillUse = DateTime.Now;
                            MapInstance.Broadcast($"ct 2 {MapNpcId} 3 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}");
                        }

                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            MapInstance.Broadcast(GenerateEff(Effect));
                        }

                        monster.CurrentHp -= damage;

                        MapInstance.Broadcast(npcMonsterSkill != null
                            ? $"su 2 {MapNpcId} 3 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0"
                            : $"su 2 {MapNpcId} 3 {Target} 0 {Npc.BasicCooldown} 11 {Npc.BasicSkill} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0");

                        LastEffect = DateTime.Now;
                        if (monster.CurrentHp < 1)
                        {
                            RemoveTarget();
                            monster.IsAlive   = false;
                            monster.LastMove  = DateTime.Now;
                            monster.CurrentHp = 0;
                            monster.CurrentMp = 0;
                            monster.Death     = DateTime.Now;
                            Target            = -1;
                        }
                    }
                }
                else
                {
                    int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange;
                    if (IsMoving)
                    {
                        const short maxDistance = 5;
                        if (!Path.Any() && distance > 1 && distance < maxDistance)
                        {
                            short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                            short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                            //go to monster
                            Path = BestFirstSearch.FindPath(new GridPos {
                                X = MapX, Y = MapY
                            }, new GridPos {
                                X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset)
                            }, MapInstance.Map.Grid);
                        }
                        if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Any())
                        {
                            int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                            maxindex = maxindex < 1 ? 1 : maxindex;
                            short  mapX        = (short)Path.ElementAt(maxindex - 1).X;
                            short  mapY        = (short)Path.ElementAt(maxindex - 1).Y;
                            double waitingtime = Map.GetDistance(new MapCell {
                                X = mapX, Y = mapY
                            }, new MapCell {
                                X = MapX, Y = MapY
                            }) / (double)Npc.Speed;
                            MapInstance.Broadcast(new BroadcastPacket(null, $"mv 2 {MapNpcId} {mapX} {mapY} {Npc.Speed}", ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                            LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                            Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000)))
                            .Subscribe(
                                x =>
                            {
                                MapX = mapX;
                                MapY = mapY;
                            });

                            Path.RemoveRange(0, maxindex > Path.Count ? Path.Count : maxindex);
                        }
                        if (Target != -1 && (MapId != monster.MapId || distance > maxDistance))
                        {
                            RemoveTarget();
                        }
                    }
                }
            }
        }
Beispiel #16
0
        private void npcLife()
        {
            double time = (DateTime.Now - LastEffect).TotalMilliseconds;

            if (time > EffectDelay)
            {
                if (IsMate || IsProtected)
                {
                    MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY);
                }
                if (Effect > 0 && EffectActivated)
                {
                    MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY);
                }
                LastEffect = DateTime.Now;
            }

            time = (DateTime.Now - LastMove).TotalMilliseconds;
            if (IsMoving && Npc.Speed > 0 && time > _movetime)
            {
                _movetime = ServerManager.RandomNumber(500, 3000);
                byte point  = (byte)ServerManager.RandomNumber(2, 4);
                byte fpoint = (byte)ServerManager.RandomNumber(0, 2);

                byte xpoint = (byte)ServerManager.RandomNumber(fpoint, point);
                byte ypoint = (byte)(point - xpoint);

                short mapX = FirstX;
                short mapY = FirstY;

                if (MapInstance.Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                {
                    double value = (xpoint + ypoint) / (double)(2 * Npc.Speed);
                    Observable.Timer(TimeSpan.FromMilliseconds(1000 * value)).Subscribe(x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });
                    LastMove = DateTime.Now.AddSeconds(value);
                    MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                }
            }
            if (Target == -1)
            {
                if (IsHostile && Shop == null)
                {
                    MapMonster monster = MapInstance.Monsters.Find(s => MapInstance == s.MapInstance && Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = s.MapX, Y = s.MapY
                    }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange));
                    ClientSession session = MapInstance.Sessions.FirstOrDefault(s => MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    }, new MapCell {
                        X = s.Character.PositionX, Y = s.Character.PositionY
                    }) < Npc.NoticeRange);

                    if (monster != null && session != null)
                    {
                        Target = monster.MapMonsterId;
                    }
                }
            }
            else if (Target != -1)
            {
                MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target);
                if (monster == null || monster.CurrentHp < 1)
                {
                    Target = -1;
                    return;
                }
                NpcMonsterSkill npcMonsterSkill = null;
                if (ServerManager.RandomNumber(0, 10) > 8)
                {
                    npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                }
                int  hitmode   = 0;
                bool onyxWings = false;
                int  damage    = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings);
                if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card)
                {
                    int reduce = damage / 100 * card.FirstData;
                    if (monster.CurrentMp < reduce)
                    {
                        monster.CurrentMp = 0;
                    }
                    else
                    {
                        monster.CurrentMp -= reduce;
                    }
                }
                int distance = Map.GetDistance(new MapCell {
                    X = MapX, Y = MapY
                }, new MapCell {
                    X = monster.MapX, Y = monster.MapY
                });
                if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange))
                {
                    if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) && Npc.Skills.Count == 0) || npcMonsterSkill != null)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastSkillUse = DateTime.Now;
                            MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum));
                        }

                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect));
                        }
                        monster.CurrentHp -= damage;
                        MapInstance.Broadcast(npcMonsterSkill != null
                            ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0)
                            : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0));
                        LastEffect = DateTime.Now;
                        if (monster.CurrentHp < 1)
                        {
                            RemoveTarget();
                            monster.IsAlive   = false;
                            monster.LastMove  = DateTime.Now;
                            monster.CurrentHp = 0;
                            monster.CurrentMp = 0;
                            monster.Death     = DateTime.Now;
                            Target            = -1;
                        }
                    }
                }
                else
                {
                    int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange;
                    if (IsMoving)
                    {
                        const short maxDistance = 5;
                        int         maxindex    = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                        if (maxindex < 1)
                        {
                            maxindex = 1;
                        }
                        if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null))
                        {
                            short xoffset = (short)ServerManager.RandomNumber(-1, 1);
                            short yoffset = (short)ServerManager.RandomNumber(-1, 1);

                            //go to monster
                            Path = BestFirstSearch.FindPathJagged(new GridPos {
                                X = MapX, Y = MapY
                            }, new GridPos {
                                X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset)
                            }, MapInstance.Map.JaggedGrid);
                            maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count;
                        }
                        if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0)
                        {
                            short  mapX        = Path[maxindex - 1].X;
                            short  mapY        = Path[maxindex - 1].Y;
                            double waitingtime = Map.GetDistance(new MapCell {
                                X = mapX, Y = mapY
                            }, new MapCell {
                                X = MapX, Y = MapY
                            }) / (double)Npc.Speed;
                            MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                            LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                            Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x =>
                            {
                                MapX = mapX;
                                MapY = mapY;
                            });

                            Path.RemoveRange(0, maxindex);
                        }
                        if (Target != -1 && (MapId != monster.MapId || distance > maxDistance))
                        {
                            RemoveTarget();
                        }
                    }
                }
            }
        }
Beispiel #17
0
        private void move()
        {
            // Normal Move Mode
            if (Monster == null || !IsAlive || _noMove)
            {
                return;
            }

            if (IsMoving && Monster.Speed > 0)
            {
                double time = (DateTime.Now - LastMove).TotalMilliseconds;
                if (Path == null)
                {
                    Path = new List <Node>();
                }
                if (Path.Count > 0) // move back to initial position after following target
                {
                    int timetowalk = 2000 / Monster.Speed;
                    if (time > timetowalk)
                    {
                        int maxindex = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                        if (Path[maxindex - 1] == null)
                        {
                            return;
                        }
                        short  mapX        = Path[maxindex - 1].X;
                        short  mapY        = Path[maxindex - 1].Y;
                        double waitingtime = Map.GetDistance(new MapCell {
                            X = mapX, Y = mapY
                        }, new MapCell {
                            X = MapX, Y = MapY
                        }) / (double)Monster.Speed;
                        LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                        Observable.Timer(TimeSpan.FromMilliseconds(timetowalk)).Subscribe(x =>
                        {
                            MapX = mapX;
                            MapY = mapY;
                            MoveEvent?.Events.ForEach(e => EventHelper.Instance.RunEvent(e, monster: this));
                        });
                        Path.RemoveRange(0, maxindex > Path.Count ? Path.Count : maxindex);
                        MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Monster, MapMonsterId, MapX, MapY, Monster.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                        return;
                    }
                }
                else if (time > _movetime)
                {
                    short mapX = FirstX, mapY = FirstY;
                    if (MapInstance.Map?.GetFreePosition(ref mapX, ref mapY, (byte)ServerManager.Instance.RandomNumber(0, 2), (byte)_random.Next(0, 2)) ?? false)
                    {
                        int distance = Map.GetDistance(new MapCell
                        {
                            X = mapX,
                            Y = mapY
                        }, new MapCell
                        {
                            X = MapX,
                            Y = MapY
                        });

                        double value = 1000d * distance / (2 * Monster.Speed);
                        Observable.Timer(TimeSpan.FromMilliseconds(value)).Subscribe(x =>
                        {
                            MapX = mapX;
                            MapY = mapY;
                        });

                        LastMove = DateTime.Now.AddMilliseconds(value);
                        MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Monster, MapMonsterId, MapX, MapY, Monster.Speed)), ReceiverType.All));
                    }
                }
            }
            HostilityTarget();
        }
Beispiel #18
0
 internal void HostilityTarget()
 {
     if (IsHostile && Target == -1)
     {
         Character character = ServerManager.Instance.Sessions.FirstOrDefault(s => s?.Character != null && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapInstance == MapInstance && Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         }) < Monster.NoticeRange)?.Character;
         if (character != null)
         {
             Target = character.CharacterId;
             if (!Monster.NoAggresiveIcon)
             {
                 character.Session.SendPacket(GenerateEff(5000));
             }
         }
     }
 }
Beispiel #19
0
        /// <summary>
        /// Calculates the damage attacker inflicts defender
        /// </summary>
        /// <param name="attacker">The attacking Entity</param>
        /// <param name="defender">The defending Entity</param>
        /// <param name="skill">The used Skill</param>
        /// <param name="hitMode">reference to HitMode</param>
        /// <param name="onyxWings"></param>
        /// <returns>Damage</returns>
        public int CalculateDamage(BattleEntity attacker, BattleEntity defender, Skill skill, ref int hitMode, ref bool onyxWings)
        {
            int[] GetAttackerBenefitingBuffs(CardType type, byte subtype)
            {
                int value1 = 0;
                int value2 = 0;
                int value3 = 0;

                int[] tmp;
                int   temp = 0;

                tmp     = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Good, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];
                tmp     = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Neutral, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];
                tmp     = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Bad, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];

                return(new int[] { value1, value2, value3, temp });
            }

            int[] GetDefenderBenefitingBuffs(CardType type, byte subtype)
            {
                int value1 = 0;
                int value2 = 0;
                int value3 = 0;

                int[] tmp;
                int   temp = 0;

                tmp     = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Good, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];
                tmp     = getBuff(defender.Level, defender.Buffs, defender.BCards, type, subtype, BuffType.Neutral, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];
                tmp     = getBuff(attacker.Level, attacker.Buffs, attacker.BCards, type, subtype, BuffType.Bad, ref temp);
                value1 += tmp[0];
                value2 += tmp[1];
                value3 += tmp[2];

                return(new int[] { value1, value2, value3, temp });
            }

            int GetShellWeaponEffectValue(ShellWeaponEffectType effectType)
            {
                return(attacker.ShellWeaponEffects?.Where(s => s.Effect == (byte)effectType)?.FirstOrDefault()?.Value ?? 0);
            }

            int GetShellArmorEffectValue(ShellArmorEffectType effectType)
            {
                return(defender.ShellArmorEffects?.Where(s => s.Effect == (byte)effectType)?.FirstOrDefault()?.Value ?? 0);
            }

            if (skill != null)
            {
                attacker.BCards.AddRange(skill.BCards);
            }

            #region Basic Buff Initialisation

            attacker.Morale += GetAttackerBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0];
            attacker.Morale += GetDefenderBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0];
            defender.Morale += GetDefenderBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased)[0];
            defender.Morale += GetAttackerBenefitingBuffs(CardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased)[0];

            attacker.AttackUpgrade  += (short)GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelIncreased)[0];
            attacker.AttackUpgrade  += (short)GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelDecreased)[0];
            defender.DefenseUpgrade += (short)GetDefenderBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelIncreased)[0];
            defender.DefenseUpgrade += (short)GetAttackerBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelDecreased)[0];

            int[] attackerpercentdamage  = GetDefenderBenefitingBuffs(CardType.RecoveryAndDamagePercent, 11);
            int[] defenderpercentdefense = GetDefenderBenefitingBuffs(CardType.RecoveryAndDamagePercent, 2);

            if (attackerpercentdamage[3] != 0)
            {
                return(defender.HPMax / 100 * attackerpercentdamage[2]);
            }
            if (defenderpercentdefense[3] != 0)
            {
                return(defender.HPMax / 100 * Math.Abs(defenderpercentdefense[2]));
            }

            /*
             *
             * Percentage Boost categories:
             *  1.: Adds to Total Damage
             *  2.: Adds to Normal Damage
             *  3.: Adds to Base Damage
             *  4.: Adds to Defense
             *  5.: Adds to Element
             *
             * Buff Effects get added, whereas
             * Shell Effects get multiplied afterwards.
             *
             * Simplified Example on Defense (Same for Attack):
             *  - 1k Defense
             *  - Costume(+5% Defense)
             *  - Defense Potion(+20% Defense)
             *  - S-Defense Shell with 20% Boost
             *
             * Calculation:
             *  1000 * 1.25 * 1.2 = 1500
             *  Def    Buff   Shell Total
             *
             * Keep in Mind that after each step, one has
             * to round the current value down if necessary
             *
             * Static Boost categories:
             *  1.: Adds to Total Damage
             *  2.: Adds to Normal Damage
             *  3.: Adds to Base Damage
             *  4.: Adds to Defense
             *  5.: Adds to Element
             *
             */

            #region Definitions

            double boostCategory1       = 1;
            double boostCategory2       = 1;
            double boostCategory3       = 1;
            double boostCategory4       = 1;
            double boostCategory5       = 1;
            double shellBoostCategory1  = 1;
            double shellBoostCategory2  = 1;
            double shellBoostCategory3  = 1;
            double shellBoostCategory4  = 1;
            double shellBoostCategory5  = 1;
            int    staticBoostCategory1 = 0;
            int    staticBoostCategory2 = 0;
            int    staticBoostCategory3 = 0;
            int    staticBoostCategory4 = 0;
            int    staticBoostCategory5 = 0;

            #endregion

            #region Type 1

            #region Static

            // None for now

            #endregion

            #region Boost

            boostCategory1      += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.DamageIncreased)[0] / 100D;
            boostCategory1      += GetAttackerBenefitingBuffs(CardType.Item, (byte)AdditionalTypes.Item.AttackIncreased)[0] / 100D;
            boostCategory1      += GetDefenderBenefitingBuffs(CardType.Item, (byte)AdditionalTypes.Item.DefenceIncreased)[0] / 100D;
            shellBoostCategory1 += GetShellWeaponEffectValue(ShellWeaponEffectType.PercentageTotalDamage) / 100D;

            if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
            {
                boostCategory1      += GetAttackerBenefitingBuffs(CardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseDamageInPVP)[0] / 100D;
                boostCategory1      += GetAttackerBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackIncreasedInPVP)[0] / 100D;
                shellBoostCategory1 += GetShellWeaponEffectValue(ShellWeaponEffectType.PercentageDamageInPVP) / 100D;
            }

            #endregion

            #endregion

            #region Type 2

            #region Static

            // None for now

            #endregion

            #region Boost

            boostCategory2 += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.DamageDecreased)[0] / 100D;

            if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
            {
                boostCategory2 += GetDefenderBenefitingBuffs(CardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.DecreaseDamageInPVP)[0] / 100D;
                boostCategory2 += GetDefenderBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackDecreasedInPVP)[0] / 100D;
            }

            #endregion

            #endregion

            #region Type 3

            #region Static

            staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksIncreased)[0];
            staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksDecreased)[0];
            staticBoostCategory3 += GetShellWeaponEffectValue(ShellWeaponEffectType.DamageImproved);

            #endregion

            #region Soft-Damage

            int[] soft = GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.IncreasingPropability);
            int[] skin = GetAttackerBenefitingBuffs(CardType.EffectSummon, (byte)AdditionalTypes.EffectSummon.DamageBoostOnHigherLvl);
            if (attacker.Level < defender.Level)
            {
                soft[0] += skin[0];
                soft[1] += skin[1];
            }
            if (ServerManager.Instance.RandomNumber() < soft[0])
            {
                boostCategory3 += soft[1] / 100D;
                if (attacker.EntityType.Equals(EntityType.Player) && attacker.Session != null)
                {
                    attacker.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.GenerateEff(UserType.Player, attacker.Session.Character.CharacterId, 15));
                }
            }

            #endregion

            #endregion

            #region Type 4

            #region Static

            staticBoostCategory4 += GetDefenderBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.AllIncreased)[0];
            staticBoostCategory4 += GetAttackerBenefitingBuffs(CardType.Defence, (byte)AdditionalTypes.Defence.AllDecreased)[0];

            #endregion

            #region Boost

            boostCategory4      += GetDefenderBenefitingBuffs(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceIncreased)[0] / 100D;
            boostCategory4      += GetAttackerBenefitingBuffs(CardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceReduced)[0] / 100D;
            shellBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.PercentageTotalDefence) / 100D;

            if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
            {
                boostCategory4      += GetDefenderBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceIncreasedInPVP)[0] / 100D;
                boostCategory4      += GetAttackerBenefitingBuffs(CardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceDecreasedInPVP)[0] / 100D;
                shellBoostCategory4 -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesPercentageEnemyDefenceInPVP) / 100D;
                shellBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.PercentageAllPVPDefence) / 100D;
            }

            int[] def = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceAllIncreased);
            if (ServerManager.Instance.RandomNumber() < def[0])
            {
                boostCategory3 += def[1] / 100D;
            }

            #endregion

            #endregion

            #region Type 5

            #region Static

            staticBoostCategory5 += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.AllIncreased)[0];
            staticBoostCategory5 += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.AllDecreased)[0];
            staticBoostCategory5 += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedElementalProperties);

            #endregion

            #region Boost

            // Nothing for now

            #endregion

            #endregion

            #region All Type Class Dependant

            int[] def2 = null;

            switch (attacker.AttackType)
            {
            case AttackType.Melee:
                def2                  = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeIncreased);
                boostCategory1       += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeIncreased)[0] / 100D;
                boostCategory1       += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MeleeDecreased)[0] / 100D;
                staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0];
                staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0];
                staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.CloseDefence);
                break;

            case AttackType.Range:
                def2                  = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased);
                boostCategory1       += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.RangedIncreased)[0] / 100D;
                boostCategory1       += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.RangedDecreased)[0] / 100D;
                staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0];
                staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0];
                staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.DistanceDefence);
                break;

            case AttackType.Magical:
                def2                  = GetAttackerBenefitingBuffs(CardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased);
                boostCategory1       += GetAttackerBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalIncreased)[0] / 100D;
                boostCategory1       += GetDefenderBenefitingBuffs(CardType.Damage, (byte)AdditionalTypes.Damage.MagicalDecreased)[0] / 100D;
                staticBoostCategory3 += GetAttackerBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased)[0];
                staticBoostCategory3 += GetDefenderBenefitingBuffs(CardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased)[0];
                staticBoostCategory4 += GetShellArmorEffectValue(ShellArmorEffectType.MagicDefence);
                break;
            }

            def[0] += def2[0];
            def[1] += def2[1];

            #endregion

            #region Softdef finishing

            if (ServerManager.Instance.RandomNumber() < def[0])
            {
                boostCategory3 += def[1] / 100D;
            }

            #endregion

            #region Element Dependant

            switch (attacker.Element)
            {
            case 1:
                defender.FireResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0];
                defender.FireResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0];
                defender.FireResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireIncreased)[0];
                defender.FireResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireDecreased)[0];
                defender.FireResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0];
                defender.FireResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0];
                defender.FireResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireIncreased)[0];
                defender.FireResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireDecreased)[0];
                if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
                {
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyFireResistanceInPVP);
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP);
                }
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedFireResistence);
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence);
                staticBoostCategory5    += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedFireProperties);
                boostCategory5          += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.FireIncreased)[0] / 100D;
                staticBoostCategory5    += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.FireIncreased)[0];
                staticBoostCategory5    += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.FireDecreased)[0];
                break;

            case 2:
                defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0];
                defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0];
                defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterIncreased)[0];
                defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterDecreased)[0];
                defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0];
                defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0];
                defender.WaterResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterIncreased)[0];
                defender.WaterResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterDecreased)[0];
                if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
                {
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyWaterResistanceInPVP);
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP);
                }
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedWaterResistence);
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence);
                staticBoostCategory5    += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedWaterProperties);
                boostCategory5          += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.WaterIncreased)[0] / 100D;
                staticBoostCategory5    += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.WaterIncreased)[0];
                staticBoostCategory5    += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.WaterDecreased)[0];
                break;

            case 3:
                defender.LightResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0];
                defender.LightResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0];
                defender.LightResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightIncreased)[0];
                defender.LightResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightDecreased)[0];
                defender.LightResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0];
                defender.LightResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0];
                defender.LightResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightIncreased)[0];
                defender.LightResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightDecreased)[0];
                if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
                {
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyLightResistanceInPVP);
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP);
                }
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedLightResistence);
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence);
                staticBoostCategory5    += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedLightProperties);
                boostCategory5          += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.LightIncreased)[0] / 100D;
                staticBoostCategory5    += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.LightIncreased)[0];
                staticBoostCategory5    += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.Light5Decreased)[0];
                break;

            case 4:
                defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased)[0];
                defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased)[0];
                defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkIncreased)[0];
                defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkDecreased)[0];
                defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased)[0];
                defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased)[0];
                defender.ShadowResistance += GetDefenderBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkIncreased)[0];
                defender.ShadowResistance += GetAttackerBenefitingBuffs(CardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkDecreased)[0];
                if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
                {
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyDarkResistanceInPVP);
                    defender.FireResistance -= GetShellWeaponEffectValue(ShellWeaponEffectType.ReducesEnemyAllResistancesInPVP);
                }
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedDarkResistence);
                defender.FireResistance += GetShellArmorEffectValue(ShellArmorEffectType.IncreasedAllResistence);
                staticBoostCategory5    += GetShellWeaponEffectValue(ShellWeaponEffectType.IncreasedDarkProperties);
                boostCategory5          += GetAttackerBenefitingBuffs(CardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DarkIncreased)[0] / 100D;
                staticBoostCategory5    += GetAttackerBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.DarkIncreased)[0];
                staticBoostCategory5    += GetDefenderBenefitingBuffs(CardType.Element, (byte)AdditionalTypes.Element.DarkDecreased)[0];
                break;
            }

            #endregion

            #endregion

            #region Attack Type Related Variables

            switch (attacker.AttackType)
            {
            case AttackType.Melee:
                defender.Defense      = defender.MeleeDefense;
                defender.ArmorDefense = defender.ArmorMeleeDefense;
                defender.Dodge        = defender.MeleeDefenseDodge;
                break;

            case AttackType.Range:
                defender.Defense      = defender.RangeDefense;
                defender.ArmorDefense = defender.ArmorRangeDefense;
                defender.Dodge        = defender.RangeDefenseDodge;
                break;

            case AttackType.Magical:
                defender.Defense      = defender.MagicalDefense;
                defender.ArmorDefense = defender.ArmorMagicalDefense;
                break;
            }

            #endregion

            #region Too Near Range Attack Penalty (boostCategory2)

            if (attacker.AttackType == AttackType.Range && Map.GetDistance(new MapCell {
                X = attacker.PositionX, Y = attacker.PositionY
            }, new MapCell {
                X = defender.PositionX, Y = defender.PositionY
            }) < 4)
            {
                boostCategory2 -= 0.3;
            }

            #endregion

            #region Morale and Dodge

            attacker.Morale -= defender.Morale;
            double chance = 0;
            if (attacker.AttackType != AttackType.Magical)
            {
                int    hitrate    = attacker.Hitrate + attacker.Morale;
                double multiplier = defender.Dodge / (hitrate > 1 ? hitrate : 1);

                if (multiplier > 5)
                {
                    multiplier = 5;
                }
                chance = (-0.25 * Math.Pow(multiplier, 3)) - (0.57 * Math.Pow(multiplier, 2)) + (25.3 * multiplier) - 1.41;
                if (chance <= 1)
                {
                    chance = 1;
                }

                //if (GetBuff(CardType.Buff, (byte)AdditionalTypes.DodgeAndDefencePercent.)[0] != 0)    TODO: Eagle Eyes AND Other Fixed Hitrates
                //{
                //    chance = 10;
                //}
            }
            int bonus = 0;
            if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
            {
                switch (attacker.AttackType)
                {
                case AttackType.Melee:
                    bonus += GetShellArmorEffectValue(ShellArmorEffectType.CloseDefenceDodgeInPVP);
                    break;

                case AttackType.Range:
                    bonus += GetShellArmorEffectValue(ShellArmorEffectType.DistanceDefenceDodgeInPVP);
                    break;

                case AttackType.Magical:
                    bonus += GetShellArmorEffectValue(ShellArmorEffectType.IgnoreMagicDamage);
                    break;
                }

                bonus += GetShellArmorEffectValue(ShellArmorEffectType.DodgeAllAttacksInPVP);
            }

            if (!defender.Invincible && ServerManager.Instance.RandomNumber() - bonus < chance)
            {
                hitMode = 1;
                return(0);
            }

            #endregion

            #region Base Damage

            int baseDamage   = ServerManager.Instance.RandomNumber(attacker.DamageMinimum, attacker.DamageMaximum + 1);
            int weaponDamage = ServerManager.Instance.RandomNumber(attacker.WeaponDamageMinimum, attacker.WeaponDamageMaximum + 1);

            #region Attack Level Calculation

            int[] atklvlfix = GetDefenderBenefitingBuffs(CardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedAttackLevel);
            int[] deflvlfix = GetAttackerBenefitingBuffs(CardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedDefenceLevel);

            if (atklvlfix[3] != 0)
            {
                attacker.AttackUpgrade = (short)atklvlfix[0];
            }
            if (deflvlfix[3] != 0)
            {
                attacker.DefenseUpgrade = (short)deflvlfix[0];
            }

            attacker.AttackUpgrade -= defender.DefenseUpgrade;

            if (attacker.AttackUpgrade < -10)
            {
                attacker.AttackUpgrade = -10;
            }
            else if (attacker.AttackUpgrade > ServerManager.Instance.Configuration.MaxUpgrade)
            {
                attacker.AttackUpgrade = ServerManager.Instance.Configuration.MaxUpgrade;
            }

            switch (attacker.AttackUpgrade)
            {
            case 0:
                weaponDamage += 0;
                break;

            case 1:
                weaponDamage += (int)(weaponDamage * 0.1);
                break;

            case 2:
                weaponDamage += (int)(weaponDamage * 0.15);
                break;

            case 3:
                weaponDamage += (int)(weaponDamage * 0.22);
                break;

            case 4:
                weaponDamage += (int)(weaponDamage * 0.32);
                break;

            case 5:
                weaponDamage += (int)(weaponDamage * 0.43);
                break;

            case 6:
                weaponDamage += (int)(weaponDamage * 0.54);
                break;

            case 7:
                weaponDamage += (int)(weaponDamage * 0.65);
                break;

            case 8:
                weaponDamage += (int)(weaponDamage * 0.9);
                break;

            case 9:
                weaponDamage += (int)(weaponDamage * 1.2);
                break;

            case 10:
                weaponDamage += (int)(weaponDamage * 2);
                break;

            default:
                if (attacker.AttackUpgrade > 0)
                {
                    weaponDamage *= attacker.AttackUpgrade / 5;
                }

                break;
            }

            #endregion

            baseDamage = (int)((int)((baseDamage + staticBoostCategory3 + weaponDamage + 15) * boostCategory3) * shellBoostCategory3);

            #endregion

            #region Defense

            switch (attacker.AttackUpgrade)
            {
            default:
                if (attacker.AttackUpgrade < 0)
                {
                    defender.ArmorDefense += defender.ArmorDefense / 5;
                }

                break;

            case -10:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 2);
                break;

            case -9:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 1.2);
                break;

            case -8:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.9);
                break;

            case -7:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.65);
                break;

            case -6:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.54);
                break;

            case -5:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.43);
                break;

            case -4:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.32);
                break;

            case -3:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.22);
                break;

            case -2:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.15);
                break;

            case -1:
                defender.ArmorDefense += (int)(defender.ArmorDefense * 0.1);
                break;

            case 0:
                defender.ArmorDefense += 0;
                break;
            }

            int defense = (int)((int)((defender.Defense + defender.ArmorDefense + staticBoostCategory4) * boostCategory4) * shellBoostCategory4);

            if (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.AllDefenceNullified)[3] != 0 ||
                (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MeleeDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Melee)) ||
                (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.RangedDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Range)) ||
                (GetAttackerBenefitingBuffs(CardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MagicDefenceNullified)[3] != 0 && attacker.AttackType.Equals(AttackType.Magical)))
            {
                defense = 0;
            }

            #endregion

            #region Normal Damage

            int normalDamage = (int)((int)((baseDamage + staticBoostCategory2 - defense) * boostCategory2) * shellBoostCategory2);

            if (normalDamage < 0)
            {
                normalDamage = 0;
            }

            #endregion

            #region Crit Damage

            attacker.CritChance += GetShellWeaponEffectValue(ShellWeaponEffectType.CriticalChance);
            attacker.CritChance -= GetShellArmorEffectValue(ShellArmorEffectType.ReducedCritChanceRecive);
            attacker.CritRate   += GetShellWeaponEffectValue(ShellWeaponEffectType.CriticalDamage);

            if (defender.CellonOptions != null)
            {
                attacker.CritRate -= defender.CellonOptions.Where(s => s.Type == CellonOptionType.CritReduce).Sum(s => s.Value);
            }

            if (ServerManager.Instance.RandomNumber() < attacker.CritChance && attacker.AttackType != AttackType.Magical)
            {
                double multiplier = attacker.CritRate / 100D;
                if (multiplier > 3)
                {
                    multiplier = 3;
                }
                normalDamage += (int)(normalDamage * multiplier);
                hitMode       = 3;
            }

            #endregion

            #region Fairy Damage

            int fairyDamage = (int)((baseDamage + 100) * attacker.ElementRate / 100D);

            #endregion

            #region Elemental Damage Advantage

            double elementalBoost = 0;

            switch (attacker.Element)
            {
            case 0:
                break;

            case 1:
                defender.Resistance = defender.FireResistance;
                switch (defender.Element)
                {
                case 0:
                    elementalBoost = 1.3;         // Damage vs no element
                    break;

                case 1:
                    elementalBoost = 1;         // Damage vs fire
                    break;

                case 2:
                    elementalBoost = 2;         // Damage vs water
                    break;

                case 3:
                    elementalBoost = 1;         // Damage vs light
                    break;

                case 4:
                    elementalBoost = 1.5;         // Damage vs darkness
                    break;
                }
                break;

            case 2:
                defender.Resistance = defender.WaterResistance;
                switch (defender.Element)
                {
                case 0:
                    elementalBoost = 1.3;
                    break;

                case 1:
                    elementalBoost = 2;
                    break;

                case 2:
                    elementalBoost = 1;
                    break;

                case 3:
                    elementalBoost = 1.5;
                    break;

                case 4:
                    elementalBoost = 1;
                    break;
                }
                break;

            case 3:
                defender.Resistance = defender.LightResistance;
                switch (defender.Element)
                {
                case 0:
                    elementalBoost = 1.3;
                    break;

                case 1:
                    elementalBoost = 1.5;
                    break;

                case 2:
                case 3:
                    elementalBoost = 1;
                    break;

                case 4:
                    elementalBoost = 3;
                    break;
                }
                break;

            case 4:
                defender.Resistance = defender.ShadowResistance;
                switch (defender.Element)
                {
                case 0:
                    elementalBoost = 1.3;
                    break;

                case 1:
                    elementalBoost = 1;
                    break;

                case 2:
                    elementalBoost = 1.5;
                    break;

                case 3:
                    elementalBoost = 3;
                    break;

                case 4:
                    elementalBoost = 1;
                    break;
                }
                break;
            }

            if (skill?.Element == 0 || (skill?.Element != attacker.Element && attacker.EntityType == EntityType.Player))
            {
                elementalBoost = 0;
            }

            #endregion

            #region Elemental Damage

            int elementalDamage = (int)((int)((int)((int)((staticBoostCategory5 + fairyDamage) * elementalBoost) * (1 - (defender.Resistance / 100D))) * boostCategory5) * shellBoostCategory5);

            if (elementalDamage < 0)
            {
                elementalDamage = 0;
            }

            #endregion

            #region Total Damage

            int totalDamage = (int)((int)((normalDamage + elementalDamage + attacker.Morale + staticBoostCategory1) * boostCategory1) * shellBoostCategory1);

            if ((attacker.EntityType == EntityType.Player || attacker.EntityType == EntityType.Mate) && (defender.EntityType == EntityType.Player || defender.EntityType == EntityType.Mate))
            {
                totalDamage /= 2;
            }

            if (defender.EntityType == EntityType.Monster || defender.EntityType == EntityType.NPC)
            {
                totalDamage -= getMonsterDamageBonus(defender.Level);
            }

            if (totalDamage < 5)
            {
                totalDamage = ServerManager.Instance.RandomNumber(1, 6);
            }

            if (attacker.EntityType == EntityType.Monster || attacker.EntityType == EntityType.NPC)
            {
                totalDamage += getMonsterDamageBonus(attacker.Level);
            }

            #endregion

            #region Onyx Wings

            int[] onyxBuff = GetAttackerBenefitingBuffs(CardType.StealBuff, (byte)AdditionalTypes.StealBuff.ChanceSummonOnyxDragon);
            if (onyxBuff[0] > ServerManager.Instance.RandomNumber())
            {
                onyxWings = true;
            }

            #endregion

            return(totalDamage);
        }
        private void Move()
        {
            // Normal Move Mode
            if (Monster == null || !IsAlive)
            {
                return;
            }

            if (IsMoving && Monster.Speed > 0)
            {
                double time = (DateTime.Now - LastMove).TotalMilliseconds;

                if (Path.Any(s => s != null)) // move back to initial position after following target
                {
                    int timetowalk = 2000 / Monster.Speed;
                    if (time > timetowalk)
                    {
                        int mapX = Path.ElementAt(0).x;
                        int mapY = Path.ElementAt(0).y;
                        Path.RemoveAt(0);
                        Observable.Timer(TimeSpan.FromMilliseconds(timetowalk))
                        .Subscribe(
                            x =>
                        {
                            MapX = (short)mapX;
                            MapY = (short)mapY;
                        });

                        LastMove = DateTime.Now;
                        Map.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                        return;
                    }
                }
                else if (time > _movetime)
                {
                    short mapX = FirstX, mapY = FirstY;
                    if (Map?.GetFreePosition(ref mapX, ref mapY, (byte)ServerManager.RandomNumber(0, 2), (byte)_random.Next(0, 2)) ?? false)
                    {
                        int distance = Map.GetDistance(new MapCell {
                            X = mapX, Y = mapY
                        }, new MapCell {
                            X = MapX, Y = MapY
                        });
                        Observable.Timer(TimeSpan.FromMilliseconds(1000 * distance / (2 * Monster.Speed)))
                        .Subscribe(
                            x =>
                        {
                            MapX = mapX;
                            MapY = mapY;
                        });

                        LastMove = DateTime.Now.AddMilliseconds(1000 * distance / (2 * Monster.Speed));
                        Map.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.All));
                    }
                }
            }

            if (Monster.IsHostile)
            {
                Character character = ServerManager.Instance.Sessions.FirstOrDefault(s => s?.Character != null && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapId == MapId && Map.GetDistance(new MapCell {
                    X = MapX, Y = MapY
                }, new MapCell {
                    X = s.Character.MapX, Y = s.Character.MapY
                }) < Monster.NoticeRange)?.Character;
                if (character != null)
                {
                    Target = character.CharacterId;
                    if (!Monster.NoAggresiveIcon)
                    {
                        character.Session.SendPacket(GenerateEff(5000));
                    }
                }
            }
        }
        /// <summary>
        /// Handle any kind of Monster interaction
        /// </summary>
        internal void MonsterLife()
        {
            if (Monster == null)
            {
                return;
            }

            // handle hit queue
            HitRequest hitRequest;

            while (HitQueue.TryDequeue(out hitRequest))
            {
                if (IsAlive)
                {
                    int hitmode = 0;

                    // calculate damage
                    int damage = hitRequest.Session.Character.GenerateDamage(this, hitRequest.Skill, ref hitmode);

                    switch (hitRequest.TargetHitType)
                    {
                    case TargetHitType.SingleTargetHit:
                    {
                        // Target Hit
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} {hitRequest.Session.Character.MapX} {hitRequest.Session.Character.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} {hitmode} {hitRequest.Skill.SkillType - 1}");
                        break;
                    }

                    case TargetHitType.SingleTargetHitCombo:
                    {
                        // Taget Hit Combo
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.SkillCombo.Animation} {hitRequest.SkillCombo.Effect} {hitRequest.Session.Character.MapX} {hitRequest.Session.Character.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} {hitmode} {hitRequest.Skill.SkillType - 1}");
                        break;
                    }

                    case TargetHitType.SingleAOETargetHit:
                    {
                        // Target Hit Single AOE
                        switch (hitmode)
                        {
                        case 1:
                            hitmode = 4;
                            break;

                        case 3:
                            hitmode = 6;
                            break;

                        default:
                            hitmode = 5;
                            break;
                        }
                        if (hitRequest.ShowTargetHitAnimation)
                        {
                            Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} 0 0 {(IsAlive ? 1 : 0)} {((int)((double)hitRequest.Session.Character.Hp / hitRequest.Session.Character.HPLoad()) * 100)} 0 0 {hitRequest.Skill.SkillType - 1}");
                        }
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} {hitRequest.Session.Character.MapX} {hitRequest.Session.Character.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} {hitmode} {hitRequest.Skill.SkillType - 1}");
                        break;
                    }

                    case TargetHitType.AOETargetHit:
                    {
                        // Target Hit AOE
                        switch (hitmode)
                        {
                        case 1:
                            hitmode = 4;
                            break;

                        case 3:
                            hitmode = 6;
                            break;

                        default:
                            hitmode = 5;
                            break;
                        }
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} {hitRequest.Session.Character.MapX} {hitRequest.Session.Character.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} {hitmode} {hitRequest.Skill.SkillType - 1}");
                        break;
                    }

                    case TargetHitType.ZoneHit:
                    {
                        // Zone HIT
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} {hitRequest.MapX} {hitRequest.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} 5 {hitRequest.Skill.SkillType - 1}");
                        break;
                    }

                    case TargetHitType.SpecialZoneHit:
                    {
                        // Special Zone hit
                        Map?.Broadcast($"su 1 {hitRequest.Session.Character.CharacterId} 3 {MapMonsterId} {hitRequest.Skill.SkillVNum} {hitRequest.Skill.Cooldown} {hitRequest.Skill.AttackAnimation} {hitRequest.SkillEffect} {hitRequest.Session.Character.MapX} {hitRequest.Session.Character.MapY} {(IsAlive ? 1 : 0)} {(int)((float)CurrentHp / (float)Monster.MaxHP * 100)} {damage} 0 {hitRequest.Skill.SkillType - 1}");
                        break;
                    }
                    }

                    // generate the kill bonus
                    hitRequest.Session.Character.GenerateKillBonus(this);
                }
                else
                {
                    // monster already has been killed, send cancel
                    hitRequest.Session.SendPacket($"cancel 2 {MapMonsterId}");
                }
            }

            // Respawn
            if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= Monster.RespawnTime / 10)
                {
                    Respawn();
                }
            }

            // normal movement
            else if (Target == -1)
            {
                Move();
            }

            // target following
            else
            {
                if (Map != null)
                {
                    ClientSession targetSession = Map.GetSessionByCharacterId(Target);

                    // remove target in some situations
                    if (targetSession == null || targetSession.Character.Invisible || targetSession.Character.Hp <= 0 || CurrentHp <= 0)
                    {
                        RemoveTarget();
                        return;
                    }

                    NpcMonsterSkill npcMonsterSkill = null;
                    if (ServerManager.RandomNumber(0, 10) > 8 && Skills != null)
                    {
                        npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                    }

                    // check if target is in range
                    if (!targetSession.Character.InvisibleGm && !targetSession.Character.Invisible && targetSession.Character.Hp > 0 &&
                        ((npcMonsterSkill != null && CurrentMp >= npcMonsterSkill.Skill.MpCost &&
                          Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    },
                                          new MapCell {
                        X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                    }) < npcMonsterSkill.Skill.Range) ||
                         (Map.GetDistance(new MapCell {
                        X = MapX, Y = MapY
                    },
                                          new MapCell {
                        X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                    }) <= Monster.BasicRange)))
                    {
                        TargetHit(targetSession, npcMonsterSkill);
                    }
                    else
                    {
                        FollowTarget(targetSession);
                    }
                }
            }
        }
Beispiel #22
0
        internal void MonsterLife()
        {
            // Respawn
            if (!Alive && Respawn)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= Monster.RespawnTime / 10)
                {
                    DamageList = new Dictionary <long, long>();
                    Alive      = true;
                    Target     = -1;
                    CurrentHp  = Monster.MaxHP;
                    CurrentMp  = Monster.MaxMP;
                    MapX       = FirstX;
                    MapY       = FirstY;
                    Path       = new List <MapCell>();
                    Map.Broadcast(GenerateIn3());
                    Map.Broadcast(GenerateEff(7), 10);
                }
                return;
            }
            else if (Target == -1)
            {
                // Normal Move Mode
                if (!Alive)
                {
                    return;
                }
                if (IsMoving && Monster.Speed > 0)
                {
                    double time = (DateTime.Now - LastMove).TotalMilliseconds;

                    if (Path.Where(s => s != null).ToList().Count > 0)
                    {
                        int timetowalk = 1000 / (2 * Monster.Speed);
                        if (time > timetowalk)
                        {
                            short mapX = Path.ElementAt(0).X;
                            short mapY = Path.ElementAt(0).Y;
                            Path.RemoveAt(0);
                            LastMove = DateTime.Now;
                            Map.Broadcast($"mv 3 {this.MapMonsterId} {this.MapX} {this.MapY} {Monster.Speed}");

                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(timetowalk);
                                MapX = mapX;
                                MapY = mapY;
                            });
                            return;
                        }
                    }
                    else if (time > _movetime)
                    {
                        _movetime = _random.Next(400, 3200);
                        byte point  = (byte)_random.Next(2, 4);
                        byte fpoint = (byte)_random.Next(0, 2);

                        byte xpoint = (byte)_random.Next(fpoint, point);
                        byte ypoint = (byte)(point - xpoint);

                        short mapX = FirstX;
                        short mapY = FirstY;
                        if (Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                        {
                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(1000 * (xpoint + ypoint) / (2 * Monster.Speed));
                                this.MapX = mapX;
                                this.MapY = mapY;
                            });
                            LastMove = DateTime.Now.AddSeconds((xpoint + ypoint) / (2 * Monster.Speed));

                            string movePacket = $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}";
                            Map.Broadcast(movePacket);
                        }
                    }
                }
                if (Monster.IsHostile)
                {
                    Character character = ServerManager.Instance.Sessions.FirstOrDefault(s => s != null && s.Character != null && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapId == MapId && Map.GetDistance(new MapCell()
                    {
                        X = MapX, Y = MapY
                    }, new MapCell()
                    {
                        X = s.Character.MapX, Y = s.Character.MapY
                    }) < 10)?.Character;
                    if (character != null)
                    {
                        Target = character.CharacterId;
                        if (!Monster.NoAggresiveIcon)
                        {
                            character.Session.SendPacket(GenerateEff(5000));
                        }
                    }
                }
            }
            else
            {
                ClientSession targetSession = Map.GetSessionByCharacterId(Target);

                if (targetSession == null || targetSession.Character.Invisible)
                {
                    Target = -1;
                    Path   = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                    {
                        X = this.MapX, Y = this.MapY, MapId = this.MapId
                    }, new MapCell()
                    {
                        X = FirstX, Y = FirstY, MapId = this.MapId
                    });
                    if (!Path.Any())
                    {
                        Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY, MapId = this.MapId
                        }, new MapCell()
                        {
                            X = FirstX, Y = FirstY, MapId = this.MapId
                        });
                    }
                }
                NpcMonsterSkill npcMonsterSkill = null;
                if (_random.Next(10) > 8)
                {
                    npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault();
                }

                int damage = 500;

                if (targetSession != null && targetSession.Character.Hp > 0 && ((npcMonsterSkill != null && CurrentMp - npcMonsterSkill.Skill.MpCost >= 0 && Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                }) < npcMonsterSkill.Skill.Range) || (Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                }) <= Monster.BasicRange)))
                {
                    if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + Monster.BasicCooldown * 200 && !Skills.Any()) || npcMonsterSkill != null)
                    {
                        if (npcMonsterSkill != null)
                        {
                            npcMonsterSkill.LastUse = DateTime.Now;
                            CurrentMp -= npcMonsterSkill.Skill.MpCost;
                            Map.Broadcast($"ct 3 {MapMonsterId} 1 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}");
                        }
                        LastMove = DateTime.Now;

                        // deal 0 damage to GM with GodMode
                        damage = targetSession.Character.HasGodMode ? 0 : 100;
                        if (targetSession.Character.IsSitting)
                        {
                            targetSession.Character.IsSitting = false;
                            Map.Broadcast(targetSession.Character.GenerateRest());
                            Thread.Sleep(500);
                        }
                        if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0)
                        {
                            Map.Broadcast(GenerateEff(npcMonsterSkill.Skill.CastEffect));
                            Thread.Sleep(npcMonsterSkill.Skill.CastTime * 100);
                        }
                        Path = new List <MapCell>();
                        targetSession.Character.LastDefence = DateTime.Now;
                        targetSession.Character.GetDamage(damage);

                        Map.Broadcast(null, ServerManager.Instance.GetUserMethod <string>(Target, "GenerateStat"), ReceiverType.OnlySomeone, "", Target);

                        if (npcMonsterSkill != null)
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} {this.MapX} {this.MapY} {(targetSession.Character.Hp > 0 ? 1 : 0)} { (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100) } {damage} 0 0");
                        }
                        else
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(targetSession.Character.Hp > 0 ? 1 : 0)} { (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100) } {damage} 0 0");
                        }

                        LastEffect = DateTime.Now;
                        if (targetSession.Character.Hp <= 0)
                        {
                            Thread.Sleep(1000);
                            ServerManager.Instance.AskRevive(targetSession.Character.CharacterId);
                            Path = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = FirstX, Y = FirstY, MapId = this.MapId
                            });
                            if (!Path.Any())
                            {
                                Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = FirstX, Y = FirstY, MapId = this.MapId
                                });
                            }
                        }
                        if (npcMonsterSkill != null && (npcMonsterSkill.Skill.Range > 0 || npcMonsterSkill.Skill.TargetRange > 0))
                        {
                            foreach (Character chara in ServerManager.GetMap(MapId).GetListPeopleInRange(npcMonsterSkill.Skill.TargetRange == 0 ? this.MapX : targetSession.Character.MapX, npcMonsterSkill.Skill.TargetRange == 0 ? this.MapY : targetSession.Character.MapY, (byte)(npcMonsterSkill.Skill.TargetRange + npcMonsterSkill.Skill.Range)).Where(s => s.CharacterId != Target && s.Hp > 0))
                            {
                                if (chara.IsSitting)
                                {
                                    chara.IsSitting = false;
                                    Map.Broadcast(chara.GenerateRest());
                                    Thread.Sleep(500);
                                }
                                damage = chara.HasGodMode ? 0 : 100;
                                bool AlreadyDead2 = chara.Hp <= 0;
                                chara.GetDamage(damage);
                                chara.LastDefence = DateTime.Now;
                                Map.Broadcast(null, chara.GenerateStat(), ReceiverType.OnlySomeone, "", chara.CharacterId);
                                Map.Broadcast($"su 3 {MapMonsterId} 1 {chara.CharacterId} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(chara.Hp > 0 ? 1 : 0)} { (int)(chara.Hp / chara.HPLoad() * 100) } {damage} 0 0");
                                if (chara.Hp <= 0 && !AlreadyDead2)
                                {
                                    Thread.Sleep(1000);
                                    ServerManager.Instance.AskRevive(chara.CharacterId);
                                }
                            }
                        }
                    }
                }
                else
                {
                    int distance = 0;
                    if (targetSession != null)
                    {
                        distance = Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY
                        }, new MapCell()
                        {
                            X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                        });
                    }
                    if (IsMoving)
                    {
                        short maxDistance = 22;
                        if (Path.Count() == 0 && targetSession != null && distance > 1 && distance < maxDistance)
                        {
                            short xoffset = (short)_random.Next(-1, 1);
                            short yoffset = (short)_random.Next(-1, 1);

                            Path = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = (short)(targetSession.Character.MapX + xoffset), Y = (short)(targetSession.Character.MapY + yoffset), MapId = this.MapId
                            });
                            if (!Path.Any())
                            {
                                Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = (short)(targetSession.Character.MapX + xoffset), Y = (short)(targetSession.Character.MapY + yoffset), MapId = this.MapId
                                });
                            }
                        }
                        if (DateTime.Now > LastMove && Monster.Speed > 0 && Path.Count > 0)
                        {
                            short mapX;
                            short mapY;
                            int   maxindex = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                            mapX = Path.ElementAt(maxindex - 1).X;
                            mapY = Path.ElementAt(maxindex - 1).Y;
                            double waitingtime = (double)(Map.GetDistance(new MapCell()
                            {
                                X = mapX, Y = mapY, MapId = MapId
                            }, new MapCell()
                            {
                                X = MapX, Y = MapY, MapId = MapId
                            })) / (double)(Monster.Speed);
                            Map.Broadcast($"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}");
                            LastMove = DateTime.Now.AddSeconds((waitingtime > 1 ? 1 : waitingtime));
                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay((int)((waitingtime > 1 ? 1 : waitingtime) * 1000));
                                this.MapX = mapX;
                                this.MapY = mapY;
                            });

                            for (int j = maxindex; j > 0; j--)
                            {
                                Path.RemoveAt(0);
                            }
                        }
                        if (Path.Count() == 0 && (targetSession == null || MapId != targetSession.Character.MapId || distance > maxDistance))
                        {
                            Path = ServerManager.GetMap(MapId).StraightPath(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = FirstX, Y = FirstY, MapId = this.MapId
                            });
                            if (!Path.Any())
                            {
                                Path = ServerManager.GetMap(MapId).JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = FirstX, Y = FirstY, MapId = this.MapId
                                });
                            }
                            Target = -1;
                        }
                    }
                }
            }
        }
Beispiel #23
0
 internal void HostilityTarget()
 {
     if (IsHostile && Target == -1)
     {
         Character character = ServerManager.Instance.Sessions.FirstOrDefault(s => s?.Character != null && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapInstance == MapInstance && Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         }) < (NoticeRange == 0 ? Monster.NoticeRange : NoticeRange))?.Character;
         if (character != null)
         {
             if (!OnNoticeEvents.Any() && MoveEvent == null)
             {
                 Target = character.CharacterId;
                 if (!Monster.NoAggresiveIcon && LastEffect.AddSeconds(5) < DateTime.Now)
                 {
                     character.Session.SendPacket(GenerateEff(5000));
                 }
             }
             OnNoticeEvents.ForEach(e =>
             {
                 EventHelper.Instance.RunEvent(e, monster: this);
             });
             OnNoticeEvents.RemoveAll(s => s != null);
         }
     }
 }
Beispiel #24
0
        private void Move()
        {
            // Normal Move Mode
            if (Monster == null || !IsAlive)
            {
                return;
            }

            if (IsMoving && Monster.Speed > 0)
            {
                double time = (DateTime.Now - LastMove).TotalMilliseconds;

                if (Path.Any())
                {
                    int timetowalk = 2000 / Monster.Speed;
                    if (time > timetowalk)
                    {
                        int    maxindex    = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                        short  mapX        = Path.ElementAt(maxindex - 1).X;
                        short  mapY        = Path.ElementAt(maxindex - 1).Y;
                        double waitingtime = Map.GetDistance(new MapCell {
                            X = mapX, Y = mapY
                        }, new MapCell {
                            X = MapX, Y = MapY
                        }) / (double)Monster.Speed;
                        LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                        Observable.Timer(TimeSpan.FromMilliseconds(timetowalk))
                        .Subscribe(
                            x =>
                        {
                            MapX = (short)mapX;
                            MapY = (short)mapY;

                            MoveEvent?.Events.ForEach(e =>
                            {
                                EventHelper.Instance.RunEvent(e, monster: this);
                            });
                            if (MoveEvent != null && MoveEvent.InZone(MapX, MapY))
                            {
                                MoveEvent = null;
                            }
                        });
                        Path.RemoveRange(0, maxindex);
                        MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                        return;
                    }
                }
                else if (time > _movetime && Target == -1)
                {
                    short mapX = FirstX, mapY = FirstY;
                    if (MapInstance.Map?.GetFreePosition(ref mapX, ref mapY, (byte)ServerManager.Instance.RandomNumber(0, 2), (byte)_random.Next(0, 2)) ?? false)
                    {
                        int distance = Map.GetDistance(new MapCell
                        {
                            X = mapX,
                            Y = mapY
                        }, new MapCell
                        {
                            X = MapX,
                            Y = MapY
                        });

                        double value = 1000d * distance / (2 * Monster.Speed);
                        Observable.Timer(TimeSpan.FromMilliseconds(value))
                        .Subscribe(
                            x =>
                        {
                            MapX = mapX;
                            MapY = mapY;
                        });

                        LastMove = DateTime.Now.AddMilliseconds(value);
                        MapInstance.Broadcast(new BroadcastPacket(null, GenerateMv3(), ReceiverType.All));
                    }
                }
            }
            HostilityTarget();
        }
        /// <summary>
        /// Follow the Monsters target to it's position.
        /// </summary>
        /// <param name="targetSession">The TargetSession to follow</param>
        private void FollowTarget(ClientSession targetSession)
        {
            int distance = 0;

            if (targetSession != null)
            {
                distance = Map.GetDistance(new MapCell {
                    X = MapX, Y = MapY
                }, new MapCell {
                    X = targetSession.Character.MapX, Y = targetSession.Character.MapY
                });
            }
            if (IsMoving)
            {
                short maxDistance = 22;
                if (!Path.Any() && targetSession != null && distance > 1 && distance < maxDistance)
                {
                    short xoffset = (short)ServerManager.RandomNumber(-1, 1);
                    short yoffset = (short)ServerManager.RandomNumber(-1, 1);

                    Path = Map.StraightPath(new GridPos {
                        x = MapX, y = MapY
                    }, new GridPos {
                        x = (short)(targetSession.Character.MapX + xoffset), y = (short)(targetSession.Character.MapY + yoffset)
                    });
                    if (!Path.Any())
                    {
                        try
                        {
                            Path = Map.JPSPlus(JumpPointParameters, new GridPos {
                                x = MapX, y = MapY
                            }, new GridPos {
                                x = (short)(targetSession.Character.MapX + xoffset), y = (short)(targetSession.Character.MapY + yoffset)
                            });
                        }
                        catch (Exception ex)
                        {
                            Logger.Log.Error($"Pathfinding using JPSPlus failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.MapX + xoffset)} TargetY: {(short)(targetSession.Character.MapY + yoffset)}", ex);
                            RemoveTarget();
                        }
                    }
                }
                if (Monster != null && DateTime.Now > LastMove && Monster.Speed > 0 && Path.Any())
                {
                    int    maxindex    = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                    short  mapX        = (short)Path.ElementAt(maxindex - 1).x;
                    short  mapY        = (short)Path.ElementAt(maxindex - 1).y;
                    double waitingtime = Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY, MapId = MapId
                    }, new MapCell {
                        X = MapX, Y = MapY, MapId = MapId
                    }) / (double)Monster.Speed;
                    Map.Broadcast(new BroadcastPacket(null, $"mv 3 {MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                    LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                    Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000)))
                    .Subscribe(
                        x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });

                    for (int j = maxindex; j > 0; j--)
                    {
                        Path.RemoveAt(0);
                    }
                }

                if (!Path.Any() && (DateTime.Now - LastEffect).Seconds > 20 && (targetSession == null || MapId != targetSession.Character.MapId || distance > maxDistance))
                {
                    RemoveTarget();
                }
            }
        }
Beispiel #26
0
 internal void HostilityTarget()
 {
     if (IsHostile && Target == -1)
     {
         Character character = ServerManager.Instance.Sessions.Where(s => s?.Character != null && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)s.Character.Faction != 678) && s.Character.Hp > 0 && !s.Character.InvisibleGm && !s.Character.Invisible && s.Character.MapInstance == MapInstance && Map.GetDistance(new MapCell {
             X = MapX, Y = MapY
         }, new MapCell {
             X = s.Character.PositionX, Y = s.Character.PositionY
         }) < Monster.NoticeRange).OrderBy(s => ServerManager.Instance.RandomNumber(0, int.MaxValue)).FirstOrDefault()?.Character;
         if (character != null)
         {
             if (OnNoticeEvents.Count == 0 && MoveEvent == null)
             {
                 Target = character.CharacterId;
                 if (!NoAggresiveIcon)
                 {
                     character.Session.SendPacket(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 5000));
                 }
             }
             OnNoticeEvents.ForEach(e => EventHelper.Instance.RunEvent(e, monster: this));
             OnNoticeEvents.RemoveAll(s => s != null);
         }
     }
 }
Beispiel #27
0
        internal void MonsterLife()
        {
            LifeTaskIsRunning = true;
            NpcMonster monster = ServerManager.GetNpc(this.MonsterVNum);

            //Respawn
            if (!Alive)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= monster.RespawnTime / 10)
                {
                    Alive     = true;
                    Target    = -1;
                    CurrentHp = monster.MaxHP;
                    CurrentMp = monster.MaxMP;
                    MapX      = firstX;
                    MapY      = firstY;

                    Map.Broadcast(GenerateIn3());
                    Map.Broadcast(GenerateEff(7));
                }
                LifeTaskIsRunning = false;
                return;
            }
            else if (Target == -1)
            {
                //Normal Move Mode
                if (monster == null || Alive == false)
                {
                    LifeTaskIsRunning = false;
                    return;
                }
                Random r            = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
                double time         = (DateTime.Now - LastMove).TotalSeconds;
                int    MoveFrequent = 5 - (int)Math.Round((double)(monster.Speed / 5));
                if (MoveFrequent < 1)
                {
                    MoveFrequent = 1;
                }
                if (IsMoving)
                {
                    if (path.Where(s => s != null).ToList().Count > 0)//fix a path problem
                    {
                        if ((DateTime.Now - LastMove).TotalSeconds > 1.0 / monster.Speed)
                        {
                            short MapX = path.ElementAt(0).X;
                            short MapY = path.ElementAt(0).Y;
                            path.RemoveAt(0);
                            LastMove = DateTime.Now;
                            Map.Broadcast($"mv 3 {this.MapMonsterId} {this.MapX} {this.MapY} {monster.Speed}");

                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(500);
                                this.MapX = MapX;
                                this.MapY = MapY;
                            });
                            LifeTaskIsRunning = false;
                            return;
                        }
                    }
                    else if (time > r.Next(1, MoveFrequent) + 1)
                    {
                        int  MoveDistance = (int)Math.Round((double)monster.Speed / 2);
                        byte xpoint       = (byte)(r.Next(1, MoveDistance));
                        byte ypoint       = (byte)(r.Next(1, MoveDistance));

                        short MapX = firstX;
                        short MapY = firstY;
                        if (ServerManager.GetMap(MapId).GetFreePosition(ref MapX, ref MapY, xpoint, ypoint))
                        {
                            LastMove = DateTime.Now;

                            string movepacket = $"mv 3 {this.MapMonsterId} {MapX} {MapY} {monster.Speed}";
                            Map.Broadcast(movepacket);

                            Task.Factory.StartNew(async() =>
                            {
                                await Task.Delay(500);
                                this.MapX = MapX;
                                this.MapY = MapY;
                            });
                        }
                    }
                }
                if (monster.IsHostile)
                {
                    Character character = ServerManager.Instance.Sessions.Where(s => s.Character != null && s.Character.Hp > 0).OrderBy(s => Map.GetDistance(new MapCell()
                    {
                        X = MapX, Y = MapY
                    }, new MapCell()
                    {
                        X = s.Character.MapX, Y = s.Character.MapY
                    })).FirstOrDefault(s => s.Character != null && !s.Character.Invisible && s.Character.MapId == MapId)?.Character;
                    if (character != null)
                    {
                        if (Map.GetDistance(new MapCell()
                        {
                            X = character.MapX, Y = character.MapY
                        }, new MapCell()
                        {
                            X = MapX, Y = MapY
                        }) < 7)
                        {
                            Target = character.CharacterId;
                            if (!monster.NoAggresiveIcon)
                            {
                                ServerManager.Instance.Sessions.FirstOrDefault(s => s != null && s.Client != null && s.Character != null && s.Character.CharacterId.Equals(Target)).Client.SendPacket(GenerateEff(5000));
                            }
                        }
                    }
                }
            }
            else
            {
                short?MapX      = ServerManager.Instance.GetProperty <short?>(Target, "MapX");
                short?MapY      = ServerManager.Instance.GetProperty <short?>(Target, "MapY");
                int?  Hp        = ServerManager.Instance.GetProperty <int?>(Target, "Hp");
                short?mapId     = ServerManager.Instance.GetProperty <short?>(Target, "MapId");
                bool? invisible = ServerManager.Instance.GetProperty <bool?>(Target, "Invisible");

                if (MapX == null || MapY == null || Hp <= 0 || invisible != null && (bool)invisible)
                {
                    Target = -1; LifeTaskIsRunning = false; return;
                }

                Random          r   = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
                NpcMonsterSkill ski = monster.Skills.Where(s => !s.Used && (DateTime.Now - s.LastUse).TotalMilliseconds >= 100 * ServerManager.GetSkill(s.SkillVNum).Cooldown).OrderBy(rnd => r.Next()).FirstOrDefault();
                Skill           sk  = null;
                if (ski != null)
                {
                    sk = ServerManager.GetSkill(ski.SkillVNum);
                }

                ClientSession targetSession = Map.Sessions.SingleOrDefault(s => s.Character.CharacterId == Target);

                int damage = 100;

                if (targetSession != null && (sk != null && Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = (short)MapX, Y = (short)MapY
                }) < sk.Range) || (Map.GetDistance(new MapCell()
                {
                    X = this.MapX, Y = this.MapY
                }, new MapCell()
                {
                    X = (short)MapX, Y = (short)MapY
                }) <= monster.BasicRange))
                {
                    if ((sk != null && ((DateTime.Now - LastEffect).TotalMilliseconds >= sk.Cooldown * 100 + 1000)) || ((DateTime.Now - LastEffect).TotalMilliseconds >= (monster.BasicCooldown < 4 ? 4 : monster.BasicCooldown) * 100 + 100))
                    {
                        if (ski != null)
                        {
                            ski.Used    = true;
                            ski.LastUse = DateTime.Now;
                            Map.Broadcast($"ct 3 {MapMonsterId} 1 {Target} {sk.CastAnimation} -1 {sk.SkillVNum}");
                        }

                        LastMove = DateTime.Now;

                        // deal 0 damage to GM with GodMode
                        if (targetSession == null)
                        {
                            damage = 0;
                        }
                        else
                        {
                            damage = targetSession.Character.HasGodMode ? 0 : 100;
                        }

                        if (sk != null && sk.CastEffect != 0)
                        {
                            Map.Broadcast(GenerateEff(sk.CastEffect));
                            Thread.Sleep(sk.CastTime * 100);
                        }
                        path = new List <MapCell>();
                        targetSession.Character.LastDefence = DateTime.Now;
                        targetSession.Character.GetDamage(damage);
                        Map.Broadcast(null, ServerManager.Instance.GetUserMethod <string>(Target, "GenerateStat"), ReceiverType.OnlySomeone, "", Target);

                        if (sk != null)
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} {ski.SkillVNum} {sk.Cooldown} {sk.AttackAnimation} {sk.Effect} {this.MapX} {this.MapY} {(targetSession.Character.Hp > 0 ? 1 : 0)} {(int)((double)targetSession.Character.Hp / ServerManager.Instance.GetUserMethod<double>(Target, "HPLoad"))} {damage} 0 0");
                        }
                        else
                        {
                            Map.Broadcast($"su 3 {MapMonsterId} 1 {Target} 0 {monster.BasicCooldown} 11 {monster.BasicSkill} 0 0 {(targetSession.Character.Hp > 0 ? 1 : 0)} {(int)((double)targetSession.Character.Hp / ServerManager.Instance.GetUserMethod<double>(Target, "HPLoad"))} {damage} 0 0");
                        }

                        if (ski != null)
                        {
                            ski.Used = false;
                        }
                        LastEffect = DateTime.Now;
                        if (targetSession.Character.Hp <= 0)
                        {
                            Thread.Sleep(1000);
                            ServerManager.Instance.AskRevive(Target);
                            Target = -1;
                        }
                        if ((sk != null && (sk.Range > 0 || sk.TargetRange > 0)))
                        {
                            foreach (Character chara in ServerManager.GetMap(MapId).GetListPeopleInRange(sk.TargetRange == 0 ? this.MapX : (short)MapX, sk.TargetRange == 0 ? this.MapY : (short)MapY, (byte)(sk.TargetRange + sk.Range)).Where(s => s.CharacterId != Target))
                            {
                                damage = chara.HasGodMode ? 0 : 100;
                                bool AlreadyDead2 = chara.Hp <= 0;
                                chara.GetDamage(damage);
                                chara.LastDefence = DateTime.Now;
                                Map.Broadcast(null, chara.GenerateStat(), ReceiverType.OnlySomeone, "", chara.CharacterId);
                                Map.Broadcast($"su 3 {MapMonsterId} 1 {chara.CharacterId} 0 {monster.BasicCooldown} 11 {monster.BasicSkill} 0 0 {(chara.Hp > 0 ? 1 : 0)} {(int)((double)chara.Hp / chara.HPLoad())} {damage} 0 0");
                                if (chara.Hp <= 0 && !AlreadyDead2)
                                {
                                    Thread.Sleep(1000);
                                    ServerManager.Instance.AskRevive(chara.CharacterId);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (IsMoving == true)
                    {
                        short maxdistance = 22;

                        if (path.Count() == 0)
                        {
                            path = ServerManager.GetMap(MapId).AStar(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = (short)MapX, Y = (short)MapY, MapId = this.MapId
                            });
                        }
                        if (path.Count > 0 && Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY, MapId = this.MapId
                        }, new MapCell()
                        {
                            X = (short)MapX, Y = (short)MapY, MapId = this.MapId
                        }) > 1)
                        {
                            this.MapX = path.ElementAt(0).X;
                            this.MapY = path.ElementAt(0).Y;
                            path.RemoveAt(0);
                        }
                        if (MapId != mapId || (Map.GetDistance(new MapCell()
                        {
                            X = this.MapX, Y = this.MapY
                        }, new MapCell()
                        {
                            X = (short)MapX, Y = (short)MapY
                        }) > maxdistance))
                        {
                            path = ServerManager.GetMap(MapId).AStar(new MapCell()
                            {
                                X = this.MapX, Y = this.MapY, MapId = this.MapId
                            }, new MapCell()
                            {
                                X = firstX, Y = firstY, MapId = this.MapId
                            });
                            Target = -1;
                        }
                        else
                        {
                            if ((DateTime.Now - LastMove).TotalSeconds > 1.0 / monster.Speed)
                            {
                                LastMove = DateTime.Now;
                                Map.Broadcast($"mv 3 {this.MapMonsterId} {this.MapX} {this.MapY} {monster.Speed}");
                            }
                        }
                    }
                }
            }
            LifeTaskIsRunning = false;
        }
Beispiel #28
0
        /// <summary>
        /// Follow the Monsters target to it's position.
        /// </summary>
        /// <param name="targetSession">The TargetSession to follow</param>
        private void followTarget(ClientSession targetSession)
        {
            if (IsMoving && !_noMove)
            {
                const short maxDistance = 22;
                int         distance    = Map.GetDistance(new MapCell()
                {
                    X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY
                }, new MapCell()
                {
                    X = MapX, Y = MapY
                });
                if (targetSession != null)
                {
                    if (targetSession.Character.LastMonsterAggro.AddSeconds(5) < DateTime.Now || targetSession.Character.BrushFire == null)
                    {
                        targetSession.Character.UpdateBushFire();
                    }
                    targetSession.Character.LastMonsterAggro = DateTime.Now;
                }
                if (Path.Count == 0 && targetSession != null)
                {
                    short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                    short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1);
                    try
                    {
                        Path = BestFirstSearch.TracePath(new Node()
                        {
                            X = MapX, Y = MapY
                        }, targetSession.Character.BrushFire, targetSession.Character.MapInstance.Map.Grid);
                    }
                    catch (Exception ex)
                    {
                        Logger.Error($"Pathfinding using Pathfinder failed. Map: {MapId} StartX: {MapX} StartY: {MapY} TargetX: {(short)(targetSession.Character.PositionX + xoffset)} TargetY: {(short)(targetSession.Character.PositionY + yoffset)}", ex);
                        RemoveTarget();
                    }
                }
                if (Monster != null && DateTime.Now > LastMove && Monster.Speed > 0 && Path.Count > 0)
                {
                    int    maxindex    = Path.Count > Monster.Speed / 2 ? Monster.Speed / 2 : Path.Count;
                    short  mapX        = Path[maxindex - 1].X;
                    short  mapY        = Path[maxindex - 1].Y;
                    double waitingtime = Map.GetDistance(new MapCell {
                        X = mapX, Y = mapY
                    }, new MapCell {
                        X = MapX, Y = MapY
                    }) / (double)Monster.Speed;
                    MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Monster, MapMonsterId, mapX, mapY, Monster.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY));
                    LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime);

                    Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x =>
                    {
                        MapX = mapX;
                        MapY = mapY;
                    });
                    distance = (int)Path[0].F;
                    Path.RemoveRange(0, maxindex > Path.Count ? Path.Count : maxindex);
                }

                if (targetSession == null || MapId != targetSession.Character.MapInstance.Map.MapId || distance > (maxDistance) + 3)
                {
                    RemoveTarget();
                }
            }
        }
Beispiel #29
0
 public IEnumerable <BattleEntity> GetBattleEntitiesInRange(MapCell pos, byte distance)
 {
     return(BattleEntities.Where(b => Map.GetDistance(b.GetPos(), pos) <= distance));
 }
Beispiel #30
0
        /// <summary>
        /// Handle any kind of Monster interaction
        /// </summary>
        private void monsterLife()
        {
            if (Monster == null)
            {
                return;
            }
            if ((DateTime.Now - LastEffect).TotalSeconds >= 5)
            {
                LastEffect = DateTime.Now;
                if (IsTarget)
                {
                    MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 824));
                }
                if (IsBonus)
                {
                    MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 826));
                }
            }

            if (IsBoss && IsAlive)
            {
                MapInstance.Broadcast(GenerateBoss());
            }

            // handle hit queue
            while (HitQueue.TryDequeue(out HitRequest hitRequest))
            {
                if (IsAlive && hitRequest.Session.Character.Hp > 0 && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)hitRequest.Session.Character.Faction != 678))
                {
                    int  hitmode        = 0;
                    bool isCaptureSkill = hitRequest.Skill.BCards.Any(s => s.Type.Equals((byte)CardType.Capture));

                    // calculate damage
                    bool         onyxWings    = false;
                    BattleEntity battleEntity = new BattleEntity(hitRequest.Session.Character, hitRequest.Skill);
                    int          damage       = DamageHelper.Instance.CalculateDamage(battleEntity, new BattleEntity(this), hitRequest.Skill, ref hitmode, ref onyxWings);
                    if (onyxWings)
                    {
                        short      onyxX  = (short)(hitRequest.Session.Character.PositionX + 2);
                        short      onyxY  = (short)(hitRequest.Session.Character.PositionY + 2);
                        int        onyxId = MapInstance.GetNextMonsterId();
                        MapMonster onyx   = new MapMonster()
                        {
                            MonsterVNum = 2371, MapX = onyxX, MapY = onyxY, MapMonsterId = onyxId, IsHostile = false, IsMoving = false, ShouldRespawn = false
                        };
                        MapInstance.Broadcast(UserInterfaceHelper.Instance.GenerateGuri(31, 1, hitRequest.Session.Character.CharacterId, onyxX, onyxY));
                        onyx.Initialize(MapInstance);
                        MapInstance.AddMonster(onyx);
                        MapInstance.Broadcast(onyx.GenerateIn());
                        CurrentHp -= damage / 2;
                        Observable.Timer(TimeSpan.FromMilliseconds(350)).Subscribe(o =>
                        {
                            MapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, onyxId, 3, MapMonsterId, -1, 0, -1, hitRequest.Skill.Effect, -1, -1, true, 92, damage / 2, 0, 0));
                            MapInstance.RemoveMonster(onyx);
                            MapInstance.Broadcast(StaticPacketHelper.Out(UserType.Monster, onyx.MapMonsterId));
                        });
                    }
                    if (hitmode != 1)
                    {
                        hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Buff)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session));
                        hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Capture)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session));
                        if (battleEntity?.ShellWeaponEffects != null)
                        {
                            foreach (ShellEffectDTO shell in battleEntity.ShellWeaponEffects)
                            {
                                switch (shell.Effect)
                                {
                                case (byte)ShellWeaponEffectType.Blackout:
                                {
                                    Buff buff = new Buff(7, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }

                                case (byte)ShellWeaponEffectType.DeadlyBlackout:
                                {
                                    Buff buff = new Buff(66, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }

                                case (byte)ShellWeaponEffectType.MinorBleeding:
                                {
                                    Buff buff = new Buff(1, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }

                                case (byte)ShellWeaponEffectType.Bleeding:
                                {
                                    Buff buff = new Buff(21, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }

                                case (byte)ShellWeaponEffectType.HeavyBleeding:
                                {
                                    Buff buff = new Buff(42, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }

                                case (byte)ShellWeaponEffectType.Freeze:
                                {
                                    Buff buff = new Buff(27, battleEntity.Level);
                                    if (ServerManager.Instance.RandomNumber() < shell.Value)
                                    {
                                        AddBuff(buff);
                                    }
                                    break;
                                }
                                }
                            }
                        }
                    }
                    if (DamageList.ContainsKey(hitRequest.Session.Character.CharacterId))
                    {
                        DamageList[hitRequest.Session.Character.CharacterId] += damage;
                    }
                    else
                    {
                        DamageList.Add(hitRequest.Session.Character.CharacterId, damage);
                    }
                    if (isCaptureSkill)
                    {
                        damage = 0;
                    }
                    if (CurrentHp <= damage)
                    {
                        SetDeathStatement();
                    }
                    else
                    {
                        CurrentHp -= damage;
                    }

                    // only set the hit delay if we become the monsters target with this hit
                    if (Target == -1)
                    {
                        LastSkill = DateTime.Now;
                    }

                    int nearestDistance = 100;
                    foreach (KeyValuePair <long, long> kvp in DamageList)
                    {
                        ClientSession session = MapInstance.GetSessionByCharacterId(kvp.Key);
                        if (session != null)
                        {
                            int distance = Map.GetDistance(new MapCell
                            {
                                X = MapX,
                                Y = MapY
                            }, new MapCell
                            {
                                X = session.Character.PositionX,
                                Y = session.Character.PositionY
                            });
                            if (distance < nearestDistance)
                            {
                                nearestDistance = distance;
                                Target          = session.Character.CharacterId;
                            }
                        }
                    }

                    switch (hitRequest.TargetHitType)
                    {
                    case TargetHitType.SingleTargetHit:
                        if (!isCaptureSkill)
                        {
                            MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        }
                        break;

                    case TargetHitType.SingleTargetHitCombo:
                        MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.SkillCombo.Animation, hitRequest.SkillCombo.Effect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        break;

                    case TargetHitType.SingleAOETargetHit:
                        switch (hitmode)
                        {
                        case 1:
                            hitmode = 4;
                            break;

                        case 3:
                            hitmode = 6;
                            break;

                        default:
                            hitmode = 5;
                            break;
                        }
                        if (hitRequest.ShowTargetHitAnimation)
                        {
                            MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        }
                        else
                        {
                            MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, 0, 0, 0, 0, 0, 0, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        }
                        break;

                    case TargetHitType.AOETargetHit:
                        switch (hitmode)
                        {
                        case 1:
                            hitmode = 4;
                            break;

                        case 3:
                            hitmode = 6;
                            break;

                        default:
                            hitmode = 5;
                            break;
                        }
                        MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        break;

                    case TargetHitType.ZoneHit:
                        MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.MapX, hitRequest.MapY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, 5, (byte)(hitRequest.Skill.SkillType - 1)));
                        break;

                    case TargetHitType.SpecialZoneHit:
                        MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1)));
                        break;
                    }

                    if (CurrentHp <= 0 && !isCaptureSkill)
                    {
                        // generate the kill bonus
                        hitRequest.Session.Character.GenerateKillBonus(this);
                    }
                }
                else
                {
                    // monster already has been killed, send cancel
                    hitRequest.Session.SendPacket(StaticPacketHelper.Cancel(2, MapMonsterId));
                }
                if (IsBoss)
                {
                    MapInstance.Broadcast(GenerateBoss());
                }
            }

            // Respawn
            if (!IsAlive && ShouldRespawn != null && !ShouldRespawn.Value)
            {
                MapInstance.RemoveMonster(this);
            }
            if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value)
            {
                double timeDeath = (DateTime.Now - Death).TotalSeconds;
                if (timeDeath >= Monster.RespawnTime / 10d)
                {
                    respawn();
                }
            }

            // normal movement
            else if (Target == -1)
            {
                move();
            }

            // target following
            else if (MapInstance != null)
            {
                GetNearestOponent();
                HostilityTarget();

                ClientSession targetSession = MapInstance.GetSessionByCharacterId(Target);

                // remove target in some situations
                if (targetSession == null || targetSession.Character.Invisible || targetSession.Character.Hp <= 0 || CurrentHp <= 0)
                {
                    RemoveTarget();
                    return;
                }

                NpcMonsterSkill npcMonsterSkill = null;
                if (Skills != null && ServerManager.Instance.RandomNumber(0, 10) > 8)
                {
                    npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill?.Cooldown)?.OrderBy(rnd => _random.Next())?.FirstOrDefault();
                }

                if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 0)
                {
                    targetHit(targetSession, npcMonsterSkill);
                }

                // check if target is in range
                if (!targetSession.Character.InvisibleGm && !targetSession.Character.Invisible && targetSession.Character.Hp > 0)
                {
                    if (npcMonsterSkill != null && CurrentMp >= npcMonsterSkill.Skill.MpCost &&
                        Map.GetDistance(new MapCell
                    {
                        X = MapX,
                        Y = MapY
                    },
                                        new MapCell
                    {
                        X = targetSession.Character.PositionX,
                        Y = targetSession.Character.PositionY
                    }) < npcMonsterSkill.Skill.Range)
                    {
                        targetHit(targetSession, npcMonsterSkill);
                    }
                    else if (Map.GetDistance(new MapCell
                    {
                        X = MapX,
                        Y = MapY
                    },
                                             new MapCell
                    {
                        X = targetSession.Character.PositionX,
                        Y = targetSession.Character.PositionY
                    }) <= Monster.BasicRange)
                    {
                        targetHit(targetSession, npcMonsterSkill);
                    }
                    else
                    {
                        followTarget(targetSession);
                    }
                }
                else
                {
                    followTarget(targetSession);
                }
            }
        }