public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> retVal = new Dictionary <string, string>();

            retVal.Add("Health", baseStats.Health.ToString());
            retVal.Add("Mana", baseStats.Mana.ToString());
            retVal.Add("Armor", baseStats.Armor.ToString());
            retVal.Add("Agility", baseStats.Agility.ToString());
            retVal.Add("Stamina", baseStats.Stamina.ToString());
            retVal.Add("Intellect", baseStats.Intellect.ToString());
            retVal.Add("Spirit", baseStats.Spirit.ToString());
            retVal.Add("Spell Power", SpellPower.ToString());
            retVal.Add("Spell Hit", String.Format("{0:F}%*{1} Hit Rating, {2:F}% Hit From Gear, {3} Rating To Cap",
                                                  100 * SpellHit,
                                                  baseStats.HitRating,
                                                  100 * StatConversion.GetSpellHitFromRating(baseStats.HitRating),
                                                  StatConversion.GetRatingFromHit(Math.Max(0, 0.17f - SpellHit))));
            retVal.Add("Spell Crit", String.Format("{0:F}%*{1} Crit Rating, {2:F}% Crit From Gear, {3:F}% Crit From Intellect",
                                                   100 * SpellCrit,
                                                   baseStats.CritRating,
                                                   100 * StatConversion.GetSpellCritFromRating(baseStats.CritRating),
                                                   100 * StatConversion.GetSpellCritFromIntellect(baseStats.Intellect)));
            retVal.Add("Spell Haste", String.Format("{0:F}%*{1} Haste Rating, {2:F}% Haste From Gear",
                                                    100 * SpellHaste,
                                                    baseStats.HasteRating,
                                                    100 * StatConversion.GetSpellHasteFromRating(baseStats.HasteRating)));
            retVal.Add("MP5 Not Casting", String.Format("{0:F0}", ManaRegen * 5.0f));
            retVal.Add("MP5 While Casting", String.Format("{0:F0}", ManaRegen5SR * 5.0f));
            retVal.Add("Total Score", String.Format("{0:F2}", SubPoints[0] + SubPoints[1]));
            retVal.Add("Selected Rotation", SelectedRotation.Name);
            retVal.Add("Selected DPS", String.Format("{0:F2}", SelectedRotation.RotationData.DPS));
            retVal.Add("Selected Time To OOM", String.Format(SelectedRotation.RotationData.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", SelectedRotation.RotationData.TimeToOOM.Minutes, SelectedRotation.RotationData.TimeToOOM.Seconds));
            retVal.Add("Selected Cycle Length", String.Format("{0:F1} s", SelectedRotation.Duration));

            StringBuilder sb             = new StringBuilder("*");
            float         rotationDamage = SelectedRotation.RotationData.DPS * SelectedRotation.Duration;

            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount / rotationDamage,
                                        SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount,
                                        SelectedRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts / rotationDamage,
                                        (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts,
                                        SelectedRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * SelectedRotation.InsectSwarmAvgHit * SelectedRotation.InsectSwarmCasts / rotationDamage,
                                        SelectedRotation.InsectSwarmAvgHit * (SelectedRotation.InsectSwarmCasts),
                                        SelectedRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount / rotationDamage,
                                        SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount,
                                        SelectedRotation.WrathCount));

            retVal.Add("Selected Spell Breakdown", sb.ToString());
            retVal.Add("Burst Rotation", BurstDPSRotation.Name);
            retVal.Add("Burst DPS", String.Format("{0:F2}", BurstDPSRotation.RotationData.BurstDPS));
            retVal.Add("Burst Time To OOM", String.Format(BurstDPSRotation.RotationData.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", BurstDPSRotation.RotationData.TimeToOOM.Minutes, BurstDPSRotation.RotationData.TimeToOOM.Seconds));
            retVal.Add("Burst Cycle Length", String.Format("{0:F1} s", BurstDPSRotation.Duration));

            sb             = new StringBuilder("*");
            rotationDamage = BurstDPSRotation.RotationData.DPS * BurstDPSRotation.Duration;
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * BurstDPSRotation.StarfireAvgHit * BurstDPSRotation.StarfireCount / rotationDamage,
                                        BurstDPSRotation.StarfireAvgHit * BurstDPSRotation.StarfireCount,
                                        BurstDPSRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * BurstDPSRotation.MoonfireAvgHit * SelectedRotation.MoonfireCasts / rotationDamage,
                                        (BurstDPSRotation.MoonfireAvgHit) * BurstDPSRotation.MoonfireCasts,
                                        BurstDPSRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * BurstDPSRotation.InsectSwarmAvgHit * BurstDPSRotation.InsectSwarmCasts / rotationDamage,
                                        BurstDPSRotation.InsectSwarmAvgHit * BurstDPSRotation.InsectSwarmCasts,
                                        BurstDPSRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * BurstDPSRotation.WrathAvgHit * BurstDPSRotation.WrathCount / rotationDamage,
                                        BurstDPSRotation.WrathAvgHit * BurstDPSRotation.WrathCount,
                                        BurstDPSRotation.WrathCount));

            retVal.Add("Burst Spell Breakdown", sb.ToString());
            retVal.Add("Starfire", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} s w/NG\n{3:F2}% max non-Eclipse\n{4:F2}% max Eclipse\n{5:F2} avg hit\n{6:F0} avg mana",
                                                 SelectedRotation.StarfireAvgHit / (SelectedRotation.StarfireAvgCast > 0 ? SelectedRotation.StarfireAvgCast : 1f),
                                                 SelectedRotation.StarfireAvgCast,
                                                 SelectedRotation.StarfireNGCastTime,
                                                 100 * SelectedRotation.StarfireNonEclipseCrit,
                                                 100 * SelectedRotation.StarfireEclipseCrit,
                                                 SelectedRotation.StarfireAvgHit,
                                                 SelectedRotation.StarfireManaCost));
            retVal.Add("Wrath", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} s w/NG\n{3:F2} avg hit\n{4:F0} avg mana",
                                              SelectedRotation.WrathAvgHit / (SelectedRotation.WrathAvgCast > 0 ? SelectedRotation.WrathAvgCast : 1f),
                                              SelectedRotation.WrathAvgCast,
                                              SelectedRotation.WrathNGCastTime,
                                              SelectedRotation.WrathAvgHit,
                                              SelectedRotation.WrathManaCost));
            retVal.Add("Moonfire", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit\n{3:F0} avg mana",
                                                 SelectedRotation.MoonfireAvgHit / (SelectedRotation.MoonfireDuration > 0 ? SelectedRotation.MoonfireDuration : 1f),
                                                 SelectedRotation.MoonfireCastTime,
                                                 (SelectedRotation.MoonfireAvgHit),
                                                 SelectedRotation.MoonfireManaCost));
            retVal.Add("Insect Swarm", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit\n{3:F0} avg mana",
                                                     SelectedRotation.InsectSwarmAvgHit / (SelectedRotation.InsectSwarmDuration > 0 ? SelectedRotation.InsectSwarmDuration : 1f),
                                                     SelectedRotation.InsectSwarmCastTime,
                                                     SelectedRotation.InsectSwarmAvgHit,
                                                     SelectedRotation.InsectSwarmManaCost));
            retVal.Add("Starfall", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per star\n{3:F0} avg mana",
                                                 SelectedRotation.StarfallDamage / 10.0f,
                                                 SelectedRotation.StarfallDamage,
                                                 SelectedRotation.StarfallDamage / (SelectedRotation.StarfallStars > 0 ? SelectedRotation.StarfallStars : 1f),
                                                 StarfallMana));
            retVal.Add("Treants", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per tree",
                                                TreantDamage / 30.0f, TreantDamage, TreantDamage / 3.0f));

            return(retVal);
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();
            string format   = "";
            int    LevelDif = combatFactors.levelDif;

            // Base Stats
            dictValues.Add("Health and Stamina", string.Format("{0:##,##0} : {1:##,##0}*" +
                                                               "{2:00,000} : Base Health" +
                                                               "\r\n{3:00,000} : Stam Bonus",
                                                               AverageStats.Health, AverageStats.Stamina,
                                                               BaseHealth,
                                                               StatConversion.GetHealthFromStamina(AverageStats.Stamina)));
            dictValues.Add("Armor", string.Format("{0}*Increases Attack Power by {1}", Armor, TeethBonus));
            #region Strength
            {
                int    formIter  = 1;
                string theFormat = "";

                float[] passiveContrsVals = new float[] {
                    combatFactors.Char.WarriorTalents.StrengthOfArms * 0.02f,
                    (combatFactors.FuryStance ? combatFactors.Char.WarriorTalents.ImprovedBerserkerStance * 0.04f : 0f),
                    BuffsStats.Strength,
                    BuffsStats.BonusStrengthMultiplier,
                };

                string[] passiveContrs = new string[] {
                    "Strength of Arms",
                    "Improved Berserker Stance",
                    "Buffs : Simple",
                    "Buffs : Multi",
                };

                theFormat += "{0:0.#}*"; // Averaged % and Averaged Rating
                theFormat += "The Pane shows Averaged Values";
                theFormat += "\r\n";
                theFormat += "\r\n= Your Passive Contributions =";
                theFormat += "\r\n{" + formIter.ToString() + ":00.#%} : " + passiveContrs[0]; formIter++;
                theFormat += "\r\n{" + formIter.ToString() + ":00.#%} : " + passiveContrs[1]; formIter++;
                theFormat += "\r\n{" + formIter.ToString() + ":0.#} : " + passiveContrs[2]; formIter++;
                theFormat += "\r\n{" + formIter.ToString() + ":00.#%} : " + passiveContrs[3]; formIter++;
                theFormat += "\r\n";
                theFormat += "\r\n= UnProc'd =";
                theFormat += "\r\nValue: {" + formIter.ToString() + ":0.#}"; formIter++;
                theFormat += "\r\nIncreases Attack Power by {" + formIter.ToString() + ":0.#}"; formIter++;
                theFormat += "\r\n";
                theFormat += "\r\n= Proc'd =";
                theFormat += "\r\nValue: {" + formIter.ToString() + ":0.#}"; formIter++;
                theFormat += "\r\nIncreases Attack Power by {" + formIter.ToString() + ":0.#}"; formIter++;

                dictValues.Add("Strength", string.Format(theFormat,
                                                         // Averaged Stats
                                                         AverageStats.Strength,
                                                         // Passive Contributions
                                                         passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2], passiveContrsVals[3],
                                                         // UnProc'd Stats
                                                         BuffedStats.Strength,
                                                         BuffedStats.Strength * 2f,
                                                         // Proc'd Stats
                                                         MaximumStats.Strength,
                                                         MaximumStats.Strength * 2f
                                                         ));
            }
            #endregion
            dictValues.Add("Attack Power", string.Format("{0}*" +
                                                         "Increases White DPS by {1:0.0}\r\n" +
                                                         "\r\n" +
                                                         "Buffed: {2:0}\r\n" +
                                                         "Proc'd: {3:0}\r\n", (int)AverageStats.AttackPower, AverageStats.AttackPower / 14f,
                                                         BuffedStats.AttackPower, MaximumStats.AttackPower));
            #region Agility
            {
                int    formIter  = 1;
                string theFormat = "";

                float[] passiveContrsVals = new float[] {
                    BuffsStats.Agility,
                    BuffsStats.BonusAgilityMultiplier,
                };

                string[] passiveContrs = new string[] { "Buffs : Simple", "Buffs : Multi" };

                theFormat += "{0:0.#}*"; // Averaged % and Averaged Rating
                theFormat += "The Pane shows Averaged Values";
                theFormat += "\r\n";
                theFormat += "\r\n= Your Passive Contributions =";
                theFormat += "\r\n{" + formIter.ToString() + ":0.#} : " + passiveContrs[0]; formIter++;
                theFormat += "\r\n{" + formIter.ToString() + ":00.#%} : " + passiveContrs[1]; formIter++;
                theFormat += "\r\n";
                theFormat += "\r\n= UnProc'd =";
                theFormat += "\r\nIncreases Crit by {" + formIter.ToString() + ":0.#%}"; formIter++;
                theFormat += "\r\nIncreases Armor by {" + formIter.ToString() + ":0.#}"; formIter++;
                theFormat += "\r\n";
                theFormat += "\r\n= Proc'd =";
                theFormat += "\r\nIncreases Crit by {" + formIter.ToString() + ":0.#%}"; formIter++;
                theFormat += "\r\nIncreases Armor by {" + formIter.ToString() + ":0.#}"; formIter++;

                dictValues.Add("Agility", string.Format(theFormat,
                                                        // Averaged Stats
                                                        AverageStats.Agility,
                                                        // Passive Contributions
                                                        passiveContrsVals[0], passiveContrsVals[1],
                                                        // UnProc'd Stats
                                                        StatConversion.GetCritFromAgility(BuffedStats.Agility, CharacterClass.Warrior),
                                                        StatConversion.GetArmorFromAgility(BuffedStats.Agility),
                                                        // Proc'd Stats
                                                        StatConversion.GetCritFromAgility(MaximumStats.Agility, CharacterClass.Warrior),
                                                        StatConversion.GetArmorFromAgility(MaximumStats.Agility)
                                                        ));
            }
            #endregion
            #region Crit
            {
                // sub to add neg number as pos, for overcapping to compensate
                // for boss level on yellows (or whites, I dont remember which)
                // Whites clip crit cap with glances, dodges, parries, misses
                float WhCritCap = 1f;// +StatConversion.NPC_LEVEL_CRIT_MOD[LevelDif];
                //float YwCritCap = 1f + StatConversion.NPC_LEVEL_CRIT_MOD[LevelDif];
                if (combatFactors.useOH)
                {
                    WhCritCap -= (Whites.OHAtkTable.Glance + Whites.OHAtkTable.AnyNotLand);
                    //    YwCritCap -= (new AttackTable(combatFactors.Char, BuffedStats, combatFactors, combatFactors.CalcOpts, FW, false, false, false)).AnyNotLand;
                }
                else
                {
                    WhCritCap -= (Whites.MHAtkTable.Glance + Whites.MHAtkTable.AnyNotLand);
                    // Yellows clip crit cap with dodges, parries, misses
                    //    YwCritCap -= (new AttackTable(combatFactors.Char, BuffedStats, combatFactors, combatFactors.CalcOpts, FW, true, false, false)).AnyNotLand;
                }
                float useRamp = 0f;
                if (combatFactors.Char.WarriorTalents.Rampage > 0f)
                {
                    useRamp = 0.05f;
                }
                float[] passiveContrsVals = new float[] {
                    0.03192f,
                    AgilityCritBonus,
                    StatConversion.GetCritFromRating(BuffedStats.CritRating + BuffedStats.DeathbringerProc),
                    combatFactors.Char.WarriorTalents.Cruelty * 0.01f,
                    (combatFactors.FuryStance ? 0.03f : 0f),
                    (combatFactors.FuryStance ? AverageStats.BonusWarrior_T9_2P_Crit : 0f),
                    BonusCritPercPoleAxeSpec,
                    BuffsStats.PhysicalCrit + useRamp,
                };
                float passiveContrsTtlVal = passiveContrsVals[0] + passiveContrsVals[1] + passiveContrsVals[2]
                                            + passiveContrsVals[3] + passiveContrsVals[4] + passiveContrsVals[5]
                                            + passiveContrsVals[6] + passiveContrsVals[7];
                string[] passiveContrs = new string[] { "Base Crit", "From Agility", "From Crit Rating", "Cruelty",
                                                        "Berserker Stance", "T9 2P Set Bonus", "Poleaxe Specialization",
                                                        "Buffs" };

                //float WhUnProcdCrit = StatConversion.GetCritFromRating(BuffedStats.CritRating + BuffedStats.DeathbringerProc);
                float WhProcdCrit            = StatConversion.GetCritFromRating(MaximumStats.CritRating + MaximumStats.DeathbringerProc - BuffedStats.CritRating - BuffedStats.DeathbringerProc);
                bool  isWhUnProcdOverCap     = passiveContrsTtlVal > WhCritCap;
                bool  isWhProcdOverCap       = passiveContrsTtlVal + WhProcdCrit > WhCritCap;
                float amountWhUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(WhCritCap - passiveContrsTtlVal));
                float amountWhProcdOverCap   = Math.Abs(StatConversion.GetRatingFromCrit(WhCritCap - (passiveContrsTtlVal + WhProcdCrit)));

                float YwUnProcdCrit = StatConversion.GetCritFromRating(BuffedStats.CritRating + BuffedStats.DeathbringerProc);
                float YwProcdCrit   = StatConversion.GetCritFromRating(MaximumStats.CritRating + MaximumStats.DeathbringerProc);
                //bool isYwUnProcdOverCap = passiveContrsTtlVal + YwUnProcdCrit > YwCritCap;
                //bool isYwProcdOverCap = passiveContrsTtlVal + YwProcdCrit > YwCritCap;
                //float amountYwUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(YwCritCap - (passiveContrsTtlVal + YwUnProcdCrit)));
                //float amountYwProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(YwCritCap - (passiveContrsTtlVal + YwProcdCrit)));

                string theFormat = GenFormattedString(passiveContrs, true,
                                                      isWhUnProcdOverCap, isWhProcdOverCap
                                                      //isYwUnProcdOverCap, isYwProcdOverCap
                                                      );

                dictValues.Add("Crit", string.Format(theFormat,
                                                     // Averaged Stats
                                                     CritPercent, AverageStats.CritRating,
                                                     // Passive Contributions
                                                     passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                                     passiveContrsVals[3], passiveContrsVals[4], passiveContrsVals[5],
                                                     passiveContrsVals[6], passiveContrsVals[7],
                                                     // UnProc'd Stats
                                                     BuffedStats.CritRating + BuffedStats.DeathbringerProc,
                                                     Math.Min(WhCritCap, passiveContrsTtlVal), amountWhUnProcdOverCap,
                                                     //Math.Min(YwCritCap, passiveContrsTtlVal + YwUnProcdCrit), amountYwUnProcdOverCap,
                                                     // Proc'd Stats
                                                     MaximumStats.CritRating + MaximumStats.DeathbringerProc,
                                                     Math.Min(WhCritCap, passiveContrsTtlVal + WhProcdCrit), amountWhProcdOverCap
                                                     //Math.Min(YwCritCap, passiveContrsTtlVal + YwProcdCrit), amountYwProcdOverCap
                                                     ));
            }
            #endregion
            #region Armor Penetration
            {
                float   ArPCap            = 1.00f;
                float[] passiveContrsVals = new float[] {
                    (!combatFactors.FuryStance ? 0.10f : 0f),
                    (!combatFactors.FuryStance ? AverageStats.BonusWarrior_T9_2P_ArP : 0f),
                    ArmorPenetrationMaceSpec
                };
                float    passiveContrsTtlVal  = passiveContrsVals[0] + passiveContrsVals[1] + passiveContrsVals[2];
                string[] passiveContrs        = new string[] { "Battle Stance", "T9 2P Set Bonus", "Mace Specialization" };
                float    UnProcdArP           = StatConversion.GetArmorPenetrationFromRating(BuffedStats.ArmorPenetrationRating);
                float    ProcdArP             = StatConversion.GetArmorPenetrationFromRating(MaximumStats.ArmorPenetrationRating);
                bool     isUnProcdOverCap     = passiveContrsTtlVal + UnProcdArP > ArPCap;
                bool     isProcdOverCap       = passiveContrsTtlVal + ProcdArP > ArPCap;
                float    amountUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromArmorPenetration(ArPCap - (passiveContrsTtlVal + UnProcdArP)));
                float    amountProcdOverCap   = Math.Abs(StatConversion.GetRatingFromArmorPenetration(ArPCap - (passiveContrsTtlVal + ProcdArP)));
                string   theFormat            = GenFormattedString(passiveContrs, true, isUnProcdOverCap, isProcdOverCap);
                dictValues.Add("Armor Penetration", string.Format(theFormat,
                                                                  // Averaged Stats
                                                                  ArmorPenetration, AverageStats.ArmorPenetrationRating,
                                                                  // Passive Contributions
                                                                  passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                                                  // UnProc'd Stats
                                                                  BuffedStats.ArmorPenetrationRating,
                                                                  Math.Min(ArPCap, passiveContrsTtlVal + UnProcdArP),
                                                                  amountUnProcdOverCap,
                                                                  // Proc'd Stats
                                                                  MaximumStats.ArmorPenetrationRating,
                                                                  Math.Min(ArPCap, passiveContrsTtlVal + ProcdArP),
                                                                  amountProcdOverCap
                                                                  ));
            }
            #endregion
            #region Haste
            {
                // Haste has no cap? Shouldn't there be a 100% cap or something?
                // We should also state the before/after effects of haste on white swings
                // Maybe a good point to show how much swing time is lost to Slams too?
                float heroism = 0f;
                if (BuffsStats._rawSpecialEffectData != null)
                {
                    foreach (SpecialEffect effect in BuffsStats._rawSpecialEffectData)
                    {
                        if (effect != null && effect.Stats.PhysicalHaste > 0)
                        {
                            heroism = effect.GetAverageStats().PhysicalHaste;
                        }
                    }
                }
                float[] passiveContrsVals = new float[] {
                    combatFactors.Char.WarriorTalents.BloodFrenzy * 0.05f,
                        BuffsStats.PhysicalHaste,
                        heroism,
                };
                float passiveContrsTtlVal = (1f + passiveContrsVals[0])
                                            * (1f + passiveContrsVals[1])
                                            * (1f + passiveContrsVals[2])
                                            - 1f;
                string[] passiveContrs = new string[] { "Blood Frenzy", "Buffs", "Heroism (Averaged)" };
                float    UnProcdHaste  = StatConversion.GetHasteFromRating(BuffedStats.HasteRating, CharacterClass.Warrior);
                float    ProcdHaste    = StatConversion.GetHasteFromRating(MaximumStats.HasteRating, CharacterClass.Warrior);
                string   theFormat     = GenFormattedString(passiveContrs);

                dictValues.Add("Haste", string.Format(theFormat,
                                                      // Averaged Stats
                                                      HastePercent, AverageStats.HasteRating,
                                                      // Passive Contributions
                                                      passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                                      // UnProc'd Stats
                                                      BuffedStats.HasteRating,
                                                      (1f + passiveContrsTtlVal) * (1f + UnProcdHaste) - 1f,
                                                      // Proc'd Stats
                                                      MaximumStats.HasteRating,
                                                      (1f + passiveContrsTtlVal) * (1f + ProcdHaste) - 1f
                                                      ));
            }
            #endregion
            #region Hit
            {
                // old
                float HitPercent   = StatConversion.GetHitFromRating(HitRating);
                float HitPercBonus = AverageStats.PhysicalHit;
                // Hit Soft Cap ratings check, how far from it
                float capA1         = StatConversion.WHITE_MISS_CHANCE_CAP[LevelDif];
                float convcapA1     = (float)Math.Ceiling(StatConversion.GetRatingFromHit(capA1));
                float sec2lastNumA1 = (convcapA1 - StatConversion.GetRatingFromHit(HitPercent) - StatConversion.GetRatingFromHit(HitPercBonus)) * -1;
                //float lastNumA1    = StatConversion.GetRatingFromExpertise((convcapA1 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                // Hit Hard Cap ratings check, how far from it
                float capA2         = StatConversion.WHITE_MISS_CHANCE_CAP_DW[LevelDif];
                float convcapA2     = (float)Math.Ceiling(StatConversion.GetRatingFromHit(capA2));
                float sec2lastNumA2 = (convcapA2 - StatConversion.GetRatingFromHit(HitPercent) - StatConversion.GetRatingFromHit(HitPercBonus)) * -1;
                //float lastNumA2   = StatConversion.GetRatingFromExpertise((sec2lastNumA2 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                dictValues.Add("Hit",
                               string.Format("{0:00.00%} : {1}*" + "{2:0.00%} : From Other Bonuses" +
                                             "\r\n{3:0.00%} : Total Hit % Bonus" +
                                             "\r\n\r\nWhite Two-Hander Cap: " +
                                             (sec2lastNumA1 > 0 ? "You can free {4:0} Rating"
                                                       : "You need {4:0} more Rating") +
                                             "\r\nWhite Dual Wield Cap: " +
                                             (sec2lastNumA2 > 0 ? "You can free {5:0} Rating"
                                                       : "You need {5:0} more Rating"),
                                             StatConversion.GetHitFromRating(AverageStats.HitRating),
                                             AverageStats.HitRating,
                                             HitPercBonus,
                                             HitPercent + HitPercBonus,
                                             (sec2lastNumA1 > 0 ? sec2lastNumA1 : sec2lastNumA1 * -1),
                                             (sec2lastNumA2 > 0 ? sec2lastNumA2 : sec2lastNumA2 * -1)
                                             ));
            }
            #endregion
            #region Expertise
            {
                // Dodge Cap ratings check, how far from it, uses lesser of MH and OH
                // Also factors in Weapon Mastery
                float capB1         = StatConversion.YELLOW_DODGE_CHANCE_CAP[LevelDif] - WeapMastPerc;
                float convcapB1     = (float)Math.Ceiling(StatConversion.GetExpertiseFromDodgeParryReduc(capB1));
                float sec2lastNumB1 = (convcapB1 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1;
                float lastNumB1     = StatConversion.GetRatingFromExpertise((convcapB1 - WeapMastPerc - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                // Parry Cap ratings check, how far from it, uses lesser of MH and OH
                float capB2         = StatConversion.YELLOW_PARRY_CHANCE_CAP[LevelDif];
                float convcapB2     = (float)Math.Ceiling(StatConversion.GetExpertiseFromDodgeParryReduc(capB2));
                float sec2lastNumB2 = (convcapB2 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1;
                float lastNumB2     = StatConversion.GetRatingFromExpertise((convcapB2 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                dictValues.Add("Expertise",
                               string.Format("{0:00.00%} : {1:00.00} : {2}*" +
                                             "Following includes Racial bonus and Strength of Arms" +
                                             "\r\n{3:00.00%} Weapon Mastery (Dodge Only)" +
                                             "\r\n{4:00.00%} : {5:00.00} : MH" +
                                             "\r\n{6:00.00%} : {7:00.00} : OH" +
                                             "\r\n\r\n" + "Dodge Cap: " +
                                             (lastNumB1 > 0 ? "You can free {8:0} Expertise ({9:0} Rating)"
                                 : "You need {8:0} more Expertise ({9:0} Rating)") +
                                             "\r\n" + "Parry Cap: " +
                                             (lastNumB2 > 0 ? "You can free {10:0} Expertise ({11:0} Rating)"
                                 : "You need {10:0} more Expertise ({11:0} Rating)"),
                                             StatConversion.GetDodgeParryReducFromExpertise(Expertise),
                                             Expertise,
                                             AverageStats.ExpertiseRating,
                                             WeapMastPerc,
                                             StatConversion.GetDodgeParryReducFromExpertise(MhExpertise), MhExpertise,
                                             StatConversion.GetDodgeParryReducFromExpertise(OhExpertise), OhExpertise,
                                             (sec2lastNumB1 > 0 ? sec2lastNumB1 : sec2lastNumB1 * -1), (lastNumB1 > 0 ? lastNumB1 : lastNumB1 * -1),
                                             (sec2lastNumB2 > 0 ? sec2lastNumB2 : sec2lastNumB2 * -1), (lastNumB2 > 0 ? lastNumB2 : lastNumB2 * -1)
                                             ));
            }
            #endregion

            dictValues.Add("Description", string.Format("DPS : PerHit : #ActsD"));
            // DPS Abilities
            format = "{0:0000} : {1:00000} : {2:000.00}";
            if (TotalDPS < 0f)
            {
                TotalDPS = 0f;
            }
            foreach (Rawr.DPSWarr.Rotation.AbilWrapper aw in Rot.GetAbilityList())
            {
                if (!aw.ability.Name.Equals("Invalid"))
                {
                    dictValues.Add(aw.ability.Name, string.Format(format, aw.allDPS, aw.ability.DamageOnUse, aw.allNumActivates)
                                   + aw.ability.GenTooltip(aw.allNumActivates, aw.allDPS / TotalDPS));
                }
            }
            // DPS General
            dictValues.Add("White DPS", string.Format("{0:0000} : {1:00000}", WhiteDPS, WhiteDmg) + Whites.GenTooltip(WhiteDPSMH, WhiteDPSOH, TotalDPS));
            dictValues.Add("Deep Wounds", string.Format("{0:0000}*{1:00.0%} of DPS", Rot.DW.TickSize, Rot.DW.TickSize / TotalDPS));
            dictValues.Add("Special DMG Procs", string.Format("{0:0000}*{1:00.0%} of DPS", SpecProcDPS, SpecProcDPS / TotalDPS));
            dictValues.Add("Total DPS", string.Format("{0:#,##0} : {1:#,###,##0}*" + Rot.GCDUsage, TotalDPS, TotalDPS * Duration));
            // Rage
            format = "{0:0000}";
            dictValues.Add("Total Generated Rage", string.Format("{0:00} = {1:0} + {2:0}", WhiteRage + OtherRage, WhiteRage, OtherRage));
            dictValues.Add("Needed Rage for Abilities", string.Format(format, NeedyRage));
            dictValues.Add("Available Free Rage", string.Format(format, FreeRage));
#if (!RAWR3 && DEBUG)
            dictValues.Add("Calculation Time", string.Format("{0}", calculationTime));
#endif
            return(dictValues);
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            dictValues.Add("Health", BasicStats.Health.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Mana", BasicStats.Mana.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Attack Power", BasicStats.AttackPower.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Agility", BasicStats.Agility.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Strength", BasicStats.Strength.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Intellect", BasicStats.Intellect.ToString("F0", CultureInfo.InvariantCulture));

            dictValues.Add("White Hit", WhiteHit.ToString("F2", CultureInfo.InvariantCulture) + "%");
            if (YellowHit < 100f && TotalExpertiseMH < 26)
            {
                float ratingRequired = (float)Math.Ceiling(4f * StatConversion.GetRatingFromExpertise(100f - YellowHit));
                dictValues.Add("Yellow Hit", String.Format("{0}% (Under Cap)*You need {1} more expertise to cap specials (WF,SS)",
                                                           YellowHit.ToString("F2", CultureInfo.InvariantCulture),
                                                           ratingRequired.ToString("F0", CultureInfo.InvariantCulture)));
            }
            else
            {
                if (ParriedAttacks > 0)
                {
                    float ratingRequired = (float)Math.Ceiling(4f * StatConversion.GetRatingFromExpertise(100f - YellowHit));
                    dictValues.Add("Yellow Hit", String.Format("{0}%*Being in front of boss allows your attacks to be parried\r\nYou would need {1} more expertise to cap specials (WF,SS)",
                                                               YellowHit.ToString("F2", CultureInfo.InvariantCulture),
                                                               ratingRequired.ToString("F0", CultureInfo.InvariantCulture)));
                }
                else
                {
                    dictValues.Add("Yellow Hit", YellowHit.ToString("F2", CultureInfo.InvariantCulture) + "%");
                }
            }
            if (OverSpellHitCap > 0.38f) // only warn if more than .38% over cap (equivalent to 10 hit rating)
            {
                dictValues.Add("Spell Hit", String.Format("{0}% (Over Cap)*Over Spell Hit Cap by {1}%",
                                                          SpellHit.ToString("F2", CultureInfo.InvariantCulture),
                                                          OverSpellHitCap.ToString("F2", CultureInfo.InvariantCulture)));
            }
            else
            {
                if (SpellHit < 100f)
                {
                    float ratingRequired = (float)Math.Ceiling(StatConversion.GetRatingFromHit(1f - SpellHit / 100f));
                    dictValues.Add("Spell Hit", String.Format("{0}% (Under Cap)*You need {1} more hit rating to cap spells (ES, LB etc)",
                                                              SpellHit.ToString("F2", CultureInfo.InvariantCulture),
                                                              ratingRequired.ToString("F0", CultureInfo.InvariantCulture)));
                }
                else
                {
                    dictValues.Add("Spell Hit", SpellHit.ToString("F2", CultureInfo.InvariantCulture) + "%");
                }
            }
            if (OverMeleeCritCap > 0.21f) // only warn if more than .21% over cap (equivalent to 10 crit rating)
            {
                dictValues.Add("Melee Crit", String.Format("{0} (Over Cap)*Crit Rating {1} (+{2}% crit chance)\r\nOver Soft Cap by {3}%",
                                                           MeleeCrit.ToString("F2", CultureInfo.InvariantCulture) + "%",
                                                           BasicStats.CritRating.ToString("F0", CultureInfo.InvariantCulture),
                                                           (StatConversion.GetCritFromRating(BasicStats.CritRating) * 100f).ToString("F2", CultureInfo.InvariantCulture),
                                                           OverMeleeCritCap.ToString("F2", CultureInfo.InvariantCulture)));
            }
            else
            {
                dictValues.Add("Melee Crit", String.Format("{0}*Crit Rating {1} (+{2}% crit chance)",
                                                           MeleeCrit.ToString("F2", CultureInfo.InvariantCulture) + "%",
                                                           BasicStats.CritRating.ToString("F0", CultureInfo.InvariantCulture),
                                                           (StatConversion.GetCritFromRating(BasicStats.CritRating) * 100f).ToString("F2", CultureInfo.InvariantCulture)));
            }

            dictValues.Add("Spell Crit", String.Format("{0}*Crit Rating {1} (+{2}% crit chance)",
                                                       SpellCrit.ToString("F2", CultureInfo.InvariantCulture) + "%",
                                                       BasicStats.CritRating.ToString("F0", CultureInfo.InvariantCulture),
                                                       (StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f).ToString("F2", CultureInfo.InvariantCulture)));

            dictValues.Add("Spellpower", BasicStats.SpellPower.ToString("F0", CultureInfo.InvariantCulture));
            dictValues.Add("Total Expertise", getExpertiseString());
            dictValues.Add("Haste Rating", String.Format("{0}*{1}% Melee Haste\r\n{2}% Spell Haste",
                                                         BasicStats.HasteRating.ToString("F0", CultureInfo.InvariantCulture),
                                                         (StatConversion.GetHasteFromRating(BasicStats.HasteRating, CharacterClass.Shaman) * 100f).ToString("F2", CultureInfo.InvariantCulture),
                                                         (StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating, CharacterClass.Shaman) * 100f).ToString("F2", CultureInfo.InvariantCulture)));
            dictValues.Add("Hit Rating", String.Format("{0}*{1}% Melee Hit\r\n{2}% Spell Hit",
                                                       BasicStats.HitRating.ToString("F0", CultureInfo.InvariantCulture),
                                                       (StatConversion.GetHitFromRating(BasicStats.HitRating) * 100f).ToString("F2", CultureInfo.InvariantCulture),
                                                       (StatConversion.GetSpellHitFromRating(BasicStats.HitRating) * 100f).ToString("F2", CultureInfo.InvariantCulture)));
            dictValues.Add("Armour Pen Rating", String.Format("{0}*{1}% Armour Penetration",
                                                              BasicStats.ArmorPenetrationRating.ToString("F0", CultureInfo.InvariantCulture),
                                                              (StatConversion.GetArmorPenetrationFromRating(BasicStats.ArmorPenetrationRating) * 100f).ToString("F2", CultureInfo.InvariantCulture)));
            float spellMiss = 100 - SpellHit;

            dictValues.Add("Avoided Attacks", String.Format("{0}%*{1}% Boss Dodged\r\n{2}% Boss Parried\r\n{3}% Spell Misses\r\n{4}% White Misses",
                                                            AvoidedAttacks.ToString("F2", CultureInfo.InvariantCulture),
                                                            DodgedAttacks.ToString("F2", CultureInfo.InvariantCulture),
                                                            ParriedAttacks.ToString("F2", CultureInfo.InvariantCulture),
                                                            spellMiss.ToString("F2", CultureInfo.InvariantCulture),
                                                            MissedAttacks.ToString("F2", CultureInfo.InvariantCulture)));
            dictValues.Add("Avg MH Speed", AvMHSpeed.ToString("F2", CultureInfo.InvariantCulture));
            dictValues.Add("Avg OH Speed", AvOHSpeed.ToString("F2", CultureInfo.InvariantCulture));
            dictValues.Add("Armor Mitigation", ArmorMitigation.ToString("F2", CultureInfo.InvariantCulture) + "%*Amount of physical damage lost due to boss armor");

            dictValues.Add("ED Uptime", String.Format("{0}%*{1}% ED Bonus Crit",
                                                      EDUptime.ToString("F2", CultureInfo.InvariantCulture),
                                                      EDBonusCrit.ToString("F2", CultureInfo.InvariantCulture)));
            dictValues.Add("Flurry Uptime", FlurryUptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Avg Time to 5 Stack", String.Format("{0} sec*{1} PPM",
                                                                SecondsTo5Stack.ToString("F2", CultureInfo.InvariantCulture),
                                                                _MWPPM.ToString("F2", CultureInfo.InvariantCulture)));
            dictValues.Add("MH Enchant Uptime", MHEnchantUptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("OH Enchant Uptime", OHEnchantUptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Trinket 1 Uptime", Trinket1Uptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Trinket 2 Uptime", Trinket2Uptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Fire Totem Uptime", FireTotemUptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Tier 10 2 pc Uptime", T10_2Uptime.ToString("F2", CultureInfo.InvariantCulture) + "%");
            dictValues.Add("Tier 10 4 pc Uptime", T10_4Uptime.ToString("F2", CultureInfo.InvariantCulture) + "%");

            dictValues.Add("DPS Points", DPSPoints.ToString("F2", CultureInfo.InvariantCulture));
            dictValues.Add("Survivability Points", SurvivabilityPoints.ToString("F2", CultureInfo.InvariantCulture));
            dictValues.Add("Overall Points", OverallPoints.ToString("F2", CultureInfo.InvariantCulture));

            dictValues.Add("White Damage", dpsOutputFormat(SwingDamage, DPSPoints, true));
            dictValues.Add("Windfury Attack", dpsOutputFormat(WindfuryAttack, DPSPoints, true));
            dictValues.Add("Flametongue Attack", dpsOutputFormat(FlameTongueAttack, DPSPoints, false));
            dictValues.Add("Lightning Bolt", dpsOutputFormat(LightningBolt, DPSPoints, false));
            dictValues.Add("Earth Shock", dpsOutputFormat(EarthShock, DPSPoints, false));
            dictValues.Add("Flame Shock", dpsOutputFormat(FlameShock, DPSPoints, false));
            dictValues.Add("Searing/Magma Totem", dpsOutputFormat(SearingMagma, DPSPoints, false));
            dictValues.Add("Stormstrike", dpsOutputFormat(Stormstrike, DPSPoints, true));
            dictValues.Add("Spirit Wolf", dpsOutputFormat(SpiritWolf, DPSPoints, true));
            dictValues.Add("Fire Nova", dpsOutputFormat(FireNova, DPSPoints, false));
            dictValues.Add("Fire Elemental", FireElemental.getDPSOutput());
            dictValues.Add("Lightning Shield", dpsOutputFormat(LightningShield, DPSPoints, false));
            dictValues.Add("Lava Lash", dpsOutputFormat(LavaLash, DPSPoints, true));
            dictValues.Add("Total DPS", DPSPoints.ToString("F2", CultureInfo.InvariantCulture));

            dictValues.Add("Enhance Version", _version);

            dictValues.Add("Status", String.Format("Enhance Model : DPS Points {0}, Survivability Points {1}, Overall Points {2}",
                                                   DPSPoints.ToString("F2", CultureInfo.InvariantCulture),
                                                   SurvivabilityPoints.ToString("F2", CultureInfo.InvariantCulture),
                                                   OverallPoints.ToString("F2", CultureInfo.InvariantCulture)));

            return(dictValues);
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> retVal = new Dictionary <string, string>();

            //
            if (baseStats == null)
            {
                baseStats = new StatsMoonkin();
            }
            if (SelectedRotation == null)
            {
                SelectedRotation = new RotationData();
            }
            if (BurstRotation == null)
            {
                BurstRotation = new RotationData();
            }
            //
            retVal.Add("Health", baseStats.Health.ToString());
            retVal.Add("Mana", baseStats.Mana.ToString());
            retVal.Add("Armor", baseStats.Armor.ToString());
            retVal.Add("Agility", baseStats.Agility.ToString());
            retVal.Add("Stamina", baseStats.Stamina.ToString());
            retVal.Add("Intellect", baseStats.Intellect.ToString());
            retVal.Add("Spirit", baseStats.Spirit.ToString());
            retVal.Add("Spell Power", SpellPower.ToString());

            float totalHitDelta = SpellHitCap - SpellHit;

            retVal.Add("Spell Hit", String.Format("{0:F}%*{1} Hit Rating, {2:F}% Hit From Gear" + (totalHitDelta != 0 ? ", {3} Rating {4}" : ""),
                                                  100 * SpellHit,
                                                  baseStats.HitRating,
                                                  100 * StatConversion.GetSpellHitFromRating(baseStats.HitRating),
                                                  StatConversion.GetRatingFromHit(Math.Abs(totalHitDelta)),
                                                  totalHitDelta > 0 ? "To Cap" : "Over Cap"));
            retVal.Add("Spell Crit", String.Format("{0:F}%*{1} Crit Rating, {2:F}% Crit From Gear, {3:F}% Crit From Intellect",
                                                   100 * SpellCrit,
                                                   baseStats.CritRating,
                                                   100 * StatConversion.GetSpellCritFromRating(baseStats.CritRating),
                                                   100 * StatConversion.GetSpellCritFromIntellect(baseStats.Intellect)));
            retVal.Add("Spell Haste", String.Format("{0:F}%*{1} Haste Rating, {2:F}% Haste From Gear",
                                                    100 * SpellHaste,
                                                    baseStats.HasteRating,
                                                    100 * StatConversion.GetSpellHasteFromRating(baseStats.HasteRating)));
            retVal.Add("Mastery", String.Format("{0:F}*{1:F} Eclipse %, {2} Rating",
                                                Mastery,
                                                Mastery * 2.0f,
                                                baseStats.MasteryRating));
            retVal.Add("Mana Regen", String.Format("{0:F0}", ManaRegen * 5.0f));
            retVal.Add("Total Score", String.Format("{0:F2}", OverallPoints));
            retVal.Add("Selected Rotation", String.Format("*{0}", SelectedRotation.Name));
            retVal.Add("Selected DPS", String.Format("{0:F2}", SelectedRotation.SustainedDPS));
            retVal.Add("Selected Time To OOM", String.Format(SelectedRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", SelectedRotation.TimeToOOM.Minutes, SelectedRotation.TimeToOOM.Seconds));
            retVal.Add("Selected Cycle Length", String.Format("{0:F1} s", SelectedRotation.Duration));

            StringBuilder sb             = new StringBuilder("*");
            float         rotationDamage = SelectedRotation.SustainedDPS * SelectedRotation.Duration;

            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount / rotationDamage,
                                        SelectedRotation.StarfireAvgHit * SelectedRotation.StarfireCount,
                                        SelectedRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts / rotationDamage,
                                        (SelectedRotation.MoonfireAvgHit) * SelectedRotation.MoonfireCasts,
                                        SelectedRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * SelectedRotation.InsectSwarmAvgHit * SelectedRotation.InsectSwarmCasts / rotationDamage,
                                        SelectedRotation.InsectSwarmAvgHit * (SelectedRotation.InsectSwarmCasts),
                                        SelectedRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount / rotationDamage,
                                        SelectedRotation.WrathAvgHit * SelectedRotation.WrathCount,
                                        SelectedRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount / rotationDamage,
                                        SelectedRotation.StarSurgeAvgHit * SelectedRotation.StarSurgeCount,
                                        SelectedRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts / rotationDamage,
                                        SelectedRotation.StarfallDamage * SelectedRotation.StarfallCasts,
                                        SelectedRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts / rotationDamage,
                                        SelectedRotation.MushroomDamage * SelectedRotation.MushroomCasts,
                                        SelectedRotation.MushroomCasts));

            retVal.Add("Selected Spell Breakdown", sb.ToString());

            retVal.Add("Burst Rotation", String.Format("*{0}", BurstRotation.Name));
            retVal.Add("Burst DPS", String.Format("{0:F2}", BurstRotation.BurstDPS));
            retVal.Add("Burst Time To OOM", String.Format(BurstRotation.TimeToOOM > new TimeSpan(0, 0, 0) ? "{0} m {1} s" : "Not during fight", BurstRotation.TimeToOOM.Minutes, BurstRotation.TimeToOOM.Seconds));
            retVal.Add("Burst Cycle Length", String.Format("{0:F1} s", BurstRotation.Duration));

            sb             = new StringBuilder("*");
            rotationDamage = BurstRotation.BurstDPS * BurstRotation.Duration;
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfire", 100 * BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount / rotationDamage,
                                        BurstRotation.StarfireAvgHit * BurstRotation.StarfireCount,
                                        BurstRotation.StarfireCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Moonfire", 100 * (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts / rotationDamage,
                                        (BurstRotation.MoonfireAvgHit) * BurstRotation.MoonfireCasts,
                                        BurstRotation.MoonfireCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Insect Swarm", 100 * BurstRotation.InsectSwarmAvgHit * BurstRotation.InsectSwarmCasts / rotationDamage,
                                        BurstRotation.InsectSwarmAvgHit * (BurstRotation.InsectSwarmCasts),
                                        BurstRotation.InsectSwarmCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wrath", 100 * BurstRotation.WrathAvgHit * BurstRotation.WrathCount / rotationDamage,
                                        BurstRotation.WrathAvgHit * BurstRotation.WrathCount,
                                        BurstRotation.WrathCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starsurge", 100 * BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount / rotationDamage,
                                        BurstRotation.StarSurgeAvgHit * BurstRotation.StarSurgeCount,
                                        BurstRotation.StarSurgeCount));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Starfall", 100 * BurstRotation.StarfallDamage * BurstRotation.StarfallCasts / rotationDamage,
                                        BurstRotation.StarfallDamage * BurstRotation.StarfallCasts,
                                        BurstRotation.StarfallCasts));
            sb.AppendLine(String.Format("{0}: {1:F2}%, {2:F2} damage, {3:F0} count", "Wild Mushroom", 100 * BurstRotation.MushroomDamage * BurstRotation.MushroomCasts / rotationDamage,
                                        BurstRotation.MushroomDamage * BurstRotation.MushroomCasts,
                                        BurstRotation.MushroomCasts));

            retVal.Add("Burst Spell Breakdown", sb.ToString());

            retVal.Add("Nature's Grace Uptime", String.Format("{0:F2}%", SelectedRotation.NaturesGraceUptime * 100));
            retVal.Add("Solar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.SolarUptime * 100));
            retVal.Add("Lunar Eclipse Uptime", String.Format("{0:F2}%", SelectedRotation.LunarUptime * 100));

            retVal.Add("Starfire", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                                 SelectedRotation.StarfireAvgHit / (SelectedRotation.StarfireAvgCast > 0 ? SelectedRotation.StarfireAvgCast : 1f),
                                                 SelectedRotation.StarfireAvgCast,
                                                 SelectedRotation.StarfireAvgHit,
                                                 SelectedRotation.StarfireAvgEnergy));
            retVal.Add("Wrath", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                              SelectedRotation.WrathAvgHit / (SelectedRotation.WrathAvgCast > 0 ? SelectedRotation.WrathAvgCast : 1f),
                                              SelectedRotation.WrathAvgCast,
                                              SelectedRotation.WrathAvgHit,
                                              SelectedRotation.WrathAvgEnergy));
            retVal.Add("Starsurge", String.Format("{0:F2} dps*{1:F2} s avg\n {2:F2} avg hit\n{3:F0} avg energy",
                                                  SelectedRotation.StarSurgeAvgHit / (SelectedRotation.StarSurgeAvgCast > 0 ? SelectedRotation.StarSurgeAvgCast : 1f),
                                                  SelectedRotation.StarSurgeAvgCast,
                                                  SelectedRotation.StarSurgeAvgHit,
                                                  SelectedRotation.StarSurgeAvgEnergy));
            retVal.Add("Moonfire", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                                                 SelectedRotation.MoonfireAvgHit / (SelectedRotation.MoonfireDuration > 0 ? SelectedRotation.MoonfireDuration : 1f),
                                                 SelectedRotation.MoonfireAvgCast,
                                                 SelectedRotation.MoonfireAvgHit));
            retVal.Add("Insect Swarm", String.Format("{0:F2} dps*{1:F2} s avg\n{2:F2} avg hit",
                                                     SelectedRotation.InsectSwarmAvgHit / (SelectedRotation.InsectSwarmDuration > 0 ? SelectedRotation.InsectSwarmDuration : 1f),
                                                     SelectedRotation.InsectSwarmAvgCast,
                                                     SelectedRotation.InsectSwarmAvgHit));
            retVal.Add("Starfall", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per star",
                                                 SelectedRotation.StarfallDamage / 10.0f,
                                                 SelectedRotation.StarfallDamage,
                                                 SelectedRotation.StarfallDamage / (SelectedRotation.StarfallStars > 0 ? SelectedRotation.StarfallStars : 1f)));
            retVal.Add("Treants", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per tree",
                                                SelectedRotation.TreantDamage / 30.0f, SelectedRotation.TreantDamage, SelectedRotation.TreantDamage / 3.0f));
            retVal.Add("Wild Mushroom", String.Format("{0:F2} dps*{1:F2} avg per cast\n{2:F2} avg per mushroom",
                                                      SelectedRotation.MushroomDamage / 10.0f,
                                                      SelectedRotation.MushroomDamage,
                                                      SelectedRotation.MushroomDamage / 3f));

            return(retVal);
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            try {
                string format   = "";
                int    LevelDif = CombatFactors.LevelDif;

                // Base Stats
                #region Health & Stamina
                dictValues.Add("Health and Stamina", string.Format("{0:##,##0} : {1:##,##0}*" +
                                                                   "{2:00,000} : Base Health" +
                                                                   "\r\n{3:00,000} : Stam Bonus",
                                                                   AverageStats.Health, AverageStats.Stamina,
                                                                   BaseHealth,
                                                                   StatConversion.GetHealthFromStamina(AverageStats.Stamina)));
                #endregion
                dictValues.Add("Armor", string.Format("{0}", Armor));
                #region Strength
                {
                    int    formIter  = 1;
                    string theFormat = "";

                    float[] passiveContrsVals = new float[] {
                        BuffsStats.Strength,
                        BuffsStats.BonusStrengthMultiplier,
                        PlateSpecValid ? 0.05f : 0.00f,
                    };

                    string[] passiveContrs = new string[] {
                        "Buffs : Simple",
                        "Buffs : Multi",
                        "Plate Specialization",
                    };

                    theFormat += "{0:0.#}*"; // Averaged % and Averaged Rating
                    theFormat += "The Pane shows Averaged Values*";
                    //theFormat += "\r\n";
                    theFormat += "\r\n= Your Passive Contributions =";
                    theFormat += "\r\n{" + string.Format("{0}", formIter) + ":0.#} : " + passiveContrs[0]; formIter++;
                    theFormat += "\r\n{" + string.Format("{0}", formIter) + ":00.#%} : " + passiveContrs[1]; formIter++;
                    theFormat += "\r\n{" + string.Format("{0}", formIter) + ":00.#%} : " + passiveContrs[2]; formIter++;
                    theFormat += "\r\n";
                    theFormat += "\r\n= UnProc'd =";
                    theFormat += "\r\nValue: {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;
                    theFormat += "\r\nIncreases Attack Power by {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;
                    theFormat += "\r\n";
                    theFormat += "\r\n= Proc'd =";
                    theFormat += "\r\nValue: {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;
                    theFormat += "\r\nIncreases Attack Power by {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;

                    dictValues.Add("Strength", string.Format(theFormat,
                                                             // Averaged Stats
                                                             AverageStats.Strength,
                                                             // Passive Contributions
                                                             passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                                             // UnProc'd Stats
                                                             BuffedStats.Strength,
                                                             BuffedStats.Strength * 2f,
                                                             // Proc'd Stats
                                                             MaximumStats.Strength,
                                                             MaximumStats.Strength * 2f
                                                             ));
                }
                #endregion
                #region Attack Power
                dictValues.Add("Attack Power", string.Format("{0}*" +
                                                             "Increases White DPS by {1:0.0}\r\n" +
                                                             "\r\n" +
                                                             "Buffed: {2:0}\r\n" +
                                                             "Proc'd: {3:0}", (int)AverageStats.AttackPower, AverageStats.AttackPower / 14f,
                                                             BuffedStats.AttackPower, MaximumStats.AttackPower));
                #endregion
                #region Agility
                {
                    int    formIter  = 1;
                    string theFormat = "";

                    float[] passiveContrsVals = new float[] {
                        BuffsStats.Agility,
                        BuffsStats.BonusAgilityMultiplier,
                    };

                    string[] passiveContrs = new string[] { "Buffs : Simple", "Buffs : Multi" };

                    theFormat += "{0:0.#}*"; // Averaged % and Averaged Rating
                    theFormat += "The Pane shows Averaged Values*";
                    //theFormat += "\r\n";
                    theFormat += "\r\n= Your Passive Contributions =";
                    theFormat += "\r\n{" + string.Format("{0}", formIter) + ":0.#} : " + passiveContrs[0]; formIter++;
                    theFormat += "\r\n{" + string.Format("{0}", formIter) + ":00.#%} : " + passiveContrs[1]; formIter++;
                    theFormat += "\r\n";
                    theFormat += "\r\n= UnProc'd =";
                    theFormat += "\r\nIncreases Crit by {" + string.Format("{0}", formIter) + ":0.#%}"; formIter++;
                    //theFormat += "\r\nIncreases Armor by {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;
                    theFormat += "\r\n";
                    theFormat += "\r\n= Proc'd =";
                    theFormat += "\r\nIncreases Crit by {" + string.Format("{0}", formIter) + ":0.#%}"; formIter++;
                    //theFormat += "\r\nIncreases Armor by {" + string.Format("{0}", formIter) + ":0.#}"; formIter++;

                    dictValues.Add("Agility", string.Format(theFormat,
                                                                                                                                            // Averaged Stats
                                                            AverageStats.Agility,
                                                                                                                                            // Passive Contributions
                                                            passiveContrsVals[0], passiveContrsVals[1],
                                                                                                                                            // UnProc'd Stats
                                                            StatConversion.GetCritFromAgility(BuffedStats.Agility, CharacterClass.Warrior),
                                                                                                                                            //StatConversion.GetArmorFromAgility(BuffedStats.Agility),
                                                                                                                                            // Proc'd Stats
                                                            StatConversion.GetCritFromAgility(MaximumStats.Agility, CharacterClass.Warrior) //,
                                                                                                                                            //StatConversion.GetArmorFromAgility(MaximumStats.Agility)
                                                            ));
                }
                #endregion
                #region Crit
                {
                    // sub to add neg number as pos, for overcapping to compensate
                    // for boss level on yellows (or whites, I dont remember which)
                    // Whites clip crit cap with glances, dodges, parries, misses
                    float WhCritCap = 1f;// +StatConversion.NPC_LEVEL_CRIT_MOD[LevelDif];
                    //float YwCritCap = 1f + StatConversion.NPC_LEVEL_CRIT_MOD[LevelDif];
                    if (CombatFactors.useOH)
                    {
                        WhCritCap -= (Whites.OHAtkTable.Glance + Whites.OHAtkTable.AnyNotLand);
                        //    YwCritCap -= (new AttackTable(combatFactors.Char, BuffedStats, combatFactors, combatFactors.CalcOpts, FW, false, false, false)).AnyNotLand;
                    }
                    else
                    {
                        WhCritCap -= (Whites.MHAtkTable.Glance + Whites.MHAtkTable.AnyNotLand);
                        // Yellows clip crit cap with dodges, parries, misses
                        //    YwCritCap -= (new AttackTable(combatFactors.Char, BuffedStats, combatFactors, combatFactors.CalcOpts, FW, true, false, false)).AnyNotLand;
                    }
                    float useRamp = 0f;
                    if (CombatFactors.Char.WarriorTalents.Rampage > 0f)
                    {
                        useRamp = 0.05f + 0.02f;
                    }
                    float[] passiveContrsVals = new float[] {
                        0.03192f,
                        AgilityCritBonus,
                        StatConversion.GetCritFromRating(BuffedStats.CritRating),
                        BuffsStats.PhysicalCrit + useRamp,
                    };
                    float passiveContrsTtlVal = passiveContrsVals[0] + passiveContrsVals[1]
                                                + passiveContrsVals[2] + passiveContrsVals[3];
                    string[] passiveContrs = new string[] { "Base Crit", "From Agility", "From Crit Rating", "Buffs" };

                    //float WhUnProcdCrit = StatConversion.GetCritFromRating(BuffedStats.CritRating + BuffedStats.DeathbringerProc);
                    float WhProcdCrit            = StatConversion.GetCritFromRating(MaximumStats.CritRating - BuffedStats.CritRating);
                    bool  isWhUnProcdOverCap     = passiveContrsTtlVal > WhCritCap;
                    bool  isWhProcdOverCap       = passiveContrsTtlVal + WhProcdCrit > WhCritCap;
                    float amountWhUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(WhCritCap - passiveContrsTtlVal));
                    float amountWhProcdOverCap   = Math.Abs(StatConversion.GetRatingFromCrit(WhCritCap - (passiveContrsTtlVal + WhProcdCrit)));

                    //float YwUnProcdCrit = StatConversion.GetCritFromRating(BuffedStats.CritRating + BuffedStats.DeathbringerProc);
                    //float YwProcdCrit = StatConversion.GetCritFromRating(MaximumStats.CritRating + MaximumStats.DeathbringerProc);
                    //bool isYwUnProcdOverCap = passiveContrsTtlVal + YwUnProcdCrit > YwCritCap;
                    //bool isYwProcdOverCap = passiveContrsTtlVal + YwProcdCrit > YwCritCap;
                    //float amountYwUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(YwCritCap - (passiveContrsTtlVal + YwUnProcdCrit)));
                    //float amountYwProcdOverCap = Math.Abs(StatConversion.GetRatingFromCrit(YwCritCap - (passiveContrsTtlVal + YwProcdCrit)));

                    string theFormat = GenFormattedString(passiveContrs, true,
                                                          isWhUnProcdOverCap, isWhProcdOverCap
                                                          //isYwUnProcdOverCap, isYwProcdOverCap
                                                          );

                    dictValues.Add("Crit", string.Format(theFormat,
                                                         // Averaged Stats
                                                         CritPercent, AverageStats.CritRating,
                                                         // Passive Contributions
                                                         passiveContrsVals[0], passiveContrsVals[1],
                                                         passiveContrsVals[2], passiveContrsVals[3],
                                                         // UnProc'd Stats
                                                         BuffedStats.CritRating,
                                                         Math.Min(WhCritCap, passiveContrsTtlVal), amountWhUnProcdOverCap,
                                                         //Math.Min(YwCritCap, passiveContrsTtlVal + YwUnProcdCrit), amountYwUnProcdOverCap,
                                                         // Proc'd Stats
                                                         MaximumStats.CritRating,
                                                         Math.Min(WhCritCap, passiveContrsTtlVal + WhProcdCrit), amountWhProcdOverCap
                                                         //Math.Min(YwCritCap, passiveContrsTtlVal + YwProcdCrit), amountYwProcdOverCap
                                                         ));
                }
                #endregion
                #region Armor Penetration
                {
                    //float ArPCap = 1.00f;
                    //float[] passiveContrsVals = new float[] { 1.00f };
                    //float passiveContrsTtlVal = passiveContrsVals[0];
                    //string[] passiveContrs = new string[] { "Colossus Smash (6 sec/20 sec). Sudden Death resets cooldown sooner." };
                    //float UnProcdArP = StatConversion.GetArmorPenetrationFromRating(BuffedStats.ArmorPenetrationRating);
                    //float ProcdArP = StatConversion.GetArmorPenetrationFromRating(MaximumStats.ArmorPenetrationRating);
                    //bool isUnProcdOverCap = passiveContrsTtlVal + UnProcdArP > ArPCap;
                    //bool isProcdOverCap = passiveContrsTtlVal + ProcdArP > ArPCap;
                    //float amountUnProcdOverCap = Math.Abs(StatConversion.GetRatingFromArmorPenetration(ArPCap - (passiveContrsTtlVal + UnProcdArP)));
                    //float amountProcdOverCap = Math.Abs(StatConversion.GetRatingFromArmorPenetration(ArPCap - (passiveContrsTtlVal + ProcdArP)));
                    //string theFormat = GenFormattedString(passiveContrs, true, isUnProcdOverCap, isProcdOverCap);
                    dictValues.Add("Armor Penetration", string.Format("{0:0%}",                                        //theFormat,
                                                                                                                       // Averaged Stats
                                                                      ArmorPenetration + AverageStats.ArmorPenetration //, AverageStats.ArmorPenetrationRating,
                                                                                                                       // Passive Contributions
                                                                                                                       //passiveContrsVals[0],
                                                                                                                       // UnProc'd Stats
                                                                                                                       //BuffedStats.ArmorPenetrationRating,
                                                                                                                       //Math.Min(ArPCap, passiveContrsTtlVal + UnProcdArP),
                                                                                                                       //amountUnProcdOverCap,
                                                                                                                       // Proc'd Stats
                                                                                                                       //MaximumStats.ArmorPenetrationRating,
                                                                                                                       //Math.Min(ArPCap, passiveContrsTtlVal + ProcdArP),
                                                                                                                       //amountProcdOverCap
                                                                      ));
                }
                #endregion
                #region Haste
                {
                    // Haste has no cap? Shouldn't there be a 100% cap or something?
                    // We should also state the before/after effects of haste on white swings
                    // Maybe a good point to show how much swing time is lost to Slams too?
                    float heroism = 0f;
                    if (BuffsStats._rawSpecialEffectData != null)
                    {
                        foreach (SpecialEffect effect in BuffsStats._rawSpecialEffectData)
                        {
                            if (effect != null && effect.Stats.PhysicalHaste > 0)
                            {
                                heroism = effect.GetAverageStats().PhysicalHaste;
                            }
                        }
                    }
                    float[] passiveContrsVals = new float[] {
                        CombatFactors.Char.WarriorTalents.BloodFrenzy * 0.025f,
                            BuffsStats.PhysicalHaste,
                            heroism,
                    };
                    float passiveContrsTtlVal = (1f + passiveContrsVals[0])
                                                * (1f + passiveContrsVals[1])
                                                * (1f + passiveContrsVals[2])
                                                - 1f;
                    string[] passiveContrs = new string[] { "Blood Frenzy", "Buffs", "Heroism (Averaged)" };
                    float    UnProcdHaste  = StatConversion.GetHasteFromRating(BuffedStats.HasteRating, CharacterClass.Warrior);
                    float    ProcdHaste    = StatConversion.GetHasteFromRating(MaximumStats.HasteRating, CharacterClass.Warrior);
                    string   theFormat     = GenFormattedString(passiveContrs);

                    dictValues.Add("Haste", string.Format(theFormat,
                                                          // Averaged Stats
                                                          HastePercent, AverageStats.HasteRating,
                                                          // Passive Contributions
                                                          passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                                          // UnProc'd Stats
                                                          BuffedStats.HasteRating,
                                                          (1f + passiveContrsTtlVal) * (1f + UnProcdHaste) - 1f,
                                                          // Proc'd Stats
                                                          MaximumStats.HasteRating,
                                                          (1f + passiveContrsTtlVal) * (1f + ProcdHaste) - 1f
                                                          ));
                }
                #endregion
                #region Hit
                {
                    // old
                    float HitPercent   = StatConversion.GetHitFromRating(HitRating);
                    float HitPercBonus = AverageStats.PhysicalHit;
                    // Hit Soft Cap ratings check, how far from it
                    float capA1         = StatConversion.WHITE_MISS_CHANCE_CAP[LevelDif];
                    float convcapA1     = (float)Math.Ceiling(StatConversion.GetRatingFromHit(capA1));
                    float sec2lastNumA1 = (convcapA1 - StatConversion.GetRatingFromHit(HitPercent) - StatConversion.GetRatingFromHit(HitPercBonus)) * -1;
                    //float lastNumA1    = StatConversion.GetRatingFromExpertise((convcapA1 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                    // Hit Hard Cap ratings check, how far from it
                    float capA2         = StatConversion.WHITE_MISS_CHANCE_CAP_DW[LevelDif];
                    float convcapA2     = (float)Math.Ceiling(StatConversion.GetRatingFromHit(capA2));
                    float sec2lastNumA2 = (convcapA2 - StatConversion.GetRatingFromHit(HitPercent) - StatConversion.GetRatingFromHit(HitPercBonus)) * -1;
                    //float lastNumA2   = StatConversion.GetRatingFromExpertise((sec2lastNumA2 - Math.Min(MhExpertise, (OhExpertise != 0 ? OhExpertise : MhExpertise))) * -1);
                    dictValues.Add("Hit",
                                   string.Format("{0:000.00%} : {1}*" + "{2:0.00%} : From Other Bonuses" +
                                                 "\r\n{3:0.00%} : Total Hit % Bonus" +
                                                 "\r\n\r\nWhite Two-Hander Cap: " +
                                                 (sec2lastNumA1 > 0 ? "You can free {4:0} Rating"
                                                           : "You need {4:0} more Rating") +
                                                 "\r\nWhite Dual Wield Cap: " +
                                                 (sec2lastNumA2 > 0 ? "You can free {5:0} Rating"
                                                           : "You need {5:0} more Rating"),
                                                 StatConversion.GetHitFromRating(AverageStats.HitRating),
                                                 AverageStats.HitRating,
                                                 HitPercBonus,
                                                 HitPercent + HitPercBonus,
                                                 (sec2lastNumA1 > 0 ? sec2lastNumA1 : sec2lastNumA1 * -1),
                                                 (sec2lastNumA2 > 0 ? sec2lastNumA2 : sec2lastNumA2 * -1)
                                                 ));
                }
                #endregion
                #region Expertise
                {
                    // Dodge Cap ratings check, how far from it, uses lesser of MH and OH
                    // Also factors in Weapon Mastery
                    float capB1         = StatConversion.YELLOW_DODGE_CHANCE_CAP[LevelDif];
                    float convcapB1     = (float)Math.Ceiling(StatConversion.GetExpertiseFromDodgeParryReduc(capB1));
                    float sec2lastNumB1 = (convcapB1 - Math.Min(MHExpertise, (OHExpertise != 0 ? OHExpertise : MHExpertise))) * -1;
                    float lastNumB1     = StatConversion.GetRatingFromExpertise((convcapB1 - Math.Min(MHExpertise, (OHExpertise != 0 ? OHExpertise : MHExpertise))) * -1);
                    // Parry Cap ratings check, how far from it, uses lesser of MH and OH
                    float capB2         = StatConversion.YELLOW_PARRY_CHANCE_CAP[LevelDif];
                    float convcapB2     = (float)Math.Ceiling(StatConversion.GetExpertiseFromDodgeParryReduc(capB2));
                    float sec2lastNumB2 = (convcapB2 - Math.Min(MHExpertise, (OHExpertise != 0 ? OHExpertise : MHExpertise))) * -1;
                    float lastNumB2     = StatConversion.GetRatingFromExpertise((convcapB2 - Math.Min(MHExpertise, (OHExpertise != 0 ? OHExpertise : MHExpertise))) * -1);
                    dictValues.Add("Expertise",
                                   string.Format("{0:000.00%} : {1:00.00} : {2}*" +
                                                 "Following includes Racial bonus" +
                                                 "\r\n{3:00.00%} : {4:00.00} : MH" +
                                                 "\r\n{5:00.00%} : {6:00.00} : OH" +
                                                 "\r\n\r\n" + "Dodge Cap: " +
                                                 (lastNumB1 > 0 ? "You can free {7:0} Expertise ({8:0} Rating)"
                                     : "You need {7:0} more Expertise ({8:0} Rating)") +
                                                 "\r\n" + "Parry Cap: " +
                                                 (lastNumB2 > 0 ? "You can free {9:0} Expertise ({10:0} Rating)"
                                     : "You need {9:0} more Expertise ({10:0} Rating)"),
                                                 StatConversion.GetDodgeParryReducFromExpertise(Expertise),
                                                 Expertise,
                                                 AverageStats.ExpertiseRating,
                                                 StatConversion.GetDodgeParryReducFromExpertise(MHExpertise), MHExpertise,
                                                 StatConversion.GetDodgeParryReducFromExpertise(OHExpertise), OHExpertise,
                                                 (sec2lastNumB1 > 0 ? sec2lastNumB1 : sec2lastNumB1 * -1), (lastNumB1 > 0 ? lastNumB1 : lastNumB1 * -1),
                                                 (sec2lastNumB2 > 0 ? sec2lastNumB2 : sec2lastNumB2 * -1), (lastNumB2 > 0 ? lastNumB2 : lastNumB2 * -1)
                                                 ));
                }
                #endregion
                #region Mastery
                {
                    dictValues.Add("Mastery",
                                   string.Format("{0:000.00} : {1:00.00}*" + "The Pane shows Averaged Values*", MasteryVal, AverageStats.MasteryRating)
                                   + (CombatFactors.FuryStance ?
                                      string.Format(
                                          @"As a Fury Warrior, you are being granted the Unshackled Fury ability.
Increases the benefit of abilities that cause or require you to be enraged by (44.8%+{0:0.0%}={1:0.0%}).
Each point of Mastery increases enrage effects by an additional 5.60%.

Also, it is changing the following:
Increases the Weapon Damage of Raging Blow
Increases the damage bonus of Death Wish and Enrage
Increases the healing of Enraged Regeneration
Increases the Rage generated by Berserker Rage through Glyph of Berserker Rage
(Might increase rage generation through damage taken with Berserker Rage active,
I'm not sure, and it's a bit hard for me to test, any input on this would be appreciated.)",
                                          MasteryVal * 0.056f, 8f * 0.056f + MasteryVal * 0.056f)
                         :
                                      string.Format(
                                          @"As an Arms Warrior, you are being granted the Strikes of Opportunity ability.
Grants a (16%+{0:0.0%}={1:0.0%}) chance for your melee attacks to instantly
trigger an additional melee attack for {2:0%} normal damage. Each point of
Mastery increases this chance by 2%.",
                                          MasteryVal * Skills.StrikesOfOpportunity.BonusChance,
                                          Skills.StrikesOfOpportunity.BaseChance + MasteryVal * Skills.StrikesOfOpportunity.BonusChance,
                                          Skills.StrikesOfOpportunity.DamageModifier)
                                      )

                                   /*// Averaged Stats
                                    * AverageStats.Mastery,
                                    * // Passive Contributions
                                    * passiveContrsVals[0], passiveContrsVals[1], passiveContrsVals[2],
                                    * // UnProc'd Stats
                                    * BuffedStats.Mastery,
                                    * BuffedStats.Mastery * 2f,
                                    * // Proc'd Stats
                                    * MaximumStats.Mastery,
                                    * StatConversion.GetMasteryFromRating MaximumStats.Mastery * 2f*/
                                   );
                }
                #endregion

                dictValues.Add("Description 1", string.Format("DPS  : PerHit  : #ActsD"));
                dictValues.Add("Description 2", string.Format("DPS  : PerHit  : #ActsD"));
                dictValues.Add("Description 3", string.Format("DPS  : PerHit  : #ActsD"));
                // DPS Abilities
                format = "{0:0000} : {1:00000} : {2:000.00}";
                if (TotalDPS < 0f)
                {
                    TotalDPS = 0f;
                }
                foreach (AbilityWrapper aw in Rot.TheAbilityList)
                {
                    if (aw.Ability is Skills.Rend)
                    {
                        AbilityWrapper TH     = Rot.GetWrapper <Skills.ThunderClap>();
                        Skills.Rend    rend   = (aw.Ability as Skills.Rend);
                        float          DPSO20 = rend.GetDPS(aw.NumActivatesO20, TH.NumActivatesO20, rend.TimeOver20Perc);
                        float          DPSU20 = rend.GetDPS(aw.NumActivatesU20, TH.NumActivatesU20, rend.TimeUndr20Perc);
                        float          allDPS = DPSU20 > 0 ? DPSO20 * rend.TimeOver20Perc + DPSU20 * rend.TimeUndr20Perc : DPSO20; // Average above and below
                        dictValues.Add(aw.Ability.Name, string.Format(format, allDPS, rend.TickSize * rend.NumTicks, aw.AllNumActivates)
                                       + rend.GenTooltip(aw.AllNumActivates, DPSO20, DPSU20, allDPS / TotalDPS));
                    }
                    else
                    {
                        dictValues.Add(aw.Ability.Name, string.Format(format, aw.AllDPS, aw.Ability.DamageOnUse, aw.AllNumActivates)
                                       + aw.Ability.GenTooltip(aw.AllNumActivates, aw.DPS_O20, aw.DPS_U20, aw.AllDPS / TotalDPS));
                    }
                }
                // DPS General
                dictValues.Add("Deep Wounds", string.Format("{0:0000}*{1:00.0%} of DPS", Rot.DW.TickSize, Rot.DW.TickSize <= 0f || TotalDPS <= 0f ? 0f : Rot.DW.TickSize / TotalDPS));
                dictValues.Add("Special DMG Procs", string.Format("{0:0000} : {1:00000} : {2:000.00}*{3:00.0%} of DPS",
                                                                  SpecProcDPS, SpecProcDmgPerHit, SpecProcActs,
                                                                  SpecProcDPS <= 0f || TotalDPS <= 0f ? 0f : SpecProcDPS / TotalDPS));
                dictValues.Add("White DPS", string.Format("{0:0000} : {1:00000} : {2:000.00}", WhiteDPS, WhiteDmg, Whites.MHActivatesAll + Whites.OHActivatesAll)
                               + Whites.GenTooltip(WhiteDPSMH, WhiteDPSOH, TotalDPS, WhiteDPSMH_U20, WhiteDPSOH_U20));
                dictValues.Add("Total DPS", string.Format("{0:#,##0} : {1:#,###,##0}*" + ((!string.IsNullOrEmpty(Rot.GCDUsage) ? Rot.GCDUsage : "No GCD Usage*") + (CombatFactors.FuryStance ? "Fury isn't Cata Ready" : "")), TotalDPS, TotalDPS * Duration));
                // Rage
                format = "{0:0000}";
                dictValues.Add("Description 4", string.Format("Gen'd: Need : Avail"));
                dictValues.Add("Rage Above 20%", string.Format("{0:0000} : {1:0000} : {2:0000}", WhiteRageO20 + OtherRageO20, NeedyRageO20, FreeRageO20));
                dictValues.Add("Rage Below 20%", string.Format("{0:0000} : {1:0000} : {2:0000}", WhiteRageU20 + OtherRageU20, NeedyRageU20, FreeRageU20));
            } catch (Exception ex) {
                new Base.ErrorBox()
                {
                    Title        = "Error in creating Stat Pane Dictionaries",
                    Function     = "GetCharacterDisplayCalculationValues()",
                    TheException = ex,
                }.Show();
            }
            return(dictValues);
        }
