private void rdbScryer_CheckedChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.AldorScryer = rdbScryer.Checked ? "Scryer" : "Aldor";
            Character.OnItemsChanged();
        }
        private void cmbTargetLevel_SelectedIndexChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.TargetLevel = int.Parse(cmbTargetLevel.SelectedItem.ToString());
            Character.OnItemsChanged();
        }
        private void txtFightLength_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.FightLength = float.Parse(txtFightLength.Text);
            Character.OnItemsChanged();
        }
        private void txtLatency_TextChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.Latency = float.Parse(txtLatency.Text);
            Character.OnItemsChanged();
        }
        private void txtManaPotDelay_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.ManaPotDelay = float.Parse(txtManaPotDelay.Text);
            Character.OnItemsChanged();
        }
Beispiel #6
0
        // Non-rotation-specific mana calculations
        private float GetEffectiveManaPool(Character character, CalculationOptionsMoonkin calcOpts, CharacterCalculationsMoonkin calcs)
        {
            float fightLength = calcs.FightLength * 60.0f;

            float innervateCooldown = 360 - calcs.BasicStats.InnervateCooldownReduction;

            // Mana/5 calculations
            float totalManaRegen = calcs.ManaRegen5SR * fightLength;

            // Mana pot calculations
            float manaRestoredByPots = 0.0f;

            foreach (Buff b in character.ActiveBuffs)
            {
                if (b.Stats.ManaRestore > 0)
                {
                    manaRestoredByPots = b.Stats.ManaRestore;
                    break;
                }
            }

            // Innervate calculations
            float innervateDelay     = calcOpts.InnervateDelay * 60.0f;
            int   numInnervates      = (calcOpts.Innervate && fightLength - innervateDelay > 0) ? ((int)(fightLength - innervateDelay) / (int)innervateCooldown + 1) : 0;
            float totalInnervateMana = numInnervates * CalculationsMoonkin.BaseMana * (4.5f + (character.DruidTalents.GlyphOfInnervate ? 0.9f : 0.0f));

            // Replenishment calculations
            float replenishmentPerTick = calcs.BasicStats.Mana * calcs.BasicStats.ManaRestoreFromMaxManaPerSecond;
            float replenishmentMana    = calcOpts.ReplenishmentUptime * replenishmentPerTick * calcs.FightLength * 60;

            return(calcs.BasicStats.Mana + totalInnervateMana + totalManaRegen + manaRestoredByPots + replenishmentMana);
        }
        private void txtShadowPriest_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.ShadowPriest = float.Parse(txtShadowPriest.Text);
            Character.OnItemsChanged();
        }
        private void cmbPotType_SelectedIndexChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.ManaPotType = cmbPotType.SelectedItem.ToString();
            Character.OnItemsChanged();
        }
        private void chkMetagem_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            Character.EnforceMetagemRequirements = chkMetagem.Checked;
            Character.OnItemsChanged();
        }
        private void txtInnervateWeaponSpi_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.InnervateWeaponSpi = float.Parse(txtInnervateWeaponSpi.Text);
            Character.OnItemsChanged();
        }
        /*private void chkManaPots_CheckedChanged(object sender, EventArgs e)
         * {
         *              CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;
         *              calcOpts.ManaPots = chkManaPots.Checked;
         *  cmbPotType.Enabled = chkManaPots.Checked;
         *  Character.OnCalculationsInvalidated();
         * }
         *
         * private void cmbPotType_SelectedIndexChanged(object sender, EventArgs e)
         * {
         *              CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;
         *              calcOpts.ManaPotType = cmbPotType.SelectedItem.ToString();
         *  Character.OnCalculationsInvalidated();
         * }*/

        private void txtInnervateDelay_Leave(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.InnervateDelay = float.Parse(txtInnervateDelay.Text);
            Character.OnCalculationsInvalidated();
        }
        private void chkPtrMode_CheckedChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.PTRMode = chkPtrMode.Checked;
            Character.OnCalculationsInvalidated();
        }
        private void cmbUserRotation_SelectedIndexChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.UserRotation = cmbUserRotation.SelectedItem.ToString();
            Character.OnCalculationsInvalidated();
        }
        private void trkReplenishmentUptime_ValueChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.ReplenishmentUptime = trkReplenishmentUptime.Value / 100.0f;
            lblUptimeValue.Text          = trkReplenishmentUptime.Value.ToString();
            Character.OnCalculationsInvalidated();
        }
        private void chkInnervate_CheckedChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.Innervate        = chkInnervate.Checked;
            txtInnervateDelay.Enabled = chkInnervate.Checked;
            Character.OnItemsChanged();
        }
        private void trkTreantLifespan_ValueChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.TreantLifespan = trkTreantLifespan.Value / 100.0f;
            lblLifespanValue.Text   = trkTreantLifespan.Value.ToString();
            Character.OnCalculationsInvalidated();
        }
Beispiel #17
0
        public override ICalculationOptionBase DeserializeDataObject(string xml)
        {
            System.Xml.Serialization.XmlSerializer serializer =
                new System.Xml.Serialization.XmlSerializer(typeof(CalculationOptionsMoonkin));
            System.IO.StringReader    reader   = new System.IO.StringReader(xml);
            CalculationOptionsMoonkin calcOpts = serializer.Deserialize(reader) as CalculationOptionsMoonkin;

            return(calcOpts);
        }
        private void chkManaPots_CheckedChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.ManaPots       = chkManaPots.Checked;
            cmbPotType.Enabled      = chkManaPots.Checked;
            txtManaPotDelay.Enabled = chkManaPots.Checked;
            Character.OnItemsChanged();
        }
        private void chkInnervateWeapon_CheckedChanged(object sender, EventArgs e)
        {
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            calcOpts.InnervateWeapon      = chkInnervateWeapon.Checked;
            txtInnervateWeaponInt.Enabled = chkInnervateWeapon.Checked;
            txtInnervateWeaponSpi.Enabled = chkInnervateWeapon.Checked;
            Character.OnItemsChanged();
        }
Beispiel #20
0
        public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem)
        {
            CharacterCalculationsMoonkin calcs = new CharacterCalculationsMoonkin();
            Stats stats = GetCharacterStats(character, additionalItem);

            calcs.BasicStats = stats;

            float hitRatingMultiplier  = 1.0f / CalculationsMoonkin.hitRatingConversionFactor;
            float critRatingMultiplier = 1.0f / CalculationsMoonkin.critRatingConversionFactor;

            calcs.SpellCrit = stats.SpellCritRating * critRatingMultiplier;
            calcs.SpellHit  = stats.SpellHitRating * hitRatingMultiplier;

            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;

            // All spells: Damage +((0.08/0.16/0.25) * Int)
            switch (calcOpts.LunarGuidance)
            {
            case 1:
                stats.SpellDamageFromIntellectPercentage += 0.08f;
                break;

            case 2:
                stats.SpellDamageFromIntellectPercentage += 0.16f;
                break;

            case 3:
                stats.SpellDamageFromIntellectPercentage += 0.25f;
                break;

            default:
                stats.SpellDamageFromIntellectPercentage += 0.0f;
                break;
            }
            calcs.ArcaneDamage = stats.SpellDamageRating + stats.SpellArcaneDamageRating + stats.SpellDamageFromIntellectPercentage * stats.Intellect + stats.SpellDamageFromSpiritPercentage * stats.Spirit;
            calcs.NatureDamage = stats.SpellDamageRating + stats.SpellNatureDamageRating + stats.SpellDamageFromIntellectPercentage * stats.Intellect + stats.SpellDamageFromSpiritPercentage * stats.Spirit;

            calcs.Latency     = calcOpts.Latency;
            calcs.FightLength = calcOpts.FightLength;
            calcs.TargetLevel = calcOpts.TargetLevel;
            calcs.Scryer      = calcOpts.AldorScryer == "Scryer";

            // 2.4 spirit regen
            float baseRegenConstant = 0.00932715221261f;
            float spiritRegen       = 0.001f + baseRegenConstant * (float)Math.Sqrt(calcs.BasicStats.Intellect) * calcs.BasicStats.Spirit;

            calcs.ManaRegen    = spiritRegen + stats.Mp5 / 5f;
            calcs.ManaRegen5SR = spiritRegen * stats.SpellCombatManaRegeneration + stats.Mp5 / 5f;

            // Run the solver to do final calculations
            MoonkinSolver.Solve(character, ref calcs);

            return(calcs);
        }
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null)
     {
         Character.CalculationOptions = new CalculationOptionsMoonkin();
     }
     calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;
     // Model Specific Code
     //
     _loadingCalculationOptions = false;
 }
        // Load the options into the form
        protected override void LoadCalculationOptions()
        {
            if (Character.CalculationOptions == null)
            {
                Character.CalculationOptions = new CalculationOptionsMoonkin();
            }

            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            cmbTargetLevel.SelectedItem = calcOpts.TargetLevel.ToString();
            txtLatency.Text             = calcOpts.Latency.ToString();
            txtFightLength.Text         = calcOpts.FightLength.ToString();
            chkInnervate.Checked        = calcOpts.Innervate;
            //chkManaPots.Checked = calcOpts.ManaPots;
            //cmbPotType.SelectedItem = calcOpts.ManaPotType;
            //cmbPotType.Enabled = chkManaPots.Checked;
            txtInnervateDelay.Text       = calcOpts.InnervateDelay.ToString();
            txtInnervateDelay.Enabled    = chkInnervate.Checked;
            trkReplenishmentUptime.Value = (int)(calcOpts.ReplenishmentUptime * 100);
            trkTreantLifespan.Value      = (int)(calcOpts.TreantLifespan * 100);
            cmbUserRotation.SelectedItem = calcOpts.UserRotation;
            chkPtrMode.Checked           = calcOpts.PTRMode;
        }
