예제 #1
0
 public DefendModel(Player player)
 {
     Player      = player;
     AttackSpeed = Lookup.TargetWeaponSpeed(Player);
     DefendTable = new DefendTable(Player);
     Calculate();
 }
예제 #2
0
 public static float TargetAvoidanceChance(Player player, HitResult avoidanceType)
 {
     switch (avoidanceType)
     {
         case HitResult.Miss:
             return StatConversion.WHITE_MISS_CHANCE_CAP[player.BossOpts.Level - 85];
         case HitResult.Dodge:
             return StatConversion.YELLOW_DODGE_CHANCE_CAP[player.BossOpts.Level - 85];
         case HitResult.Parry:
             return StatConversion.YELLOW_PARRY_CHANCE_CAP[player.BossOpts.Level - 85];
         case HitResult.Glance:
             return 0.06f + ((player.BossOpts.Level - player.Character.Level) * 0.06f);
         case HitResult.Crit:
             return -StatConversion.NPC_LEVEL_CRIT_MOD[player.BossOpts.Level - player.Character.Level]; // StatConversion returns as negative
         default:
             return 0.0f;
     }
 }
예제 #3
0
 /// <summary>
 /// This should be a positive number factoring your Defensive Stance (-10% damage taken)
 /// and your stats.DamageTakenReductionMultiplier
 /// </summary>
 /// <returns>A Percentage (1f - (1f - 0.10f) * (1f - player.Stats.DamageTakenReductionMultiplier))</returns>
 public static float StanceDamageReduction(Player player, DamageType damageType)
 {
     // In Defensive Stance
     float damageTaken = (1.0f - 0.10f) * (1.0f - player.Stats.DamageTakenReductionMultiplier);
     
     switch (damageType)
     {
         case DamageType.Arcane:
         case DamageType.Fire:
         case DamageType.Frost:
         case DamageType.Nature:
         case DamageType.Shadow:
         case DamageType.Holy:
             return (1.0f - damageTaken);
         default:
             return (1.0f - damageTaken);
     }
 }
예제 #4
0
 public static float TargetWeaponSpeed(Player player)
 {
     return player.BossOpts.DefaultMeleeAttack.AttackSpeed / (1f - player.Stats.BossAttackSpeedReductionMultiplier);
 }
예제 #5
0
 public static float BonusExpertisePercentage(Player player)
 {
     return StatConversion.GetDodgeParryReducFromExpertise(player.Stats.Expertise + 
         StatConversion.GetExpertiseFromRating(player.Stats.ExpertiseRating), CharacterClass.Warrior);
 }
예제 #6
0
        public AttackModel(Player player, AttackModelMode attackModelMode, RageModelMode rageModelMode)
        {
            Player           = player;
            DefendTable      = new DefendTable(Player);
            _attackModelMode = attackModelMode;
            _rageModelMode   = rageModelMode;

            Abilities.Add(Ability.None, Player);
            Abilities.Add(Ability.Cleave, Player);
            Abilities.Add(Ability.ConcussionBlow, Player);
            Abilities.Add(Ability.DeepWounds, Player);
            Abilities.Add(Ability.Devastate, Player);
            Abilities.Add(Ability.HeroicStrike, Player);
            Abilities.Add(Ability.HeroicThrow, Player);
            Abilities.Add(Ability.Rend, Player);
            Abilities.Add(Ability.Revenge, Player);
            Abilities.Add(Ability.ShieldSlam, Player);
            Abilities.Add(Ability.Shockwave, Player);
            Abilities.Add(Ability.Slam, Player);
            Abilities.Add(Ability.SunderArmor, Player);
            Abilities.Add(Ability.ThunderClap, Player);

            Calculate();
        }
예제 #7
0
 protected void Initialize(Player player, Ability ability)
 {
     Player  = player;
     Ability = ability;
     Calculate();
 }
예제 #8
0
 public AttackTable(Player player)
 {
     Initialize(player, Ability.None);
 }
