Example #1
0
        /// <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);
            }

            bool alreadyAdd1 = false, alreadyAdd2 = false;
            var  targetHero   = target as Obj_AI_Hero;
            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 &&
                            new[] { 3047, 1316, 1318, 1315, 1317 }.Any(i => Items.HasItem(i, targetHero)))
                        {
                            dmgReduce *= 0.9;
                        }
                        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));
        }
Example #2
0
        /// <summary>
        ///     Apples passive percent mod calculations towards the given amount of damage, a modifier onto the amount based on
        ///     passive percent effects.
        /// </summary>
        /// <param name="source">
        ///     The source
        /// </param>
        /// <param name="target">
        ///     The target
        /// </param>
        /// <param name="amount">
        ///     The amount
        /// </param>
        /// <param name="damageType">
        ///     The damage Type.
        /// </param>
        /// <returns>
        ///     The damage after passive percent modifier calculations.
        /// </returns>
        private static double PassivePercentMod(
            this Obj_AI_Base source,
            Obj_AI_Base target,
            double amount,
            DamageType damageType)
        {
            if (source is Obj_AI_Turret)
            {
                var minion = target as Obj_AI_Minion;
                if (minion != null)
                {
                    var minionType = minion.GetMinionType();
                    if (minionType.HasFlag(MinionTypes.Siege))
                    {
                        // Siege minions and super minions receive 70% damage from turrets.
                        amount *= 0.7;
                    }
                    else if (minionType.HasFlag(MinionTypes.Normal))
                    {
                        // Normal minions take 114% more damage from towers.
                        amount *= 1.14285714285714;
                    }
                }
            }

            var hero       = source as Obj_AI_Hero;
            var targetHero = target as Obj_AI_Hero;

            if (hero != null)
            {
                // DoubleEdgedSword
                if (damageType != DamageType.True && hero.GetFerocity(Ferocity.DoubleEdgedSword).IsValid())
                {
                    amount *= hero.IsMelee() ? 1.03 : 1.02;
                }

                // Oppressor
                if (hero.GetFerocity(Ferocity.Oppressor).IsValid() && target.IsMoveImpaired())
                {
                    amount *= 1.025;
                }

                if (targetHero != null)
                {
                    // Expose Weakness
                    var exposeweakBuff = targetHero.GetBuff("ExposeWeaknessDebuff");
                    if (exposeweakBuff != null && hero.Team == exposeweakBuff.Caster.Team &&
                        !exposeweakBuff.Caster.Compare(hero))
                    {
                        amount *= 1.03;
                    }

                    // Assassin
                    if (hero.GetCunning(Cunning.Assassin).IsValid() &&
                        !GameObjects.Heroes.Any(
                            h => h.Team == hero.Team && !h.Compare(hero) && h.Distance(hero) < 800))
                    {
                        amount *= 1.02;
                    }

                    // Merciless
                    var merciless = hero.GetCunning(Cunning.Merciless);
                    if (merciless.IsValid() && targetHero.HealthPercent < 40)
                    {
                        amount *= 1 + (merciless.Points / 100);
                    }

                    // Giant Slayer - Lord Dominik's Regards
                    if ((Items.HasItem(3036, hero) || Items.HasItem(3034, hero)) &&
                        hero.MaxHealth < targetHero.MaxHealth && damageType == DamageType.Physical)
                    {
                        amount *= 1
                                  + Math.Min(targetHero.MaxHealth - hero.MaxHealth, 500) / 50
                                  * (Items.HasItem(3036, hero) ? 0.015 : 0.01);
                    }
                }
            }

            // DoubleEdgedSword
            if (targetHero != null && damageType != DamageType.True &&
                targetHero.GetFerocity(Ferocity.DoubleEdgedSword).IsValid())
            {
                amount *= targetHero.IsMelee() ? 1.015 : 1.02;
            }

            return(amount);
        }
Example #3
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 GetAutoAttackDamage(this Obj_AI_Base source, Obj_AI_Base target)
        {
            double dmgPhysical = source.TotalAttackDamage, dmgMagical = 0, dmgPassive = 0;
            var    dmgReduce = 1d;

            var hero       = source as Obj_AI_Hero;
            var targetHero = target as Obj_AI_Hero;

            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 = 200;
                        if (Items.HasItem((int)ItemId.Targons_Brace, hero))
                        {
                            spoilwarDmg = 240;
                        }
                        else if (Items.HasItem((int)ItemId.Face_of_the_Mountain, hero) || eyeEquinox)
                        {
                            spoilwarDmg = 400;
                        }
                        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) &&
                new[] { 3047, 1316, 1318, 1315, 1317 }.Any(i => Items.HasItem(i, targetHero)))
            {
                dmgReduce *= 0.9;
            }

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