Beispiel #23
0
        // Non-rotation-specific mana calculations
        private float GetEffectiveManaPool(Character character, CalculationOptionsMoonkin calcOpts, CharacterCalculationsMoonkin calcs)
        {
            float fightLength = character.BossOptions.BerserkTimer * 60.0f;

            float innervateCooldown = 180;

            // Mana/5 calculations
            float totalManaRegen = calcs.ManaRegen * fightLength;

            // Mana pot calculations
            float manaRestoredByPots = 0.0f;
            foreach (Buff b in character.ActiveBuffs)
            {
                if (b.Stats.ManaRestore > 0)
                {
                    manaRestoredByPots = b.Stats.ManaRestore;
                    break;
                }
            }

            // Innervate calculations
            float innervateDelay = calcOpts.InnervateDelay * 60.0f;
            int numInnervates = (calcOpts.Innervate && fightLength - innervateDelay > 0) ? ((int)(fightLength - innervateDelay) / (int)innervateCooldown + 1) : 0;
            float totalInnervateMana = numInnervates * 0.2f * calcs.BasicStats.Mana;
            totalInnervateMana *= 1 + 0.15f * character.DruidTalents.Dreamstate;

            // Replenishment calculations
            float replenishmentPerTick = calcs.BasicStats.Mana * calcs.BasicStats.ManaRestoreFromMaxManaPerSecond;
            float replenishmentMana = calcOpts.ReplenishmentUptime * replenishmentPerTick * character.BossOptions.BerserkTimer * 60;

            return calcs.BasicStats.Mana + totalInnervateMana + totalManaRegen + manaRestoredByPots + replenishmentMana;
        }
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null) Character.CalculationOptions = new CalculationOptionsMoonkin();
     calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;
     // Model Specific Code
     //
     _loadingCalculationOptions = false;
 }
        // Load the options into the form
        protected override void LoadCalculationOptions()
        {
            if (Character.CalculationOptions == null)
            {
                Character.CalculationOptions = new CalculationOptionsMoonkin(Character);
            }
            //if (!Character.CalculationOptions.ContainsKey("TargetLevel"))
            //    calcOpts.TargetLevel = "73";
            //if (!Character.CalculationOptions.ContainsKey("EnforceMetagemRequirements"))
            //    character.EnforceMetagemRequirements = "No";
            //if (!Character.CalculationOptions.ContainsKey("Latency"))
            //    calcOpts.Latency = "0.4";
            //if (!Character.CalculationOptions.ContainsKey("FightLength"))
            //    calcOpts.FightLength = "5";
            //if (!Character.CalculationOptions.ContainsKey("Innervate"))
            //    calcOpts.Innervate = "No";
            //if (!Character.CalculationOptions.ContainsKey("InnervateDelay"))
            //    calcOpts.InnervateDelay = "1";
            //if (!Character.CalculationOptions.ContainsKey("ShadowPriest"))
            //    calcOpts.ShadowPriest = "0";
            //if (!Character.CalculationOptions.ContainsKey("ManaPots"))
            //    calcOpts.ManaPots = "No";
            //if (!Character.CalculationOptions.ContainsKey("ManaPotDelay"))
            //    calcOpts.ManaPotDelay = "1.5";
            //if (!Character.CalculationOptions.ContainsKey("ManaPotType"))
            //    calcOpts.ManaPotType = "Super Mana Potion";
            //if (!Character.CalculationOptions.ContainsKey("InnervateWeapon"))
            //    calcOpts.InnervateWeapon = "No";
            //if (!Character.CalculationOptions.ContainsKey("InnervateWeaponInt"))
            //    calcOpts.InnervateWeaponInt = "0";
            //if (!Character.CalculationOptions.ContainsKey("InnervateWeaponSpi"))
            //    calcOpts.InnervateWeaponSpi = "0";
            //if (!Character.CalculationOptions.ContainsKey("AldorScryer"))
            //    calcOpts.AldorScryer = "Aldor";

            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            cmbTargetLevel.SelectedItem   = calcOpts.TargetLevel.ToString();
            chkMetagem.Checked            = Character.EnforceMetagemRequirements;
            txtLatency.Text               = calcOpts.Latency.ToString();
            txtFightLength.Text           = calcOpts.FightLength.ToString();
            txtShadowPriest.Text          = calcOpts.ShadowPriest.ToString();
            chkInnervate.Checked          = calcOpts.Innervate;
            chkManaPots.Checked           = calcOpts.ManaPots;
            cmbPotType.SelectedItem       = calcOpts.ManaPotType;
            cmbPotType.Enabled            = chkManaPots.Checked;
            txtInnervateDelay.Text        = calcOpts.InnervateDelay.ToString();
            txtInnervateDelay.Enabled     = chkInnervate.Checked;
            txtManaPotDelay.Text          = calcOpts.ManaPotDelay.ToString();
            txtManaPotDelay.Enabled       = chkManaPots.Checked;
            chkInnervateWeapon.Checked    = calcOpts.InnervateWeapon;
            txtInnervateWeaponInt.Enabled = chkInnervateWeapon.Checked;
            txtInnervateWeaponInt.Text    = calcOpts.InnervateWeaponInt.ToString();
            txtInnervateWeaponSpi.Enabled = chkInnervateWeapon.Checked;
            txtInnervateWeaponSpi.Text    = calcOpts.InnervateWeaponSpi.ToString();
            rdbAldor.Checked              = calcOpts.AldorScryer == "Aldor";
            rdbScryer.Checked             = calcOpts.AldorScryer == "Scryer";

            if (talents != null)
            {
                talents.LoadCalculationOptions();
            }
        }
        public Stats GetBuffsStats(Character character, CalculationOptionsMoonkin calcOpts) {
            List<Buff> removedBuffs = new List<Buff>();
            List<Buff> addedBuffs = new List<Buff>();

            //float hasRelevantBuff;

            #region Passive Ability Auto-Fixing
            // Removes the Trueshot Aura Buff and it's equivalents Unleashed Rage and Abomination's Might if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            /*{
                hasRelevantBuff = character.HunterTalents.TrueshotAura;
                Buff a = Buff.GetBuffByName("Trueshot Aura");
                Buff b = Buff.GetBuffByName("Unleashed Rage");
                Buff c = Buff.GetBuffByName("Abomination's Might");
                if (hasRelevantBuff > 0)
                {
                    if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); removedBuffs.Add(a); }
                    if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); removedBuffs.Add(b); }
                    if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); removedBuffs.Add(c); }
                }
            }
            // Removes the Hunter's Mark Buff and it's Children 'Glyphed', 'Improved' and 'Both' if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            {
                hasRelevantBuff =  character.HunterTalents.ImprovedHuntersMark
                                + (character.HunterTalents.GlyphOfHuntersMark ? 1 : 0);
                Buff a = Buff.GetBuffByName("Hunter's Mark");
                Buff b = Buff.GetBuffByName("Glyphed Hunter's Mark");
                Buff c = Buff.GetBuffByName("Improved Hunter's Mark");
                Buff d = Buff.GetBuffByName("Improved and Glyphed Hunter's Mark");
                // Since we are doing base Hunter's mark ourselves, we still don't want to double-dip
                if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); /*removedBuffs.Add(a);*//* }
                // If we have an enhanced Hunter's Mark, kill the Buff
                if (hasRelevantBuff > 0) {
                    if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); /*removedBuffs.Add(b);*//* }
                    if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); /*removedBuffs.Add(c);*//* }
                    if (character.ActiveBuffs.Contains(d)) { character.ActiveBuffs.Remove(d); /*removedBuffs.Add(c);*//* }
                }
            }*/
            #endregion

            Stats statsBuffs = GetBuffsStats(character.ActiveBuffs, character.SetBonusCount);

            foreach (Buff b in removedBuffs) {
                character.ActiveBuffsAdd(b);
            }
            foreach (Buff b in addedBuffs) {
                character.ActiveBuffs.Remove(b);
            }

            return statsBuffs;
        }
