예제 #1
0
        public override float GetOptimizableCalculationValue(string calculation)
        {
            switch (calculation)
            {
            case "Health": return(BasicStats.Health);

            case "Avoided Attacks %": return(AvoidedAttacks);

            case "Hit Rating": return(BasicStats.HitRating);

            case "Hit Rating %": return(StatConversion.GetPhysicalHitFromRating(BasicStats.HitRating) * 100);

            case "Expertise Rating": return(BasicStats.ExpertiseRating);

            case "Expertise": return(StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating));

            case "Expertise Rating %": return(StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating) * 0.25f);

            case "Nature Resist": return(BasicStats.NatureResistance);

            case "Fire Resist": return(BasicStats.FireResistance);

            case "Frost Resist": return(BasicStats.FrostResistance);

            case "Shadow Resist": return(BasicStats.ShadowResistance);

            case "Arcane Resist": return(BasicStats.ArcaneResistance);
                //case "Custom Rotation DPS": return CustomRotation.DPS;
            }
            return(0f);
        }
예제 #2
0
파일: Lookup.cs 프로젝트: edekk/rawr-2.3.23
 public static float BonusExpertisePercentage(Character character, Stats stats)
 {
     return(StatConversion.GetDodgeParryReducFromExpertise(stats.Expertise +
                                                           StatConversion.GetExpertiseFromRating(stats.ExpertiseRating), CharacterClass.Warrior));
     //return (((stats.ExpertiseRating * ProtWarr.ExpertiseRatingToExpertise) + stats.Expertise)
     //        * ProtWarr.ExpertiseToDodgeParryReduction) / 100.0f;
 }
예제 #3
0
        private void Set_c_values()
        {
            _c_rwItemType  = RW.Type;
            _c_rwItemSpeed = RW.Speed;
            useRW          = _useRW; // public variable gets set once

            _c_rwRacialExpertise = GetRacialExpertiseFromWeaponType(_c_rwItemType);
            _c_rwexpertise       = StatS.Expertise + StatConversion.GetExpertiseFromRating(StatS.ExpertiseRating) + _c_rwRacialExpertise;
            _c_ymiss             = YwMissChance;
            _c_wmiss             = WhMissChance;
            _c_rwdodge           = RwDodgeChance;
            _c_rwparry           = RwParryChance;
            _c_rwblock           = RwBlockChance;
            _c_rwwcrit           = RwWhCritChance;
            _c_rwycrit           = RwYwCritChance;
            _c_glance            = GlanceChance;
        }
예제 #4
0
        private void Set_c_values()
        {
            _c_mhItemType  = MH.Type;
            _c_mhItemSpeed = MH.Speed;
            if (OH != null)
            {
                _c_ohItemType  = OH.Type;
                _c_ohItemSpeed = OH.Speed;
            }
            useMH = _useMH; // public variable gets set once
            useOH = _useOH;

            _c_mhRacialExpertise = GetRacialExpertiseFromWeaponType(_c_mhItemType);
            _c_mhexpertise       = StatS.Expertise + StatConversion.GetExpertiseFromRating(Math.Max(0, StatS.ExpertiseRating)) + _c_mhRacialExpertise;
            _c_ymiss             = YwMissChance;
            _c_wmiss             = WhMissChance;
            _c_mhdodge           = MhDodgeChance;
            _c_mhparry           = MhParryChance;
            _c_mhblock           = MhBlockChance;
            _c_mhwcrit           = MhWhCritChance;
            _c_mhycrit           = MhYwCritChance;
            _c_glance            = GlanceChance;
            if (useOH)
            {
                _c_ohRacialExpertise = GetRacialExpertiseFromWeaponType(_c_ohItemType);
                _c_ohexpertise       = StatS.Expertise + StatConversion.GetExpertiseFromRating(Math.Max(0, StatS.ExpertiseRating)) + _c_ohRacialExpertise;
                _c_ohdodge           = OhDodgeChance;
                _c_ohparry           = OhParryChance;
                _c_ohblock           = OhBlockChance;
                _c_ohwcrit           = OhWhCritChance;
                _c_ohycrit           = OhYwCritChance;
            }
            else
            {
                _c_ohItemType        = ItemType.None;
                _c_ohItemSpeed       = 0f;
                _c_ohRacialExpertise = 0f;
                _c_ohexpertise       = 0f;
                _c_ohdodge           = StatConversion.WHITE_DODGE_CHANCE_CAP[levelDif];
                _c_ohparry           = StatConversion.WHITE_PARRY_CHANCE_CAP[levelDif];
                _c_ohblock           = 0.0f;
                _c_ohwcrit           = 0.0f;
                _c_ohycrit           = 0.0f;
            }
        }
예제 #5
0
파일: CombatFactors.cs 프로젝트: rakot/rawr
        private void SetCvalues()
        {
            CMHItemType  = MH.Type;
            CMHItemSpeed = MH.Speed;
            if (OH != null)
            {
                COHItemType  = OH.Type;
                COHItemSpeed = OH.Speed;
            }
            useMH = _useMH; // public variable gets set once
            useOH = _useOH;

            CMHRacialExpertise = BaseStats.GetRacialExpertise(Char, ItemSlot.MainHand); //GetRacialExpertiseFromWeaponType(CmhItemType);
            CMHexpertise       = StatS.Expertise + StatConversion.GetExpertiseFromRating(Math.Max(0, StatS.ExpertiseRating)) + CMHRacialExpertise;
            CYmiss             = YwMissChance;
            CWmiss             = WhMissChance;
            CMHdodge           = MhDodgeChance;
            CMHparry           = MhParryChance;
            CMHblock           = MhBlockChance;
            CMHwcrit           = MhWhCritChance;
            CMHycrit           = MhYwCritChance;
            CGlance            = GlanceChance;
            if (useOH)
            {
                COHRacialExpertise = BaseStats.GetRacialExpertise(Char, ItemSlot.OffHand);// GetRacialExpertiseFromWeaponType(CohItemType);
                COhexpertise       = StatS.Expertise + StatConversion.GetExpertiseFromRating(Math.Max(0, StatS.ExpertiseRating)) + COHRacialExpertise;
                COhdodge           = OhDodgeChance;
                COhparry           = OhParryChance;
                COhblock           = OhBlockChance;
                COhwcrit           = OhWhCritChance;
                COhycrit           = OhYwCritChance;
            }
            else
            {
                COHItemType        = ItemType.None;
                COHItemSpeed       = 0f;
                COHRacialExpertise = 0f;
                COhexpertise       = 0f;
                COhdodge           = StatConversion.WHITE_DODGE_CHANCE_CAP[LevelDif];
                COhparry           = StatConversion.WHITE_PARRY_CHANCE_CAP[LevelDif];
                COhblock           = 0.0f;
                COhwcrit           = 0.0f;
                COhycrit           = 0.0f;
            }
        }