Exemple #6
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();

            //string format = "";
            CalcOpts = character.CalculationOptions as CalculationOptionsHunter;

            // Basic Stats
            dictValues.Add("Health and Stamina", string.Format("{0:##,##0} : {1:##,##0}*{2:00,000} : Base Health" +
                                                               "\r\n{3:00,000} : Stam Bonus",
                                                               BasicStats.Health, BasicStats.Stamina, BaseHealth, StatConversion.GetHealthFromStamina(BasicStats.Stamina)));
            dictValues.Add("Mana", BasicStats.Mana.ToString("F0"));
            dictValues.Add("Armor", BasicStats.Armor.ToString("F0"));
            dictValues.Add("Agility", BasicStats.Agility.ToString("F0"));
            dictValues.Add("Ranged Attack Power", string.Format("{0:0000}*Includes:" +
                                                                "\r\n{1:0000} : Base" +
                                                                "\r\n{2:0000} : Agility" +
                                                                "\r\n{3:0000} : Gear" +
                                                                "\r\nProcs were averaged out and added",
                                                                apTotal, apFromBase, apFromAGI, apFromGear));
            dictValues.Add("Intellect", BasicStats.Intellect.ToString("F0"));
            // old
            float HitPercent   = StatConversion.GetHitFromRating(BasicStats.HitRating);
            float HitPercBonus = BasicStats.PhysicalHit - HitPercent;

            // Hit Soft Cap ratings check, how far from it