Beispiel #27
0
        private static float GetEffectiveManaPool(Character character, CharacterCalculationsMoonkin calcs)
        {
            float fightLength = calcs.FightLength * 60.0f;

            float innervateCooldown = 360 - calcs.BasicStats.InnervateCooldownReduction;

            // Mana/5 calculations
            float totalManaRegen = calcs.ManaRegen5SR * fightLength;

            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;
            // Mana pot calculations
            float manaPotDelay       = calcOpts.ManaPotDelay * 60.0f;
            int   numPots            = calcOpts.ManaPots && fightLength - manaPotDelay > 0 ? ((int)(fightLength - manaPotDelay) / 120 + 1) : 0;
            float manaRestoredByPots = 0.0f;

            if (numPots > 0)
            {
                float manaPerPot = 0.0f;
                if (calcOpts.ManaPotType == "Super Mana Potion")
                {
                    manaPerPot = 2400.0f;
                }
                if (calcOpts.ManaPotType == "Fel Mana Potion")
                {
                    manaPerPot = 3200.0f;
                }
                // Bonus from Alchemist's Stone
                if (calcs.BasicStats.BonusManaPotion > 0)
                {
                    manaPerPot *= 1 + calcs.BasicStats.BonusManaPotion;
                }

                manaRestoredByPots = numPots * manaPerPot;
            }

            // Innervate calculations
            float innervateDelay     = calcOpts.InnervateDelay * 60.0f;
            int   numInnervates      = calcOpts.Innervate && fightLength - innervateDelay > 0 ? ((int)(fightLength - innervateDelay) / (int)innervateCooldown + 1) : 0;
            float totalInnervateMana = 0.0f;

            if (numInnervates > 0)
            {
                // Innervate mana rate increases only spirit-based regen
                float spiritRegen = (calcs.ManaRegen - calcs.BasicStats.Mp5 / 5f);
                // Add in calculations for an innervate weapon
                if (calcOpts.InnervateWeapon)
                {
                    float baseRegenConstant = 0.00932715221261f;
                    // Calculate the intellect from a weapon swap
                    float userIntellect = calcs.BasicStats.Intellect - (character.MainHand == null ? 0 : character.MainHand.Stats.Intellect) - (character.OffHand == null ? 0 : character.OffHand.Stats.Intellect)
                                          + calcOpts.InnervateWeaponInt;
                    // Do the same with spirit
                    float userSpirit = calcs.BasicStats.Spirit - (character.MainHand == null ? 0 : character.MainHand.Stats.Spirit) - (character.OffHand == null ? 0 : character.OffHand.Stats.Spirit)
                                       + calcOpts.InnervateWeaponSpi;
                    // The new spirit regen for innervate periods uses the new weapon stats
                    spiritRegen = baseRegenConstant * (float)Math.Sqrt(userIntellect) * userSpirit;
                }
                float innervateManaRate = spiritRegen * 4 + calcs.BasicStats.Mp5 / 5f;
                float innervateTime     = numInnervates * 20.0f;
                totalInnervateMana = innervateManaRate * innervateTime - (numInnervates * calcs.BasicStats.Mana * 0.04f);
            }
            // Shadow priest calculations
            float sPriestMp5  = calcOpts.ShadowPriest;
            float sPriestMana = sPriestMp5 / 5 * fightLength;

            return(calcs.BasicStats.Mana + totalInnervateMana + totalManaRegen + manaRestoredByPots + sPriestMana);
        }
Beispiel #28
0
        private static void UpdateSpells(Character character, ref CharacterCalculationsMoonkin calcs)
        {
            Stats stats = calcs.BasicStats;
            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;

            // Add (possibly talented) +spelldmg
            // Starfire: Damage +(0.04 * Wrath of Cenarius)
            // Wrath: Damage +(0.02 * Wrath of Cenarius)
            wrath.SpellDamageModifier    += 0.02f * calcOpts.WrathofCenarius;
            starfire.SpellDamageModifier += 0.04f * calcOpts.WrathofCenarius;

            // Add spell damage from idols
            starfire.DamagePerHit += stats.StarfireDmg;
            moonfire.DamagePerHit += stats.MoonfireDmg;
            wrath.DamagePerHit    += stats.WrathDmg;

            // Add spell-specific damage
            // Starfire, Moonfire, Wrath: Damage +(0.02 * Moonfury)
            wrath.SpecialDamageModifier    *= 1.0f + (0.02f * calcOpts.Moonfury);
            moonfire.SpecialDamageModifier *= 1.0f + (0.02f * calcOpts.Moonfury);
            starfire.SpecialDamageModifier *= 1.0f + (0.02f * calcOpts.Moonfury);

            // Wrath, Insect Swarm: Nature spell damage multipliers
            wrath.SpecialDamageModifier       *= ((1 + calcs.BasicStats.BonusNatureSpellPowerMultiplier) * (1 + calcs.BasicStats.BonusSpellPowerMultiplier));
            insectSwarm.SpecialDamageModifier *= ((1 + calcs.BasicStats.BonusNatureSpellPowerMultiplier) * (1 + calcs.BasicStats.BonusSpellPowerMultiplier));
            // Starfire, Moonfire: Arcane damage multipliers
            starfire.SpecialDamageModifier *= ((1 + calcs.BasicStats.BonusArcaneSpellPowerMultiplier) * (1 + calcs.BasicStats.BonusSpellPowerMultiplier));
            moonfire.SpecialDamageModifier *= ((1 + calcs.BasicStats.BonusArcaneSpellPowerMultiplier) * (1 + calcs.BasicStats.BonusSpellPowerMultiplier));

            // Level-based partial resistances
            wrath.SpecialDamageModifier    *= 1 - 0.02f * (calcs.TargetLevel - 70);
            starfire.SpecialDamageModifier *= 1 - 0.02f * (calcs.TargetLevel - 70);
            moonfire.SpecialDamageModifier *= 1 - 0.02f * (calcs.TargetLevel - 70);
            // Insect Swarm is a binary spell

            // Add spell-specific crit chance
            // Wrath, Starfire: Crit chance +(0.02 * Focused Starlight)
            wrath.SpecialCriticalModifier    += 0.02f * calcOpts.FocusedStarlight;
            starfire.SpecialCriticalModifier += 0.02f * calcOpts.FocusedStarlight;
            // Moonfire: Damage, Crit chance +(0.05 * Imp Moonfire)
            moonfire.SpecialDamageModifier   *= 1.0f + (0.05f * calcOpts.ImpMoonfire);
            moonfire.SpecialCriticalModifier += 0.05f * calcOpts.ImpMoonfire;

            // Add spell-specific critical strike damage
            // Starfire, Moonfire, Wrath: Crit damage +(0.2 * Vengeance)
            starfire.CriticalHitMultiplier *= 1 + 0.2f * calcOpts.Vengeance;
            moonfire.CriticalHitMultiplier *= 1 + 0.2f * calcOpts.Vengeance;
            wrath.CriticalHitMultiplier    *= 1 + 0.2f * calcOpts.Vengeance;
            // Chaotic Skyfire Diamond
            starfire.CriticalHitMultiplier *= 1.0f + 1.5f / 0.5f * stats.BonusSpellCritMultiplier;
            moonfire.CriticalHitMultiplier *= 1.0f + 1.5f / 0.5f * stats.BonusSpellCritMultiplier;
            wrath.CriticalHitMultiplier    *= 1.0f + 1.5f / 0.5f * stats.BonusSpellCritMultiplier;

            // Reduce spell-specific mana costs
            // Starfire, Moonfire, Wrath: Mana cost -(0.03 * Moonglow)
            starfire.ManaCost *= 1.0f - (0.03f * calcOpts.Moonglow);
            moonfire.ManaCost *= 1.0f - (0.03f * calcOpts.Moonglow);
            wrath.ManaCost    *= 1.0f - (0.03f * calcOpts.Moonglow);

            // Reduce spell-specific cast times
            // Wrath, Starfire: Cast time -(0.1 * Starlight Wrath)
            wrath.CastTime    -= 0.1f * calcOpts.StarlightWrath;
            starfire.CastTime -= 0.1f * calcOpts.StarlightWrath;

            // Add set bonuses
            moonfire.DoT.Duration            += stats.MoonfireExtension;
            starfire.SpecialCriticalModifier += stats.StarfireCritChance;
        }
