/// <summary> /// Gets the spell damage. /// </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>System.Double.</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); } if (!DamageLibrary.Damages.TryGetValue(source.ChampionName, out ChampionDamage value)) { return(0); } var spellData = value.GetSlot(spellSlot)?.FirstOrDefault(e => e.Stage == stage)?.SpellData; if (spellData == null) { return(0); } var scaleSlot = spellData.ScaleSlot != SpellSlot.Unknown ? spellData.ScaleSlot : spellSlot; var spellLevel = source.SpellBook.GetSpell(scaleSlot).Level; if (spellLevel == 0) { return(0); } var alreadyAdd1 = false; var targetHero = target as Obj_AI_Hero; var targetMinion = target as Obj_AI_Minion; var dmgBase = 0d; var dmgBonus = 0d; var dmgPassive = 0d; 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 scalingTarget = spellData.ScalingBuffTarget == DamageScalingTarget.Source ? source : target; var buffCount = scalingTarget.GetRealBuffCount(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) { alreadyAdd1 = true; } dmgBase = source.CalculateDamage(target, spellData.DamageType, dmgBase); } if (spellData.BonusDamages?.Count > 0) { foreach (var bonusDmg in spellData.BonusDamages) { var dmg = source.GetBonusSpellDamage(target, bonusDmg, spellLevel - 1); if (dmg <= 0) { continue; } if (!alreadyAdd1 && (spellData.IsModifiedDamage || spellData.SpellEffectType == SpellEffectType.Single)) { alreadyAdd1 = true; } dmgBonus += source.CalculateDamage(target, bonusDmg.DamageType, dmg); } } var totalDamage = dmgBase + dmgBonus; if (totalDamage > 0) { if (spellData.ScalePerCritPercent > 0) { totalDamage *= source.Crit * 100 * spellData.ScalePerCritPercent; } if (spellData.ScalePerTargetMissHealth > 0) { totalDamage *= (target.MaxHealth - target.Health) / target.MaxHealth * spellData.ScalePerTargetMissHealth + 1; } if (target is Obj_AI_Minion) { if (spellData.MaxDamageOnMinion?.Count > 0) { totalDamage = Math.Min( totalDamage, spellData.MaxDamageOnMinion[Math.Min(spellLevel - 1, spellData.MaxDamageOnMinion.Count - 1)]); } if (target.Team == GameObjectTeam.Neutral && spellData.MaxDamageOnMonster?.Count > 0) { totalDamage = Math.Min( totalDamage, spellData.MaxDamageOnMonster[Math.Min(spellLevel - 1, spellData.MaxDamageOnMonster.Count - 1)]); } } if (spellData.IsModifiedDamage) { if (targetHero != null && targetHero.HasItem(ItemId.NinjaTabi)) { dmgReduce *= 0.9; } } } if (spellData.IsApplyOnHit || spellData.IsModifiedDamage) { var itemDamage = DamageItems.ComputeItemDamages(source, target); totalDamage += source.CalculateDamage(target, DamageType.Physical, itemDamage.PhysicalDamage); totalDamage += source.CalculateDamage(target, DamageType.Magical, itemDamage.MagicalDamage); } if (source.ChampionName == "Sejuani" && target.HasBuff("sejuanistun")) { switch (target.Type) { case GameObjectType.obj_AI_Hero: if (source.Level < 7) { dmgPassive += 0.1 * target.MaxHealth; } else if (source.Level < 14) { dmgPassive += 0.15 * target.MaxHealth; } else { dmgPassive += 0.2 * target.MaxHealth; } break; case GameObjectType.obj_AI_Minion: dmgPassive += 400; break; } dmgPassive = source.CalculateDamage(target, DamageType.Magical, dmgPassive); } return(Math.Max(Math.Floor(totalDamage * dmgReduce + dmgPassive), 0)); }
/// <summary> /// Gets the spell damage. /// </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>System.Double.</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); } if (!DamageLibrary.Damages.TryGetValue(source.ChampionName, out ChampionDamage 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 alreadyAdd1 = false; var alreadyAdd2 = false; var targetHero = target as Obj_AI_Hero; var targetMinion = target as Obj_AI_Minion; var dmgBase = 0d; var dmgBonus = 0d; var dmgPassive = 0d; 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) { 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.GetBonusSpellDamage(target, bonusDmg, spellLevel - 1); if (dmg <= 0) { continue; } if (!alreadyAdd1 && (spellData.IsModifiedDamage || spellData.SpellEffectType == SpellEffectType.Single)) { alreadyAdd1 = true; } dmgBonus += source.CalculateDamage(target, bonusDmg.DamageType, dmg); if (alreadyAdd2 || !spellData.IsModifiedDamage || bonusDmg.DamageType != DamageType.Physical || targetHero == null || targetHero.ChampionName != "Fizz") { continue; } dmgBonus -= 4 + (2 * Math.Floor((targetHero.Level - 1) / 3d)); alreadyAdd2 = true; } } var totalDamage = dmgBase + dmgBonus; if (totalDamage > 0) { if (spellData.ScalePerCritPercent > 0) { totalDamage *= source.Crit * 100 * spellData.ScalePerCritPercent; } 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 += 0; // todo get passive shit if (targetHero != null) { if (spellData.IsModifiedDamage && targetHero.HasItem(3047)) { dmgReduce *= 0.9; } } } } return(Math.Max( Math.Floor( totalDamage * dmgReduce + (spellData.IsApplyOnHit || spellData.IsModifiedDamage ? source.GetPassiveFlatMod(target) : 0) + dmgPassive), 0)); }