Esempio n. 1
0
        public static int PhysicalAttack(YiObj attacker, MsgInteractType attackType = MsgInteractType.Physical)
        {
            if (!CanAttackPhysical(attacker, attacker.CurrentTarget))
            {
                return(-1);
            }

            if (attacker.HasFlag(StatusEffect.Invisibility))
            {
                attacker.RemoveStatusEffect(StatusEffect.Invisibility);
            }

            if (attacker is Player player)
            {
                if (player.AttackJob != null)
                {
                    player.AttackJob.Cancelled = true;
                }
                if (player.CurrentTarget != null && player.CurrentTarget.Alive)
                {
                    player.AttackJob = YiScheduler.Instance.DoReturn(TimeSpan.FromMilliseconds(attacker.AttackSpeed), () => MsgInteract.Handle(player, MsgInteract.Create(attacker, attacker.CurrentTarget, attackType, 0)));
                }
            }
            return(AttackCalcs.GetDamage(attacker, attacker.CurrentTarget, attackType));
        }
Esempio n. 2
0
        private static void PhysicalAttack(YiObj attacker, ref MsgInteract packet)
        {
            if (attacker.HasFlag(StatusEffect.Invisibility))
            {
                attacker.RemoveStatusEffect(StatusEffect.Invisibility);
            }
            if (attacker.HasFlag(StatusEffect.SpawnProtection))
            {
                attacker.RemoveStatusEffect(StatusEffect.SpawnProtection);
            }

            if (!GameWorld.Maps[attacker.MapId].Find(packet.TargetUniqueId, out YiObj currentTarget))
            {
                return;
            }

            attacker.CurrentTarget = currentTarget;
            packet.Value           = Physical.PhysicalAttack(attacker, packet.Type);

            attacker.Equipment.RemoveDura(MsgItemPosition.LeftWeapon);
            attacker.Equipment.RemoveDura(MsgItemPosition.RightWeapon);
            attacker.Equipment.RemoveDura(MsgItemPosition.Ring);
            attacker.AddWeaponProf(MsgItemPosition.LeftWeapon, (uint)packet.Value);
            attacker.AddWeaponProf(MsgItemPosition.RightWeapon, (uint)packet.Value);

            if (packet.Type == MsgInteractType.Archer)
            {
                packet.Value = packet.Value / 2;
            }

            if (packet.Value == -1)
            {
                return;
            }

            if (attacker.ActivatePassiveSkill(attacker, ref packet.Value, out var skill) && skill.HasValue)
            {
                attacker.CurrentSkill = skill.Value;
                Magic.ExecuteAttack((Player)attacker, attacker.Location);
                return;
            }

            ScreenSystem.Send(attacker, packet, true);
            currentTarget.GetHit(attacker, packet.Type == MsgInteractType.Archer? packet.Value * 2: packet.Value);
        }
Esempio n. 3
0
        public static bool VerifyPkMode(YiObj attacker, YiObj target)
        {
            if (target == null)
            {
                return(false);
            }
            if (target is Monster && target.Look != 900 && target.Look != 910)
            {
                return(true);
            }
            var player = attacker as Player;

            if (player == null)
            {
                return(true);
            }
            if (target.Look == 900 || target.Look == 910)
            {
                return(player.PkMode == PkMode.Kill);
            }
            if (target.HasFlag(StatusEffect.Flashing))
            {
                return(player.PkMode != PkMode.Peace);
            }
            if (target.HasFlag(StatusEffect.RedName))
            {
                return(player.PkMode == PkMode.Kill);
            }
            if (target.HasFlag(StatusEffect.BlackName))
            {
                return(player.PkMode != PkMode.Peace);
            }
            if (player.PkMode == PkMode.Team)
            {
                return(!TeamSystem.Teams[player.UniqueId].Members.ContainsKey(target.UniqueId));
            }
            return(player.PkMode == PkMode.Kill);
        }
