/// <summary> /// Get the spell damage value. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="spellSlot"> /// The spell slot /// </param> /// <param name="stage"> /// The stage /// </param> /// <returns> /// The <see cref="double" /> value of damage. /// </returns> public static double GetSpellDamage( this Obj_AI_Hero source, Obj_AI_Base target, SpellSlot spellSlot, DamageStage stage = DamageStage.Default) { if (source == null || !source.IsValid || target == null || !target.IsValid) { return 0; } ChampionDamage value; if (!DamageCollection.TryGetValue(source.ChampionName, out value)) { return 0; } var spellData = value.GetSlot(spellSlot)?.FirstOrDefault(e => e.Stage == stage)?.SpellData; if (spellData == null) { return 0; } var spellLevel = source.Spellbook.GetSpell(spellData.ScaleSlot != SpellSlot.Unknown ? spellData.ScaleSlot : spellSlot) .Level; if (spellLevel == 0) { return 0; } var baseDamage = 0d; var bonusDamage = 0d; if (spellData.Damages?.Count > 0) { if (spellData.DamageType == DamageType.Mixed) { var oriDamage = spellData.Damages[Math.Min(spellLevel - 1, spellData.Damages.Count - 1)]; baseDamage = source.CalculateMixedDamage(target, oriDamage / 2, oriDamage / 2); if (!string.IsNullOrEmpty(spellData.ScalingBuff)) { var buffCount = (spellData.ScalingBuffTarget == DamageScalingTarget.Source ? source : target).GetBuffCount( spellData.ScalingBuff); baseDamage = buffCount != 0 ? baseDamage * (buffCount + spellData.ScalingBuffOffset) : 0; } } else { baseDamage = source.CalculateDamage( target, spellData.DamageType, spellData.Damages[Math.Min(spellLevel - 1, spellData.Damages.Count - 1)]); if (!string.IsNullOrEmpty(spellData.ScalingBuff)) { var buffCount = (spellData.ScalingBuffTarget == DamageScalingTarget.Source ? source : target).GetBuffCount( spellData.ScalingBuff); baseDamage = buffCount != 0 ? baseDamage * (buffCount + spellData.ScalingBuffOffset) : 0; } } } if (spellData.DamagesPerLvl?.Count > 0) { baseDamage = source.CalculateDamage( target, spellData.DamageType, spellData.Damages[Math.Min(source.Level - 1, spellData.DamagesPerLvl.Count - 1)]); } if (spellData.BonusDamages?.Count > 0) { foreach (var bonusDmg in spellData.BonusDamages.Where(i => source.ResolveBonusSpellDamage(target, i, spellLevel - 1) > 0)) { if (bonusDmg.DamageType == DamageType.Mixed) { var oriDamage = source.ResolveBonusSpellDamage(target, bonusDmg, spellLevel - 1); bonusDamage += source.CalculateMixedDamage(target, oriDamage / 2, oriDamage / 2); } else { bonusDamage += source.CalculateDamage( target, bonusDmg.DamageType, source.ResolveBonusSpellDamage(target, bonusDmg, spellLevel - 1)); } } } var totalDamage = baseDamage + bonusDamage; var passiveDamage = 0d; if (totalDamage > 0) { if (spellData.ScalePerTargetMissHealth > 0) { totalDamage *= (target.MaxHealth - target.Health) / target.MaxHealth * spellData.ScalePerTargetMissHealth + 1; } if (target is Obj_AI_Minion && spellData.MaxDamageOnMinion?.Count > 0) { totalDamage = Math.Min( totalDamage, spellData.MaxDamageOnMinion[Math.Min(spellLevel - 1, spellData.MaxDamageOnMinion.Count - 1)]); } if (spellData.SpellEffectType == SpellEffectType.Single && target is Obj_AI_Minion) { var savagery = source.GetCunning(DamageMastery.Cunning.Savagery); if (savagery.IsValid()) { passiveDamage += savagery.Points; } } } return totalDamage + passiveDamage; }
/// <summary> /// Get the spell damage value. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="spellSlot"> /// The spell slot /// </param> /// <param name="stage"> /// The stage /// </param> /// <returns> /// The <see cref="double" /> value of damage. /// </returns> public static double LSGetSpellDamage( this AIHeroClient source, Obj_AI_Base target, SpellSlot spellSlot, DamageStage stage = DamageStage.Default) { if (source == null || !source.IsValid || target == null || !target.IsValid) { return 0; } ChampionDamage value; if (!DamageCollection.TryGetValue(source.ChampionName, out value)) { return 0; } var spellData = value.GetSlot(spellSlot)?.FirstOrDefault(e => e.Stage == stage)?.SpellData; if (spellData == null) { return 0; } var spellLevel = source.Spellbook.GetSpell(spellData.ScaleSlot != SpellSlot.Unknown ? spellData.ScaleSlot : spellSlot) .Level; if (spellLevel == 0) { return 0; } bool alreadyAdd1 = false, alreadyAdd2 = false; var targetHero = target as AIHeroClient; var targetMinion = target as Obj_AI_Minion; double dmgBase = 0, dmgBonus = 0, dmgPassive = 0; var dmgReduce = 1d; if (spellData.DamagesPerLvl?.Count > 0) { dmgBase = spellData.DamagesPerLvl[Math.Min(source.Level - 1, spellData.DamagesPerLvl.Count - 1)]; } else if (spellData.Damages?.Count > 0) { dmgBase = spellData.Damages[Math.Min(spellLevel - 1, spellData.Damages.Count - 1)]; if (!string.IsNullOrEmpty(spellData.ScalingBuff)) { var buffCount = (spellData.ScalingBuffTarget == DamageScalingTarget.Source ? source : target).GetBuffCount( spellData.ScalingBuff); dmgBase = buffCount > 0 ? dmgBase * (buffCount + spellData.ScalingBuffOffset) : 0; } } if (dmgBase > 0) { if (targetMinion != null && spellData.BonusDamageOnMinion?.Count > 0) { dmgBase += spellData.BonusDamageOnMinion[Math.Min(spellLevel - 1, spellData.BonusDamageOnMinion.Count - 1)]; } if (spellData.IsApplyOnHit || spellData.IsModifiedDamage || spellData.SpellEffectType == SpellEffectType.Single) { if (source.HasBuff("Serrated")) { dmgBase += 15; } if (targetHero != null) { if (!spellData.IsApplyOnHit && Items.HasItem((int)ItemId.Dorans_Shield, targetHero)) { dmgBase -= 8; } } else if (targetMinion != null) { var savagery = source.GetCunning(Cunning.Savagery); if (savagery.IsValid()) { dmgBase += savagery.Points; } } alreadyAdd1 = true; } dmgBase = source.CalculateDamage(target, spellData.DamageType, dmgBase); if (spellData.IsModifiedDamage && spellData.DamageType == DamageType.Physical && targetHero != null && targetHero.ChampionName == "Fizz") { dmgBase -= 4 + (2 * Math.Floor((targetHero.Level - 1) / 3d)); alreadyAdd2 = true; } } if (spellData.BonusDamages?.Count > 0) { foreach (var bonusDmg in spellData.BonusDamages) { var dmg = source.ResolveBonusSpellDamage(target, bonusDmg, spellLevel - 1); if (dmg <= 0) { continue; } if (!alreadyAdd1 && (spellData.IsModifiedDamage || spellData.SpellEffectType == SpellEffectType.Single)) { if (source.HasBuff("Serrated")) { dmg += 15; } if (targetHero != null) { if (Items.HasItem((int)ItemId.Dorans_Shield, targetHero)) { dmg -= 8; } } else if (targetMinion == null) { var savagery = source.GetCunning(Cunning.Savagery); if (savagery.IsValid()) { dmg += savagery.Points; } } alreadyAdd1 = true; } dmgBonus += source.CalculateDamage(target, bonusDmg.DamageType, dmg); if (!alreadyAdd2 && spellData.IsModifiedDamage && bonusDmg.DamageType == DamageType.Physical && targetHero != null && targetHero.ChampionName == "Fizz") { dmgBonus -= 4 + (2 * Math.Floor((targetHero.Level - 1) / 3d)); alreadyAdd2 = true; } } } var totalDamage = dmgBase + dmgBonus; if (totalDamage > 0) { if (spellData.ScalePerTargetMissHealth > 0) { totalDamage *= (target.MaxHealth - target.Health) / target.MaxHealth * spellData.ScalePerTargetMissHealth + 1; } if (target is Obj_AI_Minion && spellData.MaxDamageOnMinion?.Count > 0) { totalDamage = Math.Min( totalDamage, spellData.MaxDamageOnMinion[Math.Min(spellLevel - 1, spellData.MaxDamageOnMinion.Count - 1)]); } if (spellData.IsApplyOnHit || spellData.IsModifiedDamage) { dmgPassive += source.GetPassiveDamageInfo(target, false).Value; if (targetHero != null) { if (spellData.IsModifiedDamage && Items.HasItem(3047, targetHero)) { dmgReduce *= 0.88; } if (source.GetFerocity(Ferocity.FervorofBattle).IsValid()) { var fervorBuffCount = source.GetBuffCount("MasteryOnHitDamageStacker"); if (fervorBuffCount > 0) { dmgPassive += source.CalculateDamage( target, DamageType.Physical, (0.13 + (0.77 * source.Level)) * fervorBuffCount); } } } } } return Math.Max( Math.Floor( totalDamage * dmgReduce + (spellData.IsApplyOnHit || spellData.IsModifiedDamage ? source.PassiveFlatMod(target) : 0) + dmgPassive), 0); }
public static int GetCustomDamage(this Obj_AI_Hero source, string auraname, Obj_AI_Hero target) { if (auraname == "sheen") { return (int) source.CalculateDamage(target, DamageType.Physical, 1.0 * source.FlatPhysicalDamageMod + source.BaseAttackDamage); } if (auraname == "lichbane") { return (int) source.CalculateDamage(target, DamageType.Magical, (0.75 * source.FlatPhysicalDamageMod + source.BaseAttackDamage) + (0.50 * source.FlatMagicDamageMod)); } return 0; }
/// <summary> /// Gets the passive raw damage summary. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target. /// </param> /// <returns> /// The <see cref="double" />. /// </returns> private static PassiveDamageInfo GetPassiveDamageInfo(this Obj_AI_Hero source, Obj_AI_Base target) { var @double = 0d; var @override = false; List<PassiveDamage> value; // If you don't understand the code below, you should be flipping burgers instead. if (PassiveDamages.TryGetValue(string.Empty, out value)) { // This should fix something that should never happen. value = value.Where(i => (i.Condition?.Invoke(source, target)).GetValueOrDefault() && i.Func != null) .ToList(); @double += value.Sum( item => item.IgnoreCalculation ? item.Func(source, target) : source.CalculateDamage(target, item.DamageType, item.Func(source, target))); @override = value.Any(i => i.Override); } if (PassiveDamages.TryGetValue(source.ChampionName, out value)) { value = value.Where(i => (i.Condition?.Invoke(source, target)).GetValueOrDefault() && i.Func != null) .ToList(); @double += value.Sum( item => item.IgnoreCalculation ? item.Func(source, target) : source.CalculateDamage(target, item.DamageType, item.Func(source, target))); if (!@override) { @override = value.Any(i => i.Override); } } return new PassiveDamageInfo { Value = @double, Override = @override }; }
/// <summary> /// Get the spell damage value. /// </summary> /// <param name="source"> /// The source /// </param> /// <param name="target"> /// The target /// </param> /// <param name="spellSlot"> /// The spell slot /// </param> /// <param name="stage"> /// The stage /// </param> /// <returns> /// The <see cref="double" /> value of damage. /// </returns> public static double GetSpellDamage( this Obj_AI_Hero source, Obj_AI_Base target, SpellSlot spellSlot, DamageStage stage = DamageStage.Default) { if (source == null || !source.IsValid || target == null || !target.IsValid) { return 0d; } var spellLevel = source.Spellbook.GetSpell(spellSlot).Level; if (spellLevel == 0) { return 0d; } ChampionDamage value; if (DamageCollection.TryGetValue(source.ChampionName, out value)) { var baseDamage = 0d; var bonusDamage = 0d; var spellData = value.GetSlot(spellSlot)?.FirstOrDefault(e => e.Stage == stage)?.SpellData; if (spellData?.Damages?.Count > 0) { baseDamage = source.CalculateDamage( target, spellData.DamageType, spellData.Damages[Math.Min(spellLevel - 1, spellData.Damages.Count)]); if (!string.IsNullOrEmpty(spellData.ScalingBuff)) { var buffCount = (spellData.ScalingBuffTarget == DamageScalingTarget.Source ? source : target).GetBuffCount( spellData.ScalingBuff); if (buffCount != 0) { baseDamage *= buffCount + spellData.ScalingBuffOffset; } } } if (spellData?.BonusDamages?.Count > 0) { bonusDamage = spellData.BonusDamages.Sum( instance => source.CalculateDamage( target, instance.DamageType, source.ResolveBonusSpellDamage(target, instance, spellLevel - 1))); } return baseDamage + bonusDamage; } return 0d; }