Beispiel #29
0
        public static void Solve(Character character, ref CharacterCalculationsMoonkin calcs)
        {
            // Try to reset the cached results dictionary on each call
            cachedResults = new Dictionary <string, RotationData>();
            float effectiveSpellHit            = calcs.BasicStats.SpellHitRating;
            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;
            bool  naturesGrace = calcOpts.NaturesGrace > 0 ? true : false;
            float fightLength  = calcs.FightLength * 60.0f;

            float baseHitRate = 0.83f;

            switch (calcs.TargetLevel)
            {
            case 70:
                baseHitRate = 0.96f;
                break;

            case 71:
                baseHitRate = 0.95f;
                break;

            case 72:
                baseHitRate = 0.94f;
                break;

            case 73:
                baseHitRate = 0.83f;
                break;

            default:
                baseHitRate = 0.83f;
                break;
            }

            if (baseHitRate + effectiveSpellHit / CalculationsMoonkin.hitRatingConversionFactor > 0.99f)
            {
                effectiveSpellHit = CalculationsMoonkin.hitRatingConversionFactor * (0.99f - baseHitRate);
            }

            RecreateSpells(character, ref calcs);

            float maxDPS    = 0.0f;
            float maxRawDPS = 0.0f;

            foreach (SpellRotation rotation in SpellRotations)
            {
                // Reset all parameters to defaults
                Spell.GlobalCooldown = 1.5f;
                float effectiveArcaneDamage = calcs.ArcaneDamage;
                float effectiveNatureDamage = calcs.NatureDamage;
                float effectiveSpellCrit    = calcs.BasicStats.SpellCritRating;
                float effectiveSpellHaste   = calcs.BasicStats.SpellHasteRating;
                float effectiveMana         = GetEffectiveManaPool(character, calcs);

                // Trinkets
                trinketExtraDPS = 0.0f;
                // Do a pre-emptive call to rotation.DPS to get corrected cast times for spells
                rotation.DPS(effectiveArcaneDamage, effectiveNatureDamage, baseHitRate + effectiveSpellHit / CalculationsMoonkin.hitRatingConversionFactor, effectiveSpellCrit / CalculationsMoonkin.critRatingConversionFactor, effectiveSpellHaste / CalculationsMoonkin.hasteRatingConversionFactor, effectiveMana, fightLength, naturesGrace, calcs.BasicStats.StarfireBonusWithDot, calcs.Latency);
                rotation.ResetRotationalVariables();
                DoTrinketCalcs(calcs, rotation, baseHitRate + effectiveSpellHit / CalculationsMoonkin.hitRatingConversionFactor, ref effectiveArcaneDamage, ref effectiveNatureDamage, ref effectiveSpellCrit, ref effectiveSpellHaste);

                // JoW/mana restore procs
                effectiveMana += DoManaRestoreCalcs(calcs, rotation, baseHitRate + effectiveSpellHit / CalculationsMoonkin.hitRatingConversionFactor) * (fightLength / rotation.Duration);

                // Calculate average global cooldown based on effective haste rating (includes trinkets)
                Spell.GlobalCooldown /= 1 + effectiveSpellHaste * (1 / CalculationsMoonkin.hasteRatingConversionFactor);
                // Reset the cast time on Insect Swarm and Moonfire, since this is affected by haste
                insectSwarm.CastTime = Spell.GlobalCooldown;
                moonfire.CastTime    = Spell.GlobalCooldown;
                // Incorporate Nature's Grace with Moonfire into the rotational calculations
                if (naturesGrace && rotation.HasMoonfire && rotation.StarfireCount > 0)
                {
                    float critFromGear = effectiveSpellCrit * (1 / CalculationsMoonkin.critRatingConversionFactor);
                    starfire.CastTime -= ((1 - (rotation.AverageCritChance + critFromGear)) * (moonfire.SpecialCriticalModifier + critFromGear) * 0.5f) / rotation.StarfireCount;
                }

                float currentDPS = rotation.DPS(effectiveArcaneDamage, effectiveNatureDamage, baseHitRate + effectiveSpellHit / CalculationsMoonkin.hitRatingConversionFactor, effectiveSpellCrit / CalculationsMoonkin.critRatingConversionFactor, effectiveSpellHaste / CalculationsMoonkin.hasteRatingConversionFactor, effectiveMana, fightLength, naturesGrace, calcs.BasicStats.StarfireBonusWithDot, calcs.Latency) + trinketExtraDPS;
                // Restore Starfire's cast time because the object is reused
                if (naturesGrace && rotation.HasMoonfire && rotation.StarfireCount > 0)
                {
                    float critFromGear = effectiveSpellCrit * (1 / CalculationsMoonkin.critRatingConversionFactor);
                    starfire.CastTime += ((1 - (rotation.AverageCritChance + critFromGear)) * (moonfire.SpecialCriticalModifier + critFromGear) * 0.5f) / rotation.StarfireCount;
                }
                float currentRawDPS = rotation.RawDPS + trinketExtraDPS;
                if (currentDPS > maxDPS)
                {
                    calcs.SelectedRotation = rotation;
                    maxDPS = currentDPS;
                }
                if (currentRawDPS > maxRawDPS)
                {
                    calcs.MaxDPSRotation = rotation;
                    maxRawDPS            = currentRawDPS;
                }
                cachedResults[rotation.Name] = new RotationData()
                {
                    RawDPS    = currentRawDPS,
                    DPS       = currentDPS,
                    DPM       = rotation.DPM,
                    TimeToOOM = rotation.TimeToOOM
                };
            }
            calcs.SubPoints     = new float[] { maxDPS, maxRawDPS };
            calcs.OverallPoints = calcs.SubPoints[0] + calcs.SubPoints[1];
            calcs.Rotations     = cachedResults;
        }