예제 #9
0
 public static float MaxEffectiveMasteryRating(Player player)
 {
     if (player.DefendModel != null)
         return ((1.0f - player.DefendModel.DefendTable.BaseAnyAvoid) / 0.015f) * StatConversion.RATING_PER_MASTERY;
     else
         return float.MaxValue;
 }
예제 #10
0
 public static float StanceDamageReduction(Player player)
 {
     return StanceDamageReduction(player, DamageType.Physical);
 }
예제 #11
0
 public static float WeaponSpeed(Player player)
 {
     if (player.Character.MainHand != null)
         return Math.Max(1.0f, player.Character.MainHand.Speed / (1.0f + BonusHastePercentage(player)));
     else
         return 1.0f;
 }
예제 #12
0
 public static float TargetArmorReduction(Player player)
 {
     return StatConversion.GetArmorDamageReduction(player.Character.Level, player.BossOpts.Armor,
         player.Stats.TargetArmorReduction, 0.0f);
 }
예제 #13
0
        public static float WeaponDamage(Player player, bool normalized)
        {
            float weaponDamage = 1.0f;

            if (player.Character.MainHand != null)
            {
                float weaponSpeed     = player.Character.MainHand.Speed;
                float weaponMinDamage = player.Character.MainHand.MinDamage;
                float weaponMaxDamage = player.Character.MainHand.MaxDamage;
                float normalizedSpeed = 1.0f;
                if (player.Character.MainHand.Type == ItemType.Dagger)
                    normalizedSpeed = 1.7f;
                else
                    normalizedSpeed = 2.4f;
            
                // Non-Normalized Hits
                if (!normalized)
                    weaponDamage = ((weaponMinDamage + weaponMaxDamage) / 2.0f + (weaponSpeed * player.Stats.AttackPower / 14.0f)) + player.Stats.WeaponDamage;
                // Normalized Hits
                else
                    weaponDamage = ((weaponMinDamage + weaponMaxDamage) / 2.0f + (normalizedSpeed * player.Stats.AttackPower / 14.0f)) + player.Stats.WeaponDamage;
            }

            return weaponDamage;
        }
예제 #14
0
        public static float BonusCritPercentage(Player player, Ability ability)
        {
            // Grab base melee crit chance before adding ability-specific crit chance
            float abilityCritChance = BonusCritPercentage(player);

            switch (ability)
            {
                case Ability.Devastate:
                    abilityCritChance += (player.Talents.SwordAndBoard * 0.05f);
                    break;
                case Ability.HeroicStrike:
                    abilityCritChance += player.Talents.Incite * 0.05f;
                    break;
                case Ability.ShieldSlam:
                    abilityCritChance += player.Talents.Cruelty * 0.05f;
                    break;
                case Ability.DeepWounds:
                case Ability.Rend:
                case Ability.ShieldBash:
                case Ability.SunderArmor:
                    abilityCritChance = 0.0f;
                    break;
            }

            return Math.Min(1.0f, abilityCritChance);
        }
예제 #15
0
 public static float BonusCritPercentage(Player player)
 {
     return Math.Max(0.0f, Math.Min(1.0f, 
         StatConversion.GetPhysicalCritFromRating(player.Stats.CritRating, CharacterClass.Warrior) + 
         StatConversion.GetPhysicalCritFromAgility(player.Stats.Agility, CharacterClass.Warrior) +
         player.Stats.PhysicalCrit));
 }
예제 #16
0
 public static float BonusCritMultiplier(Player player, Ability ability)
 {
     return (2.0f * (1.0f + player.Stats.BonusCritDamageMultiplier) - 1.0f);
 }
예제 #17
0
 public static float BonusHitPercentage(Player player)
 {
     return StatConversion.GetPhysicalHitFromRating(player.Stats.HitRating, CharacterClass.Warrior) + player.Stats.PhysicalHit;
 }
예제 #18
0
 public static float StanceDamageMultipler(Player player)
 {
     // In Defensive Stance
     return (1.0f * (1.0f + player.Stats.BonusDamageMultiplier) * (1.0f + player.Stats.BonusPhysicalDamageMultiplier));
 }
