コード例 #1
0
ファイル: MapMonster.cs プロジェクト: syntox/OpenNos
        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}");
                            }
                        }
                    }
                }
            }
        }
コード例 #2
0
        /// <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);
                    }
                }
            }
        }
コード例 #3
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 = 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 (Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint))
                {
                    Observable.Timer(TimeSpan.FromMilliseconds(1000 * (xpoint + ypoint) / (2 * Npc.Speed)))
                    .Subscribe(
                        x =>
                    {
                        MapX = mapX;
                        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 (Npc.IsHostile && Shop == null)
                {
                    MapMonster monster = 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 = 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 = Map.Monsters.FirstOrDefault(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();
                }

                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;
                            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;

                        Map.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)(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)(monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0");

                        LastEffect = DateTime.Now;
                        if (monster.CurrentHp < 1)
                        {
                            if (IsMoving)
                            {
                                Path = 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
                                    });
                                }
                            }

                            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.RandomNumber(-1, 1);
                            short yoffset = (short)ServerManager.RandomNumber(-1, 1);

                            Path = Map.StraightPath(new GridPos {
                                x = MapX, y = MapY
                            }, new GridPos {
                                x = (short)(monster.MapX + xoffset), y = (short)(monster.MapY + yoffset)
                            });
                            if (!Path.Any())
                            {
                                Path = Map.JPSPlus(JumpPointParameters, new GridPos {
                                    x = MapX, y = MapY
                                }, new GridPos {
                                    x = (short)(monster.MapX + xoffset), y = (short)(monster.MapY + yoffset)
                                });
                            }
                        }
                        if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Any())
                        {
                            int    maxindex    = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.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)Npc.Speed;
                            Map.Broadcast(new BroadcastPacket(null, $"mv 2 {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 =>
                            {
                                MapX = mapX;
                                MapY = mapY;
                            });

                            for (int j = maxindex; j > 0; j--)
                            {
                                Path.RemoveAt(0);
                            }
                        }
                        if (Path.Any() && (MapId != monster.MapId || distance > maxDistance))
                        {
                            Path = 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;
                        }
                    }
                    else
                    {
                        if (distance > maxdistance)
                        {
                            Target = -1;
                        }
                    }
                }
            }
        }
コード例 #4
0
ファイル: MapMonster.cs プロジェクト: PsykoBoss/OpenNos
        /// <summary>
        /// Hit the Target Character.
        /// </summary>
        /// <param name="targetSession"></param>
        /// <param name="npcMonsterSkill"></param>
        private void TargetHit(ClientSession targetSession, NpcMonsterSkill npcMonsterSkill)
        {
            if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + Monster.BasicCooldown * 200 && !Skills.Any()) || npcMonsterSkill != null)
            {
                int damage  = 0;
                int hitmode = 0;

                if (npcMonsterSkill != null)
                {
                    damage = GenerateDamage(targetSession.Character, npcMonsterSkill.Skill, ref hitmode);
                }
                else
                {
                    damage = GenerateDamage(targetSession.Character, null, ref hitmode);
                }

                if (npcMonsterSkill != null)
                {
                    npcMonsterSkill.LastSkillUse = 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
                if (targetSession.Character.HasGodMode)
                {
                    damage = 0;
                }
                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), MapX, MapY);
                    Thread.Sleep(npcMonsterSkill.Skill.CastTime * 100);
                }
                Path = new List <GridPos>();
                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} {hitmode} 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} {hitmode} 0");
                }

                LastEffect = DateTime.Now;
                if (targetSession.Character.Hp <= 0)
                {
                    Thread.Sleep(1000);
                    ServerManager.Instance.AskRevive(targetSession.Character.CharacterId);
                    RemoveTarget();
                }
                if (npcMonsterSkill != null && (npcMonsterSkill.Skill.Range > 0 || npcMonsterSkill.Skill.TargetRange > 0))
                {
                    foreach (Character characterInRange in Map.GetCharactersInRange(npcMonsterSkill.Skill.TargetRange == 0 ? this.MapX : targetSession.Character.MapX, npcMonsterSkill.Skill.TargetRange == 0 ? this.MapY : targetSession.Character.MapY, npcMonsterSkill.Skill.TargetRange).Where(s => s.CharacterId != Target && s.Hp > 0))
                    {
                        if (characterInRange.IsSitting)
                        {
                            characterInRange.IsSitting = false;
                            Map.Broadcast(characterInRange.GenerateRest());
                            Thread.Sleep(500);
                        }
                        if (characterInRange.HasGodMode)
                        {
                            damage  = 0;
                            hitmode = 1;
                        }
                        bool AlreadyDead2 = characterInRange.Hp <= 0;
                        characterInRange.GetDamage(damage);
                        characterInRange.LastDefence = DateTime.Now;
                        Map.Broadcast(null, characterInRange.GenerateStat(), ReceiverType.OnlySomeone, "", characterInRange.CharacterId);
                        Map.Broadcast($"su 3 {MapMonsterId} 1 {characterInRange.CharacterId} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(characterInRange.Hp > 0 ? 1 : 0)} { (int)(characterInRange.Hp / characterInRange.HPLoad() * 100) } {damage} {hitmode} 0");
                        if (characterInRange.Hp <= 0 && !AlreadyDead2)
                        {
                            damage = characterInRange.HasGodMode ? 0 : 100;
                        }
                        bool alreadyDead = characterInRange.Hp <= 0;
                        characterInRange.GetDamage(damage);
                        characterInRange.LastDefence = DateTime.Now;
                        characterInRange.Session.SendPacket(characterInRange.GenerateStat());

                        Map.Broadcast($"su 3 {MapMonsterId} 1 {characterInRange.CharacterId} 0 {Monster.BasicCooldown} 11 {Monster.BasicSkill} 0 0 {(characterInRange.Hp > 0 ? 1 : 0)} { (int)(characterInRange.Hp / characterInRange.HPLoad() * 100) } {damage} {hitmode} 0");
                        if (characterInRange.Hp <= 0 && !alreadyDead)
                        {
                            Thread.Sleep(1000);
                            ServerManager.Instance.AskRevive(characterInRange.CharacterId);
                        }
                    }
                }
            }
        }
