public void OnSFXDestroy(MeteorUnit unit, Collider co)
 {
     if (DamageList.ContainsKey(unit))
     {
         DamageList[unit].Remove(co);
     }
 }
Example #2
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);
                }
            }
        }