Beispiel #30
0
        // Perform damage and mana calculations for all spells in the given rotation.  Returns damage done over the total duration.
        public float DamageDone(Character character, CharacterCalculationsMoonkin calcs, float treantLifespan, float spellPower, float spellHit, float spellCrit, float spellHaste, float masteryPoints, float latency)
        {
            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;
            DruidTalents talents = character.DruidTalents;
            Spell        sf      = Solver.Starfire;
            Spell        ss      = Solver.Starsurge;
            Spell        w       = Solver.Wrath;
            Spell        mf      = Solver.Moonfire;
            Spell        iSw     = Solver.InsectSwarm;

            // 4.1: The bug causing the Eclipse buff to be rounded down to the nearest percent has been fixed
            float eclipseBonus = 1 + MoonkinSolver.ECLIPSE_BASE + masteryPoints * 0.02f;

            RotationData.NaturesGraceUptime = (float)GetInterpolatedNGUpime(spellHaste, calcs.BasicStats.BonusWrathEnergy > 0, calcs.BasicStats.T13FourPieceActive, talents.GlyphOfStarfire);

            RotationData.Duration = (float)GetInterpolatedCastTime(calcs.SpellHaste, calcs.BasicStats.BonusWrathEnergy > 0, calcs.BasicStats.T13FourPieceActive, talents.GlyphOfStarfire);

            double[] castDistribution = GetInterpolatedCastTable(calcs.SpellHaste, calcs.BasicStats.BonusWrathEnergy > 0, calcs.BasicStats.T13FourPieceActive, talents.GlyphOfStarfire);

            double percentOfMoonfiresExtended = talents.GlyphOfStarfire ? GetPercentOfMoonfiresExtended(calcs.SpellHaste, calcs.BasicStats.BonusWrathEnergy > 0, calcs.BasicStats.T13FourPieceActive) : 0;

            DoMainNuke(calcs, ref sf, spellPower, spellHit, spellCrit, spellHaste, RotationData.NaturesGraceUptime, latency);
            DoMainNuke(calcs, ref ss, spellPower, spellHit, spellCrit, spellHaste, RotationData.NaturesGraceUptime, latency);
            DoMainNuke(calcs, ref w, spellPower, spellHit, spellCrit, spellHaste, RotationData.NaturesGraceUptime, latency);
            double gcd   = Math.Max(1, 1.5 / (1 + spellHaste)) + latency;
            double ngGcd = Math.Max(1, 1.5 / (1 + spellHaste) / (1 + 0.05 * talents.NaturesGrace)) + latency;

            // Moonfire related local variables
            float mfBaseDur, mfMeanDur, mfMaxDur, mfMeanMaxDur, mfTicks, mfMaxTicks;

            mfBaseDur = mf.DotEffect.BaseDuration;
            mfMaxDur  = mfBaseDur + (talents.GlyphOfStarfire ? 9f : 0f);

            // Determine Nature's Grace uptime against Moonfire
            float mfNGUptime = (float)Math.Min(2 * mfMaxDur / RotationData.Duration, 1);

            DoDotSpell(calcs, ref mf, spellPower, spellHit, spellCrit, spellHaste, mfNGUptime, latency);
            // Insect Swarm never benefits from Nature's Grace
            DoDotSpell(calcs, ref iSw, spellPower, spellHit, spellCrit, spellHaste, 0, latency);

            mfTicks      = mf.DotEffect.NumberOfTicks;
            mfMaxTicks   = mfTicks + (talents.GlyphOfStarfire ? 6 : 0);
            mfMeanDur    = mf.DotEffect.Duration;
            mfMeanMaxDur = mf.DotEffect.Duration + (talents.GlyphOfStarfire ? 6 * mf.DotEffect.TickLength : 0f);

            RotationData.MoonfireAvgCast    = mf.CastTime;
            RotationData.InsectSwarmAvgCast = iSw.CastTime;

            // Break the cast distribution down into its component cast counts
            double wrathCasts                 = castDistribution[1] * RotationData.Duration / w.CastTime;
            double eclipseWrathCasts          = castDistribution[5] * RotationData.Duration / w.CastTime;
            double nonEclipsedWrathPercentage = castDistribution[1] / (castDistribution[1] + castDistribution[5]);
            double eclipsedWrathPercentage    = castDistribution[5] / (castDistribution[1] + castDistribution[5]);

            RotationData.WrathAvgHit    = (float)(nonEclipsedWrathPercentage * w.DamagePerHit + eclipsedWrathPercentage * w.DamagePerHit * eclipseBonus);
            RotationData.WrathAvgEnergy = w.AverageEnergy;
            RotationData.WrathCount     = (float)(wrathCasts + eclipseWrathCasts);
            double starfireCasts                 = castDistribution[0] * RotationData.Duration / sf.CastTime;
            double eclipseStarfireCasts          = castDistribution[4] * RotationData.Duration / sf.CastTime;
            double nonEclipsedStarfirePercentage = castDistribution[0] / (castDistribution[0] + castDistribution[4]);
            double eclipsedStarfirePercentage    = castDistribution[4] / (castDistribution[0] + castDistribution[4]);

            RotationData.StarfireAvgHit    = (float)(nonEclipsedStarfirePercentage * sf.DamagePerHit + eclipsedStarfirePercentage * sf.DamagePerHit * eclipseBonus);
            RotationData.StarfireAvgEnergy = sf.AverageEnergy;
            RotationData.StarfireCount     = (float)(starfireCasts + eclipseStarfireCasts);
            double starsurgeCasts                 = castDistribution[2] * RotationData.Duration / ss.CastTime;
            double eclipseStarsurgeCasts          = castDistribution[6] * RotationData.Duration / ss.CastTime;
            double shootingStarsProcs             = castDistribution[3] * RotationData.Duration / gcd;
            double eclipseShootingStarsProcs      = castDistribution[7] * RotationData.Duration / gcd;
            double allStarsurgePercentage         = castDistribution[2] + castDistribution[6] + castDistribution[3] + castDistribution[7];
            double nonEclipsedStarsurgePercentage = (castDistribution[2] + castDistribution[3]) / allStarsurgePercentage;
            double eclipsedStarsurgePercentage    = (castDistribution[6] + castDistribution[7]) / allStarsurgePercentage;
            double starsurgePercentage            = (castDistribution[2] + castDistribution[6]) / allStarsurgePercentage;
            double shootingStarsPercentage        = (castDistribution[3] + castDistribution[7]) / allStarsurgePercentage;

            RotationData.StarSurgeAvgHit    = (float)(nonEclipsedStarsurgePercentage * ss.DamagePerHit + eclipsedStarsurgePercentage * ss.DamagePerHit * eclipseBonus);
            RotationData.StarSurgeAvgEnergy = ss.AverageEnergy;
            RotationData.StarSurgeCount     = (float)(starsurgeCasts + eclipseStarsurgeCasts + shootingStarsProcs + eclipseShootingStarsProcs);
            double moonfireCasts                 = castDistribution[8] * RotationData.Duration / mf.CastTime;
            double eclipsedMoonfireCasts         = castDistribution[10] * RotationData.Duration / mf.CastTime;
            double nonEclipsedMoonfirePercentage = castDistribution[8] / (castDistribution[8] + castDistribution[10]);
            double eclipsedMoonfirePercentage    = castDistribution[10] / (castDistribution[8] + castDistribution[10]);

            RotationData.MoonfireCasts = (float)(moonfireCasts + eclipsedMoonfireCasts);
            double insectSwarmCasts                 = castDistribution[9] * RotationData.Duration / iSw.CastTime;
            double eclipsedInsectSwarmCasts         = castDistribution[11] * RotationData.Duration / iSw.CastTime;
            double nonEclipsedInsectSwarmPercentage = castDistribution[9] / (castDistribution[9] + castDistribution[11]);
            double eclipsedInsectSwarmPercentage    = castDistribution[11] / (castDistribution[9] + castDistribution[11]);

            RotationData.InsectSwarmCasts = (float)(insectSwarmCasts + eclipsedInsectSwarmCasts);

            double unextendedMoonfireAverage = nonEclipsedMoonfirePercentage * (mf.DamagePerHit + mf.DotEffect.DamagePerHit) +
                                               eclipsedMoonfirePercentage * (mf.DamagePerHit + mf.DotEffect.DamagePerHit) * eclipseBonus;
            double mfExtendedDotDamage     = mfMaxTicks * (mf.DotEffect.DamagePerHit / mf.DotEffect.NumberOfTicks);
            double extendedMoonfireAverage = nonEclipsedMoonfirePercentage * (mf.DamagePerHit + mfExtendedDotDamage) +
                                             eclipsedMoonfirePercentage * (mf.DamagePerHit + mfExtendedDotDamage) * eclipseBonus;

            RotationData.MoonfireTicks    = (float)(percentOfMoonfiresExtended * mfMaxTicks + (1 - percentOfMoonfiresExtended) * mfTicks);
            RotationData.MoonfireDuration = (float)(percentOfMoonfiresExtended * mfMeanDur + (1 - percentOfMoonfiresExtended) * mfMeanMaxDur);
            RotationData.MoonfireAvgHit   = (float)(percentOfMoonfiresExtended * extendedMoonfireAverage + (1 - percentOfMoonfiresExtended) * unextendedMoonfireAverage);

            RotationData.InsectSwarmTicks    = RotationData.InsectSwarmCasts * iSw.DotEffect.NumberOfTicks;
            RotationData.InsectSwarmDuration = iSw.DotEffect.Duration;
            RotationData.InsectSwarmAvgHit   = (float)(nonEclipsedInsectSwarmPercentage * iSw.DotEffect.DamagePerHit +
                                                       eclipsedInsectSwarmPercentage * iSw.DotEffect.DamagePerHit * eclipseBonus);

            RotationData.StarfireAvgCast = sf.CastTime;
            RotationData.WrathAvgCast    = w.CastTime;

            RotationData.AverageInstantCast = (float)(gcd * (1 - RotationData.NaturesGraceUptime) + ngGcd * RotationData.NaturesGraceUptime);

            RotationData.StarSurgeAvgCast = (float)(starsurgePercentage * ss.CastTime + shootingStarsPercentage * RotationData.AverageInstantCast);

            // Modify the rotation duration to simulate the energy bonus from Dragonwrath procs
            if (calcs.BasicStats.DragonwrathProc > 0)
            {
                float baselineNukeDuration = RotationData.StarfireCount * RotationData.StarfireAvgCast +
                                             RotationData.WrathCount * RotationData.WrathAvgCast +
                                             RotationData.StarSurgeCount * RotationData.StarSurgeAvgCast;
                float dragonwrathNukeDuration = baselineNukeDuration / (1 + MoonkinSolver.DRAGONWRATH_PROC_RATE);
                RotationData.Duration -= (baselineNukeDuration - dragonwrathNukeDuration);
            }

            RotationData.LunarUptime = (float)(castDistribution[4] + 0.5 * castDistribution[6] + 0.5 * castDistribution[7] + 0.5 * castDistribution[10]);
            RotationData.SolarUptime = (float)(castDistribution[5] + 0.5 * castDistribution[6] + 0.5 * castDistribution[7] + 0.5 * castDistribution[10] + castDistribution[11]);

            float starfallReduction = (float)(starsurgeCasts + shootingStarsProcs + eclipseStarsurgeCasts + eclipseShootingStarsProcs) * 5f;
            float starfallCooldown  = (90f - (talents.GlyphOfStarfall ? 30f : 0f)) - (talents.GlyphOfStarsurge ? starfallReduction : 0);
            float starfallRatio     = talents.Starfall == 1 ?
                                      (RotationData.StarfallCastMode == StarfallMode.OnCooldown ? RotationData.AverageInstantCast / (starfallCooldown + RotationData.AverageInstantCast) : 0f)
                : 0f;
            float starfallTime = RotationData.StarfallCastMode == StarfallMode.LunarOnly ? RotationData.AverageInstantCast : 0f;
            float treantRatio  = talents.ForceOfNature == 1 ? RotationData.AverageInstantCast / (180f + RotationData.AverageInstantCast) : 0;

            float starfallBaseDamage = (talents.Starfall > 0 && RotationData.StarfallCastMode == StarfallMode.Unused) ? 0 : DoStarfallCalcs(calcs, spellPower, spellHit, spellCrit);

            starfallBaseDamage *= 1 + (talents.GlyphOfFocus ? 0.1f : 0f);
            // Dragonwrath
            starfallBaseDamage *= 1 + (calcs.BasicStats.DragonwrathProc > 0 ? MoonkinSolver.DRAGONWRATH_PROC_RATE : 0f);
            float starfallEclipseDamage = starfallBaseDamage * eclipseBonus;

            RotationData.TreantDamage = talents.ForceOfNature == 0 ? 0 : DoTreeCalcs(calcs, character.Level, character.BossOptions.Level, spellPower, treantLifespan);
            // T12 2-piece: 2-sec cast, 5192-6035 damage, affected by hit, 15-sec duration
            float T122PieceHitDamage = (5192 + 6035) / 2f * spellHit * (1 + calcs.BasicStats.BonusFireDamageMultiplier);
            // I'm going to assume a 150% crit modifier on the 2T12 proc until I'm told otherwise
            float T122PieceCritDamage = T122PieceHitDamage * 1.5f;
            // Use 2.5% crit rate based on EJ testing
            // Hard-code 4.5 casts/proc based on EJ testing
            float T122PieceBaseDamage = (0.975f * T122PieceHitDamage + 0.025f * T122PieceCritDamage) * 4.5f;

            // Without glyph of Starsurge, you cannot fit a Starfall in every Lunar eclipse.
            // The actual result will be better than 1/2, because you will be able to cast SFall later in each Eclipse as the fight goes on,
            // but you will miss a Lunar proc entirely eventually.
            float starfallCooldownOverlap = starfallCooldown - RotationData.Duration;
            float rotationsToMiss         = starfallCooldownOverlap > 0 ? RotationData.Duration * RotationData.LunarUptime / starfallCooldownOverlap : 0f;
            float starfallFraction        = rotationsToMiss > 0 ? (float)(Math.Ceiling(rotationsToMiss) / (Math.Ceiling(rotationsToMiss) + 1)) : 1f;

            RotationData.StarfallCasts = RotationData.StarfallCastMode == StarfallMode.OnCooldown ? starfallRatio * RotationData.Duration / RotationData.AverageInstantCast
                : (RotationData.StarfallCastMode == StarfallMode.LunarOnly ? starfallFraction : 0f);
            RotationData.TreantCasts   = treantRatio * RotationData.Duration / RotationData.AverageInstantCast;
            RotationData.StarfallStars = 10f;
            if (RotationData.StarfallCastMode == StarfallMode.LunarOnly)
            {
                RotationData.LunarUptime += starfallFraction * RotationData.AverageInstantCast / RotationData.Duration;
            }
            else if (RotationData.StarfallCastMode == StarfallMode.OnCooldown)
            {
                RotationData.SolarUptime *= 1 + starfallRatio;
                RotationData.LunarUptime *= 1 + starfallRatio;
            }

            RotationData.Duration += RotationData.StarfallCasts * RotationData.AverageInstantCast + RotationData.TreantCasts * RotationData.AverageInstantCast;

            RotationData.StarfallDamage = RotationData.StarfallCastMode == StarfallMode.OnCooldown ?
                                          RotationData.LunarUptime * starfallEclipseDamage + (1 - RotationData.LunarUptime) * starfallBaseDamage :
                                          starfallEclipseDamage;

            float moonfireDamage    = RotationData.MoonfireAvgHit * RotationData.MoonfireCasts;
            float insectSwarmDamage = RotationData.InsectSwarmAvgHit * RotationData.InsectSwarmCasts;

            // Calculate total damage done for external cooldowns per rotation
            float starfallDamage  = RotationData.StarfallDamage * RotationData.StarfallCasts;
            float treantDamage    = RotationData.TreantDamage * RotationData.TreantCasts;
            float T122PieceDamage = 0f;

            if (calcs.BasicStats.ContainsSpecialEffect(se => se.Trigger == Trigger.MageNukeCast))
            {
                foreach (SpecialEffect effect in calcs.BasicStats.SpecialEffects(se => se.Trigger == Trigger.MageNukeCast))
                {
                    T122PieceDamage = T122PieceBaseDamage * effect.GetAverageUptime(RotationData.Duration / (RotationData.WrathCount + RotationData.StarfireCount), 1f);
                }
            }

            // Calculate mana cost per cast.
            // Starfall - 35% of base mana
            float starfallManaCost = (int)(0.35f * MoonkinSolver.BaseMana) - calcs.BasicStats.SpellsManaCostReduction - calcs.BasicStats.NatureSpellsManaCostReduction;
            // Force of Nature - 12% of base mana
            float treantManaCost = (int)(0.12f * MoonkinSolver.BaseMana) - calcs.BasicStats.SpellsManaCostReduction - calcs.BasicStats.NatureSpellsManaCostReduction;

            RotationData.CastCount = RotationData.WrathCount + RotationData.StarfireCount + RotationData.StarSurgeCount +
                                     RotationData.MoonfireCasts + RotationData.InsectSwarmCasts + RotationData.StarfallCasts + RotationData.TreantCasts;
            RotationData.DotTicks = RotationData.InsectSwarmTicks + RotationData.MoonfireTicks;
            RotationData.ManaUsed = RotationData.WrathCount * w.BaseManaCost +
                                    RotationData.StarfireCount * sf.BaseManaCost +
                                    RotationData.StarSurgeCount * ss.BaseManaCost +
                                    RotationData.MoonfireCasts * mf.BaseManaCost +
                                    RotationData.InsectSwarmCasts * iSw.BaseManaCost +
                                    RotationData.StarfallCasts * starfallManaCost +
                                    RotationData.TreantCasts * treantManaCost;

            float manaSavingsFromOOC = MoonkinSolver.OOC_PROC_CHANCE * (RotationData.MoonfireCasts / RotationData.CastCount * mf.BaseManaCost) +
                                       MoonkinSolver.OOC_PROC_CHANCE * (RotationData.InsectSwarmCasts / RotationData.CastCount * iSw.BaseManaCost) +
                                       MoonkinSolver.OOC_PROC_CHANCE * (RotationData.StarfireCount / RotationData.CastCount * sf.BaseManaCost) +
                                       MoonkinSolver.OOC_PROC_CHANCE * (RotationData.WrathCount / RotationData.CastCount * w.BaseManaCost) +
                                       MoonkinSolver.OOC_PROC_CHANCE * (RotationData.StarSurgeCount / RotationData.CastCount * ss.BaseManaCost) +
                                       MoonkinSolver.OOC_PROC_CHANCE * (RotationData.StarfallCasts / RotationData.CastCount * starfallManaCost);

            RotationData.ManaUsed -= manaSavingsFromOOC;

            RotationData.ManaGained = 2 * MoonkinSolver.EUPHORIA_PERCENT * talents.Euphoria * calcs.BasicStats.Mana;

            return(RotationData.WrathAvgHit * RotationData.WrathCount +
                   RotationData.StarfireAvgHit * RotationData.StarfireCount +
                   RotationData.StarSurgeAvgHit * RotationData.StarSurgeCount +
                   moonfireDamage + insectSwarmDamage + treantDamage + starfallDamage + T122PieceDamage);
        }
