Example #1
0
        public void AbilityDK_IcyTouch_Basic()
        {
            // TODO: Get this so we don't have to do this work every test.
            Stats characterStats = new Stats();

            characterStats = BaseStats.GetBaseStats(85, CharacterClass.DeathKnight, CharacterRace.Undead);

            CombatState state = new CombatState();

            state.m_Stats   = characterStats as StatsDK;
            state.m_Talents = new DeathKnightTalents();

            // We're going to create IcyTouch and ensure that we can access everything for that
            // ability that is used by a DK.

            /*
             * AbilityDK_IcyTouch IT = new AbilityDK_IcyTouch(state);
             *
             * // Frost Fever application. is skipped for the purposes of this test.
             * Assert.IsTrue(IT.szName == "Icy Touch", "Name");
             * Assert.AreEqual(IT.AbilityCost[(int)DKCostTypes.Blood], 0, "Blood Cost");
             * Assert.AreEqual(IT.AbilityCost[(int)DKCostTypes.Frost], 1, "Frost Cost");
             * Assert.AreEqual(IT.AbilityCost[(int)DKCostTypes.UnHoly], 0, "Unholy Cost");
             * Assert.AreEqual(-10, IT.AbilityCost[(int)DKCostTypes.RunicPower], "RP Cost/Gain");
             * Assert.AreEqual((uint)((245 + 227) / 2), IT.uBaseDamage, "Base Damage");
             * Assert.AreEqual(20u, IT.uRange, "Range");
             * Assert.AreEqual(IT.tDamageType, ItemDamageType.Frost, "Damage Type");
             * Assert.AreEqual(IT.Cooldown, 1500u, "Cooldown");
             * // With the addition of GetTotalDamage function we need to add it into the basic IT check.
             * Assert.AreEqual((int)IT.uBaseDamage, IT.GetTotalDamage(), "GetTotalDamage");
             * */
        }
Example #2
0
        public void GetDRAvoidanceChanceTest_Warr_TestTableDef10000()
        {
            const float testValue = 10000f;

            ItemInstance[] IIArray = new ItemInstance[1];
            Character      toon    = new Character("TestWarrior", "Malygos", CharacterRegion.US, CharacterRace.Human, new BossOptions(), IIArray, new System.Collections.Generic.List <Buff>(), "ProtWarr"); // TODO: Initialize to an appropriate value

            Assert.IsNotNull(toon);
            //toon.Level = 80;  //Asumption here.
            toon.Class = CharacterClass.Warrior;

            Stats stats = new Stats();

            stats              += BaseStats.GetBaseStats(toon);
            stats.Defense       = 400;
            stats.DefenseRating = testValue;
            uint TargetLevel = 80;

            //float levelDiff = 0.006f;
            float[] expected = new float[HitResultCount];
            expected[(int)HitResult.Miss]  = 0.16f;
            expected[(int)HitResult.Dodge] = 0.7650f;
            expected[(int)HitResult.Parry] = 0.4700f;
            // Miss test
            float actual = (float)System.Math.Round((double)StatConversion.GetDRAvoidanceChance(toon, stats, HitResult.Miss, TargetLevel), 4);

            Assert.AreEqual(expected[(int)HitResult.Miss], actual, HitResult.Miss.ToString());
            // Dodge Test
            actual = (float)System.Math.Round((double)StatConversion.GetDRAvoidanceChance(toon, stats, HitResult.Dodge, TargetLevel), 4);
            Assert.AreEqual(expected[(int)HitResult.Dodge], actual, HitResult.Dodge.ToString());
            // Parry Test
            actual = (float)System.Math.Round((double)StatConversion.GetDRAvoidanceChance(toon, stats, HitResult.Parry, TargetLevel), 4);
            Assert.AreEqual(expected[(int)HitResult.Parry], actual, HitResult.Parry.ToString());
        }
Example #3
0
        /// <param name="stats">
        /// This should already have buffStats factored in.
        /// </param>
        public CharacterCalculationsWarlock(Character character, Stats stats, Stats petBuffs)
        {
            Character     = character;
            CalcOpts      = character.CalculationOptions as CalculationOptionsWarlock;
            BossOpts      = character.BossOptions;
            Talents       = character.WarlockTalents;
            Stats         = stats;
            PreProcStats  = Stats.Clone();
            PetBuffs      = petBuffs;
            BaseMana      = BaseStats.GetBaseStats(character).Mana;
            BaseIntellect = BaseStats.GetBaseStats(character).Intellect;
            Spells        = new Dictionary <string, Spell>();
            CastSpells    = new Dictionary <string, Spell>();
            HitChance     = Math.Min(1f, CalcOpts.GetBaseHitRate() / 100f + CalcSpellHit());

            int temp;

            if (character.SetBonusCount.TryGetValue("Shadowflame Regalia", out temp))
            {
                Warlock_T11_2P = (temp >= 2);
                Warlock_T11_4P = (temp >= 4);
            }

            if (!CalcOpts.Pet.Equals("None") && (Demonology || !CalcOpts.Pet.Equals("Felguard")))
            {
                Type type = Type.GetType("Rawr.Warlock." + CalcOpts.Pet);
                Pet = (Pet)Activator.CreateInstance(type, new object[] { this });
            }

            float personalDps = CalcPersonalDps();
            float petDps      = CalcPetDps();

            SubPoints     = new float[] { personalDps, petDps };
            OverallPoints = personalDps + petDps;
        }
Example #4
0
        /// <summary>
        /// Instant, 1 min cd, Self (Any)
        /// Generates 10 rage at the cost of health and then generates an additional 10 rage over 10 sec.
        /// </summary>
        /// <TalentsAffecting>Improved Bloodrge [+(25*Pts)% Rage Generated], Intensify Rage [-(1/9*Pts]% Cooldown]</TalentsAffecting>
        /// <GlyphsAffecting>Glyph of Bloodrage [-100% Health Cost]</GlyphsAffecting>
        public Bloodrage(Character c, Stats s, CombatFactors cf, WhiteAttacks wa, CalculationOptionsDPSWarr co, BossOptions bo)
        {
            Char = c; StatS = s; combatFactors = cf; Whiteattacks = wa; CalcOpts = co; BossOpts = bo;
            //
            Name         = "Bloodrage";
            Description  = "Generates 10 rage at the cost of health and then generates an additional 10 rage over 10 sec.";
            AbilIterater = (int)Rawr.DPSWarr.CalculationOptionsDPSWarr.Maintenances.Bloodrage_;
            Cd           = 60f * (1f - 1f / 9f * Talents.IntensifyRage); // In Seconds
            Duration     = 10f;                                          // In Seconds
            // Rage is actually reversed in the rotation
            RageCost = -(20f                                             // Base
                         + 10f)                                          // Over Time
                       * (1f + Talents.ImprovedBloodrage * 0.25f);       // Talent Bonus
            StanceOkArms = StanceOkDef = StanceOkFury = true;
            Stats Base       = BaseStats.GetBaseStats(Char.Level, CharacterClass.Warrior, Char.Race);
            float baseHealth = Base.Health + StatConversion.GetHealthFromStamina(Base.Stamina, CharacterClass.Warrior);

            HealingBase  = -1f * (float)Math.Floor(baseHealth) * 0.16f;
            HealingBonus = (Talents.GlyphOfBloodrage ? 0f : 1f);
            UseHitTable  = false;
            UsesGCD      = false;
            UseReact     = true;
            //
            Initialize();
        }
Example #5
0
        public void SetManaRegen()  //Check
        {
            baseMana = BaseStats.GetBaseStats(_character).Mana;
            float replenishRegen    = (_stats.Mana * _stats.ManaRestoreFromMaxManaPerSecond) * 5f;
            float primalWisdomRegen = (((hitsPerSMH + hitsPerSOH) * 0.40f) * (baseMana * 0.05f)) * 5f;

            baseRegen = baseMana * 0.05f;
            manaRegen = _stats.Mp5 + baseRegen + replenishRegen + primalWisdomRegen;
        }
Example #6
0
        public void SetManaRegen()
        {
            baseMana = BaseStats.GetBaseStats(_character).Mana;
            float spiRegen       = StatConversion.GetSpiritRegenSec(_stats.Spirit, _stats.Intellect);
            float replenishRegen = _stats.Mana * _stats.ManaRestoreFromMaxManaPerSecond;
            float judgementRegen = _stats.ManaRestoreFromBaseManaPPM / 60f * baseMana;

            manaRegen = _stats.Mp5 / 5 + spiRegen + replenishRegen + judgementRegen;
        }
Example #7
0
        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            CalculationOptionsHealPriest calcOpts = character.CalculationOptions as CalculationOptionsHealPriest;

            StatsPriest statsTotal = new StatsPriest()
            {
                SpellHaste = PriestInformation.GetDarkness(character.PriestTalents.Darkness),
                InnerFire  = true,
                BonusIntellectMultiplier = 0.05f,   // Cloth bonus.
                PriestSpec = PriestSpec.GetPriestSpec(character.PriestTalents),
            };

            if (statsTotal.PriestSpec == ePriestSpec.Spec_Disc)
            {
                statsTotal.SpellCombatManaRegeneration = 0.5f;
                statsTotal.BonusIntellectMultiplier    = 0.15f;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_Holy)
            {
                statsTotal.SpellCombatManaRegeneration = 0.5f + PriestInformation.GetHolyConcentration(character.PriestTalents.HolyConcentration);
                statsTotal.BonusHealingDoneMultiplier  = 0.15f;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_ERROR)
            {
                throw new Exception("Unpossible Talent Spec!");
            }

            statsTotal.Accumulate(BaseStats.GetBaseStats(character));
            statsTotal.Accumulate(GetItemStats(character, additionalItem));
            statsTotal.Accumulate(GetBuffsStats(character, calcOpts));


            statsTotal.Stamina     = (float)Math.Floor((statsTotal.Stamina) * (1 + statsTotal.BonusStaminaMultiplier));
            statsTotal.Intellect   = (float)Math.Floor((statsTotal.Intellect) * (1 + statsTotal.BonusIntellectMultiplier));
            statsTotal.Spirit      = (float)Math.Floor((statsTotal.Spirit) * (1 + statsTotal.BonusSpiritMultiplier));
            statsTotal.SpellPower += (statsTotal.InnerFire ? PriestInformation.GetInnerFireSpellPowerBonus(character) : 0) + (statsTotal.Intellect - 10);
            statsTotal.SpellPower *= (1f + statsTotal.BonusSpellPowerMultiplier);
            statsTotal.Mana       += StatConversion.GetManaFromIntellect(statsTotal.Intellect);
            statsTotal.Mana       *= (1f + statsTotal.BonusManaMultiplier);
            statsTotal.Health     += StatConversion.GetHealthFromStamina(statsTotal.Stamina);
            statsTotal.Health      = (float)Math.Floor(statsTotal.Health * (1f + statsTotal.BonusHealthMultiplier));
            statsTotal.SpellCrit  += StatConversion.GetSpellCritFromIntellect(statsTotal.Intellect)
                                     + StatConversion.GetSpellCritFromRating(statsTotal.CritRating);
            statsTotal.SpellHaste = (1f + statsTotal.SpellHaste) * (1f + StatConversion.GetSpellHasteFromRating(statsTotal.HasteRating)) - 1f;
            statsTotal.Armor     *= (1 + (statsTotal.InnerFire ? PriestInformation.GetInnerFireArmorBonus(character) : 0));

            if (statsTotal.PriestSpec == ePriestSpec.Spec_Disc)
            {
                statsTotal.ShieldDiscipline = (PriestInformation.DisciplineMasteryBase + StatConversion.GetMasteryFromRating(statsTotal.MasteryRating)) * PriestInformation.DisciplineMasteryEffect;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_Holy)
            {
                statsTotal.EchoofLight = (PriestInformation.HolyMasteryBase + StatConversion.GetMasteryFromRating(statsTotal.MasteryRating)) * PriestInformation.HolyMasteryEffect;
            }

            return(statsTotal);
        }
Example #8
0
        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            WarlockTalents            talents  = character.WarlockTalents;
            CalculationOptionsWarlock calcOpts = character.CalculationOptions as CalculationOptionsWarlock;
            BossOptions bossOpts = character.BossOptions;
            Stats       stats    = BaseStats.GetBaseStats(character);

            AccumulateItemStats(stats, character, additionalItem);
            AccumulateBuffsStats(stats, character.ActiveBuffs);
            AccumulateSetBonusStats(stats, character.SetBonusCount);
            ApplyPetsRaidBuff(stats, calcOpts.Pet, talents, character.ActiveBuffs, calcOpts);

            float[] demonicEmbraceValues = { 0f, .04f, .07f, .1f };
            Stats   statsTalents         = new Stats {
                BonusStaminaMultiplier = demonicEmbraceValues[talents.DemonicEmbrace] //Demonic Embrace
            };

            if (talents.Eradication > 0)
            {
                float[] eradicationValues = { 0f, .06f, .12f, .20f };
                statsTalents.AddSpecialEffect(
                    new SpecialEffect(
                        Trigger.CorruptionTick,
                        new Stats()
                {
                    SpellHaste = eradicationValues[talents.Eradication]
                },
                        10f,    //duration
                        0f,     //cooldown
                        .06f)); //chance
            }

            stats.Accumulate(statsTalents);
            stats.ManaRestoreFromMaxManaPerSecond
                = Math.Max(
                      stats.ManaRestoreFromMaxManaPerSecond,
                      .001f * Spell.CalcUprate(talents.SoulLeech > 0 ? 1f : 0f, 15f, bossOpts.BerserkTimer * 1.1f));
            return(stats);
        }