예제 #6
0
        protected override void Calculate()
        {
            float tableSize = 0f;

            // Miss
            if (useSpellHit)
            {
                Miss = Math.Min(1f - tableSize, Math.Max(0f, StatConversion.GetSpellMiss(-LevelDelta, false) - StatS.SpellHit - StatConversion.GetSpellHitFromRating(StatS.HitRating)));
            }
            else
            {
                Miss = Math.Min(1f - tableSize, Math.Max(0f, StatConversion.YELLOW_MISS_CHANCE_CAP[LevelDelta] - StatS.PhysicalHit - StatConversion.GetSpellHitFromRating(StatS.HitRating)));
            }
            tableSize += Miss;
            // Dodge
            if (!useSpellHit)
            {
                Dodge = Math.Min(1f - tableSize, Math.Max(0f, StatConversion.YELLOW_DODGE_CHANCE_CAP[LevelDelta]
                                                          - StatConversion.GetDodgeParryReducFromExpertise(
                                                              StatConversion.GetExpertiseFromRating(StatS.ExpertiseRating, Char.Class), Char.Class))
                                 );
                tableSize += Dodge;
            }
            else
            {
                Dodge = 0f;
            }
            // Parry
            if (!useSpellHit)
            {
                Parry = Math.Min(1f - tableSize, Math.Max(0f, StatConversion.YELLOW_PARRY_CHANCE_CAP[LevelDelta]
                                                          - StatConversion.GetDodgeParryReducFromExpertise(
                                                              StatConversion.GetExpertiseFromRating(StatS.ExpertiseRating, Char.Class), Char.Class))
                                 );
                tableSize += Parry;
            }
            else
            {
                Parry = 0f;
            }
            // Block
            //if (isWhite || Abil.CanBeBlocked) {
            //Block = Math.Min(1f - tableSize, isMH ?  combatFactors._c_mhblock : combatFactors._c_ohblock);
            //tableSize += Block;
            //} else { Block = 0f; }
            // Glancing Blow
            //if (isWhite) {
            //Glance = Math.Min(1f - tableSize, combatFactors._c_glance);
            //tableSize += Glance;
            //} else { Glance = 0f; }
            // Critical Hit
            Crit = 0;

            /*if (isWhite) {
             *  float critValueToUse = (isMH ? combatFactors._c_mhwcrit : combatFactors._c_ohwcrit);
             *  foreach (WeightedStat ws in combatFactors.critProcs)
             *  {
             *      float modCritChance = Math.Min(1f - tableSize, critValueToUse + StatConversion.GetCritFromRating(ws.Value, Char.Class))
             + StatConversion.NPC_LEVEL_CRIT_MOD[calcOpts.TargetLevel - Char.Level];
             +      Crit += ws.Chance * modCritChance;
             +  }
             +  tableSize += Crit;
             + } else if (Abil.CanCrit) {*/
            float critValueToUse = StatConversion.NPC_LEVEL_CRIT_MOD[LevelDelta]
                                   + (useSpellHit ? StatS.SpellCrit : StatS.PhysicalCrit);

            foreach (WeightedStat ws in critProcs)
            {
                float modCritChance = Math.Min(1f - tableSize, (critValueToUse + StatConversion.GetCritFromRating(ws.Value, Char.Class)) * (1f - Dodge - Miss));
                Crit += ws.Chance * modCritChance;
            }
            if (Crit < 0)
            {
                Crit = 0f;
            }
            tableSize += Crit;
            //}
            // Normal Hit
            Hit = Math.Max(0f, 1f - tableSize);
            base.Calculate();
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            dictValues.Add("Health", BasicStats.Health.ToString());
            dictValues.Add("Strength", BasicStats.Strength.ToString());
            dictValues.Add("Agility", BasicStats.Agility.ToString());
            dictValues.Add("Stamina", BasicStats.Stamina.ToString());
            dictValues.Add("Armor", string.Format("{0}*Reduces physical damage taken by {1:0.00%}", BasicStats.Armor, ArmorReduction));
            dictValues.Add("Defense", Defense.ToString() + string.Format("*Defense Rating {0}", BasicStats.DefenseRating));
            dictValues.Add("Dodge", string.Format("{0:0.00%}*Dodge Rating {1}", Dodge, BasicStats.DodgeRating));
            dictValues.Add("Parry", string.Format("{0:0.00%}*Parry Rating {1}", Parry, BasicStats.ParryRating));
            dictValues.Add("Block", string.Format("{0:0.00%}*Block Rating {1}", Block, BasicStats.BlockRating));
            dictValues.Add("Miss", string.Format("{0:0.00%}", Miss));
            dictValues.Add("Block Value", string.Format("{0}", BlockValue));
            dictValues.Add("Guaranteed Reduction", string.Format("{0:0.00%}", GuaranteedReduction));
            dictValues.Add("Avoidance", string.Format("{0:0.00%} (+Block {1:0.00%})", DodgePlusMissPlusParry, DodgePlusMissPlusParryPlusBlock));
            dictValues.Add("Total Mitigation", string.Format("{0:0.00%}", TotalMitigation));

            if (AttackerSpeed == BaseAttackerSpeed)
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s", AttackerSpeed));
            }
            else
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s*Base speed of {1:0.00}s (modified by haste)", AttackerSpeed, BaseAttackerSpeed));
            }

            dictValues.Add("Damage Taken",
                           string.Format("{0:0.0} DPS*{1:0} damage per normal attack" + Environment.NewLine +
                                         "{2:0} damage per blocked attack" + Environment.NewLine +
                                         "{3:0} damage per critically blocked attack" + Environment.NewLine +
                                         "{4:0} damage per critical attack", DamageTaken, DamageTakenPerHit, DamageTakenPerBlock, DamageTakenPerCritBlock, DamageTakenPerCrit));

            dictValues.Add("Resilience",
                           string.Format(@"{0}*Reduces the damage of critical strikes and chance to be critically hit by {1}%.",
                                         BasicStats.Resilience,
                                         StatConversion.GetCritReductionFromResilience(BasicStats.Resilience, CharacterClass.Warrior)));

            if (CritVulnerability > 0.0001f)
            {
                float resilienceNeeded = (float)Math.Ceiling((StatConversion.RATING_PER_RESILIENCE * CritVulnerability));
                dictValues.Add("Chance to be Crit",
                               string.Format("{0:0.00%}*CRITTABLE! Short by {1:0} defense or {2:0} resilience to be uncrittable.",
                                             CritVulnerability, DefenseRatingNeeded, resilienceNeeded));
            }
            else
            {
                dictValues.Add("Chance to be Crit", string.Format("{0:0.00%}*Chance to crit reduced by {1:0.00%}", CritVulnerability, CritReduction));
            }

            dictValues.Add("Nature Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.NatureResistance, NatureReduction));
            dictValues.Add("Arcane Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.ArcaneResistance, ArcaneReduction));
            dictValues.Add("Frost Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.FrostResistance, FrostReduction));
            dictValues.Add("Fire Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.FireResistance, FireReduction));
            dictValues.Add("Shadow Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.ShadowResistance, ShadowReduction));
            dictValues["Nature Survival"] = NatureSurvivalPoints.ToString();
            dictValues["Frost Survival"]  = FrostSurvivalPoints.ToString();
            dictValues["Fire Survival"]   = FireSurvivalPoints.ToString();
            dictValues["Shadow Survival"] = ShadowSurvivalPoints.ToString();
            dictValues["Arcane Survival"] = ArcaneSurvivalPoints.ToString();

            dictValues.Add("Weapon Speed", string.Format("{0:0.00}*{1:0.00%} Haste", WeaponSpeed, Haste));
            dictValues.Add("Attack Power", string.Format("{0}", BasicStats.AttackPower));
            dictValues.Add("Hit", string.Format("{0:0.00%}*Hit Rating {1}", Hit, BasicStats.HitRating));
            dictValues.Add("Expertise",
                           string.Format("{0}*Expertise Rating {1}" + Environment.NewLine + "Reduces chance to be dodged or parried by {2:0.00%}.",
                                         Math.Round(StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating, CharacterClass.Warrior) + BasicStats.Expertise),
                                         BasicStats.ExpertiseRating, Expertise));
            dictValues.Add("Haste", string.Format("{0:0.00%}*Haste Rating {1:0.00}", Haste, BasicStats.HasteRating));
            dictValues.Add("Armor Penetration",
                           string.Format("{0:0.00%}*Armor Penetration Rating {1}" + Environment.NewLine + "Armor Reduction {2}",
                                         ArmorPenetration, BasicStats.ArmorPenetrationRating, BasicStats.ArmorPenetration));
            dictValues.Add("Crit", string.Format("{0:0.00%}*Crit Rating {1}", Crit, BasicStats.CritRating));
            // Never really used in current WoW itemization, just taking up space
            // dictValues.Add("Weapon Damage", string.Format("{0}", BasicStats.WeaponDamage));
            dictValues.Add("Missed Attacks",
                           string.Format("{0:0.00%}*Attacks Missed: {1:0.00%}" + Environment.NewLine + "Attacks Dodged: {2:0.00%}" + Environment.NewLine +
                                         "Attacks Parried: {3:0.00%}", AvoidedAttacks, MissedAttacks, DodgedAttacks, ParriedAttacks));
            dictValues.Add("Total Damage/sec", string.Format("{0:0.0}", TotalDamagePerSecond));
            dictValues.Add("Total Threat/sec", string.Format("{0:0.0}*{1:0%} of Swings converted to Heroic Strikes", ThreatPerSecond, HeroicStrikeFrequency));
            dictValues.Add("Rotation", ThreatModelName + "*" + ThreatModel);

            switch (RankingMode)
            {
            case 2:
                dictValues.Add("Ranking Mode", "TankPoints*The average amount of unmitigated damage which can be taken before dying");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;

            case 3:
                dictValues.Add("Ranking Mode", "Burst Time*The average amount of time between events which have a chance to result in a burst death");
                dictValues.Add("Survival Points", string.Format("{0:0}*{1:0.00} seconds between events", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            case 4:
                dictValues.Add("Ranking Mode", "Damage Output*The average amount of DPS which can be produced");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival is not weighted in this mode", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            default:
                dictValues.Add("Ranking Mode", "Mitigation Scale*Customizable scale which allows you to weight mitigation vs. effective health.");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;
            }
            dictValues.Add("Overall Points", string.Format("{0:0}", OverallPoints));
            dictValues.Add("Mitigation Points", string.Format("{0:0}", MitigationPoints));
            dictValues.Add("Threat Points", string.Format("{0:0}", ThreatPoints));

            return(dictValues);
        }
예제 #8
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            dictValues.Add("Health", BasicStats.Health.ToString());
            dictValues.Add("Mana", BasicStats.Mana.ToString());
            dictValues.Add("Strength", BasicStats.Strength.ToString());
            dictValues.Add("Agility", BasicStats.Agility.ToString());
            dictValues.Add("Stamina", string.Format("{0}*Increases Health by {1}", BasicStats.Stamina, (BasicStats.Stamina - 20f) * 10f + 20f));
            dictValues.Add("Intellect", BasicStats.Intellect.ToString());
            dictValues.Add("Armor", string.Format("{0}*Reduces physical damage taken by {1:0.00%}" + Environment.NewLine +
                                                  "Armor Damage Reduction depends on Attacker Level.",
                                                  BasicStats.Armor, ArmorReduction));
            dictValues.Add("Dodge", string.Format("{0:0.0000%}*Dodge Rating {1}", Dodge, BasicStats.DodgeRating));
            dictValues.Add("Parry", string.Format("{0:0.0000%}*Parry Rating {1}", Parry, BasicStats.ParryRating));
            dictValues.Add("Block", string.Format("{0:0.0000%}*Block Rating {1}", Block, BasicStats.BlockRating));
            dictValues.Add("Mastery", string.Format("{0}*Mastery Rating {1}" + Environment.NewLine +
                                                    "Adds {2:0.0000%} Block", Mastery, BasicStats.MasteryRating, Mastery * 0.0225f));
            dictValues.Add("Miss", string.Format("{0:0.0000%}", Miss));
            dictValues.Add("Guaranteed Reduction", string.Format("{0:0.00%}", GuaranteedReduction));
            dictValues.Add("Avoidance", string.Format("{0:0.0000%}*Avoidance Points {1}", DodgePlusMissPlusParry, (DodgePlusMissPlusParry * 10000f)));
            dictValues.Add("Avoidance + Block", string.Format("{0:0.0000%}", DodgePlusMissPlusParryPlusBlock));
            dictValues.Add("Total Mitigation", string.Format("{0:0.00%}", TotalMitigation));

            dictValues.Add("Attacker Speed", string.Format("{0:0.00}s", AttackerSpeed));

            dictValues.Add("Damage Taken",
                           string.Format("{0:0.0} DPS*{1:0} damage per normal attack" + Environment.NewLine +
                                         "{2:0} damage per blocked attack" + Environment.NewLine +
                                         "{3:0} damage per critical attack" + Environment.NewLine +
                                         "On Average, you take" + Environment.NewLine +
                                         "{4:0.00%} of incoming damage", DPSTaken, DamageTakenPerHit, DamageTakenPerBlock, DamageTakenPerCrit, DamageTaken));

            dictValues.Add("Resilience",
                           string.Format(@"{0}" /* + "*Reduces periodic damage by {1:0.00%}." + Environment.NewLine +
                                                 * "Reduces the effect of mana-drains and the damage of critical strikes by {2:0.00%}."*/,
                                         BasicStats.Resilience //,
                                                               //StatConversion.GetCritReductionFromResilience(BasicStats.Resilience,CharacterClass.Paladin),
                                                               //StatConversion.GetCritReductionFromResilience(BasicStats.Resilience,CharacterClass.Paladin)*2f
                                         ));

            if (CritVulnerability > 0.0001f)
            {
                dictValues.Add("Chance to be Crit",
                               string.Format("{0:0.00%}*CRITTABLE! Spec 3 points into the protection talent Sanctuary to be uncrittable.",
                                             CritVulnerability));
            }
            else
            {
                dictValues.Add("Chance to be Crit", string.Format("{0:0.00%}*Chance to be crit reduced by {1:0.00%}", CritVulnerability, CritReduction));
            }

            dictValues.Add("Nature Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.NatureResistance, NatureReduction));
            dictValues.Add("Arcane Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.ArcaneResistance, ArcaneReduction));
            dictValues.Add("Frost Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.FrostResistance, FrostReduction));
            dictValues.Add("Fire Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.FireResistance, FireReduction));
            dictValues.Add("Shadow Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.ShadowResistance, ShadowReduction));
            dictValues["Nature Survival"] = NatureSurvivalPoints.ToString();
            dictValues["Frost Survival"]  = FrostSurvivalPoints.ToString();
            dictValues["Fire Survival"]   = FireSurvivalPoints.ToString();
            dictValues["Shadow Survival"] = ShadowSurvivalPoints.ToString();
            dictValues["Arcane Survival"] = ArcaneSurvivalPoints.ToString();

            dictValues.Add("Weapon Speed", string.Format("{0:0.00}*{1:0.00%} Haste", WeaponSpeed, PhysicalHaste));
            dictValues.Add("Attack Power", string.Format("{0}", BasicStats.AttackPower));
            dictValues.Add("Spell Power", string.Format("{0}", BasicStats.SpellPower));
            dictValues.Add("Hit", string.Format("{0:0.00%}*Hit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}", Hit, BasicStats.HitRating, TargetLevel));
            dictValues.Add("Spell Hit", string.Format("{0:0.00%}*Hit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                      SpellHit, BasicStats.HitRating, TargetLevel));
            dictValues.Add("Expertise",
                           string.Format("{0:0.00}*Expertise Rating {1}" + Environment.NewLine + "Reduces chance to be dodged or parried by {2:0.00%}.",
                                         StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating, CharacterClass.Paladin) + BasicStats.Expertise,
                                         BasicStats.ExpertiseRating, Expertise));
            dictValues.Add("Physical Haste", string.Format("{0:0.00%}*Haste Rating {1:0.00}", PhysicalHaste, BasicStats.HasteRating));
            dictValues.Add("Effective Target Armor",
                           string.Format("{0}*Reduces the physical damage you deal by {1:0.00%}" + Environment.NewLine + Environment.NewLine +
                                         "Effective Armor depends on Armor ignore debuffs," + Environment.NewLine +
                                         "your Armor Penetration buffs and talents." + Environment.NewLine +
                                         "Enemy Damage Reduction depends on your Level.",
                                         (float)Math.Floor(EffectiveTargetArmor), EffectiveTargetArmorDamageReduction));

            dictValues.Add("Crit", string.Format("{0:0.00%}*Crit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                 Crit, BasicStats.CritRating, TargetLevel));
            dictValues.Add("Spell Crit", string.Format("{0:0.00%}*Crit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                       SpellCrit, BasicStats.CritRating, TargetLevel));
            dictValues.Add("Weapon Damage", string.Format("{0:0.00}*As average damage per {1}" + Environment.NewLine + "Before Armor",
                                                          BasicStats.WeaponDamage, Lookup.Name(Ability.MeleeSwing)));
            dictValues.Add("Missed Attacks",
                           string.Format("{0:0.00%}*Attacks Missed: {1:0.00%}" + Environment.NewLine + "Attacks Dodged: {2:0.00%}" + Environment.NewLine +
                                         "Attacks Parried: {3:0.00%}", AvoidedAttacks, MissedAttacks, DodgedAttacks, ParriedAttacks));
            dictValues.Add("Glancing Attacks", string.Format("{0:0.00%}*{1:0.00%} Reduction" + Environment.NewLine +
                                                             "Against a Target of Level {2}", GlancingAttacks, 1.0f - GlancingReduction, TargetLevel));
            dictValues.Add("Total Damage/sec", string.Format("{0:0.0}", TotalDamagePerSecond) + "*" + ThreatModel);
            dictValues.Add("Threat/sec", string.Format("{0:0.0}", ThreatPerSecond) + "*" + ThreatModel);
            //dictValues.Add("Unlimited Threat/sec", string.Format("{0:0.0}", UnlimitedThreat) + "*" + ThreatModel);

            switch (RankingMode)
            {
            case 1:
                dictValues.Add("Ranking Mode", "Burst Time*The average amount of time between events which have a chance to result in a burst death");
                dictValues.Add("Survival Points", string.Format("{0:0}*{1:0.00} seconds between events", SurvivabilityPoints, SurvivabilityPoints / 100.0f));
                break;

            case 2:
                dictValues.Add("Ranking Mode", "Damage Output*The average amount of DPS which can be produced");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival is not weighted in this mode", SurvivabilityPoints, SurvivabilityPoints / 100.0f));
                break;

            case 0:
            default:
                dictValues.Add("Ranking Mode", "Mitigation Scale*Customizable scale which allows you to weight mitigation vs. effective health.");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivabilityPoints));
                break;
            }
            dictValues.Add("Overall Points", string.Format("{0:0}", OverallPoints));
            dictValues.Add("Mitigation Points", string.Format("{0:0}", MitigationPoints));
            dictValues.Add("Threat Points", string.Format("{0:0}", ThreatPoints));
            dictValues.Add("CTC Points", string.Format("{0:0}", CTCPoints));

            return(dictValues);
        }
예제 #9
0
        public void UpdateCalcs(bool firstPass)
        {
            // talents
            if (_calcOpts.PriorityInUse(EnhanceAbility.StormStrike))
            {
                stormstrikeBonusCrit = .25f * _talents.Stormstrike + (_talents.GlyphofStormstrike ? .1f : 0f);
            }
            else
            {
                stormstrikeBonusCrit = 0f;
            }
            //set bonus
            enhance4T11 = 0f;
            _character.SetBonusCount.TryGetValue("Battlegear of the Raging Elements", out setCount);
            if (setCount >= 4)
            {
                enhance4T11 = 0.1f;
            }

            critMultiplierSpell = 1.5f * (1 + _stats.BonusSpellCritDamageMultiplier);
            critMultiplierMelee = 2f * (1 + _stats.BonusCritDamageMultiplier);

            // Melee
            float hitBonus = _stats.PhysicalHit + StatConversion.GetHitFromRating(_stats.HitRating) + 0.06f;  //DualWieldSpecialization

            expertiseBonusMH = GetDPRfromExp(_stats.Expertise + StatConversion.GetExpertiseFromRating(_stats.ExpertiseRating) + BaseStats.GetRacialExpertise(_character, ItemSlot.MainHand));
            expertiseBonusOH = GetDPRfromExp(_stats.Expertise + StatConversion.GetExpertiseFromRating(_stats.ExpertiseRating) + BaseStats.GetRacialExpertise(_character, ItemSlot.OffHand));

            float meleeCritModifier = _stats.PhysicalCrit;
            float baseMeleeCrit     = StatConversion.GetCritFromRating(_stats.CritRating) +
                                      StatConversion.GetCritFromAgility(_stats.Agility, _character.Class) + .01f * _talents.Acuity;

            chanceDodgeMH = Math.Max(0f, DodgeChanceCap - expertiseBonusMH);
            chanceDodgeOH = Math.Max(0f, DodgeChanceCap - expertiseBonusOH);
            float ParryChance = ParryChanceCap - expertiseBonusMH;

            //chanceParryMH = (float)Math.Max(0f, _bossOpts.InBack ? ParryChance * PecentageInfrontBoss : ParryChance);
            ParryChance = ParryChanceCap - expertiseBonusOH;
            //chanceParryOH = (float)Math.Max(0f, _bossOpts.InBack ? ParryChance * PecentageInfrontBoss : ParryChance);
            chanceWhiteMissMH  = Math.Max(0f, WhiteHitCap - hitBonus) + chanceDodgeMH + chanceParryMH;
            chanceWhiteMissOH  = Math.Max(0f, WhiteHitCap - hitBonus) + chanceDodgeOH + chanceParryOH;
            chanceYellowMissMH = Math.Max(0f, YellowHitCap - hitBonus) + chanceDodgeMH + chanceParryMH; // base miss 8% now
            chanceYellowMissOH = Math.Max(0f, YellowHitCap - hitBonus) + chanceDodgeOH + chanceParryOH; // base miss 8% now

            // SetCritValues((1 + _stats.BonusCritChance) * (baseMeleeCrit + meleeCritModifier) + .00005f); //fudge factor for rounding
            SetCritValues(baseMeleeCrit + meleeCritModifier + .00005f); //fudge factor for rounding
            // set two export values so that ED crit isn't included
            exportMeleeCritMH = chanceWhiteCritMH + whiteCritDepression;
            exportMeleeCritOH = chanceWhiteCritOH + whiteCritDepression;

            // Spells
            ftBonusCrit = 0f;
            if (_calcOpts.MainhandImbue == "Flametongue")
            {
                ftBonusCrit += _talents.GlyphofFlametongueWeapon ? .02f : 0f;
            }
            if (_calcOpts.OffhandImbue == "Flametongue")
            {
                ftBonusCrit += _talents.GlyphofFlametongueWeapon ? .02f : 0f;
            }

            if (baseStats == null)
            {
                baseStats = BaseStats.GetBaseStats(_character);
            }

            elemPrecMod = _talents.ElementalPrecision > 0 ? (_stats.Spirit - baseStats.Spirit) * (_talents.ElementalPrecision / 3f) : 0f;
            float hitBonusSpell = _stats.SpellHit + StatConversion.GetSpellHitFromRating(_stats.HitRating + elemPrecMod);

            chanceSpellMiss = Math.Max(0f, SpellMissRate - hitBonusSpell);
            overSpellHitCap = Math.Max(0f, hitBonusSpell - SpellMissRate);
            float spellCritModifier = _stats.SpellCrit + _stats.SpellCritOnTarget + ftBonusCrit;
            float baseSpellCrit     = StatConversion.GetSpellCritFromRating(_stats.CritRating) +
                                      StatConversion.GetSpellCritFromIntellect(_stats.Intellect) + .01f * _talents.Acuity;

            //chanceSpellCrit = Math.Min(0.75f, (1 + _stats.BonusCritChance) * (baseSpellCrit + spellCritModifier) + .00005f); //fudge factor for rounding
            chanceSpellCrit = Math.Min(0.75f, baseSpellCrit + spellCritModifier + .00005f); //fudge factor for rounding

            float hasteBonus = StatConversion.GetHasteFromRating(_stats.HasteRating, _character.Class);

            unhastedMHSpeed = _character.MainHand == null ? 3.0f : _character.MainHand.Item.Speed;
            unhastedOHSpeed = _character.OffHand == null ? 3.0f : _character.OffHand.Item.Speed;
            float baseHastedMHSpeed    = unhastedMHSpeed / (1f + hasteBonus) / (1f + _stats.PhysicalHaste);
            float baseHastedOHSpeed    = unhastedOHSpeed / (1f + hasteBonus) / (1f + _stats.PhysicalHaste);
            float chanceToProcWFPerHit = .2f + (_character.ShamanTalents.GlyphofWindfuryWeapon ? .02f : 0f);

            if (_bossOpts.MultiTargs && _bossOpts.Targets != null && _bossOpts.Targets.Count > 0)
            {
                foreach (TargetGroup tg in _bossOpts.Targets)
                {
                    if (tg.Frequency <= 0 || tg.Chance <= 0)
                    {
                        continue; //bad one, skip it
                    }
                    float upTime = (tg.Frequency / fightLength * (tg.Duration / 1000f) * tg.Chance) / fightLength;
                    multiTargetMultiplier += (Math.Max(10, tg.NumTargs - (tg.NearBoss ? 0 : 1))) * upTime;
                }
            }

            //The Swing Loop
            //This is where we figure out feedback systems -- WF, MW, ED, Flurry, etc.
            //--------------
            flurryUptime = 1f;
            uWUptime     = 0f;
            //uFUptime = 0f;
            edUptime = 0f;
            float stormstrikeSpeed = firstPass ? (_talents.Stormstrike == 1 ? 8f : 0f) : AbilityCooldown(EnhanceAbility.StormStrike);
            float shockSpeed       = firstPass ? BaseShockSpeed : AbilityCooldown(EnhanceAbility.EarthShock);
            float lavaLashSpeed    = firstPass ? 10f : AbilityCooldown(EnhanceAbility.LavaLash);
            float fireNovaSpeed    = firstPass ? BaseFireNovaSpeed : AbilityCooldown(EnhanceAbility.FireNova);

            if (_calcOpts.PriorityInUse(EnhanceAbility.MagmaTotem))
            {
                fireTotemUptime = firstPass ? 1.0f : 60f / AbilityCooldown(EnhanceAbility.MagmaTotem);
            }
            else if (_calcOpts.PriorityInUse(EnhanceAbility.SearingTotem))
            {
                fireTotemUptime = firstPass ? 1.0f : 60f / AbilityCooldown(EnhanceAbility.SearingTotem);
            }
            else if (_calcOpts.PriorityInUse(EnhanceAbility.RefreshTotems)) // if no Searing or Magma totem use refresh of Flametongue totem.
            {
                fireTotemUptime = firstPass ? 1.0f : 300f / AbilityCooldown(EnhanceAbility.RefreshTotems);
            }

            float mwPPM             = (10f / 3f) * _talents.MaelstromWeapon;
            float flurryHasteBonus  = .10f * _talents.Flurry;
            float uWHasteBonus      = .4f + .1f * _talents.ElementalWeapons;
            float edCritBonus       = .03f * _talents.ElementalDevastation;
            float staticShockChance = .15f * _character.ShamanTalents.StaticShock;

            hitsPerSMHSS = 0f;
            hitsPerSOHSS = 0f;
            hitsPerSOH   = 0f;
            hitsPerSMH   = 0f;
            hitsPerSWF   = 0f;
            if (_talents.Stormstrike == 1)
            {
                hitsPerSMHSS = (1f - chanceYellowMissMH) / stormstrikeSpeed;
                hitsPerSOHSS = (1f - 2 * chanceYellowMissOH) / stormstrikeSpeed; //OH only swings if MH connect
            }
            hitsPerSLL = lavaLashSpeed == 0 ? 0f : (1f - chanceYellowMissOH) / lavaLashSpeed;
            float swingsPerSMHMelee = 0f;
            float swingsPerSOHMelee = 0f;
            float wfProcsPerSecond  = 0f;
            float mwProcsPerSecond  = 0f;

            secondsToFiveStack = 10f;
            float averageMeleeCritChance   = (chanceWhiteCritMH + chanceWhiteCritOH + chanceYellowCritMH + chanceYellowCritOH) / 4f;
            float averageMeleeHitChance    = ((1f - chanceWhiteMissMH - chanceDodgeMH - chanceParryMH) + (1f - chanceWhiteMissOH - chanceDodgeOH - chanceParryOH)) / 2f;
            float averageMeleeMissChance   = (chanceWhiteMissMH + chanceWhiteMissOH) / 2f;
            float whiteHitsPerSMH          = 0f;
            float whiteHitsPerSOH          = 0f;
            float moteHitsPerS             = 0f;
            float yellowHitsPerSMH         = 0f;
            float yellowHitsPerSOH         = 0f;
            float flameTongueHitsPerSecond = 0f;

            for (int i = 0; i < 5; i++)
            {
                // float bonusHaste = (1f + (flurryUptime * flurryHasteBonus));
                float bonusHaste = 1 / (1 - flurryUptime + flurryUptime / (1 + flurryHasteBonus)) / (1 - uWUptime + uWUptime / (1 + uWHasteBonus)); // use time based not proc based flurryUptime
                hastedMHSpeed     = baseHastedMHSpeed / bonusHaste;
                hastedOHSpeed     = baseHastedOHSpeed / bonusHaste;
                swingsPerSMHMelee = 1f / hastedMHSpeed;
                swingsPerSOHMelee = (hastedOHSpeed == 0f) ? 0f : 1f / hastedOHSpeed;
                whiteHitsPerSMH   = ChanceWhiteHitMH * swingsPerSMHMelee;
                whiteHitsPerSOH   = ChanceWhiteHitOH * swingsPerSOHMelee;
                moteHitsPerS      = _stats.MoteOfAnger * 2 * AverageWhiteHitChance;
                // Windfury model
                if (_calcOpts.MainhandImbue == "Windfury")
                {
                    float hitsThatProcWFPerS = whiteHitsPerSMH + hitsPerSMHSS;
                    if (unhastedOHSpeed != 0f)
                    {
                        hitsThatProcWFPerS += moteHitsPerS / 2; // half the hits will be OH and thus won't proc WF
                    }
                    else
                    {
                        hitsThatProcWFPerS += moteHitsPerS; // if no offhand then all motes will be MH weapon by definition
                    }
                    float maxExpectedWFPerFight = hitsThatProcWFPerS * chanceToProcWFPerHit * fightLength;
                    float ineligibleSeconds     = maxExpectedWFPerFight * (3.25f - hastedMHSpeed);
                    float expectedWFPerFight    = hitsThatProcWFPerS * chanceToProcWFPerHit * (fightLength - ineligibleSeconds);
                    wfProcsPerSecond = expectedWFPerFight / fightLength;
                    hitsPerSWF       = 3f * wfProcsPerSecond * (1f - chanceYellowMissMH);
                }
                yellowHitsPerSMH = hitsPerSWF + hitsPerSMHSS;
                yellowHitsPerSOH = hitsPerSOHSS + hitsPerSLL;

                //Due to attack table, a white swing has the same chance to crit as a yellow hit
// Old Flurry calc changed 10 Nov 2009
//                couldCritSwingsPerSecond = whiteHitsPerSMH + whiteHitsPerSOH + yellowHitsPerSMH + yellowHitsPerSOH;
//                float swingsThatConsumeFlurryPerSecond = swingsPerSMHMelee + swingsPerSOHMelee;
//                flurryUptime = 1f - (float)Math.Pow(1 - averageMeleeCritChance, (3 / swingsThatConsumeFlurryPerSecond) * couldCritSwingsPerSecond);  // old formulae
                flurryUptime = CalculateFlurryUptime(averageMeleeCritChance, averageMeleeHitChance, averageMeleeMissChance);
                //uWUptime = (float)Math.Max(12f / 15f, ??);  //FIXME!!!!
                uWUptime = 7.5f / 15f;  //Temp Uptime until above line is fixed

                // Maelstrom Weapon time to 5 stacks calc
                if (unhastedOHSpeed != 0f)
                {
                    hitsPerSMH       = whiteHitsPerSMH + yellowHitsPerSMH + moteHitsPerS / 2;
                    hitsPerSOH       = whiteHitsPerSOH + yellowHitsPerSOH + moteHitsPerS / 2;
                    mwProcsPerSecond = (mwPPM / (60f / unhastedMHSpeed)) * hitsPerSMH + (mwPPM / (60f / unhastedOHSpeed)) * hitsPerSOH;
                }
                else
                {
                    hitsPerSMH       = whiteHitsPerSMH + yellowHitsPerSMH + moteHitsPerS;
                    hitsPerSOH       = 0f;
                    mwProcsPerSecond = (mwPPM / (60f / unhastedMHSpeed)) * hitsPerSMH;
                }
                secondsToFiveStack = 5f / mwProcsPerSecond;

                // Elemental Devastation Uptime calc
                staticShocksPerSecond    = (hitsPerSLL + hitsPerSMHSS + hitsPerSOHSS) * staticShockChance;
                flameTongueHitsPerSecond = (_calcOpts.MainhandImbue == "Flametongue" ? HitsPerSMH : 0f) +
                                           ((_calcOpts.OffhandImbue == "Flametongue") ? HitsPerSOH : 0f);
                spellAttacksPerSec = (1f / secondsToFiveStack + 1f / shockSpeed + 1f / fireNovaSpeed + staticShocksPerSecond) // + flameTongueHitsPerSecond)
                                     * (1f - chanceSpellMiss);
                float couldCritSpellsPerS = spellAttacksPerSec;
                edUptime = 1f - (float)Math.Pow(1 - chanceSpellCrit, 10 * couldCritSpellsPerS);
                averageMeleeCritChance = (chanceWhiteCritMH + chanceWhiteCritOH + chanceYellowCritMH + chanceYellowCritOH) / 4f + edUptime * edCritBonus;
            }
            float yellowAttacksPerSecond = hitsPerSWF + hitsPerSMHSS;

            if (unhastedMHSpeed != 0)
            {
                yellowAttacksPerSecond += hitsPerSOHSS;
            }

            // set output variables
            edBonusCrit = edUptime * edCritBonus;
            //SetCritValues((1 + _stats.BonusCritChance) * (baseMeleeCrit + meleeCritModifier) + edBonusCrit + .00005f); //fudge factor for rounding
            SetCritValues(baseMeleeCrit + meleeCritModifier + edBonusCrit + .00005f); //fudge factor for rounding
            meleeAttacksPerSec = hitsPerSMH + hitsPerSOH;
            meleeCritsPerSec   = (whiteHitsPerSMH * chanceWhiteCritMH) + (whiteHitsPerSOH * chanceWhiteCritOH) +
                                 (yellowHitsPerSMH * chanceYellowCritMH) + (yellowHitsPerSOH * chanceYellowCritOH) +
                                 (_stats.MoteOfAnger * 2 * AverageWhiteCritChance);
            spellCritsPerSec  = spellAttacksPerSec * ChanceSpellCrit;
            spellCastsPerSec  = spellAttacksPerSec;
            spellMissesPerSec = spellAttacksPerSec * chanceSpellMiss;
            chanceMeleeHit    = meleeAttacksPerSec / (swingsPerSMHMelee + swingsPerSOHMelee + 2f * wfProcsPerSecond + .25f + 1f / 6f);
            maxMana           = _stats.Mana;
            float spellhaste = _stats.SpellHaste + StatConversion.GetSpellHasteFromRating(_stats.HasteRating);

            averageFSDotTime  = _talents.GlyphofFlameShock ? 27f : 18f;
            averageFSTickTime = 3f / (1f + spellhaste);
        }
예제 #10
0
파일: Lookup.cs 프로젝트: rakot/rawr
 public static float BonusExpertisePercentage(Player player)
 {
     return(StatConversion.GetDodgeParryReducFromExpertise(player.Stats.Expertise +
                                                           StatConversion.GetExpertiseFromRating(player.Stats.ExpertiseRating), CharacterClass.Warrior));
 }
예제 #11
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            dictValues.Add("Health", BasicStats.Health.ToString());
            dictValues.Add("Strength", BasicStats.Strength.ToString());
            dictValues.Add("Agility", BasicStats.Agility.ToString());
            dictValues.Add("Stamina", BasicStats.Stamina.ToString());
            dictValues.Add("Armor", string.Format("{0}*Reduces physical damage taken by {1:0.00%}", BasicStats.Armor, ArmorReduction));
            dictValues.Add("Dodge", string.Format("{0:0.00%}*Dodge Rating {1}", Dodge, BasicStats.DodgeRating));
            dictValues.Add("Parry", string.Format("{0:0.00%}*Parry Rating {1}", Parry, BasicStats.ParryRating));
            dictValues.Add("Miss", string.Format("{0:0.00%}", Miss));

            if (Block != BuffedBlock)
            {
                dictValues.Add("Block", string.Format("{0:0.00%}*Mastery Rating {1}" + Environment.NewLine +
                                                      "{2:0.00%} Normal Block Chance" + Environment.NewLine +
                                                      "{3:0.00%} Block Chance w/ Shield Block", Block, BasicStats.MasteryRating, BaseBlock, BuffedBlock));
            }
            else
            {
                dictValues.Add("Block", string.Format("{0:0.00%}*Mastery Rating {1}", Block, BasicStats.MasteryRating));
            }

            if (Block > 0)
            {
                dictValues.Add("Critical Block", string.Format("{0:0.00%} ({1:0.00%} actual)*Mastery Rating {2}", CriticalBlock / Block, CriticalBlock, BasicStats.MasteryRating));
            }
            else
            {
                dictValues.Add("Critical Block", string.Format("{0:0.00%}*Mastery Rating {1}", 0, BasicStats.MasteryRating));
            }

            dictValues.Add("Guaranteed Reduction", string.Format("{0:0.00%}", GuaranteedReduction));

            if (AnyAvoid != BaseAnyAvoid)
            {
                dictValues.Add("Avoidance", string.Format("{0:0.00%}*Avoidance: {0:0.00%}" + Environment.NewLine +
                                                          "+ Normal Block Chance: {1:0.00%}" + Environment.NewLine +
                                                          "+ Average Block Chance: {2:0.00%}" + Environment.NewLine +
                                                          "+ Block Chance w/ Shield Block: {3:0.00%}", AnyMiss, BaseAnyAvoid, AnyAvoid, BuffedAnyAvoid));
            }
            else
            {
                dictValues.Add("Avoidance", string.Format("{0:0.00%}*Avoidance: {0:0.00%}" + Environment.NewLine +
                                                          "Avoidance + Block: {1:0.00%}", AnyMiss, BaseAnyAvoid));
            }

            dictValues.Add("Total Mitigation", string.Format("{0:0.00%}", TotalMitigation));

            if (AttackerSpeed == BaseAttackerSpeed)
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s", AttackerSpeed));
            }
            else
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s*Base speed of {1:0.00}s (modified by haste)", AttackerSpeed, BaseAttackerSpeed));
            }

            dictValues.Add("Damage Taken",
                           string.Format("{0:0.0} DPS*{1:0} damage per normal attack" + Environment.NewLine +
                                         "{2:0} damage per blocked attack" + Environment.NewLine +
                                         "{3:0} damage per critically blocked attack" + Environment.NewLine +
                                         "{4:0} damage per critical attack", DamageTaken, DamageTakenPerHit, DamageTakenPerBlock, DamageTakenPerCritBlock, DamageTakenPerCrit));

            if (CritVulnerability > 0.0001f)
            {
                dictValues.Add("Chance to be Crit", string.Format("{0:0.00%}*CRITTABLE!", CritVulnerability));
            }
            else
            {
                dictValues.Add("Chance to be Crit", string.Format("{0:0.00%}*Chance to crit reduced by {1:0.00%}", CritVulnerability, CritReduction));
            }

            dictValues.Add("Nature Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.NatureResistance, NatureReduction));
            dictValues.Add("Arcane Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.ArcaneResistance, ArcaneReduction));
            dictValues.Add("Frost Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.FrostResistance, FrostReduction));
            dictValues.Add("Fire Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.FireResistance, FireReduction));
            dictValues.Add("Shadow Resist", string.Format("{0:0}*{1:0.00%} Total Reduction in Defensive Stance", BasicStats.ShadowResistance, ShadowReduction));
            dictValues["Nature Survival"] = NatureSurvivalPoints.ToString();
            dictValues["Frost Survival"]  = FrostSurvivalPoints.ToString();
            dictValues["Fire Survival"]   = FireSurvivalPoints.ToString();
            dictValues["Shadow Survival"] = ShadowSurvivalPoints.ToString();
            dictValues["Arcane Survival"] = ArcaneSurvivalPoints.ToString();

            dictValues.Add("Weapon Speed", string.Format("{0:0.00}*{1:0.00%} Haste", WeaponSpeed, Haste));
            dictValues.Add("Attack Power", string.Format("{0}", BasicStats.AttackPower));
            dictValues.Add("Hit", string.Format("{0:0.00%}*Hit Rating {1}", Hit, BasicStats.HitRating));
            dictValues.Add("Expertise",
                           string.Format("{0}*Expertise Rating {1}" + Environment.NewLine + "Reduces chance to be dodged or parried by {2:0.00%}.",
                                         Math.Round(StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating, CharacterClass.Warrior) + BasicStats.Expertise),
                                         BasicStats.ExpertiseRating, Expertise));
            dictValues.Add("Haste", string.Format("{0:0.00%}*Haste Rating {1:0.00}", Haste, BasicStats.HasteRating));
            dictValues.Add("Armor Penetration",
                           string.Format("{0:0.00%}*" + /*"Armor Penetration Rating {1}" + Environment.NewLine +*/ "Armor Reduction {1}",
                                         ArmorPenetration, /*BasicStats.ArmorPenetrationRating,*/ BasicStats.ArmorPenetration));
            dictValues.Add("Crit", string.Format("{0:0.00%}*Crit Rating {1}", Crit, BasicStats.CritRating));
            dictValues.Add("Missed Attacks",
                           string.Format("{0:0.00%}*Attacks Missed: {1:0.00%}" + Environment.NewLine + "Attacks Dodged: {2:0.00%}" + Environment.NewLine +
                                         "Attacks Parried: {3:0.00%}", AvoidedAttacks, MissedAttacks, DodgedAttacks, ParriedAttacks));
            dictValues.Add("Total Damage/sec", string.Format("{0:0.0}", TotalDamagePerSecond));
            dictValues.Add("Total Threat/sec", string.Format("{0:0.0}*Heroic Strike used every {1:0.0} seconds", ThreatPerSecond, 3.0f / HeroicStrikeFrequency));
            dictValues.Add("Rotation", ThreatModelName + "*" + ThreatModel);

            switch (RankingMode)
            {
            case 3:
                dictValues.Add("Ranking Mode", "Burst Time*The average amount of time between events which have a chance to result in a burst death");
                dictValues.Add("Survival Points", string.Format("{0:0}*{1:0.00} seconds between events", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            case 4:
                dictValues.Add("Ranking Mode", "Damage Output*The average amount of DPS which can be produced");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival is not weighted in this mode", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            default:
                dictValues.Add("Ranking Mode", "Mitigation Scale*Default scale which compares mitigation, effective health, and threat.");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;
            }
            dictValues.Add("Overall Points", string.Format("{0:0}", OverallPoints));
            dictValues.Add("Mitigation Points", string.Format("{0:0}", MitigationPoints));
            dictValues.Add("Threat Points", string.Format("{0:0}", ThreatPoints));

            return(dictValues);
        }
예제 #12
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            try
            {
                dictValues.Add("Overall Points", OverallPoints.ToString());
                dictValues.Add("DPS Points", DPSPoints.ToString());
                dictValues.Add("Survivability Points", SurvivabilityPoints.ToString());

                float baseMiss  = StatConversion.WHITE_MISS_CHANCE_CAP[TargetLevel - 85] - BasicStats.PhysicalHit;
                float baseDodge = StatConversion.WHITE_DODGE_CHANCE_CAP[TargetLevel - 85] - StatConversion.GetDodgeParryReducFromExpertise(BasicStats.Expertise);
                float capMiss   = (float)Math.Ceiling(baseMiss * StatConversion.RATING_PER_PHYSICALHIT);
                float capDodge  = (float)Math.Ceiling(baseDodge * 400f * StatConversion.RATING_PER_EXPERTISE);

                string tipMiss = string.Empty;
                if (BasicStats.HitRating > capMiss)
                {
                    tipMiss = string.Format("*Hit Rating %: {0}%\nOver the cap by {1} Hit Rating", StatConversion.GetPhysicalHitFromRating(BasicStats.HitRating) * 100, BasicStats.HitRating - capMiss);
                }
                else if (BasicStats.HitRating < capMiss)
                {
                    tipMiss = string.Format("*Hit Rating %: {0}%\nUnder the cap by {1} Hit Rating", StatConversion.GetPhysicalHitFromRating(BasicStats.HitRating) * 100, capMiss - BasicStats.HitRating);
                }
                else
                {
                    tipMiss = string.Format("*Hit Rating %: {0}%\nExactly at the cap", StatConversion.GetPhysicalHitFromRating(BasicStats.HitRating) * 100);
                }

                string tipDodge = string.Empty;
                if (BasicStats.ExpertiseRating > capDodge)
                {
                    tipDodge = string.Format("*Expertise Rating %: {0}%\nOver the cap by {1} Expertise Rating", StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating) * 0.25f, BasicStats.ExpertiseRating - capDodge);
                }
                else if (BasicStats.ExpertiseRating < capDodge)
                {
                    tipDodge = string.Format("*Expertise Rating %: {0}%\nUnder the cap by {1} Expertise Rating", StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating) * 0.25f, capDodge - BasicStats.ExpertiseRating);
                }
                else
                {
                    tipDodge = string.Format("*Expertise Rating %: {0}%\nExactly at the cap", StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating) * 0.25f);
                }

                string tipHaste = string.Format("*Haste Rating %: {0}%", StatConversion.GetPhysicalHasteFromRating(BasicStats.HasteRating, CharacterClass.Druid) * 100f);

                string tipMastery = string.Format("*Increases the damage done by your bleed abilities by {0}%", ((StatConversion.GetMasteryFromRating(BasicStats.MasteryRating, CharacterClass.Druid) + 8f) * 0.031f) * 100f);

                dictValues.Add("Health", BasicStats.Health.ToString());
                dictValues.Add("Attack Power", BasicStats.AttackPower.ToString());
                dictValues.Add("Agility", BasicStats.Agility.ToString());
                dictValues.Add("Strength", BasicStats.Strength.ToString());
                dictValues.Add("Crit Rating", BasicStats.CritRating.ToString());
                dictValues.Add("Hit Rating", BasicStats.HitRating.ToString() + tipMiss);
                dictValues.Add("Expertise Rating", BasicStats.ExpertiseRating.ToString() + tipDodge);
                dictValues.Add("Mastery Rating", BasicStats.MasteryRating.ToString() + tipMastery);
                dictValues.Add("Haste Rating", BasicStats.HasteRating.ToString() + tipHaste);

                dictValues.Add("Avoided Attacks", string.Format("{0}%*{1}% Dodged, {2}% Missed", AvoidedAttacks, DodgedAttacks, MissedAttacks));
                dictValues.Add("Crit Chance", CritChance.ToString() + "%");
                dictValues.Add("Attack Speed", AttackSpeed.ToString() + "s");
                dictValues.Add("Armor Mitigation", ArmorMitigation.ToString() + "%");

                dictValues.Add("Optimal Rotation", HighestDPSRotation.ToString());
                //dictValues.Add("Optimal Rotation DPS", HighestDPSRotation.DPS.ToString());
                //dictValues.Add("Custom Rotation DPS", CustomRotation.DPS.ToString());


                float chanceNonAvoided = 1f - (AvoidedAttacks / 100f);
                dictValues.Add("Melee", Abilities.MeleeStats.ToString());
                dictValues.Add("Mangle", Abilities.MangleStats.ToString());
                dictValues.Add("Shred", Abilities.ShredStats.ToString());
                dictValues.Add("Ravage", Abilities.RavageStats.ToString());
                dictValues.Add("Rake", Abilities.RakeStats.ToString());
                dictValues.Add("Rip", Abilities.RipStats.ToString());
                dictValues.Add("Bite", Abilities.BiteStats.ToString());


                //string[] abilityStats = MeleeStats.GetStatsTexts(HighestDPSRotation.MeleeCount, 0, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Melee Usage", abilityStats[0]);
                //dictValues.Add("Melee Stats", abilityStats[1]);
                //abilityStats = MangleStats.GetStatsTexts(HighestDPSRotation.MangleCount, 0, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Mangle Usage", abilityStats[0]);
                //dictValues.Add("Mangle Stats", abilityStats[1]);
                //abilityStats = ShredStats.GetStatsTexts(HighestDPSRotation.ShredCount, 0, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Shred Usage", abilityStats[0]);
                //dictValues.Add("Shred Stats", abilityStats[1]);
                //abilityStats = RakeStats.GetStatsTexts(HighestDPSRotation.RakeCount, 0, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Rake Usage", abilityStats[0]);
                //dictValues.Add("Rake Stats", abilityStats[1]);
                //abilityStats = RipStats.GetStatsTexts(HighestDPSRotation.RipCount, 0, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Rip Usage", abilityStats[0]);
                //dictValues.Add("Rip Stats", abilityStats[1]);
                //abilityStats = RoarStats.GetStatsTexts(HighestDPSRotation.RoarCount, HighestDPSRotation.RoarCP, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Roar Usage", abilityStats[0]);
                //dictValues.Add("Roar Stats", abilityStats[1]);
                //abilityStats = BiteStats.GetStatsTexts(HighestDPSRotation.BiteCount, HighestDPSRotation.BiteCP, HighestDPSRotation.TotalDamage, chanceNonAvoided, Duration);
                //dictValues.Add("Bite Usage", abilityStats[0]);
                //dictValues.Add("Bite Stats", abilityStats[1]);

                //string attackFormat = "{0}%*Damage Per Hit: {1}, Damage Per Swing: {2}\r\n{0}% of Total Damage, {3} Damage Done";
                //dictValues.Add("Melee Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.MeleeDamageTotal / HighestDPSRotation.DamageTotal, MeleeDamagePerHit, MeleeDamagePerSwing, HighestDPSRotation.MeleeDamageTotal));
                //dictValues.Add("Mangle Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.MangleDamageTotal / HighestDPSRotation.DamageTotal, MangleDamagePerHit, MangleDamagePerSwing, HighestDPSRotation.MangleDamageTotal));
                //dictValues.Add("Shred Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.ShredDamageTotal / HighestDPSRotation.DamageTotal, ShredDamagePerHit, ShredDamagePerSwing, HighestDPSRotation.ShredDamageTotal));
                //dictValues.Add("Rake Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.RakeDamageTotal / HighestDPSRotation.DamageTotal, RakeDamagePerHit, RakeDamagePerSwing, HighestDPSRotation.RakeDamageTotal));
                //dictValues.Add("Rip Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.RipDamageTotal / HighestDPSRotation.DamageTotal, RipDamagePerHit, RipDamagePerSwing, HighestDPSRotation.RipDamageTotal));
                //dictValues.Add("Bite Damage", string.Empty);//.Format(attackFormat, 100f * HighestDPSRotation.BiteDamageTotal / HighestDPSRotation.DamageTotal, BiteDamagePerHit, BiteDamagePerSwing, HighestDPSRotation.BiteDamageTotal));

                //string rotationDescription = string.Empty;
                //try
                //{
                //    rotationDescription = string.Format("{0}*Keep {1}cp Savage Roar up.\r\n{2}{3}{4}{5}Use {6} for combo points.",
                //        HighestDPSRotation.Name.Replace(" + ", "+"), HighestDPSRotation.RoarCP,
                //        HighestDPSRotation.Name.Contains("Rake") ? "Keep Rake up.\r\n" : "",
                //        HighestDPSRotation.Name.Contains("Rip") ? "Keep 5cp Rip up.\r\n" : "",
                //        HighestDPSRotation.Name.Contains("Mangle") ? "Keep Mangle up.\r\n" : "",
                //        HighestDPSRotation.Name.Contains("Bite") ? string.Format("Use {0}cp Ferocious Bites to spend extra combo points.\r\n", HighestDPSRotation.BiteCP) : "",
                //        HighestDPSRotation.Name.Contains("Shred") ? "Shred" : "Mangle");
                //}
                //catch (Exception ex)
                //{
                //    ex.ToString();
                //}
            }
            catch (Exception ex)
            {
                new Base.ErrorBox()
                {
                    Title        = "Error Getting Cat Dictionary Values",
                    Function     = "GetCharacterDisplayCalculationValues()",
                    TheException = ex,
                }.Show();
            }
            return(dictValues);
        }
예제 #13
0
        public void UpdateCalcs(bool firstPass)
        {
            // talents
            callOfThunder       = .05f * _talents.CallOfThunder;
            critMultiplierMelee = 2f * (1 + _stats.BonusCritMultiplier);
            critMultiplierSpell = (1.5f + .1f * _character.ShamanTalents.ElementalFury) * (1 + _stats.BonusSpellCritMultiplier);

            // Melee
            float hitBonus = _stats.PhysicalHit + StatConversion.GetHitFromRating(_stats.HitRating) + 0.02f * _talents.DualWieldSpecialization;

            expertiseBonusMH = GetDPRfromExp(_stats.Expertise + StatConversion.GetExpertiseFromRating(_stats.ExpertiseRating));
            expertiseBonusOH = GetDPRfromExp(_stats.Expertise + StatConversion.GetExpertiseFromRating(_stats.ExpertiseRating));

            // Need to modify expertiseBonusMH & OH if Orc and have racial bonus weapons
            if (_character.Race == CharacterRace.Orc)
            {
                ItemType mhType = _character.MainHand == null ? ItemType.None : _character.MainHand.Type;
                ItemType ohType = _character.OffHand == null ? ItemType.None : _character.OffHand.Type;
                if (mhType == ItemType.OneHandAxe || mhType == ItemType.FistWeapon) // patch 3.2 includes fists
                {
                    expertiseBonusMH += 0.0125f;
                }
                if (ohType == ItemType.OneHandAxe || ohType == ItemType.FistWeapon) // patch 3.2 includes fists
                {
                    expertiseBonusOH += 0.0125f;
                }
            }

            float meleeCritModifier = _stats.PhysicalCrit;
            float baseMeleeCrit     = StatConversion.GetCritFromRating(_stats.CritRating) +
                                      StatConversion.GetCritFromAgility(_stats.Agility, _character.Class) + .01f * _talents.ThunderingStrikes;

            chanceDodgeMH = Math.Max(0f, DodgeChanceCap - expertiseBonusMH);
            chanceDodgeOH = Math.Max(0f, DodgeChanceCap - expertiseBonusOH);
            float ParryChance = ParryChanceCap - expertiseBonusMH;

            chanceParryMH      = (float)Math.Max(0f, _calcOpts.InBack ? ParryChance * (1f - _calcOpts.InBackPerc / 100f) : ParryChance);
            ParryChance        = ParryChanceCap - expertiseBonusOH;
            chanceParryOH      = (float)Math.Max(0f, _calcOpts.InBack ? ParryChance * (1f - _calcOpts.InBackPerc / 100f) : ParryChance);
            chanceWhiteMissMH  = Math.Max(0f, WhiteHitCap - hitBonus) + chanceDodgeMH + chanceParryMH;
            chanceWhiteMissOH  = Math.Max(0f, WhiteHitCap - hitBonus) + chanceDodgeOH + chanceParryOH;
            chanceYellowMissMH = Math.Max(0f, YellowHitCap - hitBonus) + chanceDodgeMH + chanceParryMH; // base miss 8% now
            chanceYellowMissOH = Math.Max(0f, YellowHitCap - hitBonus) + chanceDodgeOH + chanceParryOH; // base miss 8% now

            // SetCritValues((1 + _stats.BonusCritChance) * (baseMeleeCrit + meleeCritModifier) + .00005f); //fudge factor for rounding
            SetCritValues(baseMeleeCrit + meleeCritModifier + .00005f); //fudge factor for rounding
            // set two export values so that ED crit isn't included
            exportMeleeCritMH = chanceWhiteCritMH + whiteCritDepression;
            exportMeleeCritOH = chanceWhiteCritOH + whiteCritDepression;

            // Spells
            ftBonusCrit = 0f;
            if (_calcOpts.MainhandImbue == "Flametongue")
            {
                ftBonusCrit += _talents.GlyphofFlametongueWeapon ? .02f : 0f;
            }
            if (_calcOpts.OffhandImbue == "Flametongue" && _talents.DualWield == 1)
            {
                ftBonusCrit += _talents.GlyphofFlametongueWeapon ? .02f : 0f;
            }

            float spellCritModifier = _stats.SpellCrit + _stats.SpellCritOnTarget + ftBonusCrit;
            float hitBonusSpell     = _stats.SpellHit + StatConversion.GetSpellHitFromRating(_stats.HitRating);

            chanceSpellMiss = Math.Max(0f, SpellMissRate - hitBonusSpell);
            overSpellHitCap = Math.Max(0f, hitBonusSpell - SpellMissRate);
            float baseSpellCrit = StatConversion.GetSpellCritFromRating(_stats.CritRating) +
                                  StatConversion.GetSpellCritFromIntellect(_stats.Intellect) + .01f * _talents.ThunderingStrikes;

            //chanceSpellCrit = Math.Min(0.75f, (1 + _stats.BonusCritChance) * (baseSpellCrit + spellCritModifier) + .00005f); //fudge factor for rounding
            chanceSpellCrit = Math.Min(0.75f, baseSpellCrit + spellCritModifier + .00005f); //fudge factor for rounding

            float hasteBonus = StatConversion.GetHasteFromRating(_stats.HasteRating, _character.Class);

            unhastedMHSpeed = _character.MainHand == null ? 3.0f : _character.MainHand.Item.Speed;
            unhastedOHSpeed = _character.OffHand == null ? 3.0f : _character.OffHand.Item.Speed;
            float baseHastedMHSpeed    = unhastedMHSpeed / (1f + hasteBonus) / (1f + _stats.PhysicalHaste);
            float baseHastedOHSpeed    = unhastedOHSpeed / (1f + hasteBonus) / (1f + _stats.PhysicalHaste);
            float chanceToProcWFPerHit = .2f + (_character.ShamanTalents.GlyphofWindfuryWeapon ? .02f : 0f);

            //The Swing Loop
            //This is where we figure out feedback systems -- WF, MW, ED, Flurry, etc.
            //--------------
            flurryUptime = 1f;
            edUptime     = 0f;
            float stormstrikeSpeed = firstPass ? (_talents.Stormstrike == 1 ? 8f : 0f) : AbilityCooldown(EnhanceAbility.StormStrike);
            float shockSpeed       = firstPass ? BaseShockSpeed : AbilityCooldown(EnhanceAbility.EarthShock);
            float lavaLashSpeed    = firstPass ? (_talents.LavaLash == 1 ? 6f : 0f) : AbilityCooldown(EnhanceAbility.LavaLash);
            float fireNovaSpeed    = firstPass ? BaseFireNovaSpeed : AbilityCooldown(EnhanceAbility.FireNova);

            if (_calcOpts.PriorityInUse(EnhanceAbility.MagmaTotem))
            {
                fireTotemUptime = firstPass ? 1.0f : 20f / AbilityCooldown(EnhanceAbility.MagmaTotem);
            }
            else if (_calcOpts.PriorityInUse(EnhanceAbility.SearingTotem))
            {
                fireTotemUptime = firstPass ? 1.0f : 60f / AbilityCooldown(EnhanceAbility.SearingTotem);
            }
            else if (_calcOpts.PriorityInUse(EnhanceAbility.RefreshTotems)) // if no Searing or Magma totem use refresh of Flametongue totem.
            {
                fireTotemUptime = firstPass ? 1.0f : 300f / AbilityCooldown(EnhanceAbility.RefreshTotems);
            }

            float mwPPM             = 2 * _talents.MaelstromWeapon * (1 + _stats.Enhance4T8 * 0.2f);
            float flurryHasteBonus  = .06f * _talents.Flurry + _stats.Enhance4T7;
            float edCritBonus       = .03f * _talents.ElementalDevastation;
            float staticShockChance = (.02f * _character.ShamanTalents.StaticShock + (_stats.Enhance2T9 == 1f ? 0.03f : 0f));

            hitsPerSMHSS = 0f;
            hitsPerSOHSS = 0f;
            hitsPerSOH   = 0f;
            hitsPerSMH   = 0f;
            hitsPerSWF   = 0f;
            if (_talents.Stormstrike == 1)
            {
                hitsPerSMHSS = (1f - chanceYellowMissMH) / stormstrikeSpeed;
                hitsPerSOHSS = _character.ShamanTalents.DualWield == 1 ? ((1f - 2 * chanceYellowMissOH) / stormstrikeSpeed) : 0f; //OH only swings if MH connects
            }
            hitsPerSLL = lavaLashSpeed == 0 ? 0f : (1f - chanceYellowMissOH) / lavaLashSpeed;
            float swingsPerSMHMelee = 0f;
            float swingsPerSOHMelee = 0f;
            float wfProcsPerSecond  = 0f;
            float mwProcsPerSecond  = 0f;

            secondsToFiveStack = 10f;
            float averageMeleeCritChance   = (chanceWhiteCritMH + chanceWhiteCritOH + chanceYellowCritMH + chanceYellowCritOH) / 4f;
            float averageMeleeHitChance    = ((1f - chanceWhiteMissMH - chanceDodgeMH - chanceParryMH) + (1f - chanceWhiteMissOH - chanceDodgeOH - chanceParryOH)) / 2f;
            float averageMeleeMissChance   = (chanceWhiteMissMH + chanceWhiteMissOH) / 2f;
            float whiteHitsPerSMH          = 0f;
            float whiteHitsPerSOH          = 0f;
            float moteHitsPerS             = 0f;
            float yellowHitsPerSMH         = 0f;
            float yellowHitsPerSOH         = 0f;
            float flameTongueHitsPerSecond = 0f;

            for (int i = 0; i < 5; i++)
            {
                // float bonusHaste = (1f + (flurryUptime * flurryHasteBonus));
                float bonusHaste = 1 / (1 - flurryUptime + flurryUptime / (1 + flurryHasteBonus)); // use time based not proc based flurryUptime
                hastedMHSpeed     = baseHastedMHSpeed / bonusHaste;
                hastedOHSpeed     = baseHastedOHSpeed / bonusHaste;
                swingsPerSMHMelee = 1f / hastedMHSpeed;
                swingsPerSOHMelee = (hastedOHSpeed == 0f) ? 0f : 1f / hastedOHSpeed;
                whiteHitsPerSMH   = ChanceWhiteHitMH * swingsPerSMHMelee;
                whiteHitsPerSOH   = ChanceWhiteHitOH * swingsPerSOHMelee;
                moteHitsPerS      = _stats.MoteOfAnger * 2 * AverageWhiteHitChance;
                // Windfury model
                if (_calcOpts.MainhandImbue == "Windfury")
                {
                    float hitsThatProcWFPerS = whiteHitsPerSMH + hitsPerSMHSS;
                    if (_character.ShamanTalents.DualWield == 1)
                    {
                        hitsThatProcWFPerS += moteHitsPerS / 2; // half the hits will be OH and thus won't proc WF
                    }
                    else
                    {
                        hitsThatProcWFPerS += moteHitsPerS; // if no offhand then all motes will be MH weapon by definition
                    }
                    float maxExpectedWFPerFight = hitsThatProcWFPerS * chanceToProcWFPerHit * fightLength;
                    float ineligibleSeconds     = maxExpectedWFPerFight * (3.25f - hastedMHSpeed);
                    float expectedWFPerFight    = hitsThatProcWFPerS * chanceToProcWFPerHit * (fightLength - ineligibleSeconds);
                    wfProcsPerSecond = expectedWFPerFight / fightLength;
                    hitsPerSWF       = 2f * wfProcsPerSecond * (1f - chanceYellowMissMH);
                }
                yellowHitsPerSMH = hitsPerSWF + hitsPerSMHSS;
                yellowHitsPerSOH = hitsPerSOHSS + hitsPerSLL;

                //Due to attack table, a white swing has the same chance to crit as a yellow hit
// Old Flurry calc changed 10 Nov 2009
//                couldCritSwingsPerSecond = whiteHitsPerSMH + whiteHitsPerSOH + yellowHitsPerSMH + yellowHitsPerSOH;
//                float swingsThatConsumeFlurryPerSecond = swingsPerSMHMelee + swingsPerSOHMelee;
//                flurryUptime = 1f - (float)Math.Pow(1 - averageMeleeCritChance, (3 / swingsThatConsumeFlurryPerSecond) * couldCritSwingsPerSecond);  // old formulae
                flurryUptime = CalculateFlurryUptime(averageMeleeCritChance, averageMeleeHitChance, averageMeleeMissChance);

                // Maelstrom Weapon time to 5 stacks calc
                if (_character.ShamanTalents.DualWield == 1 && unhastedOHSpeed != 0f)
                {
                    hitsPerSMH       = whiteHitsPerSMH + yellowHitsPerSMH + moteHitsPerS / 2;
                    hitsPerSOH       = whiteHitsPerSOH + yellowHitsPerSOH + moteHitsPerS / 2;
                    mwProcsPerSecond = (mwPPM / (60f / unhastedMHSpeed)) * hitsPerSMH + (mwPPM / (60f / unhastedOHSpeed)) * hitsPerSOH;
                }
                else
                {
                    hitsPerSMH       = whiteHitsPerSMH + yellowHitsPerSMH + moteHitsPerS;
                    hitsPerSOH       = 0f;
                    mwProcsPerSecond = (mwPPM / (60f / unhastedMHSpeed)) * hitsPerSMH;
                }
                secondsToFiveStack = 5f / mwProcsPerSecond;

                // Elemental Devastation Uptime calc
                staticShocksPerSecond    = (hitsPerSMH + hitsPerSOH) * staticShockChance;
                flameTongueHitsPerSecond = (_calcOpts.MainhandImbue == "Flametongue" ? HitsPerSMH : 0f) +
                                           ((_calcOpts.OffhandImbue == "Flametongue" && _talents.DualWield == 1) ? HitsPerSOH : 0f);
                spellAttacksPerSec = (1f / secondsToFiveStack + 1f / shockSpeed + 1f / fireNovaSpeed + staticShocksPerSecond) // + flameTongueHitsPerSecond)
                                     * (1f - chanceSpellMiss);
                float couldCritSpellsPerS = spellAttacksPerSec - staticShocksPerSecond;                                       // LS procs from Static Shock cannot crit
                edUptime = 1f - (float)Math.Pow(1 - chanceSpellCrit, 10 * couldCritSpellsPerS);
                averageMeleeCritChance = (chanceWhiteCritMH + chanceWhiteCritOH + chanceYellowCritMH + chanceYellowCritOH) / 4f + edUptime * edCritBonus;
            }
            float yellowAttacksPerSecond = hitsPerSWF + hitsPerSMHSS;

            if (_character.ShamanTalents.DualWield == 1 && unhastedMHSpeed != 0)
            {
                yellowAttacksPerSecond += hitsPerSOHSS;
            }

            // set output variables
            edBonusCrit = edUptime * edCritBonus;
            //SetCritValues((1 + _stats.BonusCritChance) * (baseMeleeCrit + meleeCritModifier) + edBonusCrit + .00005f); //fudge factor for rounding
            SetCritValues(baseMeleeCrit + meleeCritModifier + edBonusCrit + .00005f); //fudge factor for rounding
            meleeAttacksPerSec = hitsPerSMH + hitsPerSOH;
            meleeCritsPerSec   = (whiteHitsPerSMH * chanceWhiteCritMH) + (whiteHitsPerSOH * chanceWhiteCritOH) +
                                 (yellowHitsPerSMH * chanceYellowCritMH) + (yellowHitsPerSOH * chanceYellowCritOH) +
                                 (_stats.MoteOfAnger * 2 * AverageWhiteCritChance);
            spellCritsPerSec  = spellAttacksPerSec * ChanceSpellCrit;
            spellCastsPerSec  = spellAttacksPerSec;
            spellMissesPerSec = spellAttacksPerSec * chanceSpellMiss;
            chanceMeleeHit    = meleeAttacksPerSec / (swingsPerSMHMelee + swingsPerSOHMelee + 2f * wfProcsPerSecond + .25f + 1f / 6f);
            maxMana           = _stats.Mana;
            float spellhaste = _stats.SpellHaste + StatConversion.GetSpellHasteFromRating(_stats.HasteRating);

            averageFSDotTime = 18f / (1f + spellhaste);
        }
예제 #14
0
파일: Lookup.cs 프로젝트: edekk/rawr-2.3.23
 public static float BonusExpertisePercentage(Character character, Stats stats)
 {
     return(StatConversion.GetDodgeParryReducFromExpertise(StatConversion.GetExpertiseFromRating(stats.ExpertiseRating, CharacterClass.Paladin) + stats.Expertise, CharacterClass.Paladin));
 }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            dictValues.Add("Health", BasicStats.Health.ToString());
            dictValues.Add("Mana", BasicStats.Mana.ToString());
            dictValues.Add("Strength", BasicStats.Strength.ToString());
            dictValues.Add("Agility", BasicStats.Agility.ToString());
            dictValues.Add("Stamina", string.Format("{0}*Increases Health by {1}", BasicStats.Stamina, (BasicStats.Stamina - 20f) * 10f + 20f));
            dictValues.Add("Intellect", BasicStats.Intellect.ToString());
            dictValues.Add("Armor", string.Format("{0}*Reduces physical damage taken by {1:0.00%}" + Environment.NewLine +
                                                  "Armor Damage Reduction depends on Attacker Level.",
                                                  BasicStats.Armor, ArmorReduction));
            dictValues.Add("Defense", Defense.ToString() + string.Format("*Defense Rating {0}", BasicStats.DefenseRating));
            dictValues.Add("Dodge", string.Format("{0:0.0000%}*Dodge Rating {1}", Dodge, BasicStats.DodgeRating));
            dictValues.Add("Parry", string.Format("{0:0.0000%}*Parry Rating {1}", Parry, BasicStats.ParryRating));
            dictValues.Add("Block", string.Format("{0:0.0000%}*Block Rating {1}", Block, BasicStats.BlockRating));
            dictValues.Add("Miss", string.Format("{0:0.0000%}", Miss));
            dictValues.Add("Block Value", string.Format("{0}*{1} Active Block Value (Libram etc)", StaticBlockValue, ActiveBlockValue));
            dictValues.Add("Guaranteed Reduction", string.Format("{0:0.00%}", GuaranteedReduction));
            dictValues.Add("Avoidance", string.Format("{0:0.0000%}*Avoidance Points {1}", DodgePlusMissPlusParry, (DodgePlusMissPlusParry * 10000f)));
            dictValues.Add("Avoidance + Block", string.Format("{0:0.0000%}", DodgePlusMissPlusParryPlusBlock));
            dictValues.Add("Total Mitigation", string.Format("{0:0.00%}", TotalMitigation));

            if (AttackerSpeed == BaseAttackerSpeed)
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s", AttackerSpeed));
            }
            else
            {
                dictValues.Add("Attacker Speed", string.Format("{0:0.00}s*Base speed of {1:0.00}s (reduced by parry haste)", AttackerSpeed, BaseAttackerSpeed));
            }

            dictValues.Add("Damage Taken",
                           string.Format("{0:0.0} DPS*{1:0} damage per normal attack" + Environment.NewLine +
                                         "{2:0} damage per blocked attack" + Environment.NewLine +
                                         "{3:0} damage per critical attack" + Environment.NewLine +
                                         "On Average, you take" + Environment.NewLine +
                                         "{4:0.00%} of incoming damage", DPSTaken, DamageTakenPerHit, DamageTakenPerBlock, DamageTakenPerCrit, DamageTaken));

            dictValues.Add("Resilience",
                           string.Format(@"{0}*Reduces periodic damage and chance to be critically hit by {1:0.00%}." + Environment.NewLine +
                                         "Reduces the effect of mana-drains and the damage of critical strikes by {2:0.00%}.",
                                         BasicStats.Resilience,
                                         StatConversion.GetCritReductionFromResilience(BasicStats.Resilience, CharacterClass.Paladin),
                                         StatConversion.GetCritReductionFromResilience(BasicStats.Resilience, CharacterClass.Paladin) * 2f));

            if (CritVulnerability > 0.0001f)
            {
                double defenseNeeded    = Math.Ceiling((100 * CritVulnerability / StatConversion.DEFENSE_RATING_AVOIDANCE_MULTIPLIER) * StatConversion.RATING_PER_DEFENSE);
                double resilienceNeeded = Math.Ceiling(CritVulnerability * StatConversion.RATING_PER_RESILIENCE);
                dictValues.Add("Chance to be Crit",
                               string.Format("{0:0.00%}*CRITTABLE! Short by approximately {1:0} defense rating or approximately {2:0} resilience rating to be uncrittable.",
                                             CritVulnerability, defenseNeeded, resilienceNeeded));
            }
            else
            {
                dictValues.Add("Chance to be Crit", string.Format("{0:0.00%}*Chance to be crit reduced by {1:0.00%}", CritVulnerability, CritReduction));
            }

            if (UsingHolyShield)
            {
                if (CritVulnerabilityWithoutHolyShield > 0.0001f)
                {
                    double defenseNeeded    = Math.Ceiling((100 * CritVulnerabilityWithoutHolyShield / StatConversion.DEFENSE_RATING_AVOIDANCE_MULTIPLIER) * StatConversion.RATING_PER_DEFENSE);
                    double resilienceNeeded = Math.Ceiling(CritVulnerability * StatConversion.RATING_PER_RESILIENCE);
                    dictValues.Add("...Without Holy Shield",
                                   string.Format("{0:0.00%}*CRITTABLE! Short by approximately {1:0} defense rating or approximately {2:0} resilience rating to be uncrittable without holy shield.",
                                                 CritVulnerabilityWithoutHolyShield, defenseNeeded, resilienceNeeded));
                }
                else
                {
                    dictValues.Add("...Without Holy Shield", string.Format("{0:0.00%}*Chance to be crit reduced by {1:0.00%}", CritVulnerabilityWithoutHolyShield, CritReduction));
                }
            }
            else
            {
                dictValues.Add("...Without Holy Shield", "N/A*Not applicable");
            }

            dictValues.Add("Nature Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.NatureResistance, NatureReduction));
            dictValues.Add("Arcane Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.ArcaneResistance, ArcaneReduction));
            dictValues.Add("Frost Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.FrostResistance, FrostReduction));
            dictValues.Add("Fire Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.FireResistance, FireReduction));
            dictValues.Add("Shadow Resist", string.Format("{0:0}*{1:0.00%} Total Reduction", BasicStats.ShadowResistance, ShadowReduction));
            dictValues["Nature Survival"] = NatureSurvivalPoints.ToString();
            dictValues["Frost Survival"]  = FrostSurvivalPoints.ToString();
            dictValues["Fire Survival"]   = FireSurvivalPoints.ToString();
            dictValues["Shadow Survival"] = ShadowSurvivalPoints.ToString();
            dictValues["Arcane Survival"] = ArcaneSurvivalPoints.ToString();

            dictValues.Add("Weapon Speed", string.Format("{0:0.00}*{1:0.00%} Haste", WeaponSpeed, PhysicalHaste));
            dictValues.Add("Attack Power", string.Format("{0}", BasicStats.AttackPower));
            dictValues.Add("Spell Power", string.Format("{0}", BasicStats.SpellPower));
            dictValues.Add("Hit", string.Format("{0:0.00%}*Hit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}", Hit, BasicStats.HitRating, TargetLevel));
            dictValues.Add("Spell Hit", string.Format("{0:0.00%}*Hit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                      SpellHit, BasicStats.HitRating, TargetLevel));
            dictValues.Add("Expertise",
                           string.Format("{0:0.00}*Expertise Rating {1}" + Environment.NewLine + "Reduces chance to be dodged or parried by {2:0.00%}.",
                                         StatConversion.GetExpertiseFromRating(BasicStats.ExpertiseRating, CharacterClass.Paladin) + BasicStats.Expertise,
                                         BasicStats.ExpertiseRating, Expertise));
            dictValues.Add("Physical Haste", string.Format("{0:0.00%}*Haste Rating {1:0.00}", PhysicalHaste, BasicStats.HasteRating));
            dictValues.Add("Effective Target Armor",
                           string.Format("{0}*Reduces the physical damage you deal by {1:0.00%}" + Environment.NewLine + Environment.NewLine +
                                         "Effective Armor depends on Armor ignore debuffs," + Environment.NewLine +
                                         "your Armor Penetration buffs and talents." + Environment.NewLine +
                                         "Enemy Damage Reduction depends on your Level.",
                                         (float)Math.Floor(EffectiveTargetArmor), EffectiveTargetArmorDamageReduction));

            dictValues.Add("Effective Armor Penetration",
                           string.Format("{0:0.00%}*Armor Penetration Rating {1} = {2:0.00%}." + Environment.NewLine + "" + Environment.NewLine +
                                         "Your Armor Penetration Cap is {3} Armor, this is" + Environment.NewLine +
                                         "the highest amount your Arp Rating will ignore." + Environment.NewLine +
                                         "Your Rating currently reduces Enemy Armor by {4}." + Environment.NewLine + "" + Environment.NewLine +
                                         "Your Arp Rating is {5:0.00%} effective (GC)." + Environment.NewLine +
                                         "Note that debuffs like Sunder reduce the Cap.",
                                         EffectiveArmorPenetration, BasicStats.ArmorPenetrationRating, ArmorPenetrationFromRating,
                                         (float)Math.Floor(ArmorPenetrationCap),
                                         (float)Math.Floor(ArmorPenetrationCap * ArmorPenetrationFromRating),
                                         EffectiveArmorPenetrationRating));

            dictValues.Add("Crit", string.Format("{0:0.00%}*Crit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                 Crit, BasicStats.CritRating, TargetLevel));
            dictValues.Add("Spell Crit", string.Format("{0:0.00%}*Crit Rating {1}" + Environment.NewLine + "Against a Target of Level {2}",
                                                       SpellCrit, BasicStats.CritRating, TargetLevel));
            dictValues.Add("Weapon Damage", string.Format("{0:0.00}*As average damage per {1}" + Environment.NewLine + "Before Armor",
                                                          BasicStats.WeaponDamage, Lookup.Name(Ability.None)));
            dictValues.Add("Missed Attacks",
                           string.Format("{0:0.00%}*Attacks Missed: {1:0.00%}" + Environment.NewLine + "Attacks Dodged: {2:0.00%}" + Environment.NewLine +
                                         "Attacks Parried: {3:0.00%}", AvoidedAttacks, MissedAttacks, DodgedAttacks, ParriedAttacks));
            dictValues.Add("Glancing Attacks", string.Format("{0:0.00%}*{1:0.00%} Reduction" + Environment.NewLine +
                                                             "Against a Target of Level {2}", GlancingAttacks, 1.0f - GlancingReduction, TargetLevel));
            dictValues.Add("Total Damage/sec", string.Format("{0:0.0}", TotalDamagePerSecond) + "*" + ThreatModel);
            dictValues.Add("Threat/sec", string.Format("{0:0.0}", ThreatPerSecond) + "*" + ThreatModel);
            //dictValues.Add("Unlimited Threat/sec", string.Format("{0:0.0}", UnlimitedThreat) + "*" + ThreatModel);

            switch (RankingMode)
            {
            case 2:
                dictValues.Add("Ranking Mode", "TankPoints*The average amount of unmitigated damage which can be taken before dying");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;

            case 3:
                dictValues.Add("Ranking Mode", "Burst Time*The average amount of time between events which have a chance to result in a burst death");
                dictValues.Add("Survival Points", string.Format("{0:0}*{1:0.00} seconds between events", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            case 4:
                dictValues.Add("Ranking Mode", "Damage Output*The average amount of DPS which can be produced");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival is not weighted in this mode", SurvivalPoints, SurvivalPoints / 100.0f));
                break;

            case 5:
                dictValues.Add("Ranking Mode", "ProtWarr Mode*Average mitigated damage vs Effective Health");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;

            case 6:
                dictValues.Add("Ranking Mode", "Damage Taken*Average taken damage vs. Effective Health");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;

            case 7:
                dictValues.Add("Ranking Mode", "Ranking Mode 7*Dummy Placeholder");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival Placeholder", SurvivalPoints));
                break;

            case 8:
                dictValues.Add("Ranking Mode", "Ranking Mode 8*Dummy Placeholder");
                dictValues.Add("Survival Points", string.Format("{0:0}*Survival Placeholder", SurvivalPoints));
                break;

            default:
                dictValues.Add("Ranking Mode", "Mitigation Scale*Customizable scale which allows you to weight mitigation vs. effective health.");
                dictValues.Add("Survival Points", string.Format("{0:0}*Effective Health", SurvivalPoints));
                break;
            }
            dictValues.Add("Overall Points", string.Format("{0:0}", OverallPoints));
            dictValues.Add("Mitigation Points", string.Format("{0:0}", MitigationPoints));
            dictValues.Add("Threat Points", string.Format("{0:0}", ThreatPoints));

            return(dictValues);
        }