예제 #1
0
        private void CalculateDamage()
        {
            float baseDamage     = 0.0f;
            float critMultiplier = 0.0f;
            float duration       = 0.0f;
            float AP             = Stats.AttackPower;
            float SP             = Stats.SpellPower;

#if (RAWR3)
            int targetLevel = BossOpts.Level;
#else
            int targetLevel = CalcOpts.TargetLevel;
#endif

            #region Ability Base Damage
            switch (Ability)
            {
            // White Damage
            case Ability.None:
                baseDamage = Stats.WeaponDamage;

                DamageMultiplier *= (1.0f + Stats.BonusPhysicalDamageMultiplier)
                                    * (1.0f - (Lookup.GlancingReduction(Character, targetLevel) * AttackTable.Glance))
                                    * (1.0f - ArmorReduction);

                critMultiplier = 1.0f;
                break;

            case Ability.ShieldOfRighteousness:
                float blockValue = Stats.BlockValue + Stats.ShieldOfRighteousnessBlockValue + Stats.JudgementBlockValue + Stats.HolyShieldBlockValue;

                float blockValueDRStart = 30 * Character.Level;

                if (blockValue < blockValueDRStart)
                {
                    baseDamage = blockValue;
                }
                else if (blockValue < 39.5 * Character.Level)
                {
                    baseDamage = blockValueDRStart + (0.95f * (blockValue - blockValueDRStart)) - (0.000625f * (float)Math.Pow(blockValue - blockValueDRStart, 2));
                }
                else
                {
                    baseDamage = blockValueDRStart + (0.95f * 9.5f * Character.Level) - (0.000625f * (float)Math.Pow(9.5 * Character.Level, 2));
                }

                baseDamage += 520f
                              + Stats.BonusShieldOfRighteousnessDamage;

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier);
                critMultiplier    = 1.0f;
                break;

            case Ability.HammerOfTheRighteous:
                if (Talents.HammerOfTheRighteous == 0 || Character.MainHand == null)
                {
                    Damage = 0.0f;
                    return;
                }

                baseDamage = (Stats.WeaponDamage / Character.MainHand.Speed) * 4.0f;

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + Stats.BonusHammerOfTheRighteousMultiplier);

                critMultiplier = 1.0f;
                break;

            // Seal of Vengeance is the tiny damage that applies on each swing; Holy Vengeance is the DoT
            // While trivial threat and damage, it's modeled for compatibility with Seal of Righteousness
            case Ability.SealOfVengeance:
                baseDamage = Stats.WeaponDamage * 0.33f;

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + 0.03f * Talents.SealsOfThePure)
                                    * (1.0f + Stats.BonusSealOfVengeanceDamageMultiplier);

                critMultiplier = 1.0f;
                break;

            // 5 stacks of Holy Vengeance are assumed
            // TODO: implement stacking mechanic for beginning-of-fight TPS
            case Ability.HolyVengeance:
                baseDamage = 5f * (0.016f * SP + 0.032f * AP);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + 0.03f * Talents.SealsOfThePure)
                                    * (1.0f + Stats.BonusSealOfVengeanceDamageMultiplier);

                critMultiplier = 0.0f;
                break;

            // Judgement of Vengeance assumes 5 stacks of Holy Vengeance
            case Ability.JudgementOfVengeance:
                float holyVengeanceStacks = 5;

                baseDamage = (0.22f * SP + 0.14f * AP) * (1.0f + 0.1f * holyVengeanceStacks);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + 0.03f * Talents.SealsOfThePure)
                                    * (Talents.GlyphOfJudgement ? 1.1f : 1.0f);

                critMultiplier = 1.0f;
                break;

            case Ability.SealOfRighteousness:
                baseDamage = Lookup.WeaponSpeed(Character, Stats) * ((0.022f * AP) + (0.044f * SP));

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + 0.03f * Talents.SealsOfThePure)
                                    * (1.0f + Stats.BonusSealOfRighteousnessDamageMultiplier)
                                    * (Talents.GlyphOfSealOfRighteousness ? 1.1f : 1.0f);

                critMultiplier = 0.0f;
                break;

            case Ability.JudgementOfRighteousness:
                baseDamage = 1.0f + (0.2f * AP) + (0.32f * SP);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + 0.03f * Talents.SealsOfThePure)
                                    * (Talents.GlyphOfJudgement ? 1.1f : 1.0f);

                critMultiplier = 1.0f;
                break;

            case Ability.HolyShield:
                if (Talents.HolyShield == 0)
                {
                    Damage = 0.0f;
                    return;
                }

                baseDamage        = (211f + (0.056f * AP) + (0.09f * SP)) * 1.3f;
                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier);
                critMultiplier    = 0.0f;
                break;

            case Ability.Consecration:
                baseDamage        = 113f + (0.04f * (SP + Stats.ConsecrationSpellPower)) + (0.04f * AP);
                duration          = (Talents.GlyphOfConsecration ? 10.0f : 8.0f);
                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier);
                critMultiplier    = 0.0f;
                break;

            case Ability.Exorcism:
                baseDamage = 1087f + (0.15f * SP) + (0.15f * AP);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + Talents.SanctityOfBattle * 0.05f)
                                    * (Talents.GlyphOfExorcism ? 1.2f : 1.0f);

                critMultiplier = 0.5f;
                break;

            case Ability.AvengersShield:
                baseDamage = 1222f + (0.07f * SP) + (0.07f * AP);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (Talents.GlyphOfAvengersShield ? 2.0f : 1.0f);

                critMultiplier = 1.0f;
                break;

            case Ability.HolyWrath:
                baseDamage        = 1142f + (AP * 0.07f) + (SP * 0.07f);
                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier);
                critMultiplier    = 0.5f;
                break;

            case Ability.HammerOfWrath:
                baseDamage        = 1198f + (AP * 0.15f) + (SP * 0.15f);
                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier);
                critMultiplier    = 1.0f;
                break;

            case Ability.RetributionAura:
                baseDamage = 112f + (SP * 0.0666f);

                DamageMultiplier *= (1.0f + Stats.BonusHolyDamageMultiplier)
                                    * (1.0f + Talents.SanctifiedRetribution * 0.5f);

                critMultiplier = 0.0f;
                break;
            }
            #endregion

            // All damage multipliers, 1HWS, Armor etc...do we need to split buff/debuff ?
            baseDamage *= DamageMultiplier;

            #region Miss Chance, Avoidance Chance
            if (Lookup.IsSpell(Ability))
            {
                if (Ability == Ability.Consecration)
                {
                    // Probability calculation, since each tick can be resisted individually.
                    baseDamage = Lookup.GetConsecrationTickChances(duration, baseDamage, AttackTable.Miss);
                }
                else
                {
                    // Missed spell attacks
                    // TODO: expand Ability Model to include a check for damage type, not only spell.
                    baseDamage *= (1.0f - AttackTable.Miss);
                }
            }
            else
            {
                // Missed attacks
                if (Lookup.IsAvoidable(Ability))
                {
                    baseDamage *= (1.0f - AttackTable.AnyMiss);
                }
                else
                {
                    baseDamage *= (1.0f - AttackTable.Miss);
                }
            }
            #endregion

            #region Partial Resists
            // Partial Resists
            if (Lookup.HasPartials(Ability))
            {
                // Detailed table of Partial slices.
                float[] partialChanceTable = StatConversion.GetResistanceTable(Character.Level, targetLevel, 0.0f, Stats.SpellPenetration);

                // Here goes nothing, Damage averaged over the different partial slices that can happen.
                float partialDamage = 0.0f;

                for (int i = 0; i < 11; i++)
                {
                    partialDamage += partialChanceTable[i] * (1.0f - 0.1f * (float)i) * baseDamage;
                }

                baseDamage = partialDamage;
            }
            #endregion

            // Average critical strike bonuses
            if (Lookup.CanCrit(Ability))
            {
                baseDamage += baseDamage * critMultiplier * AttackTable.Critical;
            }

            // Final Damage the Ability deals
            Damage = baseDamage;
        }