예제 #19
0
 public static float StanceThreatMultipler(Player player)
 {
     // In Defensive Stance
     return (3.0f * (1.0f + player.Stats.ThreatIncreaseMultiplier));
 }
예제 #20
0
 public static float GlancingReduction(Player player)
 {
     return (Math.Min(0.91f, 1.3f - (0.05f * (player.BossOpts.Level - player.Character.Level) * 5.0f)) +
             Math.Max(0.99f, 1.2f - (0.03f * (player.BossOpts.Level - player.Character.Level) * 5.0f))) / 2;
 }
예제 #21
0
 public static float ArmorReduction(Player player)
 {
     return StatConversion.GetArmorDamageReduction(player.BossOpts.Level, player.Stats.Armor, 0f, 0f);
 }
예제 #22
0
        public static float MagicReduction(Player player, DamageType school)
        {
            float totalResist = 0.0f;
            switch (school)
            {
                case DamageType.Arcane: totalResist = player.Stats.ArcaneResistance; break;
                case DamageType.Fire: totalResist = player.Stats.FireResistance; break;
                case DamageType.Frost: totalResist = player.Stats.FrostResistance; break;
                case DamageType.Nature: totalResist = player.Stats.NatureResistance; break;
                case DamageType.Shadow: totalResist = player.Stats.ShadowResistance; break;
            }

            float damageReduction = Lookup.StanceDamageReduction(player, school);
            float averageResistance = StatConversion.GetAverageResistance(player.BossOpts.Level, player.Character.Level, totalResist, 0.0f);

            return Math.Max(0.0f, (1.0f - averageResistance) * (1f - damageReduction));
        }
예제 #23
0
 public DefendTable(Player player)
 {
     Initialize(player, Ability.None);
 }
예제 #24
0
 public static float AvoidanceChance(Player player, HitResult avoidanceType)
 {
     switch (avoidanceType)
     {
         case HitResult.Crit:
             return StatConversion.GetDRAvoidanceChance(player.Character, player.Stats, avoidanceType, player.BossOpts.Level) + (player.Talents.BastionOfDefense * 0.03f);
         case HitResult.CritBlock:
             return Lookup.BonusMasteryBlockPercentage(player) + player.Stats.CriticalBlock;
         default:
             return Math.Max(0.0f, StatConversion.GetDRAvoidanceChance(player.Character, player.Stats, avoidanceType, player.BossOpts.Level));
     }
 }
예제 #25
0
 public AttackTable(Player player, Ability ability)
 {
     Initialize(player, ability);
 }
