Exemplo n.º 1
0
        private void CalculateThreat()
        {
            // Base threat is always going to be the damage of the ability, if it is damaging
            float abilityThreat = Damage;

            switch (Ability)
            {
            case Ability.Cleave:
                abilityThreat += 30.0f;
                break;

            case Ability.HeroicStrike:
                abilityThreat += 28.0f;
                break;

            case Ability.HeroicThrow:
                abilityThreat *= 1.5f;
                break;

            case Ability.Revenge:
                abilityThreat += 7.0f;
                break;

            case Ability.ShieldBash:
                abilityThreat += 36.0f;
                break;

            case Ability.ShieldSlam:
                abilityThreat += 231.0f;
                break;

            case Ability.Slam:
                abilityThreat += 140.0f;
                break;

            case Ability.SunderArmor:
                abilityThreat += 395.0f + (Player.Stats.AttackPower * 0.05f);
                break;
            }

            abilityThreat *= Lookup.StanceThreatMultipler(Player);

            Threat = abilityThreat;
        }
Exemplo n.º 2
0
        private void CalculateThreat()
        {
            // Base threat is always going to be the damage of the ability, if it is damaging
            float abilityThreat = Damage;

            switch (Ability)
            {
            case Ability.Cleave:
                abilityThreat += 225.0f;
                break;

            case Ability.ConcussionBlow:
                abilityThreat *= 2.0f;
                break;

            case Ability.Devastate:
                // Glyph of Devastate doubles bonus threat
                if (Talents.GlyphOfDevastate)
                {
                    abilityThreat += (315 + (Stats.AttackPower * 0.05f)) * 2.0f;
                }
                else
                {
                    abilityThreat += 315 + (Stats.AttackPower * 0.05f);
                }
                break;

            case Ability.HeroicStrike:
                abilityThreat += 259.0f;
                break;

            case Ability.HeroicThrow:
                abilityThreat *= 1.5f;
                break;

            case Ability.MockingBlow:
                if (Talents.GlyphOfBarbaricInsults)
                {
                    abilityThreat *= 6.0f;
                }
                else
                {
                    abilityThreat *= 3.0f;
                }
                break;

            case Ability.Revenge:
                abilityThreat += 121.0f;
                break;

            case Ability.ShieldBash:
                abilityThreat += 36.0f;
                break;

            case Ability.ShieldSlam:
                abilityThreat += 770.0f;
                abilityThreat *= 1.3f;
                break;

            case Ability.Slam:
                abilityThreat += 140.0f;
                break;

            case Ability.SunderArmor:
                abilityThreat += 345.0f + (Stats.AttackPower * 0.05f);
                break;

            case Ability.ThunderClap:
                abilityThreat *= 1.85f;
                break;

            case Ability.Vigilance:
                if (Talents.GlyphOfVigilance)
                {
                    abilityThreat = (Options.VigilanceValue * 0.15f) * Talents.Vigilance;
                }
                else
                {
                    abilityThreat = (Options.VigilanceValue * 0.1f) * Talents.Vigilance;
                }
                break;
            }

            // All abilities other than Vigilance are affected by Defensive Stance
            if (Ability != Ability.Vigilance)
            {
                abilityThreat *= Lookup.StanceThreatMultipler(Character, Stats);
            }

            Threat = abilityThreat;
        }