Example #9
0
        public void GetDRAvoidanceChanceTest_DK_TestFromForums()
        {
            ItemInstance[] IIArray = new ItemInstance[1];
            Character      toon    = new Character("TestDK", "Malygos", CharacterRegion.US, CharacterRace.Human, new BossOptions(), IIArray, new System.Collections.Generic.List <Buff>(), "TankDK"); // TODO: Initialize to an appropriate value

            Assert.IsNotNull(toon);
            //toon.Level = 80;  //Asumption here.
            toon.Class = CharacterClass.DeathKnight;

            Stats stats = new Stats();

            stats              += BaseStats.GetBaseStats(toon);
            stats.Miss         += .03f; // 3% Miss from talents
            stats.Defense       = 425;  // 25 Def from SSG rune
            stats.Dodge        += .05f; // 5% dodge from talents.
            stats.DefenseRating = 566f;
            uint TargetLevel = 83;

            //float levelDiff = 0.006f;
            float[] expected = new float[HitResultCount];
            expected[(int)HitResult.Miss]    = 0.121f;
            expected[(int)HitResult.Dodge]   = 0.134f;
            expected[(int)HitResult.Parry]   = 0.098f;
            expected[(int)HitResult.Block]   = .05f;
            expected[(int)HitResult.Crit]    = .05f;
            expected[(int)HitResult.AnyMiss] = 0;
            expected[(int)HitResult.AnyHit]  = 0;
            expected[(int)HitResult.Glance]  = .05f;
            expected[(int)HitResult.Resist]  = .05f;
            expected[(int)HitResult.Hit]     = .05f;

            // Iterate through the hit result types.
            for (HitResult i = 0; i < (HitResult)HitResultCount; i++)
            {
                float actual = (float)System.Math.Round((double)StatConversion.GetDRAvoidanceChance(toon, stats, i, TargetLevel), 3);
                Assert.AreEqual(expected[(int)i], actual, i.ToString());
            }
        }
        /// <param name="stats">
        /// This should already have buffStats factored in.
        /// </param>
        public CharacterCalculationsWarlock(
            Character character, Stats stats, Stats petBuffs)
        {
            Character = character;
            Options   = (CalculationOptionsWarlock)character.CalculationOptions;
            if (Options == null)
            {
                Options = CalculationOptionsWarlock.MakeDefaultOptions();
            }
            Talents      = character.WarlockTalents;
            Stats        = stats;
            PreProcStats = Stats.Clone();
            PetBuffs     = petBuffs;
            BaseMana     = BaseStats.GetBaseStats(character).Mana;
            Spells       = new Dictionary <string, Spell>();
            CastSpells   = new Dictionary <string, Spell>();
            HitChance
                = Math.Min(
                      1f,
                      Options.GetBaseHitRate() / 100f + CalcSpellHit());

            if (!Options.Pet.Equals("None") &&
                (Talents.SummonFelguard > 0 ||
                 !Options.Pet.Equals("Felguard")))
            {
                Type type = Type.GetType("Rawr.Warlock." + Options.Pet);
                Pet = (Pet)Activator.CreateInstance(
                    type, new object[] { this });
            }

            float personalDps = CalcPersonalDps();
            float petDps      = CalcPetDps();
            float raidBuff    = CalcRaidBuff();

            SubPoints     = new float[] { personalDps, petDps, raidBuff };
            OverallPoints = personalDps + petDps + raidBuff;
        }
Example #11
0
        public virtual void UpdateSpell()
        {
            HasDirectDamage = false; HasDirectHeal = false; HasAbsorb = false; HasOverTimeDamage = false; HasOverTimeHeal = false;

            float hc = 1f / (1f + stats.SpellHaste);

            IsInstant = BaseCastTime == 0f;
            if (IsInstant)
            {
                CastTime = 0f;
            }
            else
            {
                CastTime = Math.Max(1f, BaseCastTime * hc);
            }
            GlobalCooldown = Math.Max(1f, BaseGlobalCooldown * hc);
            CritChance     = stats.SpellCrit;
            CritMultiplier = 1.5f * (1f + stats.BonusCritHealMultiplier);
            ManaCost       = BaseManaCost * BaseStats.GetBaseStats(character).Mana; // priestInformation.BaseMana;
            if (IsInstant)
            {
                ManaCost *= PriestInformation.GetMentalAgility(character.PriestTalents.MentalAgility);
            }
        }
        public override float GetOptimizableCalculationValue(string calculation)
        {
            switch (calculation)
            {
            case "Health": return(basicStats.Health);

            case "Resilience": return(basicStats.Resilience);

            case "Mana": return(basicStats.Mana);

            case "Haste Rating": return(basicStats.HasteRating);

            case "Haste %": return(basicStats.SpellHaste * 100f);

            case "Crit Rating": return(basicStats.CritRating);

            case "MB Crit %": return(new MindBlast(basicStats, character, BaseStats.GetBaseStats(character).Mana, (character.CalculationOptions as CalculationOptionsShadowPriest).PTR).CritChance * 100f);

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

            case "MF cast time (ms)": return(new MindFlay(basicStats, character, BaseStats.GetBaseStats(character).Mana, (character.CalculationOptions as CalculationOptionsShadowPriest).PTR).CastTime * 1000f);

            case "Armor": return(basicStats.Armor + basicStats.BonusArmor);

            case "Arcane Resistance": return(basicStats.ArcaneResistance + basicStats.ArcaneResistanceBuff);

            case "Fire Resistance": return(basicStats.FireResistance + basicStats.FireResistanceBuff);

            case "Frost Resistance": return(basicStats.FrostResistance + basicStats.FrostResistance);

            case "Nature Resistance": return(basicStats.NatureResistance + basicStats.NatureResistanceBuff);

            case "Shadow Resistance": return(basicStats.ShadowResistance + basicStats.ShadowResistanceBuff);
            }
            return(0f);
        }
        /// <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);
        }
Example #14
0
        /// <summary>
        /// Calculate the mana required to perform this ability.
        /// </summary>
        public virtual float Mana()
        {
            Stats statsBase = BaseStats.GetBaseStats(Character);

            return((float)Math.Floor(statsBase.Mana * Cost()));
        }