예제 #2
0
        private void CalculateDamage()
        {
            float baseDamage     = 0.0f;
            float critMultiplier = 0.0f;
            float duration       = 0.0f;
            float AP             = Stats.AttackPower;
            float SP             = Stats.SpellPower;

            int targetLevel = BossOpts.Level;

            #region Ability Base Damage
            switch (Ability)
            {
                #region Spells

            case Ability.AvengersShield:
                if (Character.OffHand == null || Character.OffHand.Type != ItemType.Shield || (Talents.Divinity == 0 && Talents.SealsOfThePure == 0 && Talents.EternalGlory == 0))
                {
                    Damage = 0f;
                    return;
                }

                baseDamage = 3113.187994f + (0.419f * AP) + (0.21f * SP);

                baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier)
                              * (Talents.GlyphOfFocusedShield ? 1.3f : 1.0f);

                critMultiplier = 1.0f;
                break;

            case Ability.HammerOfWrath:
                baseDamage = 4015.02439f + (0.039f * AP) + (0.117f * SP);

                baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;

            case Ability.HolyWrath:
                baseDamage = 2435.781339f + (0.61f * SP);

                baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 0.5f;
                break;

                #endregion

                #region Melee

            case Ability.CrusaderStrike:
                if (Character.MainHand == null)
                {
                    Damage = 0f;
                    return;
                }

                baseDamage  = Lookup.WeaponDamage(Character, Stats.AttackPower, true);
                baseDamage *= 1.2f
                              + (1.2f * (Talents.Crusade * 0.1f))
                              + (1.2f * (Talents.WrathOfTheLightbringer * 0.5f));

                baseDamage *= (1.0f + Stats.BonusPhysicalDamageMultiplier)
                              * (1.0f + Stats.BonusDamageMultiplierCrusaderStrike)
                              * (1.0f - ArmorReduction);

                critMultiplier = 1.0f;
                break;

            case Ability.HammerOfTheRighteous:
                if (Character.MainHand == null || (Character.MainHand.Type != ItemType.OneHandAxe && Character.MainHand.Type != ItemType.OneHandMace && Character.MainHand.Type != ItemType.OneHandSword) || Talents.HammerOfTheRighteous == 0)
                {
                    Damage = 0f;
                    return;
                }

                baseDamage = Lookup.WeaponDamage(Character, Stats.AttackPower, true) * 0.3f;

                baseDamage *= (1f + (Talents.Crusade * 0.1f) + (Talents.GlyphOfHammerOfTheRighteous ? 0.1f : 0f))
                              * (1.0f + Stats.BonusPhysicalDamageMultiplier)
                              * (1.0f - ArmorReduction);

                critMultiplier = 1.0f;
                break;

            case Ability.HammerOfTheRighteousProc:
                if (Character.MainHand == null || (Character.MainHand.Type != ItemType.OneHandAxe && Character.MainHand.Type != ItemType.OneHandMace && Character.MainHand.Type != ItemType.OneHandSword) || Talents.HammerOfTheRighteous == 0)
                {
                    Damage = 0f;
                    return;
                }

                baseDamage = 728.8813374f + (0.18f * AP);

                baseDamage *= (1f + (Talents.Crusade * 0.1f) + (Talents.GlyphOfHammerOfTheRighteous ? 0.1f : 0f))
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;

            case Ability.JudgementOfRighteousness:
                baseDamage = 1f + (0.2f * AP) + (0.32f * SP);

                baseDamage *= (1f + (Talents.WrathOfTheLightbringer * 0.5f) + (Talents.GlyphOfJudgement ? 0.1f : 0f))
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;

            case Ability.JudgementOfTruth:
            {
                float censureStacks = 5;

                baseDamage = 1 + (0.223f * SP) + (0.142f * AP) * (1.0f + 0.1f * censureStacks);

                baseDamage *= (1f + (Talents.WrathOfTheLightbringer * 0.5f) + (Talents.GlyphOfJudgement ? 0.1f : 0f))
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
            }
            break;

            case Ability.MeleeSwing:
                baseDamage = Stats.WeaponDamage;

                baseDamage *= (1.0f + Stats.BonusPhysicalDamageMultiplier)
                              * (1.0f - (Lookup.GlancingReduction(Character.Level, targetLevel) * AttackTable.Glance))
                              * (1.0f - ArmorReduction);

                baseDamage *= (1f + Stats.BonusWhiteDamageMultiplier);

                critMultiplier = 1.0f;
                break;

            case Ability.SealOfRighteousness:
                baseDamage = Lookup.WeaponSpeed(Character, Stats) * ((0.022f * SP) + (0.011f * AP));

                baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure)
                              * (1.0f + Stats.BonusHolyDamageMultiplier)
                              * (1.0f + Stats.BonusDamageShieldofRighteous);

                critMultiplier = 0.0f;
                break;

            case Ability.SealOfTruth:
            {
                float censureStacks = 5;

                baseDamage  = Stats.WeaponDamage * 0.018f * censureStacks;
                baseDamage += (1f + (0.01f * SP) + (0.0193f * AP));

                baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure)
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;
            }

            case Ability.ShieldOfTheRighteous:
                if (Character.OffHand == null || Character.OffHand.Type != ItemType.Shield || Talents.ShieldOfTheRighteous == 0)
                {
                    Damage = 0f;
                    return;
                }

                baseDamage = 610.4895857f + (0.6f * AP);

                baseDamage *= (1.0f + (Talents.GlyphOfShieldOfTheRighteous ? 0.1f : 0f))
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;

                #endregion

                #region DoTs

            case Ability.CensureTick:
            {
                float censureStacks = 5;

                baseDamage = ((0.01f * SP) + (0.0193f * AP)) * censureStacks;

                baseDamage *= (1.0f + 0.06f * Talents.SealsOfThePure)
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 1.0f;
                break;
            }

            case Ability.Consecration:
                baseDamage = 81.32998299f + (0.027f * SP) + (0.027f * AP); // Per tick

                duration = Talents.GlyphOfConsecration ? 12f : 10f;        //10.0f * (1f + (Talents.GlyphOfConsecration ? 0.2f : 0f));

                baseDamage *= duration
                              * (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 0.0f;
                break;

                #endregion

                #region Defensive

            case Ability.RetributionAura:
                baseDamage = 121.4802229f + (SP * 0.033f);

                baseDamage *= (1.0f + Stats.BonusHolyDamageMultiplier);

                critMultiplier = 0.0f;
                break;

                #endregion
            }

            baseDamage *= (1.0f + Stats.BonusDamageMultiplier);

            #endregion

            #region Miss Chance, Avoidance Chance
            if (Lookup.IsSpell(Ability))
            {
                if (Ability == Ability.Consecration)
                {
                    // Probability calculation, since each tick can be resisted individually.
                    baseDamage = Lookup.GetConsecrationTickChances(duration, baseDamage, AttackTable.Miss);
                }
                else
                {
                    // Missed spell attacks
                    baseDamage *= (1.0f - AttackTable.Miss);
                }
            }
            else
            {
                // Avoidable attacks
                if (Lookup.IsAvoidable(Ability))
                {
                    baseDamage *= (1.0f - AttackTable.AnyMiss);
                }
            }
            #endregion

            // Average critical strike bonuses
            if (Lookup.CanCrit(Ability))
            {
                baseDamage += baseDamage * critMultiplier * AttackTable.Critical;
            }

            // Final Damage the Ability deals
            Damage = baseDamage;
        }