Beispiel #31
0
        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {
            // Start off with a slightly modified form of druid base character stats calculations
            Stats statsRace = character.Race == Character.CharacterRace.NightElf ?
                              new Stats()
            {
                Health    = 3434f,
                Mana      = 2470f,
                Stamina   = 82f,
                Agility   = 75f,
                Intellect = 120f,
                Spirit    = 133f
            } :
            new Stats()
            {
                Health    = 3434f,
                Mana      = 2470f,
                Stamina   = 85f,
                Agility   = 64.5f,
                Intellect = 115f,
                Spirit    = 135f
            };

            // Get the gear/enchants/buffs stats loaded in
            Stats statsBaseGear = GetItemStats(character, additionalItem);
            Stats statsEnchants = GetEnchantsStats(character);
            Stats statsBuffs    = GetBuffsStats(character.ActiveBuffs);

            Stats statsGearEnchantsBuffs = statsBaseGear + statsEnchants + statsBuffs;

            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;
            // Create the total stats object
            Stats statsTotal = statsGearEnchantsBuffs + statsRace;

            // Base stats: Intellect, Stamina, Spirit, Agility
            statsTotal.Intellect = (float)Math.Floor((Math.Floor(statsRace.Intellect * (1 + statsRace.BonusIntellectMultiplier)) + statsGearEnchantsBuffs.Intellect * (1 + statsRace.BonusIntellectMultiplier)) * (1 + statsGearEnchantsBuffs.BonusIntellectMultiplier));
            statsTotal.Stamina   = (float)Math.Floor((Math.Floor(statsRace.Stamina * (1 + statsRace.BonusStaminaMultiplier)) + statsGearEnchantsBuffs.Stamina * (1 + statsRace.BonusStaminaMultiplier)) * (1 + statsGearEnchantsBuffs.BonusStaminaMultiplier));
            statsTotal.Agility   = (float)Math.Floor((Math.Floor(statsRace.Agility * (1 + statsRace.BonusAgilityMultiplier)) + statsGearEnchantsBuffs.Agility * (1 + statsRace.BonusAgilityMultiplier)) * (1 + statsGearEnchantsBuffs.BonusAgilityMultiplier));
            statsTotal.Spirit    = (float)Math.Floor((Math.Floor(statsRace.Spirit * (1 + statsRace.BonusSpiritMultiplier)) + statsGearEnchantsBuffs.Spirit * (1 + statsRace.BonusSpiritMultiplier)) * (1 + statsGearEnchantsBuffs.BonusSpiritMultiplier));

            // Base stats: Intellect% +(0.04 * Heart of the Wild)
            statsTotal.Intellect *= 1 + 0.04f * calcOpts.HotW;
            // Base stats: Stam%, Int%, Spi%, Agi% +(0.01 * Survival of the Fittest)
            statsTotal.Intellect *= 1 + 0.01f * calcOpts.SotF;
            statsTotal.Stamina   *= 1 + 0.01f * calcOpts.SotF;
            statsTotal.Agility   *= 1 + 0.01f * calcOpts.SotF;
            statsTotal.Spirit    *= 1 + 0.01f * calcOpts.SotF;
            // Base stats: Spirit% +(0.05 * Living Spirit)
            statsTotal.Spirit *= 1 + 0.05f * calcOpts.LivingSpirit;

            // Bonus multipliers
            statsTotal.BonusAgilityMultiplier   = ((1 + statsRace.BonusAgilityMultiplier) * (1 + statsGearEnchantsBuffs.BonusAgilityMultiplier)) - 1;
            statsTotal.BonusStaminaMultiplier   = ((1 + statsRace.BonusStaminaMultiplier) * (1 + statsGearEnchantsBuffs.BonusStaminaMultiplier)) - 1;
            statsTotal.BonusIntellectMultiplier = ((1 + statsRace.BonusIntellectMultiplier) * (1 + statsGearEnchantsBuffs.BonusIntellectMultiplier)) - 1;
            statsTotal.BonusSpiritMultiplier    = ((1 + statsRace.BonusSpiritMultiplier) * (1 + statsGearEnchantsBuffs.BonusSpiritMultiplier)) - 1;

            // Derived stats: Health, mana pool, armor
            statsTotal.Health = (float)Math.Round(((statsRace.Health + statsGearEnchantsBuffs.Health + (statsTotal.Stamina * 10f)) * (character.Race == Character.CharacterRace.Tauren ? 1.05f : 1f)));
            statsTotal.Mana   = (float)Math.Round(statsRace.Mana + 15f * statsTotal.Intellect) - 380;
            statsTotal.Armor  = (float)Math.Round(statsGearEnchantsBuffs.Armor + statsTotal.Agility * 2f);

            // Regen mechanic: mp5 +((0.1 * Intensity) * Spiritmp5())
            statsTotal.SpellCombatManaRegeneration += 0.1f * calcOpts.Intensity;
            // Regen mechanic: mp5 +(0.04/0.07/0.10) * Int)
            float dreamstatePercent = 0.0f;

            switch (calcOpts.Dreamstate)
            {
            case 1:
                dreamstatePercent = 0.04f;
                break;

            case 2:
                dreamstatePercent = 0.07f;
                break;

            case 3:
                dreamstatePercent = 0.1f;
                break;

            default:
                dreamstatePercent = 0.0f;
                break;
            }
            statsTotal.Mp5 += (float)(int)(dreamstatePercent * statsTotal.Intellect);

            // Hit rating
            // All spells: Hit% +(0.02 * Balance of Power)
            statsTotal.SpellHitRating += 0.02f * calcOpts.BalanceofPower * 1262f;

            // Crit rating
            // Application order: Stats, Talents, Gear
            // Add druid base crit
            statsTotal.SpellCritRating += (0.0185f * 2208f);
            // Add intellect-based crit rating to crit (all classes except warlock: 1/80)
            statsTotal.SpellCritRating += (statsTotal.Intellect / 8000.0f) * 2208f;
            // All spells: Crit% + (0.01 * Natural Perfection)
            statsTotal.SpellCritRating += 0.01f * calcOpts.NaturalPerfection * 2208f;
            // Add the crit bonus from the idol, if present
            if (character.ActiveBuffsContains("Moonkin Aura"))
            {
                statsTotal.SpellCritRating += statsTotal.IdolCritRating;
            }

            return(statsTotal);
        }