Example #15
0
        public Stats GetCharacterStats(Character character, Item additionalItem, bool computeAverageStats, CharacterCalculationsHealadin calc)
        {
            CalculationOptionsHealadin calcOpts = character.CalculationOptions as CalculationOptionsHealadin;
            BossOptions    bossOpts             = character.BossOptions;
            PaladinTalents talents = character.PaladinTalents;

            float fightLength = bossOpts.BerserkTimer;

            Stats statsRace     = BaseStats.GetBaseStats(character.Level, CharacterClass.Paladin, character.Race);
            Stats statsBaseGear = GetItemStats(character, additionalItem);
            Stats statsBuffs    = GetBuffsStats(character, calcOpts);
            Stats stats         = statsBaseGear + statsBuffs + statsRace;

            ConvertRatings(stats, talents, calcOpts);
            if (computeAverageStats)
            {
                Stats statsAverage = new Stats();

                foreach (SpecialEffect effect in stats.SpecialEffects())
                {
                    float trigger = 0f;
                    if (calc == null)
                    {
                        trigger = 1.5f / calcOpts.Activity / (1f + stats.SpellHaste);
                        if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                        {
                            trigger *= stats.SpellCrit;
                        }
                    }
                    else
                    {
                        if (effect.Trigger == Trigger.HealingSpellCast || effect.Trigger == Trigger.HealingSpellHit)
                        {
                            trigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                        {
                            trigger = 1f / Rotation.GetHealingCritsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.SpellCast || effect.Trigger == Trigger.SpellHit)
                        {
                            trigger = 1f / Rotation.GetSpellCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.DamageOrHealingDone)
                        {
                            trigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.Use)
                        {
                            trigger = 0f;
                            foreach (SpecialEffect childEffect in effect.Stats.SpecialEffects())
                            {
                                float childTrigger = 0f;

                                if (effect.Trigger == Trigger.HealingSpellCast || effect.Trigger == Trigger.HealingSpellHit)
                                {
                                    childTrigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                                }
                                else if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                                {
                                    childTrigger = 1f / Rotation.GetHealingCritsPerSec(calc);
                                }
                                else if (effect.Trigger == Trigger.SpellCast || effect.Trigger == Trigger.SpellHit)
                                {
                                    childTrigger = 1f / Rotation.GetSpellCastsPerSec(calc);
                                }

                                statsAverage.Accumulate(childEffect.Stats,
                                                        effect.GetAverageUptime(0.0f, 1.0f)
                                                        * childEffect.GetAverageStackSize(childTrigger, 1f, 1.5f, effect.Duration));
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                    statsAverage.Accumulate(effect.GetAverageStats(trigger, 1f, 1.5f, fightLength));
                }
                statsAverage.ManaRestore *= fightLength;
                statsAverage.Healed      *= fightLength;
                statsAverage.HealedPerSP *= fightLength;

                stats = statsBaseGear + statsBuffs + statsRace + statsAverage;
                ConvertRatings(stats, talents, calcOpts);
            }

            #region Set Bonuses
            int T11Count;
            character.SetBonusCount.TryGetValue("Reinforced Sapphirium Regalia", out T11Count);
            stats.BonusCritChanceDeathCoil   = 0; // using this for Holy Light crit bonus, for now
            stats.BonusCritChanceFrostStrike = 0; // yes, I'm pure evil, using this to track 4T11
            if (T11Count >= 2)
            {
                // T11 Pally 2 piece bonus: add 5% crit to HL
                stats.BonusCritChanceDeathCoil = 0.05f;
            }
            if (T11Count >= 4)
            {
                // T11 Pally 4 piece bonus: 540 spirit buff for 6 secs after HS cast
                stats.BonusCritChanceFrostStrike = 1;
            }
            #endregion Set Bonuses

            return(stats);
        }
Example #16
0
        public static void CalculateNewStats(LivingObject lobj)
        {
            if (lobj.ObjectType == OBJECTTYPE.PLAYER)
            {
                PlayerObject pobj  = (PlayerObject)lobj;
                BaseStats    stats = BaseStats.GetBaseStats(pobj);

                pobj.MaxHealth = stats.Health;
                pobj.MaxPower  = stats.Power;

                pobj.BaseStrength  = stats.Strength;
                pobj.BaseStamina   = stats.Stamina;
                pobj.BaseAgility   = stats.Agility;
                pobj.BaseIntellect = stats.Intellect;
                pobj.BaseSpirit    = stats.Spirit;

                CalculateInvStats(pobj);
            }
            else if (lobj.ObjectType == OBJECTTYPE.UNIT)
            {
                UnitBase uobj        = (UnitBase)lobj;
                int      basehealth  = 60;
                int      basestamina = Convert.ToInt32(((float)lobj.Level * ((float)lobj.Level * 0.2f)) - 1);
                if (basestamina < (uobj.Level - 1))
                {
                    basestamina = uobj.Level - 1;
                }
                int health = basehealth + (basestamina * 10);

                if (uobj.Level < 10)
                {
                    switch (uobj.Level)
                    {
                    case 1:
                        uobj.BaseAttackTime = 2000;
                        uobj.MinDamage      = (float)2.0;
                        uobj.MaxDamage      = (float)4.0;
                        break;

                    case 2:
                        uobj.BaseAttackTime = 2600;
                        uobj.MinDamage      = (float)3.0;
                        uobj.MaxDamage      = (float)6.0;
                        break;

                    case 3:
                        uobj.BaseAttackTime = 2200;
                        uobj.MinDamage      = (float)3.0;
                        uobj.MaxDamage      = (float)6.0;
                        break;

                    case 4:
                        uobj.BaseAttackTime = 2000;
                        uobj.MinDamage      = (float)3.0;
                        uobj.MaxDamage      = (float)6.0;
                        break;

                    case 5:
                        uobj.BaseAttackTime = 1800;
                        uobj.MinDamage      = (float)3.0;
                        uobj.MaxDamage      = (float)6.0;
                        break;

                    case 6:
                        uobj.BaseAttackTime = 2100;
                        uobj.MinDamage      = (float)4.0;
                        uobj.MaxDamage      = (float)8.0;
                        break;

                    case 7:
                        uobj.BaseAttackTime = 1950;
                        uobj.MinDamage      = (float)4.0;
                        uobj.MaxDamage      = (float)8.0;
                        break;

                    case 8:
                        uobj.BaseAttackTime = 1800;
                        uobj.MinDamage      = (float)4.0;
                        uobj.MaxDamage      = (float)8.0;
                        break;

                    case 9:
                        uobj.BaseAttackTime = 2200;
                        uobj.MinDamage      = (float)5.0;
                        uobj.MaxDamage      = (float)10.0;
                        break;
                    }
                }
                else
                {
                    uobj.BaseAttackTime = 2000;
                    uobj.MinDamage      = (float)uobj.Level / (float)2.0;
                    uobj.MaxDamage      = (float)uobj.Level;
                }
                uobj.MaxHealth = health;
                uobj.MaxPower  = 0;
            }
        }
Example #17
0
        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            CalculationOptionsElemental calcOpts = character.CalculationOptions as CalculationOptionsElemental;

            Stats statsRace  = BaseStats.GetBaseStats(character);
            Stats statsItems = GetItemStats(character, additionalItem);
            Stats statsBuffs = GetBuffsStats(character, calcOpts);

            Stats statsTotal = statsRace + statsItems + statsBuffs;

            if (statsTotal.HighestStat > 0)
            {
                if (statsTotal.Spirit > statsTotal.Intellect)
                {
                    statsTotal.Spirit += (statsTotal.HighestStat * 15f / 50f);
                }
                else
                {
                    statsTotal.Intellect += (statsTotal.HighestStat * 15f / 50f);
                }
            }

            statsTotal.Strength  *= 1 + statsTotal.BonusStrengthMultiplier;
            statsTotal.Agility   *= 1 + statsTotal.BonusAgilityMultiplier;
            statsTotal.Stamina   *= 1 + statsTotal.BonusStaminaMultiplier;
            statsTotal.Intellect *= 1 + statsTotal.BonusIntellectMultiplier;
            statsTotal.Spirit    *= 1 + statsTotal.BonusSpiritMultiplier;

            statsTotal.Strength  = (float)Math.Floor(statsTotal.Strength);
            statsTotal.Agility   = (float)Math.Floor(statsTotal.Agility);
            statsTotal.Stamina   = (float)Math.Floor(statsTotal.Stamina);
            statsTotal.Intellect = (float)Math.Floor(statsTotal.Intellect);
            statsTotal.Spirit    = (float)Math.Floor(statsTotal.Spirit);

            if (Character.ValidateArmorSpecialization(character, ItemType.Mail))
            {
                statsTotal.Intellect *= 1.05f;
            }

            statsTotal.AttackPower += statsTotal.Strength + statsTotal.Agility;

            statsTotal.Mana += StatConversion.GetManaFromIntellect(statsTotal.Intellect);
            statsTotal.Mana *= (float)Math.Round(1f + statsTotal.BonusManaMultiplier);

            statsTotal.Health += StatConversion.GetHealthFromStamina(statsTotal.Stamina);
            statsTotal.Health *= (float)Math.Round(1f + statsTotal.BonusHealthMultiplier);

            statsTotal.SpellCrit += StatConversion.GetSpellCritFromRating(statsTotal.CritRating);
            statsTotal.SpellCrit += StatConversion.GetSpellCritFromIntellect(statsTotal.Intellect);
            statsTotal.SpellCrit += statsTotal.SpellCritOnTarget;
            statsTotal.SpellHit  += StatConversion.GetSpellHitFromRating(statsTotal.HitRating +
                                                                         ((.33f * character.ShamanTalents.ElementalPrecision) * statsTotal.Spirit));

            // Flametongue weapon assumed
            statsTotal.SpellPower += (float)Math.Floor(747.78 * (1f + character.ShamanTalents.ElementalWeapons * .2f));
            if (character.ShamanTalents.GlyphofFlametongueWeapon)
            {
                statsTotal.SpellCrit += .02f;
            }

            // Water shield assumed
            statsTotal.Mp5 += 100;
            if (character.ShamanTalents.GlyphofWaterShield)
            {
                statsTotal.Mp5 += 30;
            }

            return(statsTotal);
        }
Example #18
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();
            Stats baseStats = BaseStats.GetBaseStats(character);

            dictValues.Add("Health", BasicStats.Health.ToString());
            dictValues.Add("Stamina", BasicStats.Stamina.ToString());
            float ResilienceCap = 0.15f, ResilienceFromRating = StatConversion.GetCritReductionFromResilience(1);
            float Resilience = StatConversion.GetCritReductionFromResilience(BasicStats.Resilience);

            dictValues.Add("Resilience", string.Format("{0}*-{1}% Damage from DoT and Mana Drains\n\r-{1}% Chance to be crit\r\n-{2}% Damage from Crits.\r\n{3}",
                                                       BasicStats.Resilience.ToString(),
                                                       (Resilience * 100f).ToString("0.00"),
                                                       (Resilience * 100f * 2.2f).ToString("0.00"),
                                                       (Resilience > ResilienceCap)?(string.Format("{0} rating above cap", ((float)Math.Floor((Resilience - ResilienceCap) / ResilienceFromRating)).ToString("0"))):(string.Format("{0} rating below cap", ((float)Math.Ceiling((ResilienceCap - Resilience) / ResilienceFromRating)).ToString("0")))));
            dictValues.Add("Mana", BasicStats.Mana.ToString());
            dictValues.Add("Intellect", BasicStats.Intellect.ToString());
            dictValues.Add("Spirit", Math.Floor(BasicStats.Spirit).ToString("0"));
            dictValues.Add("Spell Power", string.Format("{0}*{1} from Inner Fire",
                                                        Math.Floor(BasicStats.SpellPower).ToString("0"),
                                                        BasicStats.PriestInnerFire * CalculationsHealPriest.GetInnerFireSpellPowerBonus(character)));
            //dictValues.Add("Healing", Math.Floor(BasicStats.SpellPower * 1.88f).ToString("0"));
            dictValues.Add("In FSR MP5", string.Format("{0}*{1} from MP5\r\n{2} from Meditation\r\n{3} Outside FSR\r\n{4} OFSR w/MP5",
                                                       (BasicStats.Mp5 + RegenInFSR).ToString("0"),
                                                       BasicStats.Mp5.ToString("0"),
                                                       RegenInFSR.ToString("0"),
                                                       RegenOutFSR.ToString("0"),
                                                       (BasicStats.Mp5 + RegenOutFSR).ToString("0")));
            dictValues.Add("Spell Crit", string.Format("{0}%*{1}% from Intellect\r\n{2}% from {6} Crit rating\r\n{3}% from Focused Will\r\n{4}% Class Base\r\n{5}% from Buffs",
                                                       (BasicStats.SpellCrit * 100f).ToString("0.00"), (StatConversion.GetSpellCritFromIntellect(BasicStats.Intellect) * 100f).ToString("0.00"), (StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f).ToString("0.00"), character.PriestTalents.FocusedWill.ToString("0"), (baseStats.SpellCrit * 100f).ToString("0.00"), (BasicStats.SpellCrit * 100f - baseStats.SpellCrit * 100f - StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f - StatConversion.GetSpellCritFromIntellect(BasicStats.Intellect) * 100f - character.PriestTalents.FocusedWill * 1f).ToString("0.00"), BasicStats.CritRating));
            dictValues.Add("Healing Crit", string.Format("{0}%*{1} ({1}%) points in Holy Specialization\r\n{2} ({3}%) points in Renewed Hope",
                                                         ((BasicStats.SpellCrit * 100f) + character.PriestTalents.HolySpecialization * 1f + character.PriestTalents.RenewedHope * 2f).ToString("0.00"),
                                                         character.PriestTalents.HolySpecialization, character.PriestTalents.RenewedHope, character.PriestTalents.RenewedHope * 2));
            dictValues.Add("Spell Haste", string.Format("{0}%*{1}% from {2} Haste rating\r\n{3}% ({6}) points in Enlightenment\r\n{4}% from Buffs\r\n{5}s Global Cooldown",
                                                        (BasicStats.SpellHaste * 100f).ToString("0.00"), (StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating) * 100f).ToString("0.00"), BasicStats.HasteRating.ToString(), (character.PriestTalents.Enlightenment * 2).ToString("0"), (((1 + BasicStats.SpellHaste) / (1 + StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating)) / (1 + character.PriestTalents.Enlightenment * 0.02f) - 1) * 100f).ToString("0.00"), Math.Max(1.0f, 1.5f / (1 + BasicStats.SpellHaste)).ToString("0.00"), character.PriestTalents.Enlightenment));
            dictValues.Add("Armor", string.Format("{0}*{1}% Damage Reduction.",
                                                  (BasicStats.Armor + BasicStats.BonusArmor).ToString("0"),
                                                  (StatConversion.GetArmorDamageReduction(80, (BasicStats.Armor + BasicStats.BonusArmor), 0f, 0f, 0f) * 100f).ToString("0.00")));


            float[] Resistances =
            {
                0,
                BasicStats.ArcaneResistance + BasicStats.ArcaneResistanceBuff,
                BasicStats.FireResistance + BasicStats.FireResistanceBuff,
                BasicStats.FrostResistance + BasicStats.FrostResistanceBuff,
                BasicStats.NatureResistance + BasicStats.NatureResistanceBuff,
                BasicStats.ShadowResistance + BasicStats.ShadowResistanceBuff,
            };

            string[] ResistanceNames =
            {
                "None",
                "Arcane",
                "Fire",
                "Frost",
                "Nature",
                "Shadow",
            };

            string ResistanceString = "*Resistances:";

            float MaxResist      = Resistances[0];
            int   MaxResistIndex = 0;
            float AvgResist      = 0f;

            for (int x = 1; x < Resistances.Length; x++)
            {
                AvgResist += Resistances[x];
                if (Resistances[x] > MaxResist)
                {
                    MaxResist      = Resistances[x];
                    MaxResistIndex = x;
                }
                ResistanceString += string.Format("\r\n{0} : {1}", ResistanceNames[x], Resistances[x]);
            }
            AvgResist /= (Resistances.Length - 1);

            if (AvgResist == 0)
            {
                ResistanceString = "None" + ResistanceString;
            }
            else
            {
                string ResistanceName = (MaxResist == AvgResist) ? "All" : ResistanceNames[MaxResistIndex];
                ResistanceString  = string.Format("{0} : {1}", ResistanceName, MaxResist.ToString("0")) + ResistanceString;
                ResistanceString += string.Format("\r\n\r\nResist ({0}):", ResistanceName);
                ResistanceString += string.Format("\r\n{0}", StatConversion.GetResistanceTableString(character.Level + 3, character.Level, MaxResist, 0));
            }

            dictValues.Add("Resistance", ResistanceString);

            BaseSolver solver;

            if ((character.CalculationOptions as CalculationOptionsHealPriest).Role == eRole.CUSTOM)
            {
                solver = new AdvancedSolver(BasicStats, character);
            }
            else
            {
                solver = new Solver(BasicStats, character);
            }
            solver.Calculate(this);

            dictValues.Add("Role", string.Format("{0}*{1}", solver.Role, solver.ActionList));
            dictValues.Add("Burst", string.Format("{0}", HPSBurstPoints.ToString("0")));
            dictValues.Add("Sustained", string.Format("{0}", HPSSustainPoints.ToString("0")));

            dictValues.Add("Renew", new Renew(BasicStats, character).ToString());
            dictValues.Add("Flash Heal", new FlashHeal(BasicStats, character).ToString());
            dictValues.Add("Greater Heal", new Heal(BasicStats, character).ToString());
            dictValues.Add("PoH", new PrayerOfHealing(BasicStats, character).ToString());
            dictValues.Add("Binding Heal", new BindingHeal(BasicStats, character).ToString());
            dictValues.Add("Prayer of Mending", new PrayerOfMending(BasicStats, character).ToString());
            dictValues.Add("Power Word Shield", new PowerWordShield(BasicStats, character).ToString());
            dictValues.Add("Holy Nova", new HolyNova(BasicStats, character).ToString());

            if (character.PriestTalents.CircleOfHealing > 0)
            {
                dictValues.Add("CoH", new CircleOfHealing(BasicStats, character).ToString());
            }
            else
            {
                dictValues.Add("CoH", "- *No required talents");
            }

            if (character.PriestTalents.Lightwell > 0)
            {
                dictValues.Add("Lightwell", new Lightwell(BasicStats, character).ToString());
            }
            else
            {
                dictValues.Add("Lightwell", "- *No required talents");
            }

            if (character.PriestTalents.Penance > 0)
            {
                dictValues.Add("Penance", new Penance(BasicStats, character).ToString());
            }
            else
            {
                dictValues.Add("Penance", "- *No required talents");
            }

            if (Race == CharacterRace.Draenei)
            {
                dictValues.Add("Gift of the Naaru", new GiftOfTheNaaru(BasicStats, character).ToString());
            }
            else
            {
                dictValues.Add("Gift of the Naaru", "-");
            }
            dictValues.Add("Divine Hymn", new DivineHymn(BasicStats, character).ToString());
            dictValues.Add("Resurrection", new Resurrection(BasicStats, character).ToString());

            return(dictValues);
        }
