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