/// <summary> /// Gets the calculated damage based on the given damage type onto the target from source. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="damageType"> /// The damage type /// </param> /// <param name="amount"> /// The amount /// </param> /// <returns> /// The estimated damage from calculations. /// </returns> public static double CalculateDamage( this Obj_AI_Base source, Obj_AI_Base target, DamageType damageType, double amount) { var damage = 0d; switch (damageType) { case DamageType.Magical: damage = source.CalculateMagicDamage(target, amount); break; case DamageType.Physical: damage = source.CalculatePhysicalDamage(target, amount); break; case DamageType.Mixed: damage = source.CalculateMixedDamage(target, damage / 2, damage / 2); break; case DamageType.True: damage = Math.Max(Math.Floor(amount), 0); break; } return damage; }
/// <summary> /// Gets the calculated damage based on the given damage type onto the target from source. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="damageType"> /// The damage type /// </param> /// <param name="amount"> /// The amount /// </param> /// <returns> /// The estimated damage from calculations. /// </returns> public static double CalculateDamage( this Obj_AI_Base source, Obj_AI_Base target, DamageType damageType, double amount) { var damage = 0d; switch (damageType) { case DamageType.Magical: damage = source.CalculateMagicDamage(target, amount); break; case DamageType.Physical: damage = source.CalculatePhysicalDamage(target, amount); break; case DamageType.True: damage = amount; break; } return Math.Max(damage, 0); }
/// <summary> /// Gets the calculated mixed damage onto the target from source. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="physicalAmount"> /// The physical amount /// </param> /// <param name="magicalAmount"> /// The magical amount /// </param> /// <returns> /// The estimated damage from calculations. /// </returns> public static double CalculateMixedDamage( this Obj_AI_Base source, Obj_AI_Base target, double physicalAmount, double magicalAmount) { return Math.Max( source.CalculatePhysicalDamage(target, physicalAmount) + source.CalculateMagicDamage(target, magicalAmount), 0); }
/// <summary> /// Calculates the physical damage the source would deal towards the target on a specific given amount, taking in /// consideration all of the damage modifiers. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="amount"> /// The amount of damage /// </param> /// <param name="ignoreArmorPercent"> /// The amount of armor to ignore. /// </param> /// <returns> /// The amount of estimated damage dealt to target from source. /// </returns> internal static double CalculatePhysicalDamage( this Obj_AI_Base source, Obj_AI_Base target, double amount, double ignoreArmorPercent) { return source.CalculatePhysicalDamage(target, amount) * ignoreArmorPercent; }
/// <summary> /// Gets the source auto attack damage on the target. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <returns> /// The estimated auto attack damage. /// </returns> public static double GetAutoAttackDamage( this Obj_AI_Base source, Obj_AI_Base target) { double result = source.TotalAttackDamage; var damageModifier = 1d; var passive = 0d; var hero = source as Obj_AI_Hero; var targetHero = target as Obj_AI_Hero; var targetMinion = target as Obj_AI_Minion; if (hero != null) { if (hero.ChampionName == "Kalista") { result *= 0.9; } if (hero.HasBuff("Serrated")) { result += 15; } // Spoils Of War if (hero.IsMelee && targetMinion != null && targetMinion.Team != hero.Team && targetMinion.Team != GameObjectTeam.Neutral && hero.GetBuffCount("TalentReaper") > 0 && GameObjects.Heroes.Any( h => h.Team == hero.Team && h.NetworkId != hero.NetworkId && h.Distance(targetMinion) < 1100)) { return result + (Items.HasItem((int)ItemId.Relic_Shield, hero) ? 200 : (Items.HasItem((int)ItemId.Targons_Brace, hero) ? 240 : 400)); } if (targetHero != null) { // Dorans Shield if (Items.HasItem((int)ItemId.Dorans_Shield, targetHero)) { result -= 8; } // Fervor Of Battle var fervorofBattle = hero.GetFerocity(DamageMastery.Ferocity.FervorofBattle); if (fervorofBattle.IsValid()) { result += (0.9 + (0.42 * hero.Level)) * hero.GetBuffCount("MasteryOnHitDamageStacker"); } } // RiftHerald P if (targetMinion != null && hero.IsRanged && targetMinion.Team == GameObjectTeam.Neutral && Regex.IsMatch(targetMinion.Name, "SRU_RiftHerald")) { damageModifier *= 0.65; } } // Ninja Tabi if (targetHero != null && new[] { 3047, 1316, 1318, 1315, 1317 }.Any(i => Items.HasItem(i, targetHero)) && !(source is Obj_AI_Turret)) { damageModifier *= 0.9; } // Bonus Damage (Passive) if (hero != null) { var passiveInfo = hero.GetPassiveDamageInfo(target); if (passiveInfo.Override) { return passiveInfo.Value + source.PassiveFlatMod(target); } passive += passiveInfo.Value; } // This formula is right, work out the math yourself if you don't believe me return Math.Max( source.CalculatePhysicalDamage(target, result) * damageModifier + passive + source.PassiveFlatMod(target), 0); }
/// <summary> /// Gets the source auto attack damage on the target. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <returns> /// The estimated auto attack damage. /// </returns> public static double LSGetAutoAttackDamage(this Obj_AI_Base source, Obj_AI_Base target) { //return source.GetAutoAttackDamage(target); double dmgPhysical = source.FlatPhysicalDamageMod, dmgMagical = 0, dmgPassive = 0; var dmgReduce = 1d; var hero = source as AIHeroClient; var targetHero = target as AIHeroClient; var isMixDmg = false; if (hero != null) { // Spoils Of War if (hero.IsMelee() && target is Obj_AI_Minion && target.Team != GameObjectTeam.Neutral && hero.GetBuffCount("TalentReaper") > 0) { var eyeEquinox = Items.HasItem(2303, hero); if ( GameObjects.Heroes.Any( h => h.Team == hero.Team && !h.Compare(hero) && h.Distance(hero) < (eyeEquinox ? 850 : 1050))) { var spoilwarDmg = 195 + (5 * hero.Level); if (Items.HasItem((int)ItemId.Targons_Brace, hero)) { spoilwarDmg = 200 + (10 * hero.Level); } else if (Items.HasItem((int)ItemId.Face_of_the_Mountain, hero) || eyeEquinox) { spoilwarDmg = 320 + (20 * hero.Level); } if (target.Health < spoilwarDmg) { return float.MaxValue; } } } // Bonus Damage (Passive) var passiveInfo = hero.GetPassiveDamageInfo(target); dmgPassive += passiveInfo.Value; if (passiveInfo.Override) { return dmgPassive; } switch (hero.ChampionName) { case "Kalista": dmgPhysical *= 0.9; break; case "Jhin": dmgPhysical += Math.Round( (new[] { 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40 }[ hero.Level - 1] + (Math.Round((hero.Crit * 100 / 10) * 4)) + (Math.Round(((hero.AttackSpeedMod - 1) * 100 / 10) * 2.5))) / 100 * dmgPhysical); break; case "Corki": dmgPhysical /= 2; dmgMagical = dmgPhysical; isMixDmg = true; break; case "Quinn": if (target.HasBuff("quinnw")) { dmgPhysical += 10 + (5 * hero.Level) + (0.14 + (0.02 * hero.Level)) * hero.TotalAttackDamage; } break; } // Serrated Dirk if (hero.HasBuff("Serrated")) { if (!isMixDmg) { dmgPhysical += 15; } else { dmgPhysical += 7.5; dmgMagical += 7.5; } } if (targetHero != null) { // Dorans Shield if (Items.HasItem((int)ItemId.Dorans_Shield, targetHero)) { var subDmg = (dmgPhysical + dmgMagical) - 8; dmgPhysical = !isMixDmg ? subDmg : (dmgMagical = subDmg / 2); } // Fervor Of Battle if (hero.GetFerocity(Ferocity.FervorofBattle).IsValid()) { var fervorBuffCount = hero.GetBuffCount("MasteryOnHitDamageStacker"); if (fervorBuffCount > 0) { dmgPassive += hero.CalculatePhysicalDamage( target, (0.13 + (0.77 * hero.Level)) * fervorBuffCount); } } } else if (target is Obj_AI_Minion) { // Savagery var savagery = hero.GetCunning(Cunning.Savagery); if (savagery.IsValid()) { dmgPhysical += savagery.Points; } // RiftHerald P if (!hero.IsMelee() && target.Team == GameObjectTeam.Neutral && target.Name == "SRU_RiftHerald") { dmgReduce *= 0.65; } } } // Ninja Tabi if (targetHero != null && !(source is Obj_AI_Turret) && Items.HasItem(3047, targetHero)) { dmgReduce *= 0.88; } dmgPhysical = source.CalculatePhysicalDamage(target, dmgPhysical); dmgMagical = source.CalculateMagicDamage(target, dmgMagical); // Fizz P if (targetHero != null && targetHero.ChampionName == "Fizz") { dmgPhysical -= 4 + (2 * Math.Floor((targetHero.Level - 1) / 3d)); } // This formula is right, work out the math yourself if you don't believe me return Math.Max( Math.Floor((dmgPhysical + dmgMagical) * dmgReduce + source.PassiveFlatMod(target) + dmgPassive), 0); }
/// <summary> /// Gets the source auto attack damage on the target. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="includePassive"> /// Indicates whether to include passive effects. /// </param> /// <returns> /// The estimated auto attack damage. /// </returns> public static double GetAutoAttackDamage( this Obj_AI_Base source, Obj_AI_Base target, bool includePassive = false) { double result = source.TotalAttackDamage; var k = 1d; var reduction = 0d; if (!includePassive) { return source.CalculatePhysicalDamage(target, result * k - reduction); } var hero = source as Obj_AI_Hero; if (hero != null) { // Spoils of War var minionTarget = target as Obj_AI_Minion; if (hero.IsMelee() && minionTarget != null && minionTarget.IsEnemy && minionTarget.Team != GameObjectTeam.Neutral && hero.Buffs.Any(buff => buff.Name == "talentreaperdisplay" && buff.Count > 0)) { if ( GameObjects.Heroes.Any( h => h.NetworkId != source.NetworkId && h.Team == source.Team && h.Distance(minionTarget.Position) < 1100)) { var value = 0; if (Items.HasItem(3302, hero)) { value = 200; // Relic Shield } else if (Items.HasItem(3097, hero)) { value = 240; // Targon's Brace } else if (Items.HasItem(3401, hero)) { value = 400; // Face of the Mountain } return value + hero.TotalAttackDamage; } } // BotRK if (Items.HasItem(3153, hero)) { var d = 0.08 * target.Health; if (target is Obj_AI_Minion) { d = Math.Min(d, 60); } result += d; } // Arcane blade if (hero.Masteries.Any(m => m.Page == MasteryPage.Offense && m.Id == 132 && m.Points == 1)) { reduction -= CalculateMagicDamage(hero, target, 0.05 * hero.FlatMagicDamageMod); } } var targetHero = target as Obj_AI_Hero; if (targetHero != null) { // Ninja tabi if (Items.HasItem(3047, targetHero)) { k *= 0.9d; } // Doran's Shield if (Items.HasItem(1054, targetHero)) { reduction += 8; } // Nimble Fighter if (targetHero.ChampionName == "Fizz") { int f; if (targetHero.Level >= 1 && targetHero.Level < 4) { f = 4; } else if (targetHero.Level >= 4 && targetHero.Level < 7) { f = 6; } else if (targetHero.Level >= 7 && targetHero.Level < 10) { f = 8; } else if (targetHero.Level >= 10 && targetHero.Level < 13) { f = 10; } else if (targetHero.Level >= 13 && targetHero.Level < 16) { f = 12; } else { f = 14; } reduction += f; } } return source.CalculatePhysicalDamage(target, result * k - reduction); }
/// <summary> /// Gets the calculated damage based on the given damage type onto the target from source. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="damageType"> /// The damage type /// </param> /// <param name="amount"> /// The amount /// </param> /// <returns> /// The estimated damage from calculations. /// </returns> public static double CalculateDamage( this Obj_AI_Base source, Obj_AI_Base target, DamageType damageType, double amount) { switch (damageType) { case DamageType.Magical: return source.CalculateMagicDamage(target, amount); case DamageType.Physical: return source.CalculatePhysicalDamage(target, amount); case DamageType.True: return amount; default: return 0d; } }
/// <summary> /// Gets the source auto attack damage on the target. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="includePassive"> /// Indicates whether to include passive effects. /// </param> /// <returns> /// The estimated auto attack damage. /// </returns> public static double GetAutoAttackDamage( this Obj_AI_Base source, Obj_AI_Base target, bool includePassive = false) { double result = source.TotalAttackDamage; var damageModifier = 1d; var reduction = 0d; var passive = 0d; if (includePassive) { var hero = source as Obj_AI_Hero; var targetHero = target as Obj_AI_Hero; var targetMinion = target as Obj_AI_Minion; if (hero != null) { // Spoils of War if (hero.IsMelee() && targetMinion != null && targetMinion.IsEnemy && targetMinion.Team != GameObjectTeam.Neutral && hero.GetBuffCount("talentreaperdisplay") > 0) { if ( GameObjects.AllyHeroes.Any( h => h.NetworkId != source.NetworkId && h.Distance(targetMinion.Position) < 1100)) { var value = 200; // Relic Shield - 3302 if (!Items.HasItem(3302, hero)) { // 240 = Tragon's Brace (3097) // 400 = Face of the Mountain (3401) value = Items.HasItem(3097, hero) ? 240 : 400; } return value + hero.TotalAttackDamage; } } // BotRK if (Items.HasItem(3153, hero)) { var d = 0.08 * target.Health; result += targetMinion != null ? Math.Min(d, 60) : d; } // Arcane blade if (hero.Masteries.Any(m => m.Page == MasteryPage.Offense && m.Id == 132 && m.Points == 1)) { reduction -= CalculateMagicDamage(hero, target, 0.05 * hero.FlatMagicDamageMod); } } if (targetHero != null) { // Ninja tabi if (Items.HasItem(3047, targetHero)) { damageModifier *= 0.9d; } // Nimble Fighter if (targetHero.ChampionName == "Fizz") { reduction += 4 + ((targetHero.Level - (1 / 3)) * 2); } // Block // + Reduces incoming damage from champion basic attacks by 1 / 2 if (hero != null) { var mastery = targetHero.Masteries.FirstOrDefault(m => m.Page == MasteryPage.Defense && m.Id == 68); if (mastery != null && mastery.Points >= 1) { reduction += 1 * mastery.Points; } } } // Bonus Damage (Passive) if (hero != null) { var passiveInfo = hero.GetPassiveDamageInfo(target); if (passiveInfo.Override) { return source.CalculatePhysicalDamage(target, -reduction * damageModifier) + passiveInfo.Value; } passive += passiveInfo.Value; } } // This formula is right, work out the math yourself if you don't believe me return source.CalculatePhysicalDamage(target, (result - reduction) * damageModifier) + passive; }
/// <summary> /// Gets the source auto attack damage on the target. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="includePassive"> /// Indicates whether to include passive effects. /// </param> /// <returns> /// The estimated auto attack damage. /// </returns> public static double GetAutoAttackDamage( this Obj_AI_Base source, Obj_AI_Base target, bool includePassive = false) { double result = source.TotalAttackDamage; if (!includePassive) { return source.CalculatePhysicalDamage(target, result); } var k = 1d; var reduction = 0d; var hero = source as Obj_AI_Hero; if (hero != null) { // Spoils of War var minionTarget = target as Obj_AI_Minion; if (hero.IsMelee() && minionTarget != null && minionTarget.IsEnemy && minionTarget.Team != GameObjectTeam.Neutral && hero.Buffs.Any(buff => buff.Name == "talentreaperdisplay" && buff.Count > 0)) { if ( GameObjects.Heroes.Any( h => h.NetworkId != source.NetworkId && h.Team == source.Team && h.Distance(minionTarget.Position) < 1100)) { var value = 0; if (Items.HasItem(3302, hero)) { value = 200; // Relic Shield } else if (Items.HasItem(3097, hero)) { value = 240; // Targon's Brace } else if (Items.HasItem(3401, hero)) { value = 400; // Face of the Mountain } return value + hero.TotalAttackDamage; } } // BotRK if (Items.HasItem(3153, hero)) { var d = 0.08 * target.Health; if (target is Obj_AI_Minion) { d = Math.Min(d, 60); } result += d; } // Arcane blade if (hero.Masteries.Any(m => m.Page == MasteryPage.Offense && m.Id == 132 && m.Points == 1)) { reduction -= CalculateMagicDamage(hero, target, 0.05 * hero.FlatMagicDamageMod); } // Champion Passive PassiveInfo passiveInfo; if (PassiveDictionary.TryGetValue(hero.ChampionName, out passiveInfo)) { try { result += passiveInfo.GetPassivesSum(hero); } catch (Exception) { Logging.Write()( LogLevel.Fatal, $"Failure to calculate one or more passives at {hero.ChampionName}."); } } } var targetHero = target as Obj_AI_Hero; if (targetHero != null) { // Ninja tabi if (Items.HasItem(3047, targetHero)) { k *= 0.9d; } // Nimble Fighter if (targetHero.ChampionName == "Fizz") { reduction += 4 + (targetHero.Level - 1 / 3) * 2; } // Block // + Reduces incoming damage from champion basic attacks by 1 / 2 if (hero != null) { var mastery = targetHero.Masteries.FirstOrDefault(m => m.Page == MasteryPage.Defense && m.Id == 68); if (mastery != null && mastery.Points >= 1) { reduction += 1 * mastery.Points; } } } // This formula is right, work out the math yourself if you don't believe me return source.CalculatePhysicalDamage(target, (result - reduction) * k); }