Example #19
0
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string> dictValues = new Dictionary <string, string>();
            Buff   activeBuff;
            string s;
            Stats  baseStats = BaseStats.GetBaseStats(Character);

            #region General
            dictValues["Health"]     = BasicStats.Health.ToString("0");
            dictValues["Mana"]       = BasicStats.Mana.ToString("0");
            dictValues["Item Level"] = String.Format("{0}*Lowest: {1}\nHighest: {2}", Character.AvgWornItemLevel.ToString("0"), Character.MinWornItemLevel.ToString("0"), Character.MaxWornItemLevel.ToString("0"));
            dictValues["Speed"]      = String.Format("{0}%*{0}% Run speed",
                                                     ((1f + BasicStats.MovementSpeed) * 100f).ToString("0"));
            #endregion
            #region Attributes
            dictValues["Strength"]  = BasicStats.Strength.ToString();
            dictValues["Agility"]   = BasicStats.Agility.ToString();
            dictValues["Stamina"]   = BasicStats.Stamina.ToString();
            dictValues["Intellect"] = BasicStats.Intellect.ToString();
            dictValues["Spirit"]    = BasicStats.Spirit.ToString();
            #endregion
            #region Spell
            #region Spell Power
            s = String.Empty;
            float intPower = BasicStats.Intellect - 10;
            if (BasicStats.InnerFire)
            {
                s += String.Format("\n{0} from Inner Fire", PriestInformation.GetInnerFireSpellPowerBonus(Character));
            }
            activeBuff = GetActiveBuffsByGroup("Spell Power");
            if (activeBuff != null)
            {
                s += makeActiveBuffTextPercent(activeBuff, activeBuff.Stats.BonusSpellPowerMultiplier);
            }
            dictValues["Spell Power"] = String.Format("{0}*{1} from {2} Intellect{3}",
                                                      BasicStats.SpellPower.ToString("0"),
                                                      intPower.ToString("0"),
                                                      BasicStats.Intellect.ToString("0"),
                                                      s
                                                      );
            #endregion
            #region Haste
            s = String.Empty;
            if (Character.PriestTalents.Darkness > 0)
            {
                s += String.Format("\n{0}% from {1} points in Darkness", Character.PriestTalents.Darkness, Character.PriestTalents.Darkness);
            }
            activeBuff = GetActiveBuffsByGroup("Spell Haste");
            if (activeBuff != null)
            {
                s += makeActiveBuffTextPercent(activeBuff, activeBuff.Stats.SpellHaste);
            }
            activeBuff = GetActiveBuffsByGroup("Dark Intent");
            if (activeBuff != null)
            {
                s += makeActiveBuffTextPercent(activeBuff, activeBuff.Stats.SpellHaste);
            }
            dictValues["Haste"] = String.Format("{0}%*{1}% from {2} Haste Rating{3}",
                                                (BasicStats.SpellHaste * 100f).ToString("0.00"),
                                                (StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating) * 100f).ToString("0.00"), BasicStats.HasteRating.ToString("0"),
                                                s
                                                );
            #endregion
            dictValues["Hit"]         = (BasicStats.SpellHit * 100f).ToString("0.00");
            dictValues["Penetration"] = BasicStats.SpellPenetration.ToString("0");
            #region Mana Regen
            float manaRegen = StatConversion.GetSpiritRegenSec(BasicStats.Spirit, BasicStats.Intellect) * 5f;
            s          = String.Format("\n{0} Mana per 5 sec from Base Mana Regeneration", (baseStats.Mana * 0.05f).ToString("0"));
            activeBuff = GetActiveBuffsByGroup("Mana Regeneration");
            if (activeBuff != null)
            {
                s += makeActiveBuffText(activeBuff, activeBuff.Stats.Mp5);
            }
            dictValues["Mana Regen"] = String.Format("{0}*{1} from Spirit based regen{2}",
                                                     (manaRegen + BasicStats.Mp5).ToString("0"),
                                                     manaRegen.ToString("0"),
                                                     s
                                                     );
            dictValues["Combat Regen"] = String.Format("{0}*{1} from Spirit based regen{2}",
                                                       (manaRegen * BasicStats.SpellCombatManaRegeneration + BasicStats.Mp5).ToString("0"),
                                                       (manaRegen * BasicStats.SpellCombatManaRegeneration).ToString("0"),
                                                       s
                                                       );
            #endregion
            #region Crit
            s          = String.Empty;
            activeBuff = GetActiveBuffsByGroup("Critical Strike Chance");
            if (activeBuff != null)
            {
                s += makeActiveBuffTextPercent(activeBuff, activeBuff.Stats.SpellCrit);
            }
            activeBuff = GetActiveBuffsByGroup("Focus Magic, Spell Critical Strike Chance");
            if (activeBuff != null)
            {
                s += makeActiveBuffTextPercent(activeBuff, activeBuff.Stats.SpellCrit);
            }
            dictValues["Crit Chance"] = String.Format("{0}%*{1}% from {2} Crit Rating\n{3}% from {4} Intellect\n{5}% from Priest base{6}",
                                                      (BasicStats.SpellCrit * 100f).ToString("0.00"),
                                                      (StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f).ToString("0.00"), BasicStats.CritRating.ToString("0"),
                                                      (StatConversion.GetSpellCritFromIntellect(BasicStats.Intellect) * 100f).ToString("0.00"), BasicStats.Intellect.ToString("0"),
                                                      (baseStats.SpellCrit * 100f).ToString("0.00"),
                                                      s
                                                      );
            #endregion
            #region Mastery
            s = string.Empty;
            float masteryBase = 0, masteryBonus = 0;
            if (BasicStats.PriestSpec == ePriestSpec.Spec_Disc)
            {
                masteryBase  = PriestInformation.DisciplineMasteryBase;
                masteryBonus = PriestInformation.DisciplineMasteryEffect * 100f;
                s           += String.Format("\n\nEach point of mastery increases the potency of Absorbs by an additional {0}%.", masteryBonus.ToString("0.00"));
            }
            else if (BasicStats.PriestSpec == ePriestSpec.Spec_Holy)
            {
                masteryBase  = PriestInformation.HolyMasteryBase;
                masteryBonus = PriestInformation.HolyMasteryEffect * 100f;
                s           += String.Format("\n\nEach point of mastery provides an additional {0}% healing over 6 sec.", masteryBonus.ToString("0.00"));
            }
            dictValues["Mastery"] = String.Format("{0}%*{1}% from {2} Mastery Rating\n{3}% from {4} Base Mastery{5}",
                                                  ((StatConversion.GetMasteryFromRating(BasicStats.MasteryRating) + masteryBase) * masteryBonus).ToString("0.00"),
                                                  (StatConversion.GetMasteryFromRating(BasicStats.MasteryRating) * masteryBonus).ToString("0.00"), BasicStats.MasteryRating.ToString("0"),
                                                  (masteryBase * masteryBonus).ToString("0.00"), masteryBase.ToString("0"),
                                                  s
                                                  );
            #endregion
            #endregion
            #region Defense
            dictValues["Armor"] = String.Format("{0}*{1}% physical damage reduction from same level target",
                                                BasicStats.Armor.ToString("0"),
                                                (StatConversion.GetDamageReductionFromArmor(Character.Level, BasicStats.Armor) * 100f).ToString("0.00"));
            dictValues["Dodge"]      = String.Format("{0}%", (BasicStats.Dodge * 100f).ToString("0.00"));
            dictValues["Resilience"] = String.Format("{0}*{1}% damage reduction on attacks from other players\n{2}% damage reduction from spells",
                                                     BasicStats.Resilience.ToString("0"),
                                                     (StatConversion.GetDamageReductionFromResilience(BasicStats.Resilience) * 100f).ToString("0.00"),
                                                     (Character.PriestTalents.InnerSanctum * 2f).ToString("0"));
            #endregion
            #region Resistance
            string   resistTxt   = "{0}*PvP\n{1}\n\nBoss\n{2}";
            string[] resistList  = { "Arcane", "Fire", "Frost", "Nature", "Shadow" };
            float[]  resistances = { BasicStats.ArcaneResistance + BasicStats.ArcaneResistanceBuff,
                                     BasicStats.FireResistance + BasicStats.FireResistanceBuff,
                                     BasicStats.FrostResistance + BasicStats.FrostResistanceBuff,
                                     BasicStats.NatureResistance + BasicStats.NatureResistanceBuff,
                                     BasicStats.ShadowResistance + BasicStats.ShadowResistanceBuff };

            for (int x = 0; x < resistList.Length; x++)
            {
                dictValues[resistList[x]] = String.Format(resistTxt,
                                                          resistances[x].ToString("0"),
                                                          StatConversion.GetResistanceTableString(Character.Level, Character.Level, resistances[x], 0f),
                                                          StatConversion.GetResistanceTableString(Character.Level + 3, Character.Level, resistances[x], 0f)
                                                          );
            }
            #endregion
            #region Model
            CalculationOptionsHealPriest calcOpts = Character.CalculationOptions as CalculationOptionsHealPriest;
            if (calcOpts != null)
            {
                PriestSolver solver = PriestModels.GetModel(this, calcOpts, true);
                solver.Solve();
                List <string> reqs = solver.MeetsRequirements();
                string        disp;
                if (reqs.Count > 0)
                {
                    disp = String.Format("{0}\n\n{1}", solver.Name, String.Join("\n", reqs));
                }
                else
                {
                    disp = solver.Name;
                }
                dictValues["Role"]       = disp;
                dictValues["Burst Goal"] = this.BurstGoal.ToString("0");
                dictValues["Sust. Goal"] = this.SustainGoal.ToString("0");
                dictValues["Mana Goal"]  = this.ManaGoal.ToString("0");
                dictValues["Burst"]      = this.BurstPoints.ToString("0");
                dictValues["Sustained"]  = this.SustainPoints.ToString("0");
                dictValues["Mana "]      = this.ManaPoints.ToString("0");
            }
            #endregion
            #region Holy Spells
            SpellHeal spellHeal = new SpellHeal(Character, BasicStats);
            dictValues["Heal"] = String.Format("{0}*{1}", spellHeal.HPS().ToString("0"), spellHeal.ToString());
            SpellGreaterHeal spellGreaterHeal = new SpellGreaterHeal(Character, BasicStats);
            dictValues["Greater Heal"] = String.Format("{0}*{1}", spellGreaterHeal.HPS().ToString("0"), spellGreaterHeal.ToString());
            SpellFlashHeal spellFlashHeal = new SpellFlashHeal(Character, BasicStats);
            dictValues["Flash Heal"] = String.Format("{0}*{1}", spellFlashHeal.HPS().ToString("0"), spellFlashHeal.ToString());
            SpellBindingHeal spellBindingHeal = new SpellBindingHeal(Character, BasicStats);
            dictValues["Binding Heal"] = String.Format("{0}*{1}", spellBindingHeal.HPS().ToString("0"), spellBindingHeal.ToString());
            SpellRenew spellRenew = new SpellRenew(Character, BasicStats);
            dictValues["Renew"] = String.Format("{0}*{1}", spellRenew.HPS().ToString("0"), spellRenew.ToString());
            if (Character.PriestTalents.Lightwell > 0)
            {
                SpellLightwell spellLW = new SpellLightwell(Character, BasicStats);
                dictValues["Lightwell"] = String.Format("{0}*{1}", spellLW.HPS().ToString("0"), spellLW.ToString());
            }
            else
            {
                dictValues["Lightwell"] = "N/A*You do not have the talent required.";
            }
            SpellPrayerOfHealing spellProH = new SpellPrayerOfHealing(Character, BasicStats);
            dictValues["ProH"] = String.Format("{0}*{1}", spellProH.HPS().ToString("0"), spellProH.ToString());
            SpellHolyNova spellHolyNova = new SpellHolyNova(Character, BasicStats);
            dictValues["Holy Nova"] = String.Format("NYI*{1}", spellHolyNova.HPS().ToString("0"), spellHolyNova.ToString());
            if (Character.PriestTalents.CircleOfHealing > 0)
            {
                SpellCircleOfHealing spellCoH = new SpellCircleOfHealing(Character, BasicStats);
                dictValues["CoH"] = String.Format("{0}*{1}", spellCoH.HPS().ToString("0"), spellCoH.ToString());
            }
            else
            {
                dictValues["CoH"] = "N/A*You do not have the talent required.";
            }
            if (BasicStats.PriestSpec == ePriestSpec.Spec_Disc)
            {
                SpellPenance spellPenance = new SpellPenance(Character, BasicStats);
                dictValues["Penance"] = String.Format("{0}*{1}", spellPenance.HPS().ToString("0"), spellPenance.ToString());
            }
            else
            {
                dictValues["Penance"] = "N/A*You do not have the correct Talent specialization.";
            }
            if (Character.PriestTalents.Revelations > 0)
            {
                SpellSerenity spellSerenity = new SpellSerenity(Character, BasicStats);
                dictValues["HW Serenity"] = String.Format("{0}*{1}", spellSerenity.HPS().ToString("0"), spellSerenity.ToString());
                SpellSanctuary spellSanctuary = new SpellSanctuary(Character, BasicStats);
                dictValues["HW Sanctuary"] = String.Format("{0}*{1}", spellSanctuary.HPS().ToString("0"), spellSanctuary.ToString());
            }
            else
            {
                dictValues["HW Serenity"]  = "N/A*You do not have the talent required.";
                dictValues["HW Sanctuary"] = "N/A*You do not have the talent required.";
            }
            SpellPrayerOfMending spellProM = new SpellPrayerOfMending(Character, BasicStats, 1);
            dictValues["ProM"]        = String.Format("{0}*{1}", spellProM.HPS().ToString("0"), spellProM.ToString());
            spellProM                 = new SpellPrayerOfMending(Character, BasicStats);
            dictValues["ProM 5 Hits"] = String.Format("{0}*{1}", spellProM.HPS().ToString("0"), spellProM.ToString());
            SpellPowerWordShield spellPWS = new SpellPowerWordShield(Character, BasicStats);
            dictValues["PWS"] = String.Format("{0}*{1}", spellPWS.HPS().ToString("0"), spellPWS.ToString());
            SpellDivineHymn spellDivineHymn = new SpellDivineHymn(Character, BasicStats);
            dictValues["Divine Hymn"] = String.Format("{0}*{1}", spellDivineHymn.HPS().ToString("0"), spellDivineHymn.ToString());
            if (Character.Race == CharacterRace.Draenei)
            {
                SpellGiftOfTheNaaru spellGoat = new SpellGiftOfTheNaaru(Character, BasicStats);
                dictValues["Gift of the Naaru"] = String.Format("{0}*{1}", spellGoat.HPS().ToString("0"), spellGoat.ToString());
            }
            else
            {
                dictValues["Gift of the Naaru"] = "N/A*You are not a spacegoat!";
            }
            SpellResurrection spellResurrection = new SpellResurrection(Character, BasicStats);
            dictValues["Resurrection"] = String.Format("{0}*{1}", spellResurrection.CastTime.ToString("0.00"), spellResurrection.ToString());
            #endregion
            #region Shadow Spells
            #endregion
            return(dictValues);
        }