Beispiel #32
0
        // Update character calculation options when a talent point is set
        private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_loading)
            {
                CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;
                calcOpts.StarlightWrath    = cmbStarlightWrath.SelectedIndex;
                calcOpts.ForceofNature     = cmbForceofNature.SelectedIndex;
                calcOpts.WrathofCenarius   = cmbWrathofCenarius.SelectedIndex;
                calcOpts.ImprovedFF        = cmbImprovedFF.SelectedIndex;
                calcOpts.MoonkinForm       = cmbMoonkinForm.SelectedIndex;
                calcOpts.Dreamstate        = cmbDreamstate.SelectedIndex;
                calcOpts.BalanceofPower    = cmbBalanceofPower.SelectedIndex;
                calcOpts.Moonfury          = cmbMoonfury.SelectedIndex;
                calcOpts.Moonglow          = cmbMoonglow.SelectedIndex;
                calcOpts.NaturesGrace      = cmbNaturesGrace.SelectedIndex;
                calcOpts.LunarGuidance     = cmbLunarGuidance.SelectedIndex;
                calcOpts.CelestialFocus    = cmbCelestialFocus.SelectedIndex;
                calcOpts.Vengeance         = cmbVengeance.SelectedIndex;
                calcOpts.NaturesReach      = cmbNaturesReach.SelectedIndex;
                calcOpts.InsectSwarm       = cmbInsectSwarm.SelectedIndex;
                calcOpts.Brambles          = cmbBrambles.SelectedIndex;
                calcOpts.ImpMoonfire       = cmbImpMoonfire.SelectedIndex;
                calcOpts.FocusedStarlight  = cmbFocusedStarlight.SelectedIndex;
                calcOpts.ControlofNature   = cmbControlofNature.SelectedIndex;
                calcOpts.ImpNaturesGrasp   = cmbImpNaturesGrasp.SelectedIndex;
                calcOpts.NaturesGrasp      = cmbNaturesGrasp.SelectedIndex;
                calcOpts.Ferocity          = cmbFerocity.SelectedIndex;
                calcOpts.FeralAggression   = cmbFeralAggression.SelectedIndex;
                calcOpts.FeralInstinct     = cmbFeralInstinct.SelectedIndex;
                calcOpts.BrutalImpact      = cmbBrutalImpact.SelectedIndex;
                calcOpts.ThickHide         = cmbThickHide.SelectedIndex;
                calcOpts.FeralSwiftness    = cmbFeralSwiftness.SelectedIndex;
                calcOpts.FeralCharge       = cmbFeralCharge.SelectedIndex;
                calcOpts.SharpenedClaws    = cmbSharpenedClaws.SelectedIndex;
                calcOpts.ShreddingAttacks  = cmbShreddingAttacks.SelectedIndex;
                calcOpts.PredatoryStrikes  = cmbPredatoryStrikes.SelectedIndex;
                calcOpts.PrimalFury        = cmbPrimalFury.SelectedIndex;
                calcOpts.SavageFury        = cmbSavageFury.SelectedIndex;
                calcOpts.FeralFaerieFire   = cmbFeralFaerieFire.SelectedIndex;
                calcOpts.NurturingInstinct = cmbNurturingInstinct.SelectedIndex;
                calcOpts.HotW                = cmbHotW.SelectedIndex;
                calcOpts.SotF                = cmbSotF.SelectedIndex;
                calcOpts.PrimalTenacity      = cmbPrimalTenacity.SelectedIndex;
                calcOpts.LotP                = cmbLotP.SelectedIndex;
                calcOpts.ImprovedLotP        = cmbImprovedLotP.SelectedIndex;
                calcOpts.Mangle              = cmbMangle.SelectedIndex;
                calcOpts.PredatoryInstincts  = cmbPredatoryInstincts.SelectedIndex;
                calcOpts.TreeofLife          = cmbTreeofLife.SelectedIndex;
                calcOpts.ImprovedMotW        = cmbImprovedMotW.SelectedIndex;
                calcOpts.EmpoweredRejuv      = cmbEmpoweredRejuv.SelectedIndex;
                calcOpts.Furor               = cmbFuror.SelectedIndex;
                calcOpts.NaturalPerfection   = cmbNaturalPerfection.SelectedIndex;
                calcOpts.Naturalist          = cmbNaturalist.SelectedIndex;
                calcOpts.Swiftmend           = cmbSwiftmend.SelectedIndex;
                calcOpts.NaturesFocus        = cmbNaturesFocus.SelectedIndex;
                calcOpts.LivingSpirit        = cmbLivingSpirit.SelectedIndex;
                calcOpts.NaturalShapeshifter = cmbNaturalShapeshifter.SelectedIndex;
                calcOpts.ImprovedRegrowth    = cmbImprovedRegrowth.SelectedIndex;
                calcOpts.Intensity           = cmbIntensity.SelectedIndex;
                calcOpts.EmpoweredTouch      = cmbEmpoweredTouch.SelectedIndex;
                calcOpts.Subtlety            = cmbSubtlety.SelectedIndex;
                calcOpts.ImpTranquility      = cmbImpTranquility.SelectedIndex;
                calcOpts.OmenofClarity       = cmbOmenofClarity.SelectedIndex;
                calcOpts.GiftofNature        = cmbGiftofNature.SelectedIndex;
                calcOpts.TranquilSpirit      = cmbTranquilSpirit.SelectedIndex;
                calcOpts.NaturesSwiftness    = cmbNaturesSwiftness.SelectedIndex;
                calcOpts.ImprovedRejuv       = cmbImprovedRejuv.SelectedIndex;

                //ComboBox cb = (ComboBox)sender;
                //string talent = cb.Name.Substring(3);
                //Character.CalculationOptions[talent] = cb.SelectedItem.ToString();
                Character.OnItemsChanged();
            }
        }
