Beispiel #1
0
        protected override void Calculate()
        {
            // Hack to not count holy shield when we are trying to calculate crit chance without it
            if (!UseHolyShield && CalcOpts.UseHolyShield)
            {
                Stats.Accumulate(new Stats()
                {
                    Block = -0.3f
                });
            }

            float tableSize = 0.0f;

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

            // Miss
            Miss       = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Miss, targetLevel));
            tableSize += Miss;
            // Dodge
            Dodge      = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Dodge, targetLevel));
            tableSize += Dodge;
            // Parry
            Parry      = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Parry, targetLevel));
            tableSize += Parry;
            // Block
            if (Character.OffHand != null && Character.OffHand.Type == ItemType.Shield)
            {
                Block      = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Block, targetLevel));
                tableSize += Block;
            }
            // Critical Hit
            Critical   = Math.Min(1.0f - tableSize, Lookup.TargetCritChance(Character, Stats, targetLevel));
            tableSize += Critical;
            // Normal Hit
            Hit = Math.Max(0.0f, 1.0f - tableSize);
            // Partial Resists don't belong in the combat table
            Resist = 1.0f - StatConversion.GetResistanceTable(targetLevel, Character.Level, Stats.FrostResistance, 0.0f)[0];

            // Hack to put back holy shield when we are trying to calculate crit chance without it
            if (!UseHolyShield && CalcOpts.UseHolyShield)
            {
                Stats.Accumulate(new Stats()
                {
                    Block = 0.3f
                });
            }
        }
Beispiel #2
0
        protected override void Calculate()
        {
            float tableSize = 0.0f;

            int targetLevel = BossOpts.Level;

            // Miss
            Miss       = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Miss, targetLevel));
            tableSize += Miss;
            // Dodge
            Dodge      = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Dodge, targetLevel));
            tableSize += Dodge;
            // Parry
            Parry      = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Parry, targetLevel));
            tableSize += Parry;
            // Block
            if (Character.OffHand != null && Character.OffHand.Type == ItemType.Shield)
            {
                //Block = Math.Min(1.0f - tableSize, Lookup.AvoidanceChance(Character, Stats, HitResult.Block, targetLevel));
                Block = Lookup.AvoidanceChance(Character, Stats, HitResult.Block, targetLevel);
                if (Block > (1.0f - tableSize))
                {
                    BlockOverCap = Block - 1.0f + tableSize;
                }
                else
                {
                    BlockOverCap = 0.0f;
                }
                tableSize += Block;
            }
            // Critical Hit
            Critical   = Math.Min(1.0f - tableSize, Lookup.TargetCritChance(Character, Stats, targetLevel));
            tableSize += Critical;
            // Normal Hit
            Hit = Math.Max(0.0f, 1.0f - tableSize);
            // Partial Resists don't belong in the combat table
            Resist = 1.0f - StatConversion.GetResistanceTable(targetLevel, Character.Level, Stats.FrostResistance, 0.0f)[0];
        }
Beispiel #3
0
        public static float TargetAvoidanceChance(Character character, Stats stats, HitResult avoidanceType, int targetLevel)
        {
            switch (avoidanceType)
            {
            case HitResult.Miss: return(StatConversion.WHITE_MISS_CHANCE_CAP[targetLevel - 80]);

            case HitResult.Dodge: return(StatConversion.WHITE_DODGE_CHANCE_CAP[targetLevel - 80]);

            case HitResult.Parry: return(StatConversion.WHITE_PARRY_CHANCE_CAP[targetLevel - 80]);

            case HitResult.Glance: return(StatConversion.WHITE_GLANCE_CHANCE_CAP[targetLevel - 80]);

            case HitResult.Block: return(StatConversion.WHITE_BLOCK_CHANCE_CAP[targetLevel - 80]);

            case HitResult.Resist:
                // Patial resists don't belong in the combat table, they are a damage multiplier (reduction)
                // The Chance to get any Partial Resist
                float partialChance = 1.0f - StatConversion.GetResistanceTable(character.Level, targetLevel, 0.0f, stats.SpellPenetration)[0];
                return(partialChance);

            default: return(0.0f);
            }
        }
Beispiel #4
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;
        }