Example #20
0
        public void UpdateCalcs(bool firstPass)
        {
            // talents
            if (_calcOpts.PriorityInUse(EnhanceAbility.StormStrike))
            {
                stormstrikeBonusCrit = .25f * _talents.Stormstrike + (_talents.GlyphofStormstrike ? .1f : 0f);
            }
            else
            {
                stormstrikeBonusCrit = 0f;
            }
            //set bonus
            enhance4T11 = 0f;
            _character.SetBonusCount.TryGetValue("Battlegear of the Raging Elements", out setCount);
            if (setCount >= 4)
            {
                enhance4T11 = 0.1f;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            averageFSDotTime  = _talents.GlyphofFlameShock ? 27f : 18f;
            averageFSTickTime = 3f / (1f + spellhaste);
        }
Example #21
0
        public Stats GetCharacterStats(Character character, Item additionalItem, bool computeAverageStats, CharacterCalculationsHealadin calc)
        {
            PaladinTalents talents = character.PaladinTalents;

            CalculationOptionsHealadin calcOpts = character.CalculationOptions as CalculationOptionsHealadin;

            if (calcOpts == null)
            {
                calcOpts = new CalculationOptionsHealadin();
            }

#if (RAWR3)
            BossOptions bossOpts = character.BossOptions;
            if (bossOpts == null)
            {
                bossOpts = new BossOptions();
            }
#endif

#if (RAWR3)
            float fightLength = bossOpts.BerserkTimer * 60f;
#else
            float fightLength = calcOpts.Length * 60f;
#endif

            Stats statsRace     = BaseStats.GetBaseStats(character.Level, CharacterClass.Paladin, character.Race);
            Stats statsBaseGear = GetItemStats(character, additionalItem);
            Stats statsBuffs    = GetBuffsStats(character, calcOpts);
            Stats stats         = statsBaseGear + statsBuffs + statsRace;

            ConvertRatings(stats, talents, calcOpts);
            if (computeAverageStats)
            {
                Stats statsAverage = new Stats();

                foreach (SpecialEffect effect in stats.SpecialEffects())
                {
                    float trigger = 0f;
                    if (calc == null)
                    {
                        trigger = 1.5f / calcOpts.Activity / (1f + stats.SpellHaste);
                        if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                        {
                            trigger *= stats.SpellCrit;
                        }
                        else if (effect.Trigger == Trigger.HolyShockCast)
                        {
                            trigger = 6f / calcOpts.HolyShock;
                        }
                    }
                    else
                    {
                        if (effect.Trigger == Trigger.HealingSpellCast || effect.Trigger == Trigger.HealingSpellHit)
                        {
                            trigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                        {
                            trigger = 1f / Rotation.GetHealingCritsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.SpellCast || effect.Trigger == Trigger.SpellHit)
                        {
                            trigger = 1f / Rotation.GetSpellCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.DamageOrHealingDone)
                        {
                            trigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                        }
                        else if (effect.Trigger == Trigger.HolyShockCast)
                        {
                            trigger = 6f / calcOpts.HolyShock;
                        }
                        else if (effect.Trigger == Trigger.Use)
                        {
                            trigger = 0f;
                            foreach (SpecialEffect childEffect in effect.Stats.SpecialEffects())
                            {
                                float childTrigger = 0f;

                                if (effect.Trigger == Trigger.HealingSpellCast || effect.Trigger == Trigger.HealingSpellHit)
                                {
                                    childTrigger = 1f / Rotation.GetHealingCastsPerSec(calc);
                                }
                                else if (effect.Trigger == Trigger.HealingSpellCrit || effect.Trigger == Trigger.SpellCrit)
                                {
                                    childTrigger = 1f / Rotation.GetHealingCritsPerSec(calc);
                                }
                                else if (effect.Trigger == Trigger.SpellCast || effect.Trigger == Trigger.SpellHit)
                                {
                                    childTrigger = 1f / Rotation.GetSpellCastsPerSec(calc);
                                }

                                statsAverage.Accumulate(childEffect.Stats,
                                                        effect.GetAverageUptime(0.0f, 1.0f)
                                                        * childEffect.GetAverageStackSize(childTrigger, 1f, 1.5f, effect.Duration));
                            }
                        }
                        else if (effect.Trigger == Trigger.HolyLightCast)
                        {
                            trigger = 1f / Rotation.GetHolyLightCastsPerSec(calc);
                        }
                        else
                        {
                            continue;
                        }
                    }
                    statsAverage.Accumulate(effect.GetAverageStats(trigger, 1f, 1.5f, fightLength));
                }
                statsAverage.ManaRestore *= fightLength;
                statsAverage.Healed      *= fightLength;

                stats = statsBaseGear + statsBuffs + statsRace + statsAverage;
                ConvertRatings(stats, talents, calcOpts);
            }

            return(stats);
        }
Example #22
0
File: EnhSim.cs Project: rakot/rawr
        public EnhSim(Character character, CalculationOptionsEnhance calcOpts, BossOptions bossOpts)
        {
            _character = character;
            _calcOpts  = calcOpts;
            _bossOpts  = bossOpts;
            CalculationsEnhance          ce    = new CalculationsEnhance();
            CharacterCalculationsEnhance calcs = ce.GetCharacterCalculations(character, null) as CharacterCalculationsEnhance;
            Stats       stats = calcs.EnhSimStats;
            CombatStats cs    = new CombatStats(character, stats, _calcOpts, bossOpts);

            getSpecialsNames(character, stats);

            StringBuilder sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine("##########################################");
            sb.AppendLine("### Rawr.Enhance Data Export to EnhSim ###");
            sb.AppendLine("##########################################");
            sb.AppendLine();
            sb.AppendLine("config_source rawr");
            sb.AppendLine();

            float MHSpeed = character.MainHand == null ? 3.0f : character.MainHand.Item.Speed;
            float wdpsMH  = character.MainHand == null ? 46.3f : character.MainHand.Item.DPS;
            float OHSpeed = character.OffHand == null ? 3.0f : character.OffHand.Item.Speed;
            float wdpsOH  = character.OffHand == null ? 46.3f : character.OffHand.Item.DPS;

            sb.AppendLine("race                            " + character.Race.ToString().ToLower());
            sb.AppendLine("mh_speed                        " + MHSpeed.ToString("F1", CultureInfo.InvariantCulture));
            sb.AppendLine("oh_speed                        " + OHSpeed.ToString("F1", CultureInfo.InvariantCulture));
            sb.AppendLine("mh_dps                          " + wdpsMH.ToString("F1", CultureInfo.InvariantCulture));
            sb.AppendLine("oh_dps                          " + wdpsOH.ToString("F1", CultureInfo.InvariantCulture));
            sb.AppendLine("str                             " + stats.Strength.ToString("F0", CultureInfo.InvariantCulture));
            sb.AppendLine("agi                             " + stats.Agility.ToString("F0", CultureInfo.InvariantCulture));
            sb.AppendLine("int                             " + stats.Intellect.ToString("F0", CultureInfo.InvariantCulture));
            sb.AppendLine("spi                             " + stats.Spirit.ToString("F0", CultureInfo.InvariantCulture));
            sb.AppendLine("mastery_rating                  " + stats.MasteryRating.ToString("F0", CultureInfo.InvariantCulture));
            float chanceCrit = cs.ExportMeleeCritMH * 100f;

            sb.AppendLine("mh_crit                         " + chanceCrit.ToString("F2", CultureInfo.InvariantCulture));
            chanceCrit = cs.ExportMeleeCritOH * 100f;
            sb.AppendLine("oh_crit                         " + chanceCrit.ToString("F2", CultureInfo.InvariantCulture));
            float hitBonus = StatConversion.GetHitFromRating(stats.HitRating) * 100f + 6f;

            if (character.Race == CharacterRace.Draenei)
            {
                hitBonus += 1f;
            }
            sb.AppendLine("mh_hit                          " + hitBonus.ToString("F2", CultureInfo.InvariantCulture));
            sb.AppendLine("oh_hit                          " + hitBonus.ToString("F2", CultureInfo.InvariantCulture));
            sb.AppendLine("mh_expertise_rating             " + stats.ExpertiseRating.ToString("F0", CultureInfo.InvariantCulture));
            sb.AppendLine("oh_expertise_rating             " + stats.ExpertiseRating.ToString("F0", CultureInfo.InvariantCulture));
            float unleashedRage = 0f;

            switch (character.ShamanTalents.UnleashedRage)
            {
            case 1: unleashedRage = .05f; break;

            case 2: unleashedRage = .10f; break;
            }
            sb.AppendLine("ap                              " + (stats.AttackPower * (1f + unleashedRage)).ToString("F0", CultureInfo.InvariantCulture));
            float hasteBonus = StatConversion.GetHasteFromRating(stats.HasteRating, CharacterClass.Shaman) * 100f;

            sb.AppendLine("melee_haste                     " + hasteBonus.ToString("F2", CultureInfo.InvariantCulture));
            float MQUnleashedRageSpellpower = stats.AttackPower * unleashedRage * 0.50f;

            sb.AppendLine("spellpower                      " + (stats.SpellPower + MQUnleashedRageSpellpower).ToString("F0", CultureInfo.InvariantCulture));
            float chanceSpellCrit = cs.DisplaySpellCrit * 100f;

            sb.AppendLine("spell_crit                      " + chanceSpellCrit.ToString("F2", CultureInfo.InvariantCulture));
            float elemPrec = character.ShamanTalents.ElementalPrecision > 0 ? (stats.Spirit - BaseStats.GetBaseStats(character).Spirit) * (character.ShamanTalents.ElementalPrecision / 3f) : 0f;

            hitBonus = StatConversion.GetSpellHitFromRating(stats.HitRating + elemPrec) * 100f;
            if (character.Race == CharacterRace.Draenei)
            {
                hitBonus += 1f;
            }
            sb.AppendLine("spell_hit                       " + hitBonus.ToString("F2", CultureInfo.InvariantCulture));
            hasteBonus = StatConversion.GetSpellHasteFromRating(stats.HasteRating) * 100f;
            sb.AppendLine("spell_haste                     " + hasteBonus.ToString("F2", CultureInfo.InvariantCulture));
            sb.AppendLine("max_mana                        " + stats.Mana.ToString());
            sb.AppendLine("mp5                             " + stats.Mp5.ToString());
            sb.AppendLine();
            sb.AppendLine("mh_imbue                        " + _calcOpts.MainhandImbue.ToString().ToLower());
            sb.AppendLine("oh_imbue                        " + _calcOpts.OffhandImbue.ToString().ToLower());
            sb.AppendLine();
            sb.AppendLine("mh_enchant                      " + _mhEnchant);
            sb.AppendLine("oh_enchant                      " + _ohEnchant);
            String weaponType = "-";

            if (character.MainHand != null)
            {
                if (character.MainHand.Type == ItemType.OneHandAxe || character.MainHand.Type == ItemType.TwoHandAxe)
                {
                    weaponType = "axe";
                }
                if (character.MainHand.Type == ItemType.FistWeapon)
                {
                    weaponType = "fist";
                }
                if (character.MainHand.Type == ItemType.OneHandMace || character.MainHand.Type == ItemType.TwoHandMace)
                {
                    weaponType = "mace";
                }
            }
            sb.AppendLine("mh_weapon                       " + weaponType);
            weaponType = "-";
            if (character.OffHand != null)
            {
                if (character.OffHand.Type == ItemType.OneHandAxe)
                {
                    weaponType = "axe";
                }
                if (character.OffHand.Type == ItemType.FistWeapon)
                {
                    weaponType = "fist";
                }
                if (character.OffHand.Type == ItemType.OneHandMace)
                {
                    weaponType = "mace";
                }
            }
            sb.AppendLine("oh_weapon                       " + weaponType);
            sb.AppendLine();
            sb.AppendLine("trinket1                        " + _trinket1name);
            sb.AppendLine("trinket2                        " + _trinket2name);
            sb.AppendLine();
            sb.AppendLine(getSetBonuses(character));
            sb.AppendLine("metagem                         " + _metagem);
            sb.AppendLine();
            string glovesEnchant = character.HandsTinkering == null ? string.Empty : character.HandsTinkering.Name;

            if (glovesEnchant == "Synapse Springs")
            {
                sb.AppendLine("gloves_enchant                  synapse_springs");
            }
            else if (glovesEnchant == "Tazik Shocker")
            {
                sb.AppendLine("gloves_enchant                  tazik_shocker");
            }
            else
            {
                sb.AppendLine("gloves_enchant                  -");
            }
            string cloakEnchant = character.BackEnchant == null ? string.Empty : character.BackEnchant.Name;

            if (cloakEnchant == "Lightweave Embroidery")
            {
                sb.AppendLine("cloak_enchant                   lightweave_embroidery");
            }
            else if (cloakEnchant == "Swordguard Embroidery")
            {
                sb.AppendLine("cloak_enchant                   swordguard_embroidery");
            }
            else
            {
                sb.AppendLine("cloak_enchant                   -");
            }
            string weaponSetProc = "-";

            if (character.MainHand != null && character.OffHand != null)
            {
                if (character.MainHand.Id == 63537 && character.OffHand.Id == 63538)
                {
                    weaponSetProc = "agony_and_torment";
                }
            }
            sb.AppendLine("weapon_set_proc                   " + weaponSetProc);

            /*addGlyphs(character, sb);
             * sb.AppendLine();
             * sb.AppendLine("#############");
             * sb.AppendLine("## Talents ##");
             * sb.AppendLine("#############");
             * sb.AppendLine("primary_talent                  enhancement");
             * sb.AppendLine();
             * sb.AppendLine("elemental_weapons               " + character.ShamanTalents.ElementalWeapons + "/2");
             * sb.AppendLine("focused_strikes                 " + character.ShamanTalents.FocusedStrikes + "/3");
             * sb.AppendLine("improved_shields                " + character.ShamanTalents.ImprovedShields + "/3");
             * sb.AppendLine("elemental_devastation           " + character.ShamanTalents.ElementalDevastation + "/3");
             * sb.AppendLine("flurry                          " + character.ShamanTalents.Flurry + "/3");
             * sb.AppendLine("static_shock                    " + character.ShamanTalents.StaticShock + "/3");
             * sb.AppendLine("improved_fire_nova              " + character.ShamanTalents.ImprovedFireNova + "/2");
             * sb.AppendLine("searing_flames                  " + character.ShamanTalents.SearingFlames + "/3");
             * sb.AppendLine("frozen_power                    " + character.ShamanTalents.FrozenPower + "/2");
             * sb.AppendLine("shamanistic_rage                " + character.ShamanTalents.ShamanisticRage + "/1");
             * sb.AppendLine("unleashed_rage                  " + character.ShamanTalents.UnleashedRage + "/2");
             * sb.AppendLine("maelstrom_weapon                " + character.ShamanTalents.MaelstromWeapon + "/3");
             * sb.AppendLine("improved_lava_lash              " + character.ShamanTalents.ImprovedLavaLash + "/2");
             * sb.AppendLine();
             * //elemental talents in EnhSim have not been updated, so keep exporting old talent choices where appropriate.
             * sb.AppendLine("convection                      " + character.ShamanTalents.Convection + "/2");
             * sb.AppendLine("concussion                      " + character.ShamanTalents.Concussion + "/3");
             * sb.AppendLine("call_of_flame                   " + character.ShamanTalents.CallOfFlame + "/2");
             * sb.AppendLine("reverberation                   " + character.ShamanTalents.Reverberation + "/2");
             * sb.AppendLine("elemental_precision             " + character.ShamanTalents.ElementalPrecision + "/3");
             * sb.AppendLine("elemental_focus                 " + character.ShamanTalents.ElementalFocus + "/1");
             * sb.AppendLine("elemental_oath                  " + character.ShamanTalents.ElementalOath + "/2");
             * sb.AppendLine("lava_flows                      " + character.ShamanTalents.LavaFlows + "/3");
             * sb.AppendLine("storm_earth_and_fire            " + "0" + "/3");
             * sb.AppendLine("elemental_mastery               " + character.ShamanTalents.ElementalMastery + "/1");
             * sb.AppendLine("feedback                        " + character.ShamanTalents.Feedback + "/3");
             * sb.AppendLine("lava_surge                      " + character.ShamanTalents.LavaSurge + "/2");
             * sb.AppendLine();
             *
             * addBuffs(character, sb);
             * // add extras
             * sb.AppendLine();
             * sb.AppendLine("combat_length                   " + (_bossOpts.BerserkTimer/60f).ToString("F2", CultureInfo.InvariantCulture));*/
            _configText = sb.ToString();
        }
        public override Dictionary <string, string> GetCharacterDisplayCalculationValues()
        {
            Dictionary <string, string>    dictValues = new Dictionary <string, string>();
            CalculationOptionsShadowPriest calcOpts   = character.CalculationOptions as CalculationOptionsShadowPriest;
            BossOptions BossOpts  = character.BossOptions;
            Stats       baseStats = BaseStats.GetBaseStats(character.Level, character.Class, character.Race);
            bool        Ptr       = calcOpts.PTR;

            dictValues.Add("Health", BasicStats.Health.ToString());
            float ResilienceCap = 0.15f, ResilienceFromRating = StatConversion.GetCritReductionFromResilience(1);
            float Resilience = StatConversion.GetCritReductionFromResilience(BasicStats.Resilience);

            dictValues.Add("Resilience", string.Format("{0}*-{1}% Damage from DoT and Mana Drains\n\r-{1}% Chance to be crit\r\n-{2}% Damage from Crits.\r\n{3}",
                                                       BasicStats.Resilience.ToString(),
                                                       (Resilience * 100f).ToString("0.00"),
                                                       (Resilience * 100f * 2.2f).ToString("0.00"),
                                                       (Resilience > ResilienceCap) ? (string.Format("{0} rating above cap", ((float)Math.Floor((Resilience - ResilienceCap) / ResilienceFromRating)).ToString("0"))) : (string.Format("{0} rating below cap", ((float)Math.Ceiling((ResilienceCap - Resilience) / ResilienceFromRating)).ToString("0")))));
            dictValues.Add("Stamina", BasicStats.Stamina.ToString());
            dictValues.Add("Mana", BasicStats.Mana.ToString());
            dictValues.Add("Intellect", BasicStats.Intellect.ToString());
            dictValues.Add("Spirit", Math.Floor(BasicStats.Spirit).ToString("0"));
            dictValues.Add("Spell Power", String.Format("{0}*{1} Bonus Shadow\r\n{2} Bonus Holy\r\n{3} from Inner Fire",
                                                        Math.Floor(BasicStats.SpellPower),
                                                        Math.Floor(BasicStats.SpellPower + BasicStats.SpellShadowDamageRating),
                                                        Math.Floor(BasicStats.SpellPower /*+ BasicStats.SpellHolyDamageRating*/),
                                                        BasicStats.PriestInnerFire * CalculationsShadowPriest.GetInnerFireSpellPowerBonus(character)));
            dictValues.Add("Regen", String.Format("{0}*MP5: {1}\r\nOutFSR: {2}", RegenInFSR.ToString("0"), BasicStats.Mp5.ToString(), RegenOutFSR.ToString("0")));

            dictValues.Add("Crit", string.Format("{0}%*{1}% from {2} Spell Crit rating\r\n{3}% from Intellect\r\n{4}% from Focused Will\r\n{5}% from Base Crit\r\n{6}% from Buffs\r\n{7}% on Mind Blast, Mind Flay and Mind Sear.\r\n{8}% on VT, SW:P and DP\r\n{9}% on Smite, Holy Fire and Penance.",
                                                 (BasicStats.SpellCrit * 100f).ToString("0.00"),
                                                 (StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f).ToString("0.00"),
                                                 BasicStats.CritRating.ToString("0"),
                                                 (StatConversion.GetSpellCritFromIntellect(BasicStats.Intellect) * 100f).ToString("0.00"),
                                                 character.PriestTalents.FocusedWill,
                                                 (baseStats.SpellCrit * 100f).ToString("0.00"),
                                                 (BasicStats.SpellCrit * 100f - StatConversion.GetSpellCritFromRating(BasicStats.CritRating) * 100f - StatConversion.GetSpellCritFromIntellect(BasicStats.Intellect) * 100f - baseStats.SpellCrit * 100f - character.PriestTalents.FocusedWill).ToString("0.00"),
                                                 (BasicStats.SpellCrit * 100f + character.PriestTalents.MindMelt * 2f).ToString("0.00"),
                                                 (BasicStats.SpellCrit * 100f + character.PriestTalents.MindMelt * 3f).ToString("0.00"),
                                                 (BasicStats.SpellCrit * 100f + character.PriestTalents.HolySpecialization * 1f).ToString("0.00")));

#if RAWR3 || SILVERLIGHT
            float Hit = 100 - (StatConversion.GetSpellMiss(character.Level - BossOpts.Level, false) * 100);
#else
            float Hit = 100 - (StatConversion.GetSpellMiss(-calcOpts.TargetLevel, false) * 100);
#endif
            float  BonusHit   = BasicStats.SpellHit * 100f;
            float  RacialHit  = 0;
            string RacialText = "";
            if (character.Race == CharacterRace.Draenei)
            {
                RacialHit  = 1;
                RacialText = "1% from Draenei Racial\r\n";
                if (!character.ActiveBuffsContains("Heroic Presence"))
                {
                    BonusHit += 1;
                }
            }
            float DebuffHit = character.PriestTalents.Misery * 1f;
            if (character.ActiveBuffsConflictingBuffContains("Spell Hit Chance Taken"))
            {
                DebuffHit = 3f;
            }
            else
            {
                BonusHit += DebuffHit;
            }

            float RHitRating     = 0.01f / StatConversion.GetSpellHitFromRating(1);
            float ShadowFocusHit = character.PriestTalents.ShadowFocus * 1f;
            float HitShadow      = Hit + BonusHit + ShadowFocusHit;
            float HitHoly        = Hit + BonusHit;
            dictValues.Add("Hit", string.Format("{0}%*{1}% from {2} Hit Rating\r\n{3}% from Buffs\r\n{4}% from {5} points in Misery\r\n{6}% from {7} points in Shadow Focus\r\n{8}{9}% Hit with Shadow spells, {10}\r\n{11}% Hit with Holy spells, {12}",
                                                BonusHit.ToString("0.00"),
                                                (StatConversion.GetSpellHitFromRating(BasicStats.HitRating) * 100f).ToString("0.00"), BasicStats.HitRating,
                                                (BonusHit - StatConversion.GetSpellHitFromRating(BasicStats.HitRating) * 100f - RacialHit - DebuffHit).ToString("0.00"),
                                                DebuffHit, character.PriestTalents.Misery,
                                                ShadowFocusHit, character.PriestTalents.ShadowFocus,
                                                RacialText,
                                                HitShadow.ToString("0.00"), (HitShadow > 100f) ? string.Format("{0} hit rating above cap", Math.Floor((HitShadow - 100f) * RHitRating)) : string.Format("{0} hit rating below cap", Math.Ceiling((100f - HitShadow) * RHitRating)),
                                                HitHoly.ToString("0.00"), (HitHoly > 100f) ? string.Format("{0} hit rating above cap", Math.Floor((HitHoly - 100f) * RHitRating)) : string.Format("{0} hit rating below cap", Math.Ceiling((100f - HitHoly) * RHitRating))));

            dictValues.Add("Haste", string.Format("{0}%*{1}% from {2} Haste rating\r\n{3}% ({6}) points in Enlightenment\r\n{4}% from Buffs\r\n{5}s Global Cooldown",
                                                  (BasicStats.SpellHaste * 100f).ToString("0.00"), (StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating) * 100f).ToString("0.00"), BasicStats.HasteRating.ToString(), (character.PriestTalents.Enlightenment * 2).ToString("0"), (((1f + BasicStats.SpellHaste) / (1f + StatConversion.GetSpellHasteFromRating(BasicStats.HasteRating)) / (1f + character.PriestTalents.Enlightenment * 0.02f) - 1f) * 100f).ToString("0.00"), Math.Max(1.0f, 1.5f / (1 + BasicStats.SpellHaste)).ToString("0.00"), character.PriestTalents.Enlightenment));
            dictValues.Add("Armor", string.Format("{0}*{1}% Damage Reduction.",
                                                  (BasicStats.Armor + BasicStats.BonusArmor).ToString("0"),
                                                  (StatConversion.GetArmorDamageReduction(80, (BasicStats.Armor + BasicStats.BonusArmor), 0f, 0f, 0f) * 100f).ToString("0.00")));

            float[] Resistances =
            {
                0,
                BasicStats.ArcaneResistance + BasicStats.ArcaneResistanceBuff,
                BasicStats.FireResistance + BasicStats.FireResistanceBuff,
                BasicStats.FrostResistance + BasicStats.FrostResistanceBuff,
                BasicStats.NatureResistance + BasicStats.NatureResistanceBuff,
                BasicStats.ShadowResistance + BasicStats.ShadowResistanceBuff,
            };

            string[] ResistanceNames =
            {
                "None",
                "Arcane",
                "Fire",
                "Frost",
                "Nature",
                "Shadow",
            };

            string ResistanceString = "*Resistances:";

            float MaxResist      = Resistances[0];
            int   MaxResistIndex = 0;
            float AvgResist      = 0f;
            for (int x = 1; x < Resistances.Length; x++)
            {
                AvgResist += Resistances[x];
                if (Resistances[x] > MaxResist)
                {
                    MaxResist      = Resistances[x];
                    MaxResistIndex = x;
                }
                ResistanceString += string.Format("\r\n{0} : {1}", ResistanceNames[x], Resistances[x]);
            }
            AvgResist /= (Resistances.Length - 1);

            if (AvgResist == 0)
            {
                ResistanceString = "None" + ResistanceString;
            }
            else
            {
                string ResistanceName = (MaxResist == AvgResist) ? "All" : ResistanceNames[MaxResistIndex];
                ResistanceString  = string.Format("{0} : {1}", ResistanceName, MaxResist.ToString("0")) + ResistanceString;
                ResistanceString += string.Format("\r\n\r\nResist ({0}):", ResistanceName);
                ResistanceString += string.Format("\r\n{0}", StatConversion.GetResistanceTableString(character.Level + 3, character.Level, MaxResist, 0));
            }

            dictValues.Add("Resistance", ResistanceString);

            SolverBase solver = GetSolver(character, BasicStats);
            solver.Calculate(this);

            dictValues.Add("Rotation", string.Format("{0}*{1}", solver.Name, solver.Rotation));
            if (solver.SpellSimulation != null)
            {
                String s = "Spell Cast List:";
                int    i = 0;
                foreach (Spell spell in solver.SpellSimulation)
                {
                    if (i++ % 10 == 0)
                    {
                        s += "\r\n";
                    }
                    s += ", " + spell.Name;
                }
                s += "\r\n---Repeat---";
                dictValues.Add("Castlist", string.Format("{0}*{1}", solver.SpellSimulation.Count, s));
            }
            else
            {
                dictValues.Add("Castlist", "Empty");
            }
            dictValues.Add("DPS", string.Format("{0}*Damage Pr Second", solver.DPS.ToString("0")));
            //dictValues.Add("SustainDPS", string.Format("{0}*Mana restrained DPS", solver.SustainDPS.ToString("0")));

            float baseMana = BaseStats.GetBaseStats(character).Mana;

            dictValues.Add("SW Pain", new ShadowWordPain(BasicStats, character, baseMana, Ptr).ToString());
            DevouringPlague dp = new DevouringPlague(BasicStats, character, baseMana, Ptr);
            dictValues.Add("Devouring Plague", dp.ToString());
            if (dp.ImprovedDP != null)
            {
                dictValues.Add("Imp. Devouring Plague", dp.ImprovedDP.ToString());
            }
            else
            {
                dictValues.Add("Imp. Devouring Plague", "- *No required talents");
            }
            dictValues.Add("SW Death", new ShadowWordDeath(BasicStats, character, baseMana, Ptr).ToString());
            dictValues.Add("Mind Blast", new MindBlast(BasicStats, character, baseMana, Ptr).ToString());
            dictValues.Add("PW Shield", new PowerWordShield(BasicStats, character, baseMana, Ptr).ToString());

            if (character.PriestTalents.VampiricTouch > 0)
            {
                dictValues.Add("Vampiric Touch", new VampiricTouch(BasicStats, character, baseMana, Ptr).ToString());
            }
            else
            {
                dictValues.Add("Vampiric Touch", "- *No required talents");
            }

            if (character.PriestTalents.MindFlay > 0)
            {
                dictValues.Add("Mind Flay", new MindFlay(BasicStats, character, baseMana, Ptr).ToString());
            }
            else
            {
                dictValues.Add("Mind Flay", "- *No required talents");
            }

            dictValues.Add("Shadowfiend", new Shadowfiend(BasicStats, character, baseMana, Ptr).ToString());

            dictValues.Add("Smite", new Smite(BasicStats, character, baseMana, Ptr).ToString());
            dictValues.Add("Holy Fire", new HolyFire(BasicStats, character, baseMana, Ptr).ToString());
            if (character.PriestTalents.Penance > 0)
            {
                dictValues.Add("Penance", new Penance(BasicStats, character, baseMana, Ptr).ToString());
            }
            else
            {
                dictValues.Add("Penance", "- *No required talents");
            }

            return(dictValues);
        }
Example #24
0
        public static void solve(CharacterCalculationsElemental calculatedStats, CalculationOptionsElemental calcOpts, BossOptions bossOpts)
        {
            Stats         stats     = calculatedStats.BasicStats;
            Character     character = calculatedStats.LocalCharacter;
            ShamanTalents talents   = character.ShamanTalents;

            /* Effects:
             * Clearcasting (-40% mana cost next 2 spells)
             * Glyph of flame shock or not
             * Clearcasting (5/10% more total damage)
             * Elemental Mastery (+15% haste chance, 15 sec/3 min cd)
             * Trinkets
             *
             * Assume LvB used on CD and FS either after LvB, on dot drop or before LvB
             * Filler: LB
             * NYI Optional: use of CL
             */
            Estimation e;
            Rotation   rot;
            float      damage;
            Stats      procStats;

#if RAWR3 || SILVERLIGHT
            float FightDuration = bossOpts.BerserkTimer;
#else
            float FightDuration = calcOpts.FightDuration;
#endif

            // WITHOUT PROCS
            e   = new Estimation(stats, new Stats {
            }, talents, calcOpts);
            rot = e.getPriorityRotation(calcOpts.RotationType);
            // WITH PROCS
            int nPasses = 2, k;
            for (k = 0; k < nPasses; k++)
            {
                procStats = DoSpecialEffects(character, stats, rot, FightDuration);
                //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot);
                e.Update(stats, procStats, talents, calcOpts);
                rot = e.getPriorityRotation(calcOpts.RotationType);
            }

            // Thunderstorm usage
            float thunderstormRegen = 0f;
            #region Thunderstorm
            if (calcOpts.UseThunderstorm)
            {
                float procsPerSecond = Thunderstorm.getProcsPerSecond(talents.GlyphofThunder, (int)FightDuration);
                thunderstormRegen += (talents.GlyphofThunderstorm ? .1f : .08f) * stats.Mana * procsPerSecond * 5;
            }
            #endregion

            /* Regen variables: (divide by 5 for regen per second)
             * While casting: ManaRegInFSR
             * During regen: ManaRegOutFSR */
            #region Calculate Regen
            float spiRegen       = 5 * StatConversion.GetSpiritRegenSec(stats.Spirit, stats.Intellect);
            float replenishRegen = 5 * stats.Mana * stats.ManaRestoreFromMaxManaPerSecond;
            float judgementRegen = 5 * rot.GetBaseCastTime() / rot.Duration * stats.ManaRestoreFromBaseManaPPM / 60f * BaseStats.GetBaseStats(character).Mana;
            float ManaRegInFSR   = spiRegen * stats.SpellCombatManaRegeneration + stats.Mp5 + replenishRegen + judgementRegen + thunderstormRegen;
            float ManaRegOutFSR  = spiRegen + stats.Mp5 + replenishRegen + thunderstormRegen;
            float ManaRegen      = ManaRegInFSR;
            #endregion

            // TotalDamage, CastFraction, TimeUntilOOM
            #region Calculate total damage in the fight
            float TimeUntilOOM = 0;
            float effectiveMPS = rot.MPS - ManaRegen / 5f;
            if (effectiveMPS <= 0)
            {
                TimeUntilOOM = FightDuration;
            }
            else
            {
                TimeUntilOOM = (calculatedStats.BasicStats.Mana) / effectiveMPS;
            }
            if (TimeUntilOOM > FightDuration)
            {
                TimeUntilOOM = FightDuration;
            }

            #region SpecialEffects from procs etc.
            procStats = DoSpecialEffects(character, stats, rot, FightDuration);
            //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot);
            //damage procs (Thunder Capacitor etc.) are effected by spellcrit and damage debuffs
            damage = procStats.ArcaneDamage * (1 + stats.BonusArcaneDamageMultiplier) + procStats.NatureDamage * (1 + stats.BonusNatureDamageMultiplier) + procStats.FireDamage * (1 + stats.BonusFireDamageMultiplier) + procStats.ShadowDamage * (1 + stats.BonusShadowDamageMultiplier);
            if (damage > 0)
            {
                damage  *= (1 + stats.SpellCrit * .5f); // but only with the normal 50% dmg bonus
                rot.DPS += damage;
            }
            #endregion

            float TotalDamage     = TimeUntilOOM * rot.DPS;
            float TimeToRegenFull = 5f * calculatedStats.BasicStats.Mana / ManaRegOutFSR;
            float TimeToBurnAll   = calculatedStats.BasicStats.Mana / effectiveMPS;
            float CastFraction    = 1f;
            if (ManaRegOutFSR > 0 && FightDuration > TimeUntilOOM)
            {
                float timeLeft = FightDuration - TimeUntilOOM;
                if (TimeToRegenFull + TimeToBurnAll == 0)
                {
                    CastFraction = 0;
                }
                else
                {
                    CastFraction = TimeToBurnAll / (TimeToRegenFull + TimeToBurnAll);
                }
                TotalDamage += timeLeft * rot.DPS * CastFraction;
            }
            #endregion

            float bsRatio = ((float)calcOpts.BSRatio) * 0.01f;
            calculatedStats.BurstPoints     = (1f - bsRatio) * 2f * rot.DPS;
            calculatedStats.SustainedPoints = bsRatio * 2f * TotalDamage / FightDuration;
            calculatedStats.OverallPoints   = calculatedStats.BurstPoints + calculatedStats.SustainedPoints;

            calculatedStats.CombatStats = stats.Clone();
            calculatedStats.CombatStats.Accumulate(procStats);

            calculatedStats.ManaRegenInFSR    = ManaRegInFSR;
            calculatedStats.ManaRegenOutFSR   = ManaRegOutFSR;
            calculatedStats.ReplenishMP5      = replenishRegen;
            calculatedStats.LightningBolt     = rot.LB;
            calculatedStats.ChainLightning    = rot.CL;
            calculatedStats.FlameShock        = rot.FS;
            calculatedStats.LavaBurst         = rot.LvB;
            calculatedStats.EarthShock        = rot.ES;
            calculatedStats.FrostShock        = rot.FrS;
            calculatedStats.FireNova          = rot.FN;
            calculatedStats.SearingTotem      = rot.ST;
            calculatedStats.MagmaTotem        = rot.MT;
            calculatedStats.TimeToOOM         = TimeUntilOOM;
            calculatedStats.CastRegenFraction = CastFraction;
            calculatedStats.CastsPerSecond    = rot.getCastsPerSecond();
            calculatedStats.CritsPerSecond    = rot.getWeightedCritchance() * rot.getCastsPerSecond();
            calculatedStats.MissesPerSecond   = rot.getCastsPerSecond() * (1f - rot.getWeightedHitchance());
            calculatedStats.LvBPerSecond      = rot.getCastsPerSecond(typeof(LavaBurst));
            calculatedStats.LBPerSecond       = rot.getCastsPerSecond(typeof(LightningBolt));
            calculatedStats.FSPerSecond       = rot.getCastsPerSecond(typeof(FlameShock));
            calculatedStats.LatencyPerSecond  = rot.LatencyPerSecond;
            calculatedStats.RotationDPS       = rot.DPS;
            calculatedStats.RotationMPS       = rot.MPS;
            calculatedStats.TotalDPS          = TotalDamage / FightDuration;
            rot.ClearCasting.TryGetValue(typeof(FlameShock), out calculatedStats.ClearCast_FlameShock);
            rot.ClearCasting.TryGetValue(typeof(LavaBurst), out calculatedStats.ClearCast_LavaBurst);
            rot.ClearCasting.TryGetValue(typeof(LightningBolt), out calculatedStats.ClearCast_LightningBolt);
            calculatedStats.Rotation        = rot.ToString();
            calculatedStats.RotationDetails = rot.ToDetailedString();
        }
Example #25
0
        private List <Ability> SetupAbilities()
        {
            List <Ability> abilities       = new List <Ability>();
            float          convection      = 1f - _talents.Convection * 0.02f;
            float          baseMana        = BaseStats.GetBaseStats(_character).Mana;
            float          elementalFocus  = (_talents.ElementalFocus == 1) ? .6f * _cs.ChanceSpellCrit : 1f;
            float          ESMana          = _talents.ShamanisticFocus == 1 ? baseMana * 0.55f * 0.18f : baseMana * 0.18f; // 45% reduction if Shamanistic Focus
            float          FSMana          = _talents.ShamanisticFocus == 1 ? baseMana * 0.55f * 0.17f : baseMana * 0.17f; // 45% reduction if Shamanistic Focus
            float          fireElementalCD = _talents.GlyphofFireElementalTotem ? 300f : 600f;
            float          gcd             = Math.Max(1.0f, 1.5f / (1f + _stats.SpellHaste + StatConversion.GetSpellHasteFromRating(_stats.HasteRating)));

            int priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.ShamanisticRage);

            if (priority > 0 && _talents.ShamanisticRage == 1)
            {
                abilities.Add(new Ability(EnhanceAbility.ShamanisticRage, 60f, 1.5f, 0f, priority, false, true));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.FeralSpirits);
            if (priority > 0 && _talents.FeralSpirit == 1)
            {
                abilities.Add(new Ability(EnhanceAbility.FeralSpirits, 180f, gcd, 0.12f * baseMana, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.LightningBolt);
            if (priority > 0 && _talents.MaelstromWeapon > 0)
            {
                abilities.Add(new Ability(EnhanceAbility.LightningBolt, _cs.SecondsToFiveStack, gcd, 0.1f * baseMana * convection * elementalFocus, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.FlameShock);
            if (priority > 0)
            {
                if (_talents.GlyphofShocking)
                {
                    abilities.Add(new Ability(EnhanceAbility.FlameShock, _cs.AverageFSDotTime, 1.0f, FSMana * convection * elementalFocus, priority, false, false));
                }
                else
                {
                    abilities.Add(new Ability(EnhanceAbility.FlameShock, _cs.AverageFSDotTime, gcd, FSMana * convection * elementalFocus, priority, false, false));
                }
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.StormStrike);
            if (priority > 0 && _talents.Stormstrike == 1)
            {
                abilities.Add(new Ability(EnhanceAbility.StormStrike, 8f, 1.5f, 0.08f * baseMana, priority, false, true));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.EarthShock);
            if (priority > 0)
            {
                if (_talents.GlyphofShocking)
                {
                    abilities.Add(new Ability(EnhanceAbility.EarthShock, _cs.BaseShockSpeed, 1.0f, ESMana * convection * elementalFocus, priority, false, false));
                }
                else
                {
                    abilities.Add(new Ability(EnhanceAbility.EarthShock, _cs.BaseShockSpeed, gcd, ESMana * convection * elementalFocus, priority, false, false));
                }
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.LavaLash);
            if (priority > 0 && _talents.LavaLash == 1)
            {
                abilities.Add(new Ability(EnhanceAbility.LavaLash, 6f, 1.5f, 0.04f * baseMana, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.FireNova);
            if (priority > 0)
            {
                abilities.Add(new Ability(EnhanceAbility.FireNova, _cs.BaseFireNovaSpeed, gcd, 0.22f * baseMana, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.FireElemental);
            if (priority > 0 && _calcOpts.FireElemental)
            {
                abilities.Add(new Ability(EnhanceAbility.FireElemental, fireElementalCD, 1.0f, 0.23f * baseMana, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.MagmaTotem);
            if (priority > 0 && _calcOpts.Magma)
            {
                abilities.Add(new Ability(EnhanceAbility.MagmaTotem, 20f, 1.0f, 0.27f * baseMana * elementalFocus, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.SearingTotem);
            if (priority > 0 && !_calcOpts.Magma)
            {
                abilities.Add(new Ability(EnhanceAbility.SearingTotem, 60f, 1.0f, 0.07f * baseMana * elementalFocus, priority, false, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.LightningShield);
            if (priority > 0 && _talents.StaticShock > 0)
            {
                abilities.Add(new Ability(EnhanceAbility.LightningShield, _cs.StaticShockAvDuration, gcd, 0f, priority, true, false));
            }

            priority = _calcOpts.GetAbilityPriorityValue(EnhanceAbility.RefreshTotems);
            if (priority > 0)
            {
                abilities.Add(new Ability(EnhanceAbility.RefreshTotems, 300f, 1.0f, 0.24f * baseMana, _calcOpts.GetAbilityPriorityValue(EnhanceAbility.RefreshTotems), true, false)); // patch 3.2 takes just 1 second GCD to refresh totems.
            }
            abilities.Sort();
            return(abilities);
        }
Example #26
0
        /// <summary>Gets the total Stats of the Character</summary>
        /// <param name="character">
        /// The Character to get the total Stats of
        /// </param>
        /// <param name="additionalItem">
        /// An additional item to grant the Character the stats of (as if it
        /// were worn)
        /// </param>
        /// <returns>The total stats for the Character</returns>
        public override Stats GetCharacterStats(
            Character character, Item additionalItem)
        {
            WarlockTalents            talents = character.WarlockTalents;
            CalculationOptionsWarlock options
                = character.CalculationOptions as CalculationOptionsWarlock;
            Stats stats = BaseStats.GetBaseStats(character);

            // Items
            AccumulateItemStats(stats, character, additionalItem);

            // Buffs
            AccumulateBuffsStats(stats, character.ActiveBuffs);
            if (options.Imbue.Equals("Grand Spellstone"))
            {
                stats.HasteRating += 60f * (1f + talents.MasterConjuror * 1.5f);
            }
            else
            {
                Debug.Assert(options.Imbue.Equals("Grand Firestone"));
                stats.CritRating += 49f * (1f + talents.MasterConjuror * 1.5f);
            }
            ApplyPetsRaidBuff(
                stats, options.Pet, talents, character.ActiveBuffs);
            float aegis = 1f + talents.DemonicAegis * 0.10f;

            stats.SpellPower += 180f * aegis;                     // fel armor
            stats.SpellDamageFromSpiritPercentage += .3f * aegis; // fel armor

            // Talents
            float[] talentValues = { 0f, .04f, .07f, .1f };
            Stats   statsTalents = new Stats {
                //Demonic Embrace: increases your stamina by 4/7/10%
                BonusStaminaMultiplier = talentValues[talents.DemonicEmbrace],

                //Fel Vitality: increases your maximum Health & Mana by 1/2/3%
                BonusHealthMultiplier = talents.FelVitality * 0.01f,
                BonusManaMultiplier   = talents.FelVitality * 0.01f,

                //Suppression: increases your chance to hit with spells by
                //1/2/3%
                SpellHit = (talents.Suppression * 0.01f),

                //Demonic Tactics: increases your spell crit chance by
                //2/4/6/8/10%
                //Backlash: increases your spell crit chance by 1/2/3%
                BonusCritChance
                    = talents.DemonicTactics * 0.02f + talents.Backlash * 0.01f
            };

            if (talents.Eradication > 0)
            {
                talentValues = new float[] { 0f, .06f, .12f, .20f };
                statsTalents.AddSpecialEffect(
                    new SpecialEffect(
                        Trigger.CorruptionTick,
                        new Stats()
                {
                    SpellHaste = talentValues[talents.Eradication]
                },
                        6f,
                        0f,
                        .06f));
            }
            stats.Accumulate(statsTalents);
            stats.ManaRestoreFromMaxManaPerSecond
                = Math.Max(
                      stats.ManaRestoreFromMaxManaPerSecond,
                      .002f
                      * Spell.CalcUprate(
                          talents.ImprovedSoulLeech * .5f,
                          15f,
                          options.Duration * 1.1f));

            return(stats);
        }
Example #27
0
        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            PriestTalents talents = character.PriestTalents;

            Stats statsTotal = new Stats();

            Stats baseStats = BaseStats.GetBaseStats(character.Level, character.Class, character.Race);
            Stats itemStats = GetItemStats(character, additionalItem);
            Stats buffStats = GetBuffsStats(character, _calculationOptions);

            // Get the gear/enchants/buffs stats loaded in
            statsTotal.Accumulate(baseStats);
            statsTotal.Accumulate(itemStats);
            statsTotal.Accumulate(buffStats);

            Stats statsTalents = new Stats()
            {
                // we can only wear items that are cloth so we always have our specialization, even naked.
                BonusIntellectMultiplier = 0.05f,

                BonusShadowDamageMultiplier = (1 + 0.02f * talents.TwinDisciplines) *
                                              (1 + 0.02f * talents.TwistedFaith) *
                                              (1 + 0.15f * talents.Shadowform) - 1,

                BonusHolyDamageMultiplier = (1 + 0.02f * talents.TwinDisciplines) - 1,

                // this is the shadow priest model so they must have 'Shadow Power'
                BonusSpellPowerMultiplier = .15f,
            };

            statsTotal.Accumulate(statsTalents);

            statsTotal.Stamina    = (float)Math.Floor(statsTotal.Stamina * (1 + statsTotal.BonusStaminaMultiplier));
            statsTotal.Intellect += (float)Math.Floor(itemStats.Intellect * statsTotal.BonusIntellectMultiplier);
            statsTotal.Spirit     = (float)Math.Round(statsTotal.Spirit * (1 + statsTotal.BonusSpiritMultiplier));

            statsTotal.Health += (float)Math.Floor(StatConversion.GetHealthFromStamina(statsTotal.Stamina) * (1f + statsTotal.BonusHealthMultiplier));

            statsTotal.Mana = (float)Math.Round(statsTotal.Mana + StatConversion.GetManaFromIntellect(statsTotal.Intellect));
            statsTotal.Mana = (float)Math.Round(statsTotal.Mana * (1f + statsTotal.BonusManaMultiplier));

            statsTotal.SpellPower += statsTotal.Intellect - 10;

            float hasteFromRating = StatConversion.GetSpellHasteFromRating(statsTotal.HasteRating);
            float talentedHaste   = (1 + hasteFromRating) * (1 + talents.Darkness * .01f) - 1;

            statsTotal.SpellHaste += character.Race == CharacterRace.Goblin ? talentedHaste * 1.01f : talentedHaste;

            float baseBonus = (float)Math.Floor(baseStats.Spirit * statsTotal.BonusSpiritMultiplier);
            float itemBonus = (float)Math.Floor(itemStats.Spirit * statsTotal.BonusSpiritMultiplier);
            float spiritFromItemsAndEffects = baseBonus + itemBonus + itemStats.Spirit;
            float hitRatingFromSpirit       = (0.5f * talents.TwistedFaith) * Math.Max(0f, spiritFromItemsAndEffects);

            statsTotal.HitRating += hitRatingFromSpirit;
            statsTotal.SpellHit  += StatConversion.GetSpellHitFromRating(statsTotal.HitRating);

            // ignoring the base crit percentage here as the in-game tooltip says that the int -> crit conversion contains the base.
            float critFromInt    = StatConversion.GetSpellCritFromIntellect(statsTotal.Intellect) + 0.012375f;
            float critFromRating = StatConversion.GetSpellCritFromRating(statsTotal.CritRating);

            statsTotal.SpellCrit = character.Race == CharacterRace.Worgen ? (critFromInt + critFromRating) + .01f : (critFromInt + critFromRating);

            // Armor
            statsTotal.Armor      = statsTotal.Armor * (1f + statsTotal.BaseArmorMultiplier);
            statsTotal.BonusArmor = statsTotal.BonusArmor * (1f + statsTotal.BonusArmorMultiplier);
            statsTotal.Armor     += statsTotal.BonusArmor;
            statsTotal.Armor      = (float)Math.Round(statsTotal.Armor);

            return(statsTotal);
        }