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