コード例 #5
0
ファイル: MapMonster.cs プロジェクト: PsykoBoss/OpenNos
        private void Move()
        {
            // Normal Move Mode
            if (!IsAlive)
            {
                return;
            }

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

                if (Path.Where(s => s != null).Any())
                {
                    int timetowalk = 1000 / (2 * Monster.Speed);
                    if (time > timetowalk)
                    {
                        int mapX = Path.ElementAt(0).x;
                        int mapY = Path.ElementAt(0).y;
                        Path.RemoveAt(0);

                        Task.Factory.StartNew(async() =>
                        {
                            await Task.Delay(timetowalk);
                            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)
                    {
                        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));
                        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));
                    }
                }
            }
        }
コード例 #6
0
ファイル: MapMonster.cs プロジェクト: PsykoBoss/OpenNos
        /// <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 = 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 = Map.StraightPath(new GridPos()
                    {
                        x = this.MapX, y = this.MapY
                    }, new GridPos()
                    {
                        x = (short)(targetSession.Character.MapX + xoffset), y = (short)(targetSession.Character.MapY + yoffset)
                    });
                    if (!Path.Any())
                    {
                        Path = Map.JPSPlus(new GridPos()
                        {
                            x = this.MapX, y = this.MapY
                        }, new GridPos()
                        {
                            x = (short)(targetSession.Character.MapX + xoffset), y = (short)(targetSession.Character.MapY + yoffset)
                        });
                    }
                }
                if (DateTime.Now > LastMove && Monster.Speed > 0 && Path.Any())
                {
                    short mapX;
                    short mapY;
                    int   maxindex = Path.Count > Monster.Speed / 2 ? Monster.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)(Monster.Speed);
                    Map.Broadcast(new BroadcastPacket(null, $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                    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 && (DateTime.Now - LastEffect).Seconds > 20 && (targetSession == null || MapId != targetSession.Character.MapId || distance > maxDistance))
                {
                    RemoveTarget();
                }
            }
        }
コード例 #7
0
ファイル: MapMonster.cs プロジェクト: Ziratoxdu36/OpenNos
        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), MapX, MapY, 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).Any())
                    {
                        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(new BroadcastPacket(null, $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));

                            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));

                            Map.Broadcast(new BroadcastPacket(null, $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}", 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
                    }) < 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 || targetSession.Character.Hp <= 0)
                {
                    Target = -1;
                    Path   = Map.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 = Map.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 = 100;

                if (targetSession != null && !targetSession.Character.InvisibleGm && !targetSession.Character.Invisible && 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), MapX, MapY, 10);
                            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 = Map.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 = Map.JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = FirstX, Y = FirstY, MapId = this.MapId
                                });
                            }
                            Target = -1;
                        }
                        if (npcMonsterSkill != null && (npcMonsterSkill.Skill.Range > 0 || npcMonsterSkill.Skill.TargetRange > 0))
                        {
                            foreach (Character chara in Map.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 = Map.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 = Map.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.Any())
                        {
                            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(new BroadcastPacket(null, $"mv 3 {this.MapMonsterId} {mapX} {mapY} {Monster.Speed}", ReceiverType.AllInRange, xCoordinate: mapX, yCoordinate: mapY));
                            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 = Map.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 = Map.JPSPlus(new MapCell()
                                {
                                    X = this.MapX, Y = this.MapY, MapId = this.MapId
                                }, new MapCell()
                                {
                                    X = FirstX, Y = FirstY, MapId = this.MapId
                                });
                            }
                            Target = -1;
                        }
                    }
                }
            }
        }