Esempio n. 4
0
        private static bool CanAttackPhysical(YiObj attacker, YiObj target)
        {
            try
            {
                var conditions = new[]
                {
                    !target.HasFlag(StatusEffect.SpawnProtection),
                    VerifyPkMode(attacker, target),
                    Position.GetDistance(attacker, target) <= attacker.AttackRange,
                    target.Alive,
                    attacker.Alive
                };

                if (GameWorld.Maps.TryGetValue(attacker.MapId, out var map))
                {
                    if (map.Flags.HasFlag(MapFlags.NewbieProtect) && target.Level < 27 && target is Player)
                    {
                        attacker.GetMessage("SYSTEM", attacker.Name.TrimEnd('\0'), "You can't attack players below level 27 here.", MsgTextType.Action);
                        return(false);
                    }
                    if (map.Flags.HasFlag(MapFlags.NoPk) && target is Player)
                    {
                        attacker.GetMessage("SYSTEM", attacker.Name.TrimEnd('\0'), "You can't attack players here.", MsgTextType.Action);
                        return(false);
                    }
                }

                return(Conditions.True(conditions));
            }
            catch (Exception e)
            {
                if (Debugger.IsAttached)
                {
                    Output.WriteLine($"[CanAttack] {e.Message} \r\n {e.StackTrace}");
                }
                return(false);
            }
        }