예제 #26
0
        private StatsWarrior GetSpecialEffectStats(Player player)
        {
            StatsWarrior statsSpecialEffects = new StatsWarrior();

            Dictionary<Trigger, float> triggerIntervals = new Dictionary<Trigger, float>();
            Dictionary<Trigger, float> triggerChances   = new Dictionary<Trigger, float>();

            player.DefendModel = new DefendModel(player);
            player.AttackModel = new AttackModel(player, AttackModelMode.Optimal);

            float effectiveMasteryRating        = Lookup.MaxEffectiveMasteryRating(player);
            float effectiveBuffedMasteryRating  = effectiveMasteryRating * (1.0f - 10.0f / player.CalcOpts.ShieldBlockInterval) +
                                                    Lookup.MaxEffectiveBuffedMasteryRating(player) * (10.0f / player.CalcOpts.ShieldBlockInterval);
            
            triggerIntervals[Trigger.Use]                   = 0.0f;
            triggerIntervals[Trigger.MeleeAttack]           = player.AttackModel.WeaponAttacksPerSecond;
            triggerIntervals[Trigger.MeleeHit]              = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.MeleeCrit]             = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.PhysicalHit]           = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.PhysicalAttack]        = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.PhysicalCrit]          = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.ExecuteHit]            = triggerIntervals[Trigger.MeleeAttack];
            triggerIntervals[Trigger.DoTTick]               = (player.Talents.DeepWounds > 0) ? 2.0f : 0.0f;
            triggerIntervals[Trigger.DamageDone]            = triggerIntervals[Trigger.MeleeAttack] + triggerIntervals[Trigger.DoTTick];
            triggerIntervals[Trigger.DamageOrHealingDone]   = triggerIntervals[Trigger.DamageDone];
            triggerIntervals[Trigger.DamageTaken]           = 1.0f / player.DefendModel.AttackerSwingsPerSecond;
            triggerIntervals[Trigger.DamageAvoided]         = triggerIntervals[Trigger.DamageTaken];
            triggerIntervals[Trigger.DamageParried]         = triggerIntervals[Trigger.DamageTaken];
            triggerIntervals[Trigger.DamageTakenPutsMeBelow35PercHealth] = triggerIntervals[Trigger.DamageTaken];
            triggerIntervals[Trigger.ShieldBlock]           = 60f - (player.Talents.ShieldMastery * 10f);

            triggerChances[Trigger.Use]                     = 1.0f;
            triggerChances[Trigger.MeleeAttack]             = 1.0f;
            triggerChances[Trigger.MeleeHit]                = player.AttackModel.HitsPerSecond / player.AttackModel.WeaponAttacksPerSecond;
            triggerChances[Trigger.MeleeCrit]               = player.AttackModel.CritsPerSecond / player.AttackModel.WeaponAttacksPerSecond;
            triggerChances[Trigger.PhysicalAttack]          = 1.0f;
            triggerChances[Trigger.PhysicalHit]             = triggerChances[Trigger.MeleeHit];
            triggerChances[Trigger.PhysicalCrit]            = triggerChances[Trigger.MeleeCrit];
            triggerChances[Trigger.ExecuteHit]              = triggerChances[Trigger.MeleeHit];
            triggerChances[Trigger.DoTTick]                 = (player.Talents.DeepWounds > 0) ? 1.0f : 0.0f;
            triggerChances[Trigger.DamageDone]              = (player.AttackModel.HitsPerSecond + ((player.Talents.DeepWounds > 0) ? 2.0f : 0.0f))
                                                                / (player.AttackModel.WeaponAttacksPerSecond + ((player.Talents.DeepWounds > 0) ? 1.0f : 0.0f));
            triggerChances[Trigger.DamageOrHealingDone]     = triggerChances[Trigger.DamageDone];
            triggerChances[Trigger.DamageTaken]             = player.DefendModel.AttackerHitsPerSecond / player.DefendModel.AttackerSwingsPerSecond;
            triggerChances[Trigger.DamageAvoided]           = player.DefendModel.DefendTable.AnyAvoid;
            triggerChances[Trigger.DamageParried]           = player.DefendModel.DefendTable.Parry;
            triggerChances[Trigger.DamageTakenPutsMeBelow35PercHealth] = triggerChances[Trigger.DamageTaken] * 0.35f;
            triggerChances[Trigger.ShieldBlock]             = 1.0f;

            foreach (SpecialEffect effect in player.Stats.SpecialEffects())
            {
                if (RelevantTriggers.Contains(effect.Trigger))
                {
                    // Effective Mastery Capping on Large Proc Effects
                    if ((effect.Trigger == Trigger.Use && effect.Stats.MasteryRating > effectiveMasteryRating) || effect.Stats.MasteryRating > effectiveBuffedMasteryRating)
                    {
                        Stats cappedStats = new Stats();
                        cappedStats.Accumulate(effect.Stats);
                        // Assume Use Effects Bypass Shield Block Collision
                        if (effect.Trigger == Trigger.Use)
                            cappedStats.MasteryRating = effectiveMasteryRating;
                        else
                            cappedStats.MasteryRating = effectiveBuffedMasteryRating;
                        // calculate average up-time of this trinket
                        float averageUpTime = 0.0f;
                        if (effect.Trigger == Trigger.ExecuteHit)
                            averageUpTime = effect.GetAverageFactor(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], player.AttackModel.WeaponSpeed, player.BossOpts.BerserkTimer * (float)player.BossOpts.Under20Perc);
                        else
                            averageUpTime = effect.GetAverageFactor(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], player.AttackModel.WeaponSpeed, player.BossOpts.BerserkTimer);
                        // accumulate the capped stats from the trinket into our final stats
                        statsSpecialEffects.Accumulate(cappedStats, averageUpTime);
                    }
                    else
                    {
                        if (effect.Trigger == Trigger.ExecuteHit)
                            effect.AccumulateAverageStats(statsSpecialEffects, triggerIntervals, triggerChances, player.AttackModel.WeaponSpeed, player.BossOpts.BerserkTimer * (float)player.BossOpts.Under20Perc);
                        else
                            effect.AccumulateAverageStats(statsSpecialEffects, triggerIntervals, triggerChances, player.AttackModel.WeaponSpeed, player.BossOpts.BerserkTimer);
                    }
                }
            }

            // Base Stats
            statsSpecialEffects.Stamina = (float)Math.Floor(statsSpecialEffects.Stamina * (1.0f + player.Stats.BonusStaminaMultiplier));
            statsSpecialEffects.Strength = (float)Math.Floor(statsSpecialEffects.Strength * (1.0f + player.Stats.BonusStrengthMultiplier));
            statsSpecialEffects.Agility = (float)Math.Floor(statsSpecialEffects.Agility * (1.0f + player.Stats.BonusAgilityMultiplier));

            return statsSpecialEffects;
        }