#if RAWR3 || SILVERLIGHT
            float capA1 = StatConversion.WHITE_MISS_CHANCE_CAP[BossOpts.Level - character.Level];
#else
            float capA1 = StatConversion.WHITE_MISS_CHANCE_CAP[CalcOpts.TargetLevel - character.Level];
#endif
            float convcapA1     = (float)Math.Ceiling(StatConversion.GetRatingFromHit(capA1));
            float sec2lastNumA1 = (convcapA1 - StatConversion.GetRatingFromHit(HitPercent) - StatConversion.GetRatingFromHit(HitPercBonus)) * -1;
            dictValues.Add("Hit",
                           string.Format("{0:00.00%} : {1}*" + "{2:0.00%} : From Other Bonuses" +
                                         Environment.NewLine + "{3:0.00%} : Total Hit % Bonus" +
                                         Environment.NewLine + Environment.NewLine + "Ranged Cap: " +
                                         (sec2lastNumA1 > 0 ? "You can free {4:0} Rating"
                                                   : "You need {4:0} more Rating"),
                                         StatConversion.GetHitFromRating(BasicStats.HitRating),
                                         BasicStats.HitRating,
                                         HitPercBonus,
                                         HitPercent + HitPercBonus,
                                         (sec2lastNumA1 > 0 ? sec2lastNumA1 : sec2lastNumA1 * -1)
                                         ));
            dictValues.Add("Crit", string.Format("{0:00.00%} : {1}*Includes:" +
                                                 "\r\n{2:00.00%} : Base Crit" +
                                                 "\r\n{3:00.00%} : Agility" +
                                                 "\r\n{4:00.00%} : Rating" +
                                                 "\r\n{5:00.00%} : Racial" +
                                                 "\r\n{6:00.00%} : Proc Effects" +
                                                 "\r\n{7:00.00%} : Lethal Shots" +
                                                 "\r\n{8:00.00%} : Killer Instincts" +
                                                 "\r\n{9:00.00%} : Master Marksman" +
                                                 "\r\n{10:00.00%} : Master Tactician" +
                                                 "\r\n{11:00.00%} : Buffs & Debuffs" +
                                                 "\r\n{12:00.00%} : Level Adjustment" +
                                                 "\r\n\r\nNote that individual Shots will handle their own crit caps",
                                                 critRateOverall, BasicStats.CritRating,
                                                 critBase, critFromAgi, critFromRating, critFromRacial,
                                                 critFromProcRating, critFromLethalShots, critFromKillerInstincts,
                                                 critFromMasterMarksman, critFromMasterTactician, critFromBuffs,
                                                 critFromDepression * -1f));
            dictValues.Add("Armor Penetration", string.Format("{0:00.00%} : {1}" + "*Enemy's Damage Reduction from armor: {2:00.00%}",
                                                              StatConversion.GetArmorPenetrationFromRating(BasicStats.ArmorPenetrationRating),
                                                              BasicStats.ArmorPenetrationRating,
                                                              damageReductionFromArmor));
            dictValues.Add("Haste", string.Format("{0:00.00%} : {1:0}*Includes:" +
                                                  "\r\n{2:00.00%} : Base" +
                                                  "\r\n{3:00.00%} : Rating" +
                                                  "\r\n{4:00.00%} : Serpent's Swiftness" +
                                                  "\r\n{5:00.00%} : Buffs" +
                                                  "\r\n{6:00.00%} : Rapid Fire" +
                                                  "\r\n{7:00.00%} : Proc Effects",
                                                  BasicStats.PhysicalHaste, BasicStats.HasteRating,
                                                  hasteFromBase, hasteFromRating, hasteFromTalentsStatic, hasteFromRangedBuffs,
                                                  hasteFromRapidFire, hasteFromProcs));
            dictValues.Add("Attack Speed", BaseAttackSpeed.ToString("F2"));

            // Pet Stats
            dictValues.Add("Pet Attack Power", pet.PetStats.AttackPower.ToString("F0") +
                           string.Format("*Full Pet Stats:\r\n"
                                         + "Strength: {0:0.0}\r\n"
                                         + "Agility: {1:0.0}\r\n"
                                         + "Hit: {2:0.00%}\r\n"
                                         + "PhysCrit: {3:0.00%}\r\n"
                                         + "PhysHaste: {4:0.00%}\r\n",
                                         pet.PetStats.Strength,
                                         pet.PetStats.Agility,
                                         pet.PetStats.PhysicalHit,
                                         pet.PetStats.PhysicalCrit,
                                         pet.PetStats.PhysicalHaste));
            dictValues.Add("Pet Hit %", petHitTotal.ToString("P2"));
            dictValues.Add("Pet Dodge %", petTargetDodge.ToString("P2"));
            dictValues.Add("Pet Melee Crit %", petCritTotalMelee.ToString("P2") + "*includes:\n" +
                           petCritFromBase.ToString("P2") + " from base\n" +
                           petCritFromAgility.ToString("P2") + " from agility\n" +
                           petCritFromSpidersBite.ToString("P2") + " from Spider's Bite\n" +
                           petCritFromFerocity.ToString("P2") + " from Ferocity\n" +
                           petCritFromGear.ToString("P2") + " from gear\n" +
                           petCritFromBuffs.ToString("P2") + " from buffs\n" +
                           petCritFromTargetDebuffs.ToString("P2") + " from target debuffs\n" +
                           petCritFromDepression.ToString("P2") + " from depression");
            dictValues.Add("Pet Specials Crit %", petCritTotalSpecials.ToString("P2") + "*includes:\n" +
                           petCritTotalMelee.ToString("P2") + " from melee crit\n" +
                           petCritFromCobraStrikes.ToString("P2") + " from Cobra Strikes");
            dictValues.Add("Pet White DPS", petWhiteDPS.ToString("F2"));
            dictValues.Add("Pet Kill Command DPS", petKillCommandDPS.ToString("F2"));
            dictValues.Add("Pet Specials DPS", petSpecialDPS.ToString("F2") /*+
                                                                             * string.Format("Breakout:\r\n"
                                                                             + "Furious Howl: Use {0} DPS {1:0.00}"
                                                                             + "Bite: Use {2} DPS {3:0.00}",
                                                                             + pet.priorityRotation.getSkillFrequency(PetAttacks.FuriousHowl), 0f,
                                                                             + pet.priorityRotation.getSkillFrequency(PetAttacks.Bite), pet.priorityRotation.dps - petWhiteDPS)*/);

            // Shot Stats
            dictValues.Add("Aimed Shot", aimedShot.GenTooltip());
            dictValues.Add("Arcane Shot", arcaneShot.GenTooltip());
            dictValues.Add("Multi Shot", multiShot.GenTooltip());
            dictValues.Add("Silencing Shot", silencingShot.GenTooltip());
            dictValues.Add("Steady Shot", steadyShot.GenTooltip());
            dictValues.Add("Kill Shot", killShot.GenTooltip());
            dictValues.Add("Explosive Shot", explosiveShot.GenTooltip());
            dictValues.Add("Black Arrow", blackArrow.GenTooltip());
            dictValues.Add("Volley", volley.GenTooltip());
            dictValues.Add("Chimera Shot", chimeraShot.GenTooltip());

            //dictValues.Add("Rapid Fire", rapidFire.GenTooltip());
            //dictValues.Add("Readiness", readiness.GenTooltip());
            //dictValues.Add("Bestial Wrath", bestialWrath.GenTooltip());

            // Sting Stats
            dictValues.Add("Serpent Sting", serpentSting.GenTooltip());
            dictValues.Add("Scorpid Sting", scorpidSting.GenTooltip());
            dictValues.Add("Viper Sting", viperSting.GenTooltip());

            // Trap Stats
            dictValues.Add("Immolation Trap", immolationTrap.GenTooltip());
            dictValues.Add("Explosive Trap", explosiveTrap.GenTooltip());
            dictValues.Add("Freezing Trap", freezingTrap.GenTooltip());
            dictValues.Add("Frost Trap", frostTrap.GenTooltip());

            // Mana
            dictValues.Add("Mana Usage Per Second", manaUsageTotal.ToString("F2") + "*includes:\n" +
                           manaUsageRotation.ToString("F2") + " from shot rotation\n" +
                           manaUsageKillCommand.ToString("F2") + " from Kill Command");
            dictValues.Add("Mana Regen Per Second", manaRegenTotal.ToString("F2") + "*includes:\n" +
                           (manaRegenGearBuffs + manaRegenConstantViper + manaRegenViper + manaRegenRoarOfRecovery
                            + manaRegenRapidRecuperation + manaRegenChimeraViperProc + manaRegenInvigoration
                            + manaRegenHuntingParty + manaRegenTargetDebuffs + manaRegenFromPots > 0f ?
                            (manaRegenGearBuffs != 0 ? manaRegenGearBuffs.ToString("F2") + " from Gear and Buffs\n" : "") +
                            (manaRegenConstantViper != 0 ? manaRegenConstantViper.ToString("F2") + " from Constant Aspect of the Viper\n" : "") +
                            (manaRegenViper != 0 ? manaRegenViper.ToString("F2") + " from Aspect of the Viper\n" : "") +
                            (manaRegenRoarOfRecovery != 0 ? manaRegenRoarOfRecovery.ToString("F2") + " from Roar of Recovery\n" : "") +
                            (manaRegenRapidRecuperation != 0 ? manaRegenRapidRecuperation.ToString("F2") + " from Rapid Recuperation\n" : "") +
                            (manaRegenChimeraViperProc != 0 ? manaRegenChimeraViperProc.ToString("F2") + " from Chimera Viper String Proc\n" : "") +
                            (manaRegenInvigoration != 0 ? manaRegenInvigoration.ToString("F2") + " from Invigoration\n" : "") +
                            (manaRegenHuntingParty != 0 ? manaRegenHuntingParty.ToString("F2") + " from Hunting Party\n" : "") +
                            (manaRegenTargetDebuffs != 0 ? manaRegenTargetDebuffs.ToString("F2") + " from Target Debuffs\n" : "") +
                            (manaRegenFromPots != 0 ? manaRegenFromPots.ToString("F2") + " from Pots" : "")
                : "Nothing to add")
                           );
            dictValues.Add("Normal Change", manaChangeDuringNormal.ToString("F2"));
            dictValues.Add("Change during Viper", manaChangeDuringViper.ToString("F2"));
            dictValues.Add("Time to OOM", manaTimeToOOM.ToString("F2"));
            dictValues.Add("Time to Full", manaTimeToFull.ToString("F2"));
            dictValues.Add("Viper Damage Penalty", aspectViperPenalty.ToString("P2"));
            dictValues.Add("Viper Uptime", aspectUptimeViper.ToString("P2"));
            dictValues.Add("No Mana Damage Penalty", NoManaDPSDownTimePerc.ToString("P2"));

            // Hunter DPS
            dictValues.Add("Autoshot DPS", AutoshotDPS.ToString("F2"));
            dictValues.Add("Priority Rotation DPS", CustomDPS.ToString("F2"));
            dictValues.Add("Wild Quiver DPS", WildQuiverDPS.ToString("F2"));
            dictValues.Add("Kill Shot low HP gain", killShotSub20FinalGain.ToString("F2") + "*" +
                           "Kill Shot freq: " + killShot.Freq.ToString("F2") + " -> " + killShot.start_freq.ToString("F2") + "\n" +
                           "Steady Shot freq: " + steadyShot.Freq.ToString("F2") + " -> " + killShotSub20NewSteadyFreq.ToString("F2") + "\n" +
                           "Kill Shot DPS: " + killShot.DPS.ToString("F2") + " -> " + killShotSub20NewDPS.ToString("F2") + "\n" +
                           "Steady Shot DPS: " + steadyShot.DPS.ToString("F2") + " -> " + killShotSub20NewSteadyDPS.ToString("F2") + "\n" +
                           "DPS Gain when switched: " + killShotSub20Gain.ToString("F2") + "\n" +
                           "Time spent sub-20%: " + killShotSub20TimeSpent.ToString("P2"));
            dictValues.Add("Aspect Loss", aspectBeastLostDPS.ToString("F2") + "*" +
                           "Hawk Uptime: " + aspectUptimeHawk.ToString("P2") + "\n" +
                           "Viper Uptime: " + aspectUptimeViper.ToString("P2") + "\n" +
                           "Beast Uptime: " + aspectUptimeBeast.ToString("P2"));
            dictValues.Add("Piercing Shots DPS", PiercingShotsDPS.ToString("F2") + "*" +
                           "Steady Shot: " + PiercingShotsDPSSteadyShot.ToString("F2") + "\n" +
                           "Aimed Shot: " + PiercingShotsDPSAimedShot.ToString("F2") + "\n" +
                           "Chimera Shot: " + PiercingShotsDPSChimeraShot.ToString("F2") + "\n");
            dictValues.Add("Special DMG Procs DPS", SpecProcDPS.ToString("F2"));

            // Combined DPS
            string zod = (BonusAttackProcsDPS != 0 ? string.Format("*Includes:\r\nZod's Proc: {0:0.0}", BonusAttackProcsDPS) : "");
            dictValues.Add("Hunter DPS", HunterDpsPoints.ToString("F2") + zod);
            dictValues.Add("Pet DPS", PetDpsPoints.ToString("F2"));
            dictValues.Add("Total DPS", OverallPoints.ToString("F2"));

            return(dictValues);
        }