Esempio n. 5
0
        public static void Recalculate(YiObj entity)
        {
            if (entity == null || entity.UniqueId == 0)
            {
                return;
            }
            var defense      = 0;
            var dodge        = 0;
            var magicDefense = 0;
            var magicAttack  = 0;
            var maximumHp    = 0;
            var maximumMp    = 0;
            var job          = entity.Class;

            if (job == 100)
            {
                job += 20;
            }

            if (Collections.Statpoints.ContainsKey(job / 10 * 100 + entity.Level) && !entity.Reborn)
            {
                var agility  = (ushort)Collections.Statpoints[job / 10 * 100 + entity.Level].Agility;
                var spirit   = (ushort)Collections.Statpoints[job / 10 * 100 + entity.Level].Spirit;
                var strength = (ushort)Collections.Statpoints[job / 10 * 100 + entity.Level].Strength;
                var vitality = (ushort)Collections.Statpoints[job / 10 * 100 + entity.Level].Vitality;
                entity.Agility  = agility;
                entity.Spirit   = spirit;
                entity.Vitality = vitality;
                entity.Strength = strength;
            }

            int minimumPhsyicalAttack = entity.Strength;
            int maximumPhsyicalAttack = entity.Strength;

            maximumHp += entity.Strength * 3;
            maximumHp += entity.Agility * 3;
            maximumHp += entity.Vitality * 24;
            maximumHp += entity.Spirit * 3;

            maximumMp += (ushort)(entity.Spirit * 5);
            if (entity.Class > 100 && entity.Class < 200)
            {
                maximumMp += (ushort)(maximumMp * (entity.Class % 10));
            }

            switch (entity.Class)
            {
            case 11:
                maximumHp = (int)(maximumHp * 1.05);
                break;

            case 12:
                maximumHp = (int)(maximumHp * 1.08);
                break;

            case 13:
                maximumHp = (int)(maximumHp * 1.10);
                break;

            case 14:
                maximumHp = (int)(maximumHp * 1.12);
                break;

            case 15:
                maximumHp = (int)(maximumHp * 1.15);
                break;

            case 41:
                entity.AttackSpeed = (int)(entity.AttackSpeed * 0.85);
                break;

            case 42:
                entity.AttackSpeed = (int)(entity.AttackSpeed * 0.75);
                break;

            case 43:
                entity.AttackSpeed = (int)(entity.AttackSpeed * 0.65);
                break;

            case 44:
                entity.AttackSpeed = (int)(entity.AttackSpeed * 0.55);
                break;

            case 45:
                entity.AttackSpeed = (int)(entity.AttackSpeed * 0.45);
                break;
            }

            foreach (var item in entity.Equipment)
            {
                minimumPhsyicalAttack += item.Value.MinimumPhsyicalAttack;
                maximumPhsyicalAttack += item.Value.MaximumPhsyicalAttack;
                defense            += item.Value.Defense;
                magicDefense       += item.Value.MagicDefense;
                magicAttack        += item.Value.MagicAttack;
                maximumHp          += item.Value.Enchant;
                maximumHp          += item.Value.PotAddHp;
                maximumMp          += item.Value.PotAddMp;
                entity.Bless       -= item.Value.Bless; //TODO Doublecheck. Tq is weird.
                dodge              += item.Value.Dodge;
                entity.AttackRange += item.Value.Range;
                if (item.Value.Frequency > 0)
                {
                    entity.AttackSpeed += 1000 - item.Value.Frequency;
                }
                if (item.Key == MsgItemPosition.RightWeapon || item.Key == MsgItemPosition.LeftWeapon)
                {
                    var subType = item.Value.ItemId / 1000;
                    var sum     = (from skill in entity.Skills where skill.Value.Info.WeaponSubType == subType where skill.Value.Level > 12 && skill.Value.Level <= 20 select(20.00f - skill.Value.Level) / 100).Sum();
                    minimumPhsyicalAttack += (int)sum;
                    maximumPhsyicalAttack += (int)sum;
                }
                switch ((ItemNames)item.Value.Gem1)
                {
                case ItemNames.ShortNormalPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.05f);
                    break;

                case ItemNames.ShortRefPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.1f);
                    break;

                case ItemNames.ShortSuperPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.15f);
                    break;

                case ItemNames.ShortNormalDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.05f);
                    break;

                case ItemNames.ShortRefDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.1f);
                    break;

                case ItemNames.ShortSuperDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.15f);
                    break;

                case ItemNames.ShortNormalFuryGem:
                    dodge += (int)(dodge * 0.05f);
                    break;

                case ItemNames.ShortRefFuryGem:
                    dodge += (int)(dodge * 0.1f);
                    break;

                case ItemNames.ShortSuperFuryGem:
                    dodge += (int)(dodge * 0.15f);
                    break;

                case ItemNames.ShortNormalRainbowGem:
                    entity.ExpBonus += 0.10f;
                    break;

                case ItemNames.ShortRefRainbowGem:
                    entity.ExpBonus += 0.15f;
                    break;

                case ItemNames.ShortSuperRainbowGem:
                    entity.ExpBonus += 0.25f;
                    break;

                case ItemNames.ShortNormalVioletGem:
                    entity.WeaponExpBonus += 0.30f;
                    break;

                case ItemNames.ShortRefVioletGem:
                    entity.WeaponExpBonus += 0.50f;
                    break;

                case ItemNames.ShortSuperVioletGem:
                    entity.WeaponExpBonus += 1.00f;
                    break;

                case ItemNames.ShortNormalMoonGem:
                    entity.MagicExpBonus += 0.30f;
                    break;

                case ItemNames.ShortRefMoonGem:
                    entity.MagicExpBonus += 0.50f;
                    break;

                case ItemNames.ShortSuperMoonGem:
                    entity.MagicExpBonus += 1.00f;
                    break;

                case ItemNames.ShortNormalTortoiseGem:
                    defense -= (int)(defense * 0.02f);
                    break;

                case ItemNames.ShortRefTortoiseGem:
                    defense -= (int)(defense * 0.04f);
                    break;

                case ItemNames.ShortSuperTortoiseGem:
                    defense -= (int)(defense * 0.06f);
                    break;
                }
                switch ((ItemNames)item.Value.Gem2)
                {
                case ItemNames.ShortNormalPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.05f);
                    break;

                case ItemNames.ShortRefPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.1f);
                    break;

                case ItemNames.ShortSuperPhoenixGem:
                    magicAttack = (int)(magicAttack * 0.15f);
                    break;

                case ItemNames.ShortNormalDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.05f);
                    break;

                case ItemNames.ShortRefDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.1f);
                    break;

                case ItemNames.ShortSuperDragonGem:
                    minimumPhsyicalAttack += (int)(minimumPhsyicalAttack * 0.15f);
                    break;

                case ItemNames.ShortNormalFuryGem:
                    dodge += (int)(dodge * 0.05f);
                    break;

                case ItemNames.ShortRefFuryGem:
                    dodge += (int)(dodge * 0.1f);
                    break;

                case ItemNames.ShortSuperFuryGem:
                    dodge += (int)(dodge * 0.15f);
                    break;

                case ItemNames.ShortNormalRainbowGem:
                    entity.ExpBonus += 0.10f;
                    break;

                case ItemNames.ShortRefRainbowGem:
                    entity.ExpBonus += 0.15f;
                    break;

                case ItemNames.ShortSuperRainbowGem:
                    entity.ExpBonus += 0.25f;
                    break;

                case ItemNames.ShortNormalVioletGem:
                    entity.WeaponExpBonus += 0.30f;
                    break;

                case ItemNames.ShortRefVioletGem:
                    entity.WeaponExpBonus += 0.50f;
                    break;

                case ItemNames.ShortSuperVioletGem:
                    entity.WeaponExpBonus += 1.00f;
                    break;

                case ItemNames.ShortNormalMoonGem:
                    entity.MagicExpBonus += 0.30f;
                    break;

                case ItemNames.ShortRefMoonGem:
                    entity.MagicExpBonus += 0.50f;
                    break;

                case ItemNames.ShortSuperMoonGem:
                    entity.MagicExpBonus += 1.00f;
                    break;

                case ItemNames.ShortNormalTortoiseGem:
                    defense -= (int)(defense * 0.02f);
                    break;

                case ItemNames.ShortRefTortoiseGem:
                    defense -= (int)(defense * 0.04f);
                    break;

                case ItemNames.ShortSuperTortoiseGem:
                    defense -= (int)(defense * 0.06f);
                    break;
                }
                if (!Collections.ItemBonus.ContainsKey(item.Value.BonusId))
                {
                    continue;
                }
                maximumHp             += Collections.ItemBonus[item.Value.BonusId].Life;
                defense               += Collections.ItemBonus[item.Value.BonusId].Defence;
                dodge                 += (ushort)Collections.ItemBonus[item.Value.BonusId].Dexterity;
                dodge                 += (ushort)Collections.ItemBonus[item.Value.BonusId].Dodge;
                magicAttack           += Collections.ItemBonus[item.Value.BonusId].MAtk;
                magicDefense          += Collections.ItemBonus[item.Value.BonusId].MDef;
                maximumPhsyicalAttack += Collections.ItemBonus[item.Value.BonusId].MaxAtk;
                minimumPhsyicalAttack += Collections.ItemBonus[item.Value.BonusId].MinAtk;
            }

            entity.MinimumPhsyicalAttack = minimumPhsyicalAttack;
            entity.MaximumPhsyicalAttack = maximumPhsyicalAttack;
            entity.Defense      = defense;
            entity.Dexterity    = entity.Dexterity;
            entity.MagicDefense = magicDefense;
            entity.MagicAttack  = magicAttack;
            entity.MaximumHp    = (ushort)maximumHp;
            entity.MaximumMp    = (ushort)maximumMp;

            var arrows = entity.GetEquip(MsgItemPosition.LeftWeapon);

            if (arrows != null)
            {
                if (arrows.ItemId / 10 == 105010)
                {
                    entity.MinimumPhsyicalAttack = (int)(entity.MinimumPhsyicalAttack * 0.85);
                    entity.MaximumPhsyicalAttack = (int)(entity.MaximumPhsyicalAttack * 0.85);
                }

                if (arrows.ItemId / 10 == 105020)
                {
                    entity.AttackSpeed           = 500;
                    entity.MinimumPhsyicalAttack = 0;
                    entity.MaximumPhsyicalAttack = 0;
                }

                if (arrows.ItemId / 10 == 105040)
                {
                    entity.MinimumPhsyicalAttack = (int)(entity.MinimumPhsyicalAttack * 1.15);
                    entity.MaximumPhsyicalAttack = (int)(entity.MaximumPhsyicalAttack * 1.15);
                }
            }

            if (entity.HasFlag(StatusEffect.MagicShield) || entity.HasFlag(StatusEffect.XpShield))
            {
                entity.Defense = entity.Defense;
            }
            if (entity.HasFlag(StatusEffect.StarOfAccuracy) || entity.HasFlag(StatusEffect.XpAccuracy))
            {
                entity.AttackSpeed = (int)(entity.AttackSpeed * Math.Max(1, entity.AttackSpeedBonus));
            }

            entity.AttackSpeed -= 250;
            if (entity.AttackSpeed < 500)
            {
                entity.AttackSpeed = 500;
            }

            if (entity.HasFlag(StatusEffect.Cyclone))
            {
                entity.AttackSpeed /= 2;
            }
            dodge            += entity.Agility + 25;
            entity.Dexterity += (ushort)dodge;
        }