Beispiel #33
0
        // Load talent points from a character's calculation options.
        public void LoadCalculationOptions()
        {
            _loading = true;
            CalculationOptionsMoonkin calcOpts = Character.CalculationOptions as CalculationOptionsMoonkin;

            cmbStarlightWrath.SelectedItem    = calcOpts.StarlightWrath.ToString();
            cmbForceofNature.SelectedItem     = calcOpts.ForceofNature.ToString();
            cmbWrathofCenarius.SelectedItem   = calcOpts.WrathofCenarius.ToString();
            cmbImprovedFF.SelectedItem        = calcOpts.ImprovedFF.ToString();
            cmbMoonkinForm.SelectedItem       = calcOpts.MoonkinForm.ToString();
            cmbDreamstate.SelectedItem        = calcOpts.Dreamstate.ToString();
            cmbBalanceofPower.SelectedItem    = calcOpts.BalanceofPower.ToString();
            cmbMoonfury.SelectedItem          = calcOpts.Moonfury.ToString();
            cmbMoonglow.SelectedItem          = calcOpts.Moonglow.ToString();
            cmbNaturesGrace.SelectedItem      = calcOpts.NaturesGrace.ToString();
            cmbLunarGuidance.SelectedItem     = calcOpts.LunarGuidance.ToString();
            cmbCelestialFocus.SelectedItem    = calcOpts.CelestialFocus.ToString();
            cmbVengeance.SelectedItem         = calcOpts.Vengeance.ToString();
            cmbNaturesReach.SelectedItem      = calcOpts.NaturesReach.ToString();
            cmbInsectSwarm.SelectedItem       = calcOpts.InsectSwarm.ToString();
            cmbBrambles.SelectedItem          = calcOpts.Brambles.ToString();
            cmbImpMoonfire.SelectedItem       = calcOpts.ImpMoonfire.ToString();
            cmbFocusedStarlight.SelectedItem  = calcOpts.FocusedStarlight.ToString();
            cmbControlofNature.SelectedItem   = calcOpts.ControlofNature.ToString();
            cmbImpNaturesGrasp.SelectedItem   = calcOpts.ImpNaturesGrasp.ToString();
            cmbNaturesGrasp.SelectedItem      = calcOpts.NaturesGrasp.ToString();
            cmbFerocity.SelectedItem          = calcOpts.Ferocity.ToString();
            cmbFeralAggression.SelectedItem   = calcOpts.FeralAggression.ToString();
            cmbFeralInstinct.SelectedItem     = calcOpts.FeralInstinct.ToString();
            cmbBrutalImpact.SelectedItem      = calcOpts.BrutalImpact.ToString();
            cmbThickHide.SelectedItem         = calcOpts.ThickHide.ToString();
            cmbFeralSwiftness.SelectedItem    = calcOpts.FeralSwiftness.ToString();
            cmbFeralCharge.SelectedItem       = calcOpts.FeralCharge.ToString();
            cmbSharpenedClaws.SelectedItem    = calcOpts.SharpenedClaws.ToString();
            cmbShreddingAttacks.SelectedItem  = calcOpts.ShreddingAttacks.ToString();
            cmbPredatoryStrikes.SelectedItem  = calcOpts.PredatoryStrikes.ToString();
            cmbPrimalFury.SelectedItem        = calcOpts.PrimalFury.ToString();
            cmbSavageFury.SelectedItem        = calcOpts.SavageFury.ToString();
            cmbFeralFaerieFire.SelectedItem   = calcOpts.FeralFaerieFire.ToString();
            cmbNurturingInstinct.SelectedItem = calcOpts.NurturingInstinct.ToString();
            cmbHotW.SelectedItem                = calcOpts.HotW.ToString();
            cmbSotF.SelectedItem                = calcOpts.SotF.ToString();
            cmbPrimalTenacity.SelectedItem      = calcOpts.PrimalTenacity.ToString();
            cmbLotP.SelectedItem                = calcOpts.LotP.ToString();
            cmbImprovedLotP.SelectedItem        = calcOpts.ImprovedLotP.ToString();
            cmbMangle.SelectedItem              = calcOpts.Mangle.ToString();
            cmbPredatoryInstincts.SelectedItem  = calcOpts.PredatoryInstincts.ToString();
            cmbTreeofLife.SelectedItem          = calcOpts.TreeofLife.ToString();
            cmbImprovedMotW.SelectedItem        = calcOpts.ImprovedMotW.ToString();
            cmbEmpoweredRejuv.SelectedItem      = calcOpts.EmpoweredRejuv.ToString();
            cmbFuror.SelectedItem               = calcOpts.Furor.ToString();
            cmbNaturalPerfection.SelectedItem   = calcOpts.NaturalPerfection.ToString();
            cmbNaturalist.SelectedItem          = calcOpts.Naturalist.ToString();
            cmbSwiftmend.SelectedItem           = calcOpts.Swiftmend.ToString();
            cmbNaturesFocus.SelectedItem        = calcOpts.NaturesFocus.ToString();
            cmbLivingSpirit.SelectedItem        = calcOpts.LivingSpirit.ToString();
            cmbNaturalShapeshifter.SelectedItem = calcOpts.NaturalShapeshifter.ToString();
            cmbImprovedRegrowth.SelectedItem    = calcOpts.ImprovedRegrowth.ToString();
            cmbIntensity.SelectedItem           = calcOpts.Intensity.ToString();
            cmbEmpoweredTouch.SelectedItem      = calcOpts.EmpoweredTouch.ToString();
            cmbSubtlety.SelectedItem            = calcOpts.Subtlety.ToString();
            cmbImpTranquility.SelectedItem      = calcOpts.ImpTranquility.ToString();
            cmbOmenofClarity.SelectedItem       = calcOpts.OmenofClarity.ToString();
            cmbGiftofNature.SelectedItem        = calcOpts.GiftofNature.ToString();
            cmbTranquilSpirit.SelectedItem      = calcOpts.TranquilSpirit.ToString();
            cmbNaturesSwiftness.SelectedItem    = calcOpts.NaturesSwiftness.ToString();
            cmbImprovedRejuv.SelectedItem       = calcOpts.ImprovedRejuv.ToString();

            _loading = false;

            //// Iterate through all controls on the form
            //foreach (Control c in Controls)
            //{
            //    // Iterate into group boxes only
            //    if (c is GroupBox)
            //    {
            //        // Iterate through all controls in the group box
            //        foreach (Control innerControl in c.Controls)
            //        {
            //            // Load calculation options into combo boxes only
            //            if (innerControl is ComboBox)
            //            {
            //                // Get the substring that is the actual talent name
            //                ComboBox cb = (ComboBox)innerControl;
            //                string talent = cb.Name.Substring(3);

            //                // If the talent is not in the calculation options, add it
            //                if (!Character.CalculationOptions.ContainsKey(talent))
            //                    Character.CalculationOptions[talent] = "0";

            //                // Load the value from the character into the combo box
            //                cb.SelectedItem = Character.CalculationOptions[talent];
            //            }
            //        }
            //    }
            //}
        }