/// <summary> /// Builds a dictionary containing the values to display for each of the calculations defined in /// CharacterDisplayCalculationLabels. The key should be the Label of each display calculation, /// and the value should be the value to display, optionally appended with '*' followed by any /// string you'd like displayed as a tooltip on the value. /// </summary> /// <returns>A Dictionary<string, string> containing the values to display for each of the /// calculations defined in CharacterDisplayCalculationLabels.</returns> public override Dictionary <string, string> GetCharacterDisplayCalculationValues() { Dictionary <string, string> dictValues = new Dictionary <string, string>(); #region Simulation stats dictValues.Add("Rotation", String.Format("{0}*{1}", Name, Abilities)); dictValues.Add("Warlock DPS", String.Format("{0:0}", DpsPoints)); dictValues.Add("Pet DPS", String.Format("{0:0}", PetDPSPoints)); dictValues.Add("Total DPS", String.Format("{0:0}", OverallPoints)); dictValues.Add("Damage Done", String.Format("{0:0}", OverallDamage)); dictValues.Add("Mana Used", String.Format("{0:0}", TotalManaCost)); #endregion #region HP/Mana stats dictValues.Add("Health", String.Format("{0:0}", TotalStats.Health)); dictValues.Add("Mana", String.Format("{0:0}", TotalStats.Mana)); #endregion #region Base stats dictValues.Add("Strength", String.Format("{0}", TotalStats.Strength)); dictValues.Add("Agility", String.Format("{0}", TotalStats.Agility)); dictValues.Add("Stamina", String.Format("{0}", TotalStats.Stamina)); dictValues.Add("Intellect", String.Format("{0}", TotalStats.Intellect)); dictValues.Add("Spirit", String.Format("{0}", TotalStats.Spirit)); dictValues.Add("Armor", String.Format("{0}", TotalStats.Armor)); #endregion #region Pet stats Minion minion = MinionFactory.CreateMinion(Options.Pet, Character, TotalStats); if (minion != null) { dictValues.Add("Pet Strength", String.Format("{0}", minion.Strength())); dictValues.Add("Pet Agility", String.Format("{0}", minion.Agility())); dictValues.Add("Pet Stamina", String.Format("{0:0}", minion.Stamina())); dictValues.Add("Pet Intellect", String.Format("{0:0}", minion.Intellect())); dictValues.Add("Pet Spirit", String.Format("{0}", minion.Spirit())); dictValues.Add("Pet Armor", String.Format("{0}", minion.Armor())); } #endregion #region Spell stats //pet scaling consts: http://www.wowwiki.com/Warlock_minions const float petInheritedAttackPowerPercentage = 0.57f; const float petInheritedSpellPowerPercentage = 0.15f; dictValues.Add("Bonus Damage", String.Format("{0}*Shadow Damage\t{1}\r\nFire Damage\t{2}\r\n\r\nYour Fire Damage increases your pet's Attack Power by {3} and Spell Damage by {4}.", TotalStats.SpellPower, TotalStats.SpellPower + TotalStats.SpellShadowDamageRating, TotalStats.SpellPower + TotalStats.SpellFireDamageRating, Math.Round((TotalStats.SpellPower + TotalStats.SpellFireDamageRating) * petInheritedAttackPowerPercentage, 0), Math.Round((TotalStats.SpellPower + TotalStats.SpellFireDamageRating) * petInheritedSpellPowerPercentage, 0) )); #region Hit / Miss chance //float bonusHit = TotalStats.SpellHit; float onePercentOfHitRating = (1 / StatConversion.GetSpellHitFromRating(1)); float hitFromRating = StatConversion.GetSpellHitFromRating(TotalStats.HitRating); float hitFromTalents = (Character.WarlockTalents.Suppression * 0.01f); float hitFromBuffs = (TotalStats.SpellHit - hitFromRating - hitFromTalents); float targetHit = (Options.TargetHit / 100f); float totalHit = (targetHit + TotalStats.SpellHit); float missChance = (totalHit > 1 ? 0 : (1 - totalHit)); //calculate the amount of hit rating that is over or under the cap float hitDelta = (totalHit > 1) ? (float)Math.Floor((totalHit - 1) * onePercentOfHitRating) : (float)Math.Ceiling((1 - totalHit) * onePercentOfHitRating); //now we can calculate the hitcap value float hitCap = (totalHit > 1) ? TotalStats.HitRating - hitDelta : TotalStats.HitRating + hitDelta; dictValues.Add("Hit Rating", String.Format("{0}*{1:0.00%} Hit Chance (max 100%) | {2:0.00%} Miss Chance \r\n\r\n" + "{3:0.00%}\t Base Hit Chance on a Level {4:0} target\r\n" + "{5:0.00%}\t from {6:0} Hit Rating [gear, food and/or flasks]\r\n" + "{7:0.00%}\t from Talent: Suppression\r\n" + "{8:0.00%}\t from Buffs: Racial and/or Spell Hit Chance Taken\r\n\r\n" + "{9}\r\n\r\n" + "Hit Rating caps:\r\n" + "446 - hard cap (no hit from talents, gear or buffs)\r\n" + "420 - Heroic Presence\r\n" + "368 - Suppression\r\n" + "342 - Suppression and Heroic Presence\r\n" + "289 - Suppression, Improved Faerie Fire / Misery\r\n" + "263 - Suppression, Improved Faerie Fire / Misery and Heroic Presence", TotalStats.HitRating, totalHit, missChance, targetHit, Options.TargetLevel, hitFromRating, TotalStats.HitRating, hitFromTalents, hitFromBuffs, String.Format("You are {0} hit rating {1} the {2} cap.", hitDelta, ((totalHit > 1) ? "above" : "below"), hitCap) )); dictValues.Add("Miss chance", String.Format("{0:0.00%}", missChance)); #endregion #region Crit % Stats statsBase = BaseStats.GetBaseStats(Character); float critFromRating = StatConversion.GetSpellCritFromRating(TotalStats.CritRating); float critFromIntellect = StatConversion.GetSpellCritFromIntellect(TotalStats.Intellect); float critFromBuffs = TotalStats.SpellCrit - statsBase.SpellCrit - critFromRating - critFromIntellect - (Character.WarlockTalents.DemonicTactics * 0.02f) - (Character.WarlockTalents.Backlash * 0.01f); dictValues.Add("Crit Chance", String.Format("{0:0.00%}*" + "{1:0.00%}\tfrom {2:0} Spell Crit rating\r\n" + "{3:0.00%}\tfrom {4:0} Intellect\r\n" + "{5:0.000%}\tfrom Warlock Class Bonus\r\n" + "{6:0%}\tfrom Talent: Demonic Tactics\r\n" + "{7:0%}\tfrom Talent: Backlash\r\n" + "{8:0%}\tfrom Buffs", TotalStats.SpellCrit, critFromRating, TotalStats.CritRating, critFromIntellect, TotalStats.Intellect, statsBase.SpellCrit, (Character.WarlockTalents.DemonicTactics * 0.02f), (Character.WarlockTalents.Backlash * 0.01f), critFromBuffs )); #endregion dictValues.Add("Haste Rating", String.Format("{0}%*{1}%\tfrom {2} Haste rating\r\n{3}%\tfrom Buffs\r\n{4}s\tGlobal Cooldown", (TotalStats.SpellHaste * 100f).ToString("0.00"), (StatConversion.GetSpellHasteFromRating(TotalStats.HasteRating) * 100f).ToString("0.00"), TotalStats.HasteRating, (TotalStats.SpellHaste * 100f - StatConversion.GetSpellHasteFromRating(TotalStats.HasteRating) * 100f).ToString("0.00"), Math.Max(1.0f, 1.5f / (1 + TotalStats.SpellHaste)).ToString("0.00"))); dictValues.Add("Mana Regen", String.Format("{0}*{0} mana regenerated every 5 seconds while not casting\r\n{1} mana regenerated every 5 seconds while casting", GetManaRegenOutOfCombat(), GetManaRegenInCombat())); #endregion #region Shadow school dictValues.Add("Shadow Bolt", new ShadowBolt(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.Haunt > 0) { dictValues.Add("Haunt", new Haunt(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Haunt", "- *Required talent not available"); } dictValues.Add("Corruption", new Corruption(TotalStats, Character, Options).ToString()); dictValues.Add("Curse of Agony", new CurseOfAgony(TotalStats, Character, Options).ToString()); dictValues.Add("Curse of Doom", new CurseOfDoom(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.UnstableAffliction > 0) { dictValues.Add("Unstable Affliction", new UnstableAffliction(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Unstable Affliction", "- *Required talent not available"); } dictValues.Add("Death Coil", new DeathCoil(TotalStats, Character, Options).ToString()); dictValues.Add("Drain Life", new DrainLife(TotalStats, Character, Options).ToString()); dictValues.Add("Drain Soul", new DrainSoul(TotalStats, Character, Options).ToString()); dictValues.Add("Seed of Corruption", new SeedOfCorruption(TotalStats, Character, Options).ToString()); dictValues.Add("Shadowflame", new Shadowflame(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.Shadowburn > 0) { dictValues.Add("Shadowburn", new Shadowburn(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Shadowburn", "- *Required talent not available"); } if (Character.WarlockTalents.Shadowfury > 0) { dictValues.Add("Shadowfury", new Shadowfury(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Shadowfury", "- *Required talent not available"); } dictValues.Add("Life Tap", new LifeTap(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.DarkPact > 0) { dictValues.Add("Dark Pact", new DarkPact(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Dark Pact", "- *Required talent not available"); } #endregion #region Fire school dictValues.Add("Incinerate", new Incinerate(TotalStats, Character, Options).ToString()); dictValues.Add("Immolate", new Immolate(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.Conflagrate > 0) { dictValues.Add("Conflagrate", new Conflagrate(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Conflagrate", "- *Required talent not available"); } if (Character.WarlockTalents.ChaosBolt > 0) { dictValues.Add("Chaos Bolt", new ChaosBolt(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Chaos Bolt", "- *Required talent not available"); } dictValues.Add("Rain of Fire", new RainOfFire(TotalStats, Character, Options).ToString()); dictValues.Add("Hellfire", new Hellfire(TotalStats, Character, Options).ToString()); if (Character.WarlockTalents.Metamorphosis > 0) { dictValues.Add("Immolation Aura", new ImmolationAura(TotalStats, Character, Options).ToString()); } else { dictValues.Add("Immolation Aura", "- *Required talent not available"); } dictValues.Add("Searing Pain", new SearingPain(TotalStats, Character, Options).ToString()); dictValues.Add("Soul Fire", new SoulFire(TotalStats, Character, Options).ToString()); #endregion return(dictValues); }