Esempio n. 6
0
        public static int MagicDmg(YiObj attacker, YiObj target)
        {
            float damage;

            var reborn = 1.00f;

            if (target.Reborn)
            {
                reborn -= 0.30f; //30%
            }
            var dodge = 1.00f;

            dodge -= target.Dexterity / 100;

            if (attacker.CurrentSkill.Id == 1115 || attacker.CurrentSkill.Info.WeaponSubType != 0 && attacker.CurrentSkill.Info.WeaponSubType != 500)
            {
                damage = YiCore.Random.Next(attacker.MinimumPhsyicalAttack, attacker.MaximumPhsyicalAttack);
                if (attacker.HasFlag(StatusEffect.SuperMan) && target is Player)
                {
                    damage *= 0.2f; //PvP Reduction!
                }
                if (attacker.CurrentSkill.Info.Power > 30000)
                {
                    damage *= (float)(attacker.CurrentSkill.Info.Power - 30000) / 100;
                }
                else
                {
                    damage += attacker.CurrentSkill.Info.Power;
                }

                damage -= target.Defense;
            }
            else if (attacker.CurrentSkill.Info.WeaponSubType == 500)
            {
                damage = YiCore.Random.Next(attacker.MinimumPhsyicalAttack, attacker.MaximumPhsyicalAttack);
                if (attacker.HasFlag(StatusEffect.SuperMan) && target is Player)
                {
                    damage *= 0.2f; //PvP Reduction!
                }
                if (attacker.CurrentSkill.Info.Power > 30000)
                {
                    damage *= (float)(attacker.CurrentSkill.Info.Power - 30000) / 100;
                }
                else
                {
                    damage += attacker.CurrentSkill.Info.Power;
                }
            }
            else
            {
                damage = attacker.MagicAttack;
                if (attacker.CurrentSkill.Info.Power > 30000)
                {
                    damage *= (float)(attacker.CurrentSkill.Info.Power - 3000) / 100;
                }
                else
                {
                    damage += attacker.CurrentSkill.Info.Power;
                }

                damage *= (float)(100 - Math.Min(target.MagicDefense, 95)) / 100;
                damage -= target.MagicDefense; //target.MagicBlock;
                damage *= 0.65f;
            }

            damage *= reborn;

            if (damage < 1)
            {
                damage = 1;
            }

            return((int)Math.Round(damage, 0));
        }