예제 #27
0
 public AttackModel(Player player, AttackModelMode attackModelMode)
     : this(player, attackModelMode, RageModelMode.Infinite)
 {
 }
예제 #28
0
 public static float TargetCritChance(Player player)
 {
     return Math.Max(0.0f, 0.05f - AvoidanceChance(player, HitResult.Crit));
 }
예제 #29
0
        public StatsWarrior GetBuffsStats(Player player)
        {
            Base.StatsWarrior statsBuffs = new Base.StatsWarrior();
            statsBuffs.Accumulate(GetBuffsStats(player.Character.ActiveBuffs, player.Character.SetBonusCount));

            if (player.Character.ActiveBuffs.Find<Buff>(x => x.SpellId == 22738) != null)
            {
                statsBuffs.BonusWarrior_PvP_4P_InterceptCDReduc = 5f;
            }
            if (player.Character.ActiveBuffs.Find<Buff>(x => x.SpellId == 70843) != null)
            {
                statsBuffs.BonusShieldSlamDamageMultiplier = 0.20f;
                statsBuffs.BonusShockwaveDamageMultiplier = 0.20f;
            }
            if (player.Character.ActiveBuffs.Find<Buff>(x => x.SpellId == 70844) != null)
            {
                //Your Battle Shout and Commanding Shout abilities now cause you to absorb damage equal to 20% of your maximum health. Lasts 10 sec.
                //statsBuffs.BonusWarrior_PvP_4P_InterceptCDReduc = 5f;
            }
            if (player.Character.ActiveBuffs.Find<Buff>(x => x.SpellId == 90296) != null)
            {
                statsBuffs.BonusShieldSlamDamageMultiplier = 0.05f;
            }
            if (player.Character.ActiveBuffs.Find<Buff>(x => x.SpellId == 90296) != null)
            {
                statsBuffs.BonusShieldWallDurMultiplier = 0.50f;
            }

            int T12count;
            player.Character.SetBonusCount.TryGetValue("Molten Giant Battleplate", out T12count);
            if (T12count >= 2)
            {
                statsBuffs.BonusShieldSlamDamageMultiplier = 0.20f;
            }
            if (T12count >= 4)
            {
                statsBuffs.AddSpecialEffect(_SE_4T12[player.Talents.ShieldMastery]);
            }

            return statsBuffs;
        }
예제 #30
0
 public static float BonusMasteryBlockPercentage(Player player)
 {
     return 0.015f * (8.0f + StatConversion.GetMasteryFromRating(player.Stats.MasteryRating, CharacterClass.Warrior));
 }