Exemplo n.º 3
0
        private void Calculate()
        {
            Dictionary <Ability, float> modelAbilities = new Dictionary <Ability, float>();
            float modelLength        = 0.0f;
            float modelThreat        = 0.0f;
            float modelDamage        = 0.0f;
            float modelCrits         = 0.0f;
            float modelHits          = 0.0f;
            float modelWeaponAttacks = 0.0f;

            // Rotation Auto-Detection
            if (AttackModelMode == AttackModelMode.Optimal)
            {
                if (Talents.Shockwave == 1 && Talents.SwordAndBoard == 3)
                {
                    if (Talents.ImprovedRevenge > 0)
                    {
                        AttackModelMode = AttackModelMode.FullProtectionRevenge;
                    }
                    else
                    {
                        AttackModelMode = AttackModelMode.FullProtection;
                    }
                }
                else if (Talents.SwordAndBoard == 3)
                {
                    if (Talents.ImprovedRevenge > 0)
                    {
                        AttackModelMode = AttackModelMode.SwordAndBoardRevenge;
                    }
                    else
                    {
                        AttackModelMode = AttackModelMode.SwordAndBoard;
                    }
                }
                else if (Talents.Devastate == 1)
                {
                    if (Talents.ImprovedRevenge > 0)
                    {
                        AttackModelMode = AttackModelMode.DevastateRevenge;
                    }
                    else
                    {
                        AttackModelMode = AttackModelMode.Devastate;
                    }
                }
                else if (Talents.UnrelentingAssault == 2)
                {
                    AttackModelMode = AttackModelMode.UnrelentingAssault;
                }
                else
                {
                    AttackModelMode = AttackModelMode.Basic;
                }
            }

            switch (AttackModelMode)
            {
            case AttackModelMode.Basic:
            {
                // Basic Rotation
                // Shield Slam -> Revenge -> Sunder Armor -> Sunder Armor
                Name        = "Basic Cycle";
                Description = "Shield Slam -> Revenge -> Sunder Armor -> Sunder Armor";
                modelLength = 6.0f;
                modelAbilities.Add(Ability.ShieldSlam, 1.0f);
                modelAbilities.Add(Ability.Revenge, 1.0f);
                modelAbilities.Add(Ability.SunderArmor, 2.0f);
                break;
            }

            case AttackModelMode.Devastate:
            {
                // Devastate Rotation
                // Shield Slam -> Devastate -> Devastate -> Devastate
                Name        = "Devastate";
                Description = "Shield Slam -> Devastate -> Devastate -> Devastate";
                modelLength = 6.0f;
                modelAbilities.Add(Ability.ShieldSlam, 1.0f);
                modelAbilities.Add(Ability.Devastate, 3.0f);
                break;
            }

            case AttackModelMode.DevastateRevenge:
            {
                // Devastate + Revenge Rotation
                // Shield Slam -> Revenge -> Devastate -> Devastate
                Name        = "Devastate + Revenge";
                Description = "Shield Slam -> Revenge -> Devastate -> Devastate";
                modelLength = 6.0f;
                modelAbilities.Add(Ability.ShieldSlam, 1.0f);
                modelAbilities.Add(Ability.Revenge, 1.0f);
                modelAbilities.Add(Ability.Devastate, 2.0f);
                break;
            }

            case AttackModelMode.SwordAndBoard:
            case AttackModelMode.SwordAndBoardRevenge:
            case AttackModelMode.FullProtection:
            case AttackModelMode.FullProtectionRevenge:
            {
                // Sword And Board Rotation
                // Shield Slam > Revenge > Devastate
                // The distribution of abilities in the model is as follows:
                // 1.0 * Shield Slam + 0.73 * Revenge + 1.4596 * Devastate
                // -or-
                // Shield Slam > Revenge > Devastate @ 3s Shield Slam Cooldown > Shockwave > Devastate
                // The distribution of abilities in the model is as follows:
                // 1.0 * Shield Slam + 0.73 * Revenge + 1.133 * Devastate + 0.3266 * (Concussion Blow/Shockwave/Devastate)
                // The cycle length is 4.7844s, abilities per cycle is 3.1896
                Name        = "Sword and Board";
                Description = "Shield Slam > ";
                if (AttackModelMode == AttackModelMode.SwordAndBoardRevenge || AttackModelMode == AttackModelMode.FullProtectionRevenge)
                {
                    Name        += " + Revenge";
                    Description += "Revenge > Devastate";
                }
                else
                {
                    Description += "Devastate";
                }
                if (AttackModelMode == AttackModelMode.FullProtection || AttackModelMode == AttackModelMode.FullProtectionRevenge)
                {
                    Name        += " + Shockwave";
                    Description += "\n@ 1.5s Shield Slam Cooldown: Shockwave > Devastate";
                }

                modelLength = 4.7844f;
                modelAbilities.Add(Ability.ShieldSlam, 1.0f);
                modelAbilities.Add(Ability.Devastate, 1.133f);

                // Add Revenge, if applicable
                if (AttackModelMode == AttackModelMode.SwordAndBoardRevenge || AttackModelMode == AttackModelMode.FullProtectionRevenge)
                {
                    modelAbilities.Add(Ability.Revenge, 0.73f);
                }
                else
                {
                    modelAbilities[Ability.Devastate] += 0.73f;
                }

                // Add Shockwave, if applicable
                if (AttackModelMode == AttackModelMode.FullProtection || AttackModelMode == AttackModelMode.FullProtectionRevenge)
                {
                    modelAbilities.Add(Ability.Shockwave, (0.3266f / 3.0f));
                    modelAbilities[Ability.Devastate] += (0.3266f / 3.0f) * 2.0f;
                }
                else
                {
                    modelAbilities[Ability.Devastate] += 0.3266f;
                }

                break;
            }

            case AttackModelMode.UnrelentingAssault:
            {
                Name        = "Unrelenting Assault";
                Description = "Revenge Only";
                modelLength = 1.0f;
                modelAbilities.Add(Ability.Revenge, 1.0f);
                break;
            }
            }

            // Accumulate base model statistics
            foreach (KeyValuePair <Ability, float> modelAbility in modelAbilities)
            {
                AbilityModel ability = Abilities[modelAbility.Key];
                modelThreat += ability.Threat * modelAbility.Value;
                modelDamage += ability.Damage * modelAbility.Value;
                if (ability.Damage > 0.0f)
                {
                    modelHits  += ability.HitPercentage * modelAbility.Value;
                    modelCrits += ability.CritPercentage * modelAbility.Value;
                }
                if (ability.IsWeaponAttack)
                {
                    modelWeaponAttacks += modelAbility.Value;
                }
            }

            // Simple GCD-Based Latency Adjustment
            modelLength *= Lookup.GlobalCooldownSpeed(Character, true) / Lookup.GlobalCooldownSpeed(Character, false);

            // Weapon Swings/Heroic Strike
            float attackerSwings         = (modelLength / ParryModel.BossAttackSpeed);
            float attackerHits           = DefendTable.AnyHit * attackerSwings;
            float weaponSwings           = modelLength / ParryModel.WeaponSpeed;
            float heroicStrikePercentage = Math.Max(0.0f, Math.Min(1.0f, Options.HeroicStrikeFrequency));

            AbilityModel heroicStrike = Abilities[Ability.HeroicStrike];

            modelThreat += heroicStrike.Threat * weaponSwings * heroicStrikePercentage;
            modelDamage += heroicStrike.Damage * weaponSwings * heroicStrikePercentage;
            modelHits   += heroicStrike.HitPercentage * weaponSwings * heroicStrikePercentage;
            modelCrits  += heroicStrike.CritPercentage * weaponSwings * heroicStrikePercentage;

            AbilityModel whiteSwing = Abilities[Ability.None];

            modelThreat += whiteSwing.Threat * weaponSwings * (1.0f - heroicStrikePercentage);
            modelDamage += whiteSwing.Damage * weaponSwings * (1.0f - heroicStrikePercentage);
            modelCrits  += whiteSwing.CritPercentage * weaponSwings * (1.0f - heroicStrikePercentage);
            modelHits   += whiteSwing.HitPercentage * weaponSwings * (1.0f - heroicStrikePercentage);

            modelWeaponAttacks += weaponSwings;

            // Damage Shield
            AbilityModel damageShield = Abilities[Ability.DamageShield];

            modelThreat += damageShield.Threat * attackerHits;
            modelDamage += damageShield.Damage * attackerHits;

            // Deep Wounds
            AbilityModel deepWounds = Abilities[Ability.DeepWounds];

            modelThreat += deepWounds.Threat * modelCrits;
            modelDamage += deepWounds.Damage * modelCrits;

            // Misc. Power Gains
            modelThreat += DefendTable.DodgeParryBlock * (modelLength / ParryModel.BossAttackSpeed) * 25.0f *
                           (Talents.ShieldSpecialization * 0.2f);
            modelThreat += DefendTable.DodgeParryBlock * (modelLength / ParryModel.BossAttackSpeed) * 1.0f *
                           Lookup.StanceThreatMultipler(Character, Stats) * (Talents.ImprovedDefensiveStance * 0.5f);

            // Vigilance, is already calculated as TPS
            if (Options.UseVigilance)
            {
                modelThreat += Abilities[Ability.Vigilance].Threat * modelLength;
            }

            // Final Per-Second Calculations
            ThreatPerSecond         = modelThreat / modelLength;
            DamagePerSecond         = modelDamage / modelLength;
            WeaponAttacksPerSecond  = modelWeaponAttacks / modelLength;
            HitsPerSecond           = modelHits / modelLength;
            CritsPerSecond          = modelCrits / modelLength;
            AttackerSwingsPerSecond = attackerSwings / modelLength;
            AttackerHitsPerSecond   = attackerHits / modelLength;
        }