Esempio n. 7
0
        public static uint AdjustExp(int damage, YiObj attacker, YiObj target)
        {
            byte level = 120;

            if (attacker.Level < 120)
            {
                level = attacker.Level;
            }

            float exp      = Math.Min(damage, target.CurrentHp);
            var   deltaLvl = level - target.Level;

            if (target.IsGreen(attacker))
            {
                if (deltaLvl >= 3 && deltaLvl <= 5)
                {
                    exp *= 0.70f;
                }
                else if (deltaLvl > 5 && deltaLvl <= 10)
                {
                    exp *= 0.20f;
                }
                else if (deltaLvl > 10 && deltaLvl <= 20)
                {
                    exp *= 0.10f;
                }
                else if (deltaLvl > 20)
                {
                    exp *= 0.05f;
                }
            }
            else if (target.IsRed(attacker))
            {
                exp *= 1.30f;
            }
            else if (target.IsBlack(attacker))
            {
                if (deltaLvl >= -10 && deltaLvl < -5)
                {
                    exp *= 1.5f;
                }
                else if (deltaLvl >= -20 && deltaLvl < -10)
                {
                    exp *= 1.8f;
                }
                else if (deltaLvl < -20)
                {
                    exp *= 2.3f;
                }
            }

            double adjustedExp = Math.Max(1, exp);

            if (target is Player)
            {
                if (target.HasFlag(StatusEffect.RedName))
                {
                    adjustedExp = adjustedExp * 0.1;
                }
                else if (target.HasFlag(StatusEffect.BlackName))
                {
                    adjustedExp = adjustedExp * 0.2;
                }
                else
                {
                    adjustedExp = adjustedExp * 0.02;
                }

                if (attacker is Player)
                {
                    target.Experience -= (uint)Math.Max(1, adjustedExp);
                }
            }

            return((uint)Math.Max(1, adjustedExp));
        }
Esempio n. 8
0
        public static int GetDamage(YiObj attacker, YiObj target, MsgInteractType attackType)
        {
            if (!YiCore.Success(attacker.Dexterity))
            {
                return(0);
            }

            var damage = 1.0d;

            switch (attackType)
            {
            case MsgInteractType.Physical:
                damage = YiCore.Random.Next(attacker.MinimumPhsyicalAttack, attacker.MaximumPhsyicalAttack);
                if (attacker is Monster)
                {
                    damage = YiCore.Random.Next(attacker.MinimumPhsyicalAttack, attacker.MaximumPhsyicalAttack);
                }
                if (target is Monster monster)
                {
                    damage = AdjustPvE((float)damage, attacker, monster);
                }
                if (attacker is Monster monster1 && target != null)
                {
                    damage = AdjustEvP((float)damage, monster1, target);
                }
                if (target != null)
                {
                    damage -= target.Defense;
                }
                break;

            case MsgInteractType.Magic:
                damage = attacker.MagicAttack;
                //if (attacker is Monster)
                //    damage = (attacker as Monster).Base.MagicAttack;

                //if (attacker is YiObj && target is Monster)
                //    damage = AdjustPvE(damage, (YiObj)attacker, (Monster)target);
                //if (attacker is Monster && target is YiObj)
                //    damage = AdjustEvP(damage, (Monster)attacker, (YiObj)target);
                if (target != null)
                {
                    damage *= (float)(100 - Math.Min(target.MagicDefense, 95)) / 100;
                    damage -= target.MagicDefense;     //MagicBlock
                    damage *= 0.65;
                }
                else
                {
                    damage *= 0.75;
                }
                break;

            case MsgInteractType.Archer:
                if (attacker == null)
                {
                    return(0);
                }

                damage = YiCore.Random.Next(attacker.MinimumPhsyicalAttack, attacker.MaximumPhsyicalAttack);
                damage = AdjustPvE((float)damage, attacker, attacker.CurrentTarget as Monster);
                break;
            }

            if (target != null)
            {
                if (target.Reborn)
                {
                    damage *= 0.7;
                }

                damage *= Math.Max(target.Bless, 1);
            }
            if (damage > 0)
            {
                damage = YiCore.Random.Next((int)(damage / 1.2), (int)damage);
            }

            damage *= 0.75;

            damage = Math.Max(1, damage);

            if (attacker is Player aPlayer)
            {
                if (target == null)
                {
                    return((int)Math.Round(damage, 0));
                }

                if (attacker.HasFlag(StatusEffect.SuperMan))
                {
                    damage *= 10;
                }
            }

            if (target != null)
            {
                TeamSystem.ShareExp(attacker, target, (uint)Math.Round(target.MaximumHp * 0.05));
            }
            attacker.Experience += AdjustExp((int)Math.Round(damage, 0), attacker, target);

            return((int)Math.Round(damage, 0));
        }