private void ScaleRaidBuffsToLevel_Click(object sender, RoutedEventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            Buff.LoadDefaultBuffs(null, calculationOptions.PlayerLevel);
            Character.OnCalculationsInvalidated();
        }
Esempio n. 2
0
        private void ComputeTalentTotals()
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;
            List <string>          totals             = new List <string>();

            foreach (Control c in Controls)
            {
                if (c is GroupBox)
                {
                    int total = 0;
                    foreach (Control cc in c.Controls)
                    {
                        if (cc is ComboBox)
                        {
                            ComboBox cb     = (ComboBox)cc;
                            string   talent = cb.Name.Substring(8);
                            total += calculationOptions.GetTalentByName(talent);
                        }
                    }
                    totals.Add(total.ToString());
                }
            }
            totals.Reverse();
            Text = "Mage Talents (" + string.Join("/", totals.ToArray()) + ")";
        }
Esempio n. 3
0
        public void LoadCalculationOptions()
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            calculationSuspended = true;
            foreach (Control c in Controls)
            {
                if (c is GroupBox)
                {
                    foreach (Control cc in c.Controls)
                    {
                        if (cc is ComboBox)
                        {
                            ComboBox cb     = (ComboBox)cc;
                            string   talent = cb.Name.Substring(8);

                            cb.SelectedItem = calculationOptions.GetTalentByName(talent).ToString();
                        }
                    }
                }
            }
            UpdateWotLK();
            calculationSuspended = false;
            ComputeTalentTotals();
        }
Esempio n. 4
0
        private void buttonUpdateItems_Click(object sender, EventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            calculationOptions.CooldownRestrictions = Regex.Replace(textBoxCooldownRestrictions.Text, "(\r|\n)+", Environment.NewLine);
            Character.OnCalculationsInvalidated();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            calculationOptions.CooldownRestrictions = Regex.Replace(textBoxCooldownRestrictions.Text, "(\r|\n)+", Environment.NewLine);
            // setting the property already triggers invalidation
            //Character.OnCalculationsInvalidated();
        }
Esempio n. 6
0
        public CalculationOptionsMage Clone()
        {
            CalculationOptionsMage clone = (CalculationOptionsMage)MemberwiseClone();

            clone.IncrementalSetArmor        = null;
            clone.IncrementalSetStateIndexes = null;
            clone.IncrementalSetSegments     = null;
            clone.IncrementalSetSpells       = null;
            return(clone);
        }
        private void CustomSpellMix_Click(object sender, RoutedEventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            if (calculationOptions.CustomSpellMix == null)
            {
                calculationOptions.CustomSpellMix = new List <SpellWeight>();
            }
            CustomSpellMixDialog dialog = new CustomSpellMixDialog(calculationOptions.CustomSpellMix);

            dialog.Show();
        }
        private void buttonCustomSpellMix_Click(object sender, EventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            if (calculationOptions.CustomSpellMix == null)
            {
                calculationOptions.CustomSpellMix = new List <SpellWeight>();
            }
            CustomSpellMixForm form = new CustomSpellMixForm(calculationOptions.CustomSpellMix);

            form.ShowDialog(this);
        }
Esempio n. 9
0
        private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;
            ComboBox cb     = (ComboBox)sender;
            string   talent = cb.Name.Substring(8);

            calculationOptions.SetTalentByName(talent, int.Parse(cb.SelectedItem.ToString()));
            if (!calculationSuspended)
            {
                Character.OnItemsChanged();
                ComputeTalentTotals();
            }
        }
Esempio n. 10
0
        public virtual float CalculateDotAverageDamage(Stats baseStats, CalculationOptionsMage calculationOptions, float spellPower, bool forceHit, out float damagePerSpellPower)
        {
            float resistMultiplier = (forceHit ? 1.0f : HitRate) * PartialResistFactor;
            float commonMultiplier = SpellModifier * resistMultiplier;
            float averageDamage    = 0.0f;

            damagePerSpellPower = 0.0f;
            if (BasePeriodicDamage > 0.0f)
            {
                float dotFactor = commonMultiplier * DotDamageModifier;
                averageDamage       = BasePeriodicDamage * dotFactor;
                damagePerSpellPower = DotDamageCoefficient * dotFactor;
            }
            return(averageDamage + damagePerSpellPower * spellPower);
        }
Esempio n. 11
0
        protected override void LoadCalculationOptions()
        {
            if (Character.CalculationOptions == null)
            {
                Character.CalculationOptions = new CalculationOptionsMage(Character);
            }
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            loading = true;
            calculationOptionsMageBindingSource.DataSource = calculationOptions;
            checkBoxEnforceMetagemRequirements.Checked     = Character.EnforceMetagemRequirements;

            if (talents != null)
            {
                talents.LoadCalculationOptions();
            }

            loading = false;
        }
        private void HotStreakUtilization_Click(object sender, RoutedEventArgs e)
        {
            string armor = "Molten Armor";
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;
            CalculationsMage       calculations       = (CalculationsMage)Calculations.Instance;
            Solver solver = new Solver(Character, calculationOptions, false, false, false, 0, armor, false, false, true, false);

            solver.Initialize(null);
            CastingState baseState = new CastingState(solver, 0, false, 0);

            FireCycleGenerator generator = new FireCycleGenerator(baseState);

            GenericCycle c1 = new GenericCycle("test", baseState, generator.StateList, true);
            Cycle        c2 = baseState.GetCycle(CycleId.FBLBPyro);

            Dictionary <string, SpellContribution> dict1 = new Dictionary <string, SpellContribution>();
            Dictionary <string, SpellContribution> dict2 = new Dictionary <string, SpellContribution>();

            c1.AddDamageContribution(dict1, 1.0f);
            c2.AddDamageContribution(dict2, 1.0f);

            float predicted = dict2["Pyroblast"].Hits / dict2["Fireball"].Hits;
            float actual    = dict1["Pyroblast"].Hits / dict1["Fireball"].Hits;

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("Pyro/Nuke Ratio:");
            sb.AppendLine();
            sb.AppendLine("Approximation Model: " + predicted);
            sb.AppendLine("Exact Model: " + actual);
            sb.AppendLine();
            // predicted = raw * (1 - wastedold)
            // actual = raw * (1 - wasted)
            // wasted = 1 - actual / predicted * (1 - wastedold)
            sb.AppendLine("Predicted Wasted Hot Streaks: " + (1 - actual / predicted));

            MessageBox.Show(sb.ToString());
        }
Esempio n. 13
0
        public Stats GetCharacterStats(Character character, Item additionalItem, Stats rawStats, CalculationOptionsMage calculationOptions, bool includeArmor)
        {
            float statsRaceHealth;
            float statsRaceMana;
            float statsRaceStrength;
            float statsRaceAgility;
            float statsRaceStamina;
            float statsRaceIntellect;
            float statsRaceSpirit;
            switch (calculationOptions.PlayerLevel)
            {
                case 70:
                    statsRaceHealth = 3213f;
                    statsRaceMana = 1961f;
                    switch (character.Race)
                    {
                        case CharacterRace.BloodElf:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 49f;
                            statsRaceIntellect = 149f;
                            statsRaceSpirit = 144;
                            break;
                        case CharacterRace.Draenei:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 50f;
                            statsRaceIntellect = 152f;
                            statsRaceSpirit = 147;
                            break;
                        case CharacterRace.Human:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 51f;
                            statsRaceIntellect = 151f;
                            statsRaceSpirit = 145;
                            break;
                        case CharacterRace.Troll:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 52f;
                            statsRaceIntellect = 147f;
                            statsRaceSpirit = 146;
                            break;
                        case CharacterRace.Undead:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 52f;
                            statsRaceIntellect = 149f;
                            statsRaceSpirit = 150;
                            break;
                        case CharacterRace.Gnome:
                        default:
                            statsRaceStrength = 28f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 50f;
                            statsRaceIntellect = 154f;
                            statsRaceSpirit = 145;
                            break;
                    }
                    break;
                case 71:
                    statsRaceHealth = 3308f;
                    statsRaceMana = 2063f;
                    statsRaceStrength = 28f;
                    statsRaceAgility = 42f;
                    statsRaceStamina = 51f;
                    statsRaceIntellect = 157f;
                    statsRaceSpirit = 148f;
                    break;
                case 72:
                    statsRaceHealth = 3406f;
                    statsRaceMana = 2166f;
                    statsRaceStrength = 28f;
                    statsRaceAgility = 43f;
                    statsRaceStamina = 52f;
                    statsRaceIntellect = 160f;
                    statsRaceSpirit = 151f;
                    break;
                case 73:
                    statsRaceHealth = 3505f;
                    statsRaceMana = 2269f;
                    statsRaceStrength = 28f;
                    statsRaceAgility = 43f;
                    statsRaceStamina = 53f;
                    statsRaceIntellect = 163f;
                    statsRaceSpirit = 154f;
                    break;
                case 74:
                    statsRaceHealth = 3623f;
                    statsRaceMana = 2372f;
                    statsRaceStrength = 29f;
                    statsRaceAgility = 44f;
                    statsRaceStamina = 53f;
                    statsRaceIntellect = 166f;
                    statsRaceSpirit = 156f;
                    break;
                case 75:
                    statsRaceHealth = 3726f;
                    statsRaceMana = 2474f;
                    statsRaceStrength = 29f;
                    statsRaceAgility = 44f;
                    statsRaceStamina = 54f;
                    statsRaceIntellect = 169f;
                    statsRaceSpirit = 159f;
                    break;
                case 76:
                    statsRaceHealth = 3830f;
                    statsRaceMana = 2577f;
                    statsRaceStrength = 29f;
                    statsRaceAgility = 44f;
                    statsRaceStamina = 55f;
                    statsRaceIntellect = 172f;
                    statsRaceSpirit = 162f;
                    break;
                case 77:
                    statsRaceHealth = 3937f;
                    statsRaceMana = 2680f;
                    statsRaceStrength = 30f;
                    statsRaceAgility = 45f;
                    statsRaceStamina = 56f;
                    statsRaceIntellect = 175f;
                    statsRaceSpirit = 165f;
                    break;
                case 78:
                    statsRaceHealth = 4063f;
                    statsRaceMana = 2783f;
                    statsRaceStrength = 30f;
                    statsRaceAgility = 45f;
                    statsRaceStamina = 56f;
                    statsRaceIntellect = 178f;
                    statsRaceSpirit = 168f;
                    break;
                case 79:
                    statsRaceHealth = 4172f;
                    statsRaceMana = 2885f;
                    statsRaceStrength = 30f;
                    statsRaceAgility = 46f;
                    statsRaceStamina = 57f;
                    statsRaceIntellect = 181f;
                    statsRaceSpirit = 171f;
                    break;
                case 80:
                default:
                    statsRaceHealth = 6783f;
                    statsRaceMana = 2988f;
                    switch (character.Race)
                    {
                        case CharacterRace.BloodElf:
                            statsRaceStrength = 33f;
                            statsRaceAgility = 45f;
                            statsRaceStamina = 57f;
                            statsRaceIntellect = 185f;
                            statsRaceSpirit = 173f;
                            break;
                        case CharacterRace.Draenei:
                            statsRaceStrength = 37f;
                            statsRaceAgility = 40f;
                            statsRaceStamina = 58f;
                            statsRaceIntellect = 182f;
                            statsRaceSpirit = 176f;
                            break;
                        case CharacterRace.Human:
                            statsRaceStrength = 36f;
                            statsRaceAgility = 43f;
                            statsRaceStamina = 59f;
                            statsRaceIntellect = 181f;
                            statsRaceSpirit = 174f;
                            break;
                        case CharacterRace.Troll:
                            statsRaceStrength = 37f;
                            statsRaceAgility = 45f;
                            statsRaceStamina = 60f;
                            statsRaceIntellect = 177f;
                            statsRaceSpirit = 175f;
                            break;
                        case CharacterRace.Undead:
                            statsRaceStrength = 35f;
                            statsRaceAgility = 41f;
                            statsRaceStamina = 60f;
                            statsRaceIntellect = 179f;
                            statsRaceSpirit = 179f;
                            break;
                        case CharacterRace.Gnome:
                        default:
                            statsRaceStrength = 31f;
                            statsRaceAgility = 45f;
                            statsRaceStamina = 59f;
                            statsRaceIntellect = 184f;
                            statsRaceSpirit = 174f;
                            break;
                    }
                    break;
                case 81:
                    statsRaceHealth = 9551f;
                    statsRaceMana = 4287f;
                    statsRaceStrength = 31f;
                    statsRaceAgility = 46f;
                    statsRaceStamina = 60f;
                    statsRaceIntellect = 188f;
                    statsRaceSpirit = 177f;
                    break;
                case 82:
                    statsRaceHealth = 13418f;
                    statsRaceMana = 6102f;
                    statsRaceStrength = 31f;
                    statsRaceAgility = 46f;
                    statsRaceStamina = 60f;
                    statsRaceIntellect = 191f;
                    statsRaceSpirit = 180f;
                    break;
                case 83:
                    statsRaceHealth = 13418f;
                    statsRaceMana = 6102f;
                    statsRaceStrength = 31f;
                    statsRaceAgility = 46f;
                    statsRaceStamina = 60f;
                    statsRaceIntellect = 191f;
                    statsRaceSpirit = 180f;
                    break;
                case 84:
                    statsRaceHealth = 13418f;
                    statsRaceMana = 6102f;
                    statsRaceStrength = 31f;
                    statsRaceAgility = 46f;
                    statsRaceStamina = 60f;
                    statsRaceIntellect = 191f;
                    statsRaceSpirit = 180f;
                    break;
                case 85:
                    statsRaceHealth = 36853f;
                    statsRaceMana = 17138f;
                    switch (character.Race)
                    {
                        case CharacterRace.NightElf:
                            statsRaceStrength = 33f;
                            statsRaceAgility = 50f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 198f;
                            statsRaceSpirit = 190f;
                            break;
                        case CharacterRace.BloodElf:
                            statsRaceStrength = 34f;
                            statsRaceAgility = 48f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 201f;
                            statsRaceSpirit = 188f;
                            break;
                        case CharacterRace.Draenei:
                            statsRaceStrength = 38f;
                            statsRaceAgility = 43f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 198f;
                            statsRaceSpirit = 192f;
                            break;
                        case CharacterRace.Dwarf:
                            statsRaceStrength = 42f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 64f;
                            statsRaceIntellect = 197f;
                            statsRaceSpirit = 189f;
                            break;
                        case CharacterRace.Goblin:
                            statsRaceStrength = 34f;
                            statsRaceAgility = 48f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 201f;
                            statsRaceSpirit = 188f;
                            break;
                        case CharacterRace.Human:
                            statsRaceStrength = 37f;
                            statsRaceAgility = 46f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 198f;
                            statsRaceSpirit = 189f;
                            break;
                        case CharacterRace.Orc:
                            statsRaceStrength = 40f;
                            statsRaceAgility = 43f;
                            statsRaceStamina = 64f;
                            statsRaceIntellect = 195f;
                            statsRaceSpirit = 192f;
                            break;
                        case CharacterRace.Tauren:
                            statsRaceStrength = 42f;
                            statsRaceAgility = 42f;
                            statsRaceStamina = 64f;
                            statsRaceIntellect = 194f;
                            statsRaceSpirit = 192f;
                            break;
                        case CharacterRace.Troll:
                            statsRaceStrength = 38f;
                            statsRaceAgility = 48f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 194f;
                            statsRaceSpirit = 191f;
                            break;
                        case CharacterRace.Undead:
                            statsRaceStrength = 36f;
                            statsRaceAgility = 44f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 195f;
                            statsRaceSpirit = 195f;
                            break;
                        case CharacterRace.Worgen:
                            statsRaceStrength = 40f;
                            statsRaceAgility = 48f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 194f;
                            statsRaceSpirit = 189f;
                            break;
                        case CharacterRace.Gnome:
                        default:
                            statsRaceStrength = 32f;
                            statsRaceAgility = 48f;
                            statsRaceStamina = 63f;
                            statsRaceIntellect = 201f;
                            statsRaceSpirit = 190f;
                            break;
                    }
                    break;
            }
            MageTalents talents = character.MageTalents;

            float statsRaceBonusIntellectMultiplier = 0.0f;
            float statsRaceBonusManaMultiplier = 1.0f + rawStats.BonusManaMultiplier;
            if (character.Race == CharacterRace.Gnome)
            {
                statsRaceBonusManaMultiplier *= 1.05f;
            }
            float statsTalentBonusIntellectMultiplier = 0f;
            float statsRaceBonusSpiritMultiplier = 0.0f;
            if (character.Race == CharacterRace.Human)
            {
                statsRaceBonusSpiritMultiplier = 0.03f;
            }

            float statsWizardryBonusIntellectMultiplier = 0.0f;
            if (calculationOptions.PlayerLevel >= 50)
            {
                statsWizardryBonusIntellectMultiplier = 0.05f;
            }

            Stats statsTotal = rawStats;

            float statsTalentBonusSpiritMultiplier = 0.0f;
            if (calculationOptions.EffectSpiritMultiplier != 1.0f)
            {
                statsTotal.BonusSpiritMultiplier = (1 + statsTotal.BonusSpiritMultiplier) * calculationOptions.EffectSpiritMultiplier - 1;
            }
            statsTotal.Strength = (float)Math.Round((statsRaceStrength + statsTotal.Strength) * (1 + statsTotal.BonusStrengthMultiplier) - 0.00001);
            statsTotal.Agility = (float)Math.Round((statsRaceAgility + statsTotal.Agility) * (1 + statsTotal.BonusAgilityMultiplier) - 0.00001);
            statsTotal.Intellect = (float)Math.Round((Math.Floor(0.00001 + statsRaceIntellect * (1 + statsRaceBonusIntellectMultiplier) * (1 + statsWizardryBonusIntellectMultiplier) * (1 + statsTalentBonusIntellectMultiplier)) + Math.Floor(0.00001 + statsTotal.Intellect * (1 + statsRaceBonusIntellectMultiplier) * (1 + statsWizardryBonusIntellectMultiplier) * (1 + statsTalentBonusIntellectMultiplier))) * (1 + statsTotal.BonusIntellectMultiplier) - 0.00001);
            statsTotal.Stamina = (float)Math.Round((statsRaceStamina + statsTotal.Stamina) * (1 + statsTotal.BonusStaminaMultiplier) - 0.00001);
            statsTotal.Spirit = (float)Math.Round((Math.Floor(0.00001 + statsRaceSpirit * (1 + statsRaceBonusSpiritMultiplier) * (1 + statsTalentBonusSpiritMultiplier)) + Math.Floor(0.00001 + statsTotal.Spirit * (1 + statsRaceBonusSpiritMultiplier) * (1 + statsTalentBonusSpiritMultiplier))) * (1 + statsTotal.BonusSpiritMultiplier) - 0.00001);

            statsTotal.Health = (float)Math.Round((statsTotal.Health + statsRaceHealth + (statsTotal.Stamina * 14f)) * (character.Race == CharacterRace.Tauren ? 1.05f : 1f) * (1 + statsTotal.BonusHealthMultiplier));
            statsTotal.Mana = (float)Math.Round((statsTotal.Mana + statsRaceMana + 15f * statsTotal.Intellect) * statsRaceBonusManaMultiplier);
            statsTotal.Armor = (float)Math.Round(statsTotal.Armor);

            statsTotal.BonusIntellectMultiplier = (1 + statsRaceBonusIntellectMultiplier) * (1 + statsWizardryBonusIntellectMultiplier) * (1 + statsTalentBonusIntellectMultiplier) * (1 + statsTotal.BonusIntellectMultiplier) - 1;
            statsTotal.BonusManaMultiplier = statsRaceBonusManaMultiplier - 1;

            if (character.Race == CharacterRace.BloodElf)
            {
                statsTotal.Mp5 += 5 * 0.06f * statsTotal.Mana / 120;
            }
            if (character.Race == CharacterRace.Draenei)
            {
                statsTotal.SpellHit += 0.01f;
            }

            float allResist = 0;
            if (includeArmor)
            {
                if (statsTotal.MageMageArmor > 0)
                {
                    statsTotal.ManaRestoreFromMaxManaPerSecond += 0.006f * (talents.GlyphOfMageArmor ? 1.2f : 1.0f);
                    allResist += calculationOptions.GetSpellValueRound(0.048f);
                }
                if (statsTotal.MageMoltenArmor > 0)
                {
                    statsTotal.SpellCrit += 0.03f + (talents.GlyphOfMoltenArmor ? 0.02f : 0.0f);
                }
            }
            if (calculationOptions.EffectCritBonus > 0)
            {
                statsTotal.SpellCrit += calculationOptions.EffectCritBonus;
            }
            if (character.Race == CharacterRace.Worgen)
            {
                statsTotal.SpellCrit += 0.01f;
            }
            if (character.Race == CharacterRace.Goblin)
            {
                statsTotal.SpellHaste += 0.01f;
            }
            /*if (talents.GlyphOfManaGem)
            {
                statsTotal.BonusManaGem += 0.4f;
            }*/

            //statsTotal.Mp5 += calculationOptions.ShadowPriest;

            float spellDamageFromIntellectPercentage = 0f;

            statsTotal.SpellPower += (float)Math.Floor(spellDamageFromIntellectPercentage * statsTotal.Intellect);
            statsTotal.SpellPower += statsTotal.Intellect - 10;
            //statsTotal.SpellPower += spellDamageFromSpiritPercentage * statsTotal.Spirit;

            statsTotal.CritBonusDamage += calculationOptions.EffectCritDamageBonus;

            statsTotal.ArcaneResistance += allResist + statsTotal.ArcaneResistanceBuff;
            statsTotal.FireResistance += allResist + statsTotal.FireResistanceBuff;
            statsTotal.FrostResistance += allResist + statsTotal.FrostResistanceBuff;
            statsTotal.NatureResistance += allResist + statsTotal.NatureResistanceBuff;
            statsTotal.ShadowResistance += allResist + statsTotal.ShadowResistanceBuff;

            int playerLevel = calculationOptions.PlayerLevel;
            float maxHitRate = 1.0f;
            float bossHitRate = Math.Min(maxHitRate, ((playerLevel <= calculationOptions.TargetLevel + 2) ? (0.96f - (playerLevel - calculationOptions.TargetLevel) * 0.01f) : (0.94f - (playerLevel - calculationOptions.TargetLevel - 2) * 0.11f)));
            statsTotal.Mp5 -= 5 * calculationOptions.EffectShadowManaDrain * calculationOptions.EffectShadowManaDrainFrequency * bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.ShadowResistance, 0));

            float fullResistRate = calculationOptions.EffectArcaneOtherBinary * (1 - bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.ArcaneResistance, 0)));
            fullResistRate += calculationOptions.EffectFireOtherBinary * (1 - bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.FireResistance, 0)));
            fullResistRate += calculationOptions.EffectFrostOtherBinary * (1 - bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.FrostResistance, 0)));
            fullResistRate += calculationOptions.EffectShadowOtherBinary * (1 - bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.ShadowResistance, 0)));
            fullResistRate += calculationOptions.EffectNatureOtherBinary * (1 - bossHitRate * (1 - StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.NatureResistance, 0)));
            fullResistRate += calculationOptions.EffectHolyOtherBinary * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectArcaneOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectFireOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectFrostOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectShadowOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectNatureOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectHolyOther * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectShadowManaDrainFrequency * (1 - bossHitRate);
            fullResistRate += calculationOptions.EffectShadowSilenceFrequency * (1 - bossHitRate * StatConversion.GetAverageResistance(calculationOptions.TargetLevel, calculationOptions.PlayerLevel, statsTotal.ShadowResistance, 0));

            return statsTotal;
        }
Esempio n. 14
0
        public virtual void CalculateDerivedStats(CastingState castingState, bool outOfFiveSecondRule, bool pom, bool spammedDot, bool round, bool forceHit, bool forceMiss, bool dotUptime)
        {
            MageTalents            mageTalents        = castingState.MageTalents;
            Stats                  baseStats          = castingState.BaseStats;
            CalculationOptionsMage calculationOptions = castingState.CalculationOptions;

            SpellModifier *= AdditiveSpellModifier;

            if (CritRate < 0.0f)
            {
                CritRate = 0.0f;
            }
            if (CritRate > 1.0f)
            {
                CritRate = 1.0f;
            }

            Ticks     = template.Ticks;
            CastProcs = template.CastProcs;
            HitProcs  = Ticks * HitRate;
            CritProcs = HitProcs * CritRate;
            if ((MagicSchool == MagicSchool.Fire || MagicSchool == MagicSchool.FrostFire) && mageTalents.Ignite > 0)
            {
                IgniteProcs = CritProcs;
            }
            else
            {
                IgniteProcs = 0;
            }
            TargetProcs = HitProcs;

            Pom = pom;
            if (Instant)
            {
                InterruptProtection = 1;
            }

            CastTime = template.CalculateCastTime(castingState, InterruptProtection, CritRate, pom, BaseCastTime, out ChannelReduction);

            // add crit rate for on use stacking crit effects (would be better if it was computed
            // on cycle level, but right now the architecture doesn't allow that too well)
            // we'd actually need some iterations of this as cast time can depend on crit etc, just ignore that for now
            for (int i = 0; i < castingState.Solver.StackingNonHasteEffectCooldownsCount; i++)
            {
                EffectCooldown effectCooldown = castingState.Solver.StackingNonHasteEffectCooldowns[i];
                if (castingState.EffectsActive(effectCooldown.Mask))
                {
                    Stats stats = effectCooldown.SpecialEffect.Stats;
                    for (int j = 0; j < stats._rawSpecialEffectDataSize; j++)
                    {
                        SpecialEffect effect = stats._rawSpecialEffectData[j];
                        if (effect.Chance == 1f && effect.Cooldown == 0f && (effect.Trigger == Trigger.DamageSpellCrit || effect.Trigger == Trigger.SpellCrit))
                        {
                            if (effect.Stats.CritRating < 0 && effectCooldown.SpecialEffect.Stats.CritRating > 0)
                            {
                                float critScale = castingState.CalculationOptions.LevelScalingFactor / 1400f;
                                CritRate += SpecialEffect.GetAverageStackingCritRate(CastTime, effectCooldown.SpecialEffect.Duration, HitRate, CritRate, effectCooldown.SpecialEffect.Stats.CritRating * critScale, effect.Stats.CritRating * critScale, effect.MaxStack);
                                if (CritRate > 1.0f)
                                {
                                    CritRate = 1.0f;
                                }
                            }
                        }
                    }
                }
            }

            if (DotTickInterval > 0)
            {
                if (spammedDot)
                {
                    DotProcs = (float)Math.Floor(Math.Min(CastTime, DotDuration) / DotTickInterval);
                }
                else
                {
                    DotProcs = DotDuration / DotTickInterval;
                }
            }
            else
            {
                DotProcs = 0;
            }

            SpammedDot = spammedDot;
            if (Ticks > 0 && !forceMiss)
            {
                if (dotUptime)
                {
                    AverageDamage = CalculateDirectAverageDamage(castingState.Solver, RawSpellDamage, forceHit, out DamagePerSpellPower, out IgniteDamage, out IgniteDamagePerSpellPower);
                    AverageThreat = AverageDamage * ThreatMultiplier;

                    DotAverageDamage = CalculateDotAverageDamage(baseStats, calculationOptions, RawSpellDamage, forceHit, out DotDamagePerSpellPower);
                    DotAverageThreat = DotAverageDamage * ThreatMultiplier;
                }
                else
                {
                    AverageDamage = CalculateAverageDamage(castingState.Solver, RawSpellDamage, spammedDot, forceHit, out DamagePerSpellPower, out IgniteDamage, out IgniteDamagePerSpellPower);
                    AverageThreat = AverageDamage * ThreatMultiplier;
                }
            }
            else
            {
                AverageDamage             = 0;
                AverageThreat             = 0;
                DamagePerSpellPower       = 0;
                IgniteDamage              = 0;
                IgniteDamagePerSpellPower = 0;
                if (dotUptime)
                {
                    DotAverageDamage       = 0;
                    DotAverageThreat       = 0;
                    DotDamagePerSpellPower = 0;
                }
            }
            if (ChannelReduction != 0)
            {
                Ticks               *= (1 - ChannelReduction);
                HitProcs            *= (1 - ChannelReduction);
                CritProcs           *= (1 - ChannelReduction);
                TargetProcs         *= (1 - ChannelReduction);
                CastProcs            = CastProcs2 + (CastProcs - CastProcs2) * (1 - ChannelReduction);
                AverageDamage       *= (1 - ChannelReduction);
                AverageThreat       *= (1 - ChannelReduction);
                DamagePerSpellPower *= (1 - ChannelReduction);
            }
            AverageCost = CalculateCost(castingState.Solver, round);

            Absorb      = 0;
            TotalAbsorb = 0;

            if (outOfFiveSecondRule)
            {
                OO5SR = 1;
            }
            else
            {
                OO5SR = 0;
            }
        }
Esempio n. 15
0
        private void CycleGeneratorComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string armor;
            Solver solver;
            CalculationOptionsMage calculationOptions = character.CalculationOptions as CalculationOptionsMage;
            CalculationsMage       calculations       = (CalculationsMage)Calculations.Instance;

            switch ((string)((ComboBoxItem)CycleGeneratorComboBox.SelectedItem).Content)
            {
            case "Arcane":
            default:
                armor  = "Mage Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGeneratorBeta(castingState, true, false, false, false);
                break;

            case "Arcane Dragonwrath":
                armor  = "Mage Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGeneratorLegendary(castingState, true, false, false, false);
                break;

            case "Arcane Hyper Regen":
                armor  = "Mage Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGeneratorBeta(castingState, true, false, false, true);
                break;

            case "Arcane AOE":
                armor  = "Mage Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneAOECycleGenerator(castingState, true, false, false);
                break;

            case "Frost":
                armor  = "Molten Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGeneratorBeta(castingState, false, 0.0f, false, 0.0f);
                break;

            case "Frost+Deep Freeze":
                armor  = "Molten Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGeneratorBeta(castingState, true, 30.0f, false, 0.0f);
                break;

            case "Frost+Freeze":
                armor  = "Molten Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGeneratorBeta(castingState, false, 0.0f, true, 25.0f);
                break;

            case "Frost+Freeze+Deep Freeze":
                armor  = "Molten Armor";
                solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false, true, false, false);
                solver.Initialize(null);
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGeneratorBeta(castingState, true, 30.0f, true, 25.0f);
                break;
            }

            if (castingState == null || generator == null)
            {
                return;
            }

            if (character.Ranged != null)
            {
                wand = new WandTemplate(solver, (MagicSchool)character.Ranged.Item.DamageType, character.Ranged.Item.MinDamage, character.Ranged.Item.MaxDamage, character.Ranged.Item.Speed).GetSpell(castingState);
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(generator.StateDescription);

            sb.AppendLine();
            for (int i = 0; i < generator.ControlOptions.Length; i++)
            {
                sb.Append(i);
                sb.Append(": ");
                sb.Append(generator.StateList[Array.IndexOf(generator.ControlIndex, i)]);
                sb.Append(": ");
                List <int> keys = new List <int>();
                foreach (var kvp in generator.SpellMap[i])
                {
                    keys.Add(generator.SpellList.IndexOf(kvp.Key));
                }
                keys.Sort();
                foreach (var key in keys)
                {
                    sb.Append(key);
                    sb.Append("=");
                    sb.Append(generator.SpellList[key]);
                    sb.Append("  ");
                }
                sb.AppendLine();
            }

            sb.AppendLine();
            sb.AppendLine("Transitions:");
            sb.AppendLine();

            for (int i = 0; i < generator.ControlOptions.Length; i++)
            {
                foreach (var kvp in generator.SpellMap[i])
                {
                    sb.Append(i);
                    sb.Append(": ");
                    sb.Append(kvp.Key);
                    sb.Append(" => ");

                    List <int> list = new List <int>();
                    for (int s = 0; s < generator.ControlIndex.Length; s++)
                    {
                        if (generator.ControlIndex[s] == i)
                        {
                            foreach (CycleControlledStateTransition transition in generator.StateList[s].Transitions)
                            {
                                string n;
                                if (transition.Spell != null)
                                {
                                    n = transition.Spell.Name;
                                }
                                else
                                {
                                    n = "Pause";
                                }
                                if (n == kvp.Key)
                                {
                                    int target = generator.ControlIndex[transition.TargetState.Index];
                                    if (!list.Contains(target))
                                    {
                                        list.Add(target);
                                    }
                                }
                            }
                        }
                    }

                    list.Sort();
                    sb.Append(string.Join(",", list));

                    sb.AppendLine();
                }
            }


            Description.Text   = sb.ToString();
            ControlString.Text = generator.ConvertCycleNameInternalToEasy(new string('0', generator.ControlOptions.Length));

            //ControlString.SelectAll();
            ControlString.Focus();

            Calculate_Click(null, null);
        }
Esempio n. 16
0
        public CastingState(CharacterCalculationsMage calculations, Stats characterStats, CalculationOptionsMage calculationOptions, string armor, Character character, bool arcanePower, bool moltenFury, bool icyVeins, bool heroism, bool destructionPotion, bool flameCap, bool trinket1, bool trinket2, bool combustion, bool drums, int incrementalSetIndex)
        {
            this.calculations   = calculations;
            IncrementalSetIndex = incrementalSetIndex;

            float levelScalingFactor;

            if (calculationOptions.WotLK)
            {
                levelScalingFactor = (float)((52f / 82f) * Math.Pow(63f / 131f, (calculationOptions.PlayerLevel - 70) / 10f));
            }
            else
            {
                levelScalingFactor = (1 - (70 - 60) / 82f * 3);
            }

            SpellDamageRating = characterStats.SpellDamageRating;
            SpellHasteRating  = characterStats.SpellHasteRating;

            if (destructionPotion)
            {
                SpellDamageRating += 120;
            }

            if (trinket1)
            {
                Stats t = character.Trinket1.Stats;
                SpellDamageRating += t.SpellDamageFor20SecOnUse2Min + t.SpellDamageFor15SecOnManaGem + t.SpellDamageFor15SecOnUse90Sec + t.SpellDamageFor15SecOnUse2Min;
                SpellHasteRating  += t.SpellHasteFor20SecOnUse2Min + t.SpellHasteFor20SecOnUse5Min;
                Mp5OnCastFor20Sec  = t.Mp5OnCastFor20SecOnUse2Min;
                if (t.SpellDamageFor15SecOnManaGem > 0.0)
                {
                    ManaGemActivation = true;
                }
            }
            if (trinket2)
            {
                Stats t = character.Trinket2.Stats;
                SpellDamageRating += t.SpellDamageFor20SecOnUse2Min + t.SpellDamageFor15SecOnManaGem + t.SpellDamageFor15SecOnUse90Sec + t.SpellDamageFor15SecOnUse2Min;
                SpellHasteRating  += t.SpellHasteFor20SecOnUse2Min + t.SpellHasteFor20SecOnUse5Min;
                Mp5OnCastFor20Sec  = t.Mp5OnCastFor20SecOnUse2Min;
                if (t.SpellDamageFor15SecOnManaGem > 0.0)
                {
                    ManaGemActivation = true;
                }
            }
            if (drums)
            {
                SpellHasteRating += 80;
            }

            CastingSpeed    = 1 + SpellHasteRating / 995f * levelScalingFactor;
            ArcaneDamage    = characterStats.SpellArcaneDamageRating + SpellDamageRating;
            FireDamage      = characterStats.SpellFireDamageRating + SpellDamageRating + (flameCap ? 80.0f : 0.0f);
            FrostDamage     = characterStats.SpellFrostDamageRating + SpellDamageRating;
            NatureDamage    = /* characterStats.SpellNatureDamageRating + */ SpellDamageRating;
            ShadowDamage    = characterStats.SpellShadowDamageRating + SpellDamageRating;
            FrostFireDamage = Math.Max(FireDamage, FrostDamage);

            float spellCritPerInt = 0f;
            float spellCritBase   = 0f;
            float baseRegen       = 0f;

            switch (calculationOptions.PlayerLevel)
            {
            case 70:
                spellCritPerInt = 0.0125f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.009327f;
                break;

            case 71:
                spellCritPerInt = 0.0116f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.009079f;
                break;

            case 72:
                spellCritPerInt = 0.0108f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.008838f;
                break;

            case 73:
                spellCritPerInt = 0.0101f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.008603f;
                break;

            case 74:
                spellCritPerInt = 0.0093f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.008375f;
                break;

            case 75:
                spellCritPerInt = 0.0087f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.008152f;
                break;

            case 76:
                spellCritPerInt = 0.0081f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.007936f;
                break;

            case 77:
                spellCritPerInt = 0.0075f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.007725f;
                break;

            case 78:
                spellCritPerInt = 0.007f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.00752f;
                break;

            case 79:
                spellCritPerInt = 0.0065f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.00732f;
                break;

            case 80:
                spellCritPerInt = 0.006f;
                spellCritBase   = 0.9075f;
                baseRegen       = 0.007125f;
                break;
            }
            SpellCrit = 0.01f * (characterStats.Intellect * spellCritPerInt + spellCritBase) + 0.01f * calculationOptions.ArcaneInstability + (calculationOptions.WotLK ? 0.015f : 0.01f) * calculationOptions.ArcanePotency + characterStats.SpellCritRating / 1400f * levelScalingFactor + characterStats.SpellCrit;
            if (destructionPotion)
            {
                SpellCrit += 0.02f;
            }
            SpellHit = characterStats.SpellHitRating * levelScalingFactor / 800f;

            int   targetLevel = calculationOptions.TargetLevel;
            int   playerLevel = calculationOptions.PlayerLevel;
            float maxHitRate  = (calculationOptions.WotLK) ? 1.00f : 0.99f;

            ArcaneHitRate    = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit + (calculationOptions.WotLK ? 0.01f : 0.02f) * calculationOptions.ArcaneFocus);
            FireHitRate      = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit + 0.01f * calculationOptions.ElementalPrecision);
            FrostHitRate     = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit + 0.01f * calculationOptions.ElementalPrecision);
            NatureHitRate    = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit);
            ShadowHitRate    = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit);
            FrostFireHitRate = Math.Min(maxHitRate, ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + SpellHit + 0.01f * calculationOptions.ElementalPrecision);

            SpiritRegen       = 0.001f + characterStats.Spirit * baseRegen * (float)Math.Sqrt(characterStats.Intellect);
            ManaRegen         = SpiritRegen + characterStats.Mp5 / 5f + SpiritRegen * 4 * 20 * calculationOptions.Innervate / calculationOptions.FightDuration + calculationOptions.ManaTide * 0.24f * characterStats.Mana / calculationOptions.FightDuration;
            ManaRegen5SR      = SpiritRegen * characterStats.SpellCombatManaRegeneration + characterStats.Mp5 / 5f + SpiritRegen * (5 - characterStats.SpellCombatManaRegeneration) * 20 * calculationOptions.Innervate / calculationOptions.FightDuration + calculationOptions.ManaTide * 0.24f * characterStats.Mana / calculationOptions.FightDuration;
            ManaRegenDrinking = ManaRegen + 240f;
            HealthRegen       = 0.0312f * characterStats.Spirit + characterStats.Hp5 / 5f;
            HealthRegenCombat = characterStats.Hp5 / 5f;
            HealthRegenEating = ManaRegen + 250f;
            MeleeMitigation   = (1 - 1 / (1 + 0.1f * characterStats.Armor / (8.5f * (70 + 4.5f * (70 - 59)) + 40)));
            Defense           = 350 + characterStats.DefenseRating / 2.37f;
            int molten = (armor == "Molten Armor") ? 1 : 0;

            PhysicalCritReduction = (0.04f * (Defense - 5 * 70) / 100 + characterStats.Resilience / 2500f * levelScalingFactor + molten * 0.05f);
            SpellCritReduction    = (characterStats.Resilience / 2500f * levelScalingFactor + molten * 0.05f);
            CritDamageReduction   = (characterStats.Resilience / 2500f * 2f * levelScalingFactor);
            Dodge = ((0.0443f * characterStats.Agility + 3.28f + 0.04f * (Defense - 5 * 70)) / 100f + characterStats.DodgeRating / 1200 * levelScalingFactor);

            // spell calculations

            ArcanePower       = arcanePower;
            MoltenFury        = moltenFury;
            IcyVeins          = icyVeins;
            Heroism           = heroism;
            DestructionPotion = destructionPotion;
            FlameCap          = flameCap;
            Trinket1          = trinket1;
            Trinket2          = trinket2;
            Combustion        = combustion;
            DrumsOfBattle     = drums;

            if (icyVeins)
            {
                CastingSpeed *= 1.2f;
            }
            if (heroism)
            {
                CastingSpeed *= 1.3f;
            }
            if (calculationOptions.WotLK)
            {
                CastingSpeed *= (1f + 0.02f * calculationOptions.NetherwindPresence);
            }

            Latency            = calculationOptions.Latency;
            ClearcastingChance = 0.02f * calculationOptions.ArcaneConcentration;

            GlobalCooldownLimit = 1f;
            GlobalCooldown      = Math.Max(GlobalCooldownLimit, 1.5f / CastingSpeed);

            ArcaneSpellModifier = (1 + 0.01f * calculationOptions.ArcaneInstability) * (1 + 0.01f * calculationOptions.PlayingWithFire) * (1 + characterStats.BonusSpellPowerMultiplier) * (1 + 0.02f * calculationOptions.TormentTheWeak * calculationOptions.SlowedTime);
            if (arcanePower)
            {
                ArcaneSpellModifier *= 1.3f;
            }
            if (moltenFury)
            {
                ArcaneSpellModifier *= (1 + 0.1f * calculationOptions.MoltenFury);
            }
            FireSpellModifier      = ArcaneSpellModifier * (1 + 0.02f * calculationOptions.FirePower);
            FrostSpellModifier     = ArcaneSpellModifier * (1 + 0.02f * calculationOptions.PiercingIce) * (1 + 0.01f * calculationOptions.ArcticWinds);
            NatureSpellModifier    = ArcaneSpellModifier;
            ShadowSpellModifier    = ArcaneSpellModifier;
            FrostFireSpellModifier = ArcaneSpellModifier * (1 + 0.02f * calculationOptions.FirePower) * (1 + 0.02f * calculationOptions.PiercingIce) * (1 + 0.01f * calculationOptions.ArcticWinds) * Math.Max(1 + characterStats.BonusFireSpellPowerMultiplier, 1 + characterStats.BonusFrostSpellPowerMultiplier);
            ArcaneSpellModifier   *= (1 + characterStats.BonusArcaneSpellPowerMultiplier);
            FireSpellModifier     *= (1 + characterStats.BonusFireSpellPowerMultiplier);
            FrostSpellModifier    *= (1 + characterStats.BonusFrostSpellPowerMultiplier);
            NatureSpellModifier   *= (1 + characterStats.BonusNatureSpellPowerMultiplier);
            ShadowSpellModifier   *= (1 + characterStats.BonusShadowSpellPowerMultiplier);

            ResilienceCritDamageReduction = 1;
            ResilienceCritRateReduction   = 0;

            ArcaneCritBonus    = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.25f * calculationOptions.SpellPower)) * ResilienceCritDamageReduction;
            FireCritBonus      = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.25f * calculationOptions.SpellPower)) * (1 + 0.08f * calculationOptions.Ignite) * ResilienceCritDamageReduction;
            FrostCritBonus     = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.2f * calculationOptions.IceShards + 0.25f * calculationOptions.SpellPower)) * ResilienceCritDamageReduction;
            FrostFireCritBonus = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.2f * calculationOptions.IceShards + 0.25f * calculationOptions.SpellPower)) * (1 + 0.08f * calculationOptions.Ignite) * ResilienceCritDamageReduction;
            NatureCritBonus    = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.25f * calculationOptions.SpellPower)) * ResilienceCritDamageReduction;
            ShadowCritBonus    = (1 + (1.5f * (1 + characterStats.BonusSpellCritMultiplier) - 1) * (1 + 0.25f * calculationOptions.SpellPower)) * ResilienceCritDamageReduction;

            ArcaneCritRate = SpellCrit;
            FireCritRate   = SpellCrit + 0.02f * calculationOptions.CriticalMass + 0.01f * calculationOptions.Pyromaniac;
            if (combustion)
            {
                CombustionDuration = ComputeCombustion(FireCritRate);
                FireCritRate       = 3 / CombustionDuration;
            }
            FrostFireCritRate = FireCritRate + characterStats.SpellFrostCritRating / 22.08f / 100f;
            FrostCritRate     = SpellCrit + characterStats.SpellFrostCritRating / 22.08f / 100f;
            NatureCritRate    = SpellCrit;
            ShadowCritRate    = SpellCrit;

            float threatFactor = (1 + characterStats.ThreatIncreaseMultiplier) * (1 - characterStats.ThreatReductionMultiplier);

            ArcaneThreatMultiplier    = threatFactor * (1 - calculationOptions.ArcaneSubtlety * 0.2f);
            FireThreatMultiplier      = threatFactor * (1 - calculationOptions.BurningSoul * 0.05f);
            FrostThreatMultiplier     = threatFactor * (1 - ((calculationOptions.FrostChanneling > 0) ? (0.01f + 0.03f * calculationOptions.FrostChanneling) : 0f));
            FrostFireThreatMultiplier = threatFactor * (1 - calculationOptions.BurningSoul * 0.05f) * (1 - ((calculationOptions.FrostChanneling > 0) ? (0.01f + 0.03f * calculationOptions.FrostChanneling) : 0f));
            NatureThreatMultiplier    = threatFactor;
            ShadowThreatMultiplier    = threatFactor;
        }
Esempio n. 17
0
        public void UpdateWotLK()
        {
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            SuspendLayout();
            if (calculationOptions.WotLK)
            {
                Height = 993;
                groupBoxArcane.Height = 923;
                groupBoxFire.Height   = 923;
                groupBoxFrost.Height  = 923;
                if (comboBoxArcaneFocus.Items.Count == 6)
                {
                    comboBoxArcaneFocus.Items.RemoveAt(4); comboBoxArcaneFocus.Items.RemoveAt(4);
                }
                if (comboBoxMagicAbsorption.Items.Count == 6)
                {
                    comboBoxMagicAbsorption.Items.RemoveAt(3); comboBoxMagicAbsorption.Items.RemoveAt(3); comboBoxMagicAbsorption.Items.RemoveAt(3);
                }
                if (comboBoxArcaneFortitude.Items.Count == 2)
                {
                    comboBoxArcaneFortitude.Items.AddRange(new string[] { "2", "3" });
                }
                if (comboBoxPrismaticCloak.Items.Count == 3)
                {
                    comboBoxPrismaticCloak.Items.AddRange(new string[] { "3" });
                }
                if (comboBoxArcanePotency.Items.Count == 4)
                {
                    comboBoxArcanePotency.Items.RemoveAt(3);
                }
                if (comboBoxIncinerate.Items.Count == 3)
                {
                    comboBoxIncinerate.Items.AddRange(new string[] { "3" });
                }
                if (comboBoxIceFloes.Items.Count == 3)
                {
                    comboBoxIceFloes.Items.AddRange(new string[] { "3" });
                }
            }
            else
            {
                Height = 747;
                groupBoxArcane.Height = 673;
                groupBoxFire.Height   = 673;
                groupBoxFrost.Height  = 673;
                if (comboBoxArcaneFocus.Items.Count == 4)
                {
                    comboBoxArcaneFocus.Items.AddRange(new string[] { "4", "5" });
                }
                if (comboBoxMagicAbsorption.Items.Count == 3)
                {
                    comboBoxMagicAbsorption.Items.AddRange(new string[] { "3", "4", "5" });
                }
                if (comboBoxArcaneFortitude.Items.Count == 4)
                {
                    comboBoxArcaneFortitude.Items.RemoveAt(2); comboBoxArcaneFortitude.Items.RemoveAt(2);
                }
                if (comboBoxPrismaticCloak.Items.Count == 4)
                {
                    comboBoxPrismaticCloak.Items.RemoveAt(3);
                }
                if (comboBoxArcanePotency.Items.Count == 2)
                {
                    comboBoxArcanePotency.Items.AddRange(new string[] { "3" });
                }
                if (comboBoxIncinerate.Items.Count == 4)
                {
                    comboBoxIncinerate.Items.RemoveAt(3);
                }
                if (comboBoxIceFloes.Items.Count == 4)
                {
                    comboBoxIceFloes.Items.RemoveAt(3);
                }
            }
            ResumeLayout();
        }
Esempio n. 18
0
        public float CalculateCastTime(CastingState castingState, float interruptProtection, float critRate, bool pom, float baseCastTime, out float channelReduction)
        {
            CalculationOptionsMage calculationOptions = castingState.CalculationOptions;
            float castingSpeed       = castingState.CastingSpeed;
            float spellHasteRating   = castingState.SpellHasteRating;
            float levelScalingFactor = calculationOptions.LevelScalingFactor;
            float hasteFactor        = levelScalingFactor / 1000f;
            float rootCastingSpeed   = castingSpeed / (1 + spellHasteRating * hasteFactor);

            float InterruptFactor = 0f;
            float maxPushback     = 0f;

            if (calculationOptions.InterruptFrequency > 0f)
            {
                // interrupt factors of more than once per spell are not supported, so put a limit on it (up to twice is probably approximately correct)
                InterruptFactor = Math.Min(calculationOptions.InterruptFrequency, 2 * castingSpeed / baseCastTime);
                if (castingState.IcyVeins)
                {
                    interruptProtection = 1;
                }
                maxPushback = 0.5f * Math.Max(0, 1 - interruptProtection);
                if (Channeled)
                {
                    maxPushback = 0.0f;
                }
            }

            if (pom)
            {
                baseCastTime = 0.0f;
            }

            float globalCooldown = Math.Max(Spell.GlobalCooldownLimit, 1.5f / castingSpeed);
            float latency;

            if (baseCastTime <= 1.5f || Instant)
            {
                latency = calculationOptions.LatencyGCD;
            }
            else if (Channeled)
            {
                latency = calculationOptions.LatencyChannel;
            }
            else
            {
                latency = calculationOptions.LatencyCast;
            }
            float averageTicks = Ticks;
            float castTime     = baseCastTime / castingSpeed;

            if (calculationOptions.Beta && Channeled)
            {
                float tickCastTime = castTime / Ticks;
                averageTicks = (float)Math.Floor(baseCastTime / tickCastTime);
                castTime     = averageTicks * tickCastTime;
            }
            if (InterruptFactor > 0)
            {
                castTime = castTime * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f) * maxPushback * InterruptFactor;
            }
            castTime += latency;
            float gcdcap = globalCooldown + calculationOptions.LatencyGCD;

            if (castTime < gcdcap)
            {
                castTime = gcdcap;
            }
            channelReduction = 0.0f;

            if (!calculationOptions.AdvancedHasteProcs)
            {
                for (int i = 0; i < castingState.Solver.HasteRatingEffectsCount; i++)
                {
                    SpecialEffect effect   = castingState.Solver.HasteRatingEffects[i];
                    float         procs    = 0.0f;
                    int           triggers = 0;
                    switch (effect.Trigger)
                    {
                    case Trigger.DamageSpellCast:
                    case Trigger.SpellCast:
                        procs    = CastProcs;
                        triggers = (int)procs;
                        break;

                    case Trigger.DamageSpellCrit:
                    case Trigger.SpellCrit:
                        procs    = critRate * averageTicks;
                        triggers = (int)averageTicks;
                        break;

                    case Trigger.DamageSpellHit:
                    case Trigger.SpellHit:
                        procs    = HitRate * averageTicks;
                        triggers = (int)averageTicks;
                        break;
                    }
                    if (procs == 0.0f)
                    {
                        continue;
                    }
                    float procHaste = effect.Stats.HasteRating;
                    if (effect.Cooldown >= effect.Duration)
                    {
                        // hasted casttime
                        float speed = rootCastingSpeed * (1 + (spellHasteRating + procHaste) * hasteFactor);
                        float gcd   = Math.Max(Spell.GlobalCooldownLimit, 1.5f / speed);
                        float cast  = baseCastTime / speed;
                        if (calculationOptions.Beta && Channeled)
                        {
                            float tickCastTime = cast / Ticks;
                            cast = (float)Math.Floor(baseCastTime / tickCastTime) * tickCastTime;
                        }
                        if (InterruptFactor > 0)
                        {
                            cast = cast * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f) * maxPushback * InterruptFactor;
                        }
                        cast  += latency;
                        gcdcap = gcd + calculationOptions.LatencyGCD;
                        if (cast < gcdcap)
                        {
                            cast = gcdcap;
                        }

                        float castsAffected = 0;
                        if (triggers > 1)
                        {
                            // multi tick spell (i.e. AM)
                            for (int c = 0; c < triggers; c++)
                            {
                                castsAffected += (float)Math.Ceiling((effect.Duration - c * castTime / triggers) / cast);
                            }
                            castsAffected /= triggers;
                        }
                        else
                        {
                            // single tick spell
                            castsAffected = (float)Math.Ceiling(effect.Duration / cast); // should the first proc be already hasted?
                        }
                        float effectiveDuration = castsAffected * cast;
                        // this isn't completely accurate, we should have made a separate SpecialEffect and change the actual duration
                        // but performance would hurt so this'll have to do
                        spellHasteRating += procHaste * (effectiveDuration / effect.Duration) * effect.GetAverageUptime(castTime / triggers, procs / triggers, 3.0f, calculationOptions.FightDuration);
                        //spellHasteRating += procHaste * castsAffected * cast / (effect.Cooldown + castTime / procs / effect.Chance);
                        //Haste += castingState.BasicStats.SpellHasteFor6SecOnCast_15_45 * 6f / (45f + CastTime / CastProcs / 0.15f);
                        castingSpeed = rootCastingSpeed * (1 + spellHasteRating * hasteFactor);

                        globalCooldown = Math.Max(Spell.GlobalCooldownLimit, 1.5f / castingSpeed);
                        castTime       = baseCastTime / castingSpeed;
                        if (calculationOptions.Beta && Channeled)
                        {
                            float tickCastTime = castTime / Ticks;
                            averageTicks = (float)Math.Floor(baseCastTime / tickCastTime);
                            castTime     = averageTicks * tickCastTime;
                        }
                        if (InterruptFactor > 0)
                        {
                            castTime = castTime * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f) * maxPushback * InterruptFactor;
                        }
                        castTime += latency;
                        gcdcap    = globalCooldown + calculationOptions.LatencyGCD;
                        if (castTime < gcdcap)
                        {
                            castTime = gcdcap;
                        }
                    }
                    else if (effect.Cooldown == 0 && (effect.Trigger == Trigger.SpellCrit || effect.Trigger == Trigger.DamageSpellCrit))
                    {
                        float rawHaste = spellHasteRating;

                        castingSpeed /= (1 + spellHasteRating / 1000f * levelScalingFactor);
                        float proccedSpeed    = castingSpeed * (1 + (rawHaste + procHaste) / 1000f * levelScalingFactor);
                        float proccedGcd      = Math.Max(Spell.GlobalCooldownLimit, 1.5f / proccedSpeed);
                        float proccedCastTime = baseCastTime / proccedSpeed;
                        float proccedTicks    = averageTicks;
                        if (calculationOptions.Beta && Channeled)
                        {
                            float tickCastTime = proccedCastTime / Ticks;
                            proccedTicks = (float)Math.Floor(baseCastTime / tickCastTime);
                            castTime     = proccedTicks * tickCastTime;
                        }
                        if (InterruptFactor > 0)
                        {
                            proccedCastTime = proccedCastTime * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f) * maxPushback * InterruptFactor;
                        }
                        proccedCastTime += latency;
                        if (proccedCastTime < proccedGcd + calculationOptions.LatencyGCD)
                        {
                            proccedCastTime = proccedGcd + calculationOptions.LatencyGCD;
                        }
                        int chancesToProc = (int)(((int)Math.Floor(effect.Duration / proccedCastTime) + 1) * proccedTicks);
                        if (!(Instant || pom))
                        {
                            chancesToProc -= 1;
                        }
                        if (AreaEffect)
                        {
                            chancesToProc *= calculationOptions.AoeTargets;
                        }
                        spellHasteRating = rawHaste + procHaste * (1 - (float)Math.Pow(1 - effect.Chance * critRate, chancesToProc));
                        //Haste = rawHaste + castingState.BasicStats.SpellHasteFor5SecOnCrit_50 * ProcBuffUp(1 - (float)Math.Pow(1 - 0.5f * CritRate, HitProcs), 5, CastTime);
                        castingSpeed  *= (1 + spellHasteRating / 1000f * levelScalingFactor);
                        globalCooldown = Math.Max(Spell.GlobalCooldownLimit, 1.5f / castingSpeed);
                        castTime       = baseCastTime / castingSpeed;
                        if (calculationOptions.Beta && Channeled)
                        {
                            float tickCastTime = castTime / Ticks;
                            averageTicks = (float)Math.Floor(baseCastTime / tickCastTime);
                            castTime     = averageTicks * tickCastTime;
                        }
                        if (InterruptFactor > 0)
                        {
                            castTime = castTime * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f + latency) * maxPushback * InterruptFactor;
                        }
                        castTime += latency;
                        if (castTime < globalCooldown + calculationOptions.LatencyGCD)
                        {
                            castTime = globalCooldown + calculationOptions.LatencyGCD;
                        }
                    }
                }
                // on use stacking items
                for (int i = 0; i < castingState.Solver.StackingHasteEffectCooldownsCount; i++)
                {
                    EffectCooldown effectCooldown = castingState.Solver.StackingHasteEffectCooldowns[i];
                    if (castingState.EffectsActive(effectCooldown.Mask))
                    {
                        Stats stats = effectCooldown.SpecialEffect.Stats;
                        for (int j = 0; j < stats._rawSpecialEffectDataSize; j++)
                        {
                            SpecialEffect effect    = stats._rawSpecialEffectData[j];
                            float         procHaste = effect.Stats.HasteRating;
                            if (procHaste > 0)
                            {
                                float procs = 0.0f;
                                switch (effect.Trigger)
                                {
                                case Trigger.DamageSpellCast:
                                case Trigger.SpellCast:
                                    procs = CastProcs;
                                    break;

                                case Trigger.DamageSpellCrit:
                                case Trigger.SpellCrit:
                                    procs = critRate * averageTicks;
                                    break;

                                case Trigger.DamageSpellHit:
                                case Trigger.SpellHit:
                                    procs = HitRate * averageTicks;
                                    break;
                                }
                                if (procs == 0.0f)
                                {
                                    continue;
                                }
                                // until they put in some good trinkets with such effects just do a quick dirty calculation
                                float effectHasteRating;
                                if (procs > averageTicks)
                                {
                                    // some 100% on cast procs, happens because AM has 6 cast procs and only 5 ticks
                                    effectHasteRating = effect.GetAverageStackSize(castTime / procs, 1.0f, 3.0f, effectCooldown.SpecialEffect.Duration) * procHaste;
                                }
                                else
                                {
                                    effectHasteRating = effect.GetAverageStackSize(castTime / averageTicks, procs / averageTicks, 3.0f, effectCooldown.SpecialEffect.Duration) * procHaste;
                                }

                                castingSpeed     /= (1 + spellHasteRating / 1000f * levelScalingFactor);
                                spellHasteRating += effectHasteRating;
                                castingSpeed     *= (1 + spellHasteRating / 1000f * levelScalingFactor);

                                globalCooldown = Math.Max(Spell.GlobalCooldownLimit, 1.5f / castingSpeed);
                                castTime       = baseCastTime / castingSpeed;
                                if (calculationOptions.Beta && Channeled)
                                {
                                    float tickCastTime = castTime / Ticks;
                                    averageTicks = (float)Math.Floor(baseCastTime / tickCastTime);
                                    castTime     = averageTicks * tickCastTime;
                                }
                                if (InterruptFactor > 0)
                                {
                                    castTime = castTime * (1 + InterruptFactor * maxPushback) - (maxPushback * 0.5f) * maxPushback * InterruptFactor;
                                }
                                castTime += latency;
                                if (castTime < globalCooldown + calculationOptions.LatencyGCD)
                                {
                                    castTime = globalCooldown + calculationOptions.LatencyGCD;
                                }
                            }
                        }
                    }
                }
            }

            if (Channeled && calculationOptions.Beta)
            {
                channelReduction = 1 - averageTicks / Ticks;
            }

            // channeled pushback
            if (Channeled && InterruptFactor > 0)
            {
                int maxLostTicks = (int)Math.Ceiling(averageTicks * 0.25f * Math.Max(0, 1 - interruptProtection));
                // pushbacks that happen up to pushbackCastTime cut the cast time to pushbackCastTime
                // pushbacks that happen after just terminate the channel
                // [---|---X---|---|---]
                castTime -= latency;
                float tickFactor = 0;
                for (int i = 0; i < maxLostTicks; i++)
                {
                    tickFactor += InterruptFactor * castTime / averageTicks * (i + 1) / averageTicks;
                }
                tickFactor += InterruptFactor * (averageTicks - maxLostTicks) * castTime / averageTicks * maxLostTicks / averageTicks;
                if (calculationOptions.Beta)
                {
                    channelReduction = 1 - averageTicks * (1 - tickFactor) / Ticks;
                }
                else
                {
                    channelReduction = tickFactor;
                }
                castTime = castTime * (1 - tickFactor) + latency;
            }

            return(castTime);
        }
Esempio n. 19
0
        public void InitializeDamage(Solver solver, bool areaEffect, int range, MagicSchool magicSchool, int cost, float minDamage, float maxDamage, float spellDamageCoefficient, float periodicDamage, float dotDamageCoefficient, float hitProcs, float castProcs, float dotDuration)
        {
            Stats                  baseStats          = solver.BaseStats;
            MageTalents            mageTalents        = solver.MageTalents;
            CalculationOptionsMage calculationOptions = solver.CalculationOptions;

            AreaEffect        = areaEffect;
            AreaEffectDot     = areaEffect;
            MaximumAOETargets = 10;
            int manaReduction = (int)baseStats.SpellsManaCostReduction;

            if (manaReduction == 405)
            {
                // Shard of Woe hax
                manaReduction = 205;
            }
            BaseCost               = Math.Max(cost - manaReduction, 0);
            MagicSchool            = magicSchool;
            Ticks                  = hitProcs;
            CastProcs              = castProcs;
            CastProcs2             = castProcs;
            BaseMinDamage          = minDamage;
            BaseMaxDamage          = maxDamage;
            SpellDamageCoefficient = spellDamageCoefficient;
            BasePeriodicDamage     = periodicDamage;
            DotDamageCoefficient   = dotDamageCoefficient;
            DotDuration            = dotDuration;

            BaseDirectDamageModifier = 1.0f;
            BaseDotDamageModifier    = 1.0f;
            BaseCostModifier         = 1.0f;

            float baseCostAmplifier = calculationOptions.EffectCostMultiplier;

            if (mageTalents.EnduringWinter > 0)
            {
                BaseCostModifier -= 0.03f * mageTalents.EnduringWinter + (mageTalents.EnduringWinter == 3 ? 0.01f : 0.00f);
            }
            BaseCostAmplifier = baseCostAmplifier;

            float baseInterruptProtection = baseStats.InterruptProtection;

            baseInterruptProtection += 0.23f * mageTalents.BurningSoul + (mageTalents.BurningSoul == 3 ? 0.01f : 0.0f);
            BaseInterruptProtection  = baseInterruptProtection;

            float realResistance;

            switch (MagicSchool)
            {
            case MagicSchool.Arcane:
                BaseSpellModifier         = solver.BaseArcaneSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseArcaneAdditiveSpellModifier;
                BaseCritRate     = solver.BaseArcaneCritRate;
                CritBonus        = solver.BaseArcaneCritBonus;
                HitRate          = solver.BaseArcaneHitRate;
                ThreatMultiplier = solver.ArcaneThreatMultiplier;
                realResistance   = calculationOptions.ArcaneResist;
                IgniteFactor     = 0;
                break;

            case MagicSchool.Fire:
                BaseSpellModifier         = solver.BaseFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFireCritRate;
                CritBonus        = solver.BaseFireCritBonus;
                HitRate          = solver.BaseFireHitRate;
                ThreatMultiplier = solver.FireThreatMultiplier;
                realResistance   = calculationOptions.FireResist;
                IgniteFactor     = solver.IgniteFactor;
                break;

            case MagicSchool.FrostFire:
                BaseSpellModifier         = solver.BaseFrostFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostFireCritRate;
                CritBonus        = solver.BaseFrostFireCritBonus;
                HitRate          = solver.BaseFrostFireHitRate;
                ThreatMultiplier = solver.FrostFireThreatMultiplier;
                if (calculationOptions.FireResist == -1)
                {
                    realResistance = calculationOptions.FrostResist;
                }
                else if (calculationOptions.FrostResist == -1)
                {
                    realResistance = calculationOptions.FireResist;
                }
                else
                {
                    realResistance = Math.Min(calculationOptions.FireResist, calculationOptions.FrostResist);
                }
                Range        = range;
                IgniteFactor = solver.IgniteFactor;
                break;

            case MagicSchool.Frost:
                BaseSpellModifier         = solver.BaseFrostSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostCritRate;
                CritBonus        = solver.BaseFrostCritBonus;
                HitRate          = solver.BaseFrostHitRate;
                ThreatMultiplier = solver.FrostThreatMultiplier;
                realResistance   = calculationOptions.FrostResist;
                IgniteFactor     = 0;
                break;

            case MagicSchool.Nature:
                BaseSpellModifier         = solver.BaseNatureSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseNatureAdditiveSpellModifier;
                BaseCritRate     = solver.BaseNatureCritRate;
                CritBonus        = solver.BaseNatureCritBonus;
                HitRate          = solver.BaseNatureHitRate;
                ThreatMultiplier = solver.NatureThreatMultiplier;
                realResistance   = calculationOptions.NatureResist;
                Range            = range;
                IgniteFactor     = 0;
                break;

            case MagicSchool.Shadow:
                BaseSpellModifier         = solver.BaseShadowSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseShadowAdditiveSpellModifier;
                BaseCritRate     = solver.BaseShadowCritRate;
                CritBonus        = solver.BaseShadowCritBonus;
                HitRate          = solver.BaseShadowHitRate;
                ThreatMultiplier = solver.ShadowThreatMultiplier;
                realResistance   = calculationOptions.ShadowResist;
                Range            = range;
                IgniteFactor     = 0;
                break;

            case MagicSchool.Holy:
            default:
                BaseSpellModifier         = solver.BaseHolySpellModifier;
                BaseAdditiveSpellModifier = solver.BaseHolyAdditiveSpellModifier;
                BaseCritRate     = solver.BaseHolyCritRate;
                CritBonus        = solver.BaseHolyCritBonus;
                HitRate          = solver.BaseHolyHitRate;
                ThreatMultiplier = solver.HolyThreatMultiplier;
                realResistance   = calculationOptions.HolyResist;
                Range            = range;
                IgniteFactor     = 0;
                break;
            }

            NonHSCritRate = baseStats.SpellCritOnTarget;

            int playerLevel = calculationOptions.PlayerLevel;
            int targetLevel;

            if (areaEffect)
            {
                targetLevel = calculationOptions.AoeTargetLevel;
                float hitRate = ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + solver.BaseSpellHit;
                if (hitRate > Spell.MaxHitRate)
                {
                    hitRate = Spell.MaxHitRate;
                }
                HitRate = hitRate;
            }
            else
            {
                targetLevel = calculationOptions.TargetLevel;
            }

            RealResistance      = realResistance;
            PartialResistFactor = (realResistance == -1) ? 0 : (1 - StatConversion.GetAverageResistance(playerLevel, targetLevel, realResistance, baseStats.SpellPenetration));
        }
Esempio n. 20
0
        public void InitializeEffectDamage(Solver solver, MagicSchool magicSchool, float minDamage, float maxDamage)
        {
            Stats                  baseStats          = solver.BaseStats;
            MageTalents            mageTalents        = solver.MageTalents;
            CalculationOptionsMage calculationOptions = solver.CalculationOptions;

            //AreaEffect = areaEffect;
            //BaseCost = cost - (int)baseStats.SpellsManaReduction;
            MagicSchool   = magicSchool;
            BaseMinDamage = minDamage;
            BaseMaxDamage = maxDamage;
            //BasePeriodicDamage = periodicDamage;
            //SpellDamageCoefficient = spellDamageCoefficient;
            //Ticks = 1;
            //CastProcs = 0;
            //CastProcs2 = 0;
            //DotDamageCoefficient = dotDamageCoefficient;
            //DotDuration = dotDuration;

            BaseDirectDamageModifier = 1.0f;
            BaseDotDamageModifier    = 1.0f;
            BaseCostModifier         = 1.0f;

            //Range = range;

            /*float baseCostAmplifier = calculationOptions.EffectCostMultiplier;
             * baseCostAmplifier *= (1.0f - 0.01f * mageTalents.Precision);
             * if (mageTalents.FrostChanneling > 0) baseCostAmplifier *= (1.0f - 0.01f - 0.03f * mageTalents.FrostChanneling);
             * if (MagicSchool == MagicSchool.Arcane) baseCostAmplifier *= (1.0f - 0.01f * mageTalents.ArcaneFocus);
             * BaseCostAmplifier = baseCostAmplifier;*/

            /*float baseInterruptProtection = baseStats.InterruptProtection;
             * if (MagicSchool == MagicSchool.Fire || MagicSchool == MagicSchool.FrostFire)
             * {
             *  baseInterruptProtection += 0.35f * mageTalents.BurningSoul;
             *  AffectedByFlameCap = true;
             * }
             * BaseInterruptProtection = baseInterruptProtection;*/

            float realResistance;

            switch (MagicSchool)
            {
            case MagicSchool.Arcane:
                BaseSpellModifier         = solver.BaseArcaneSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseArcaneAdditiveSpellModifier;
                BaseCritRate     = solver.BaseArcaneCritRate;
                CritBonus        = solver.BaseArcaneCritBonus;
                HitRate          = solver.BaseArcaneHitRate;
                ThreatMultiplier = solver.ArcaneThreatMultiplier;
                realResistance   = calculationOptions.ArcaneResist;
                break;

            case MagicSchool.Fire:
                BaseSpellModifier         = solver.BaseFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFireCritRate;
                CritBonus        = solver.BaseFireCritBonus;
                HitRate          = solver.BaseFireHitRate;
                ThreatMultiplier = solver.FireThreatMultiplier;
                realResistance   = calculationOptions.FireResist;
                break;

            case MagicSchool.FrostFire:
                BaseSpellModifier         = solver.BaseFrostFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostFireCritRate;
                CritBonus        = solver.BaseFrostFireCritBonus;
                HitRate          = solver.BaseFrostFireHitRate;
                ThreatMultiplier = solver.FrostFireThreatMultiplier;
                if (calculationOptions.FireResist == -1)
                {
                    realResistance = calculationOptions.FrostResist;
                }
                else if (calculationOptions.FrostResist == -1)
                {
                    realResistance = calculationOptions.FireResist;
                }
                else
                {
                    realResistance = Math.Min(calculationOptions.FireResist, calculationOptions.FrostResist);
                }
                break;

            case MagicSchool.Frost:
                BaseSpellModifier         = solver.BaseFrostSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostCritRate;
                CritBonus        = solver.BaseFrostCritBonus;
                HitRate          = solver.BaseFrostHitRate;
                ThreatMultiplier = solver.FrostThreatMultiplier;
                realResistance   = calculationOptions.FrostResist;
                break;

            case MagicSchool.Nature:
                BaseSpellModifier         = solver.BaseNatureSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseNatureAdditiveSpellModifier;
                BaseCritRate     = solver.BaseNatureCritRate;
                CritBonus        = solver.BaseNatureCritBonus;
                HitRate          = solver.BaseNatureHitRate;
                ThreatMultiplier = solver.NatureThreatMultiplier;
                realResistance   = calculationOptions.NatureResist;
                break;

            case MagicSchool.Shadow:
                BaseSpellModifier         = solver.BaseShadowSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseShadowAdditiveSpellModifier;
                BaseCritRate     = solver.BaseShadowCritRate;
                CritBonus        = solver.BaseShadowCritBonus;
                HitRate          = solver.BaseShadowHitRate;
                ThreatMultiplier = solver.ShadowThreatMultiplier;
                realResistance   = calculationOptions.ShadowResist;
                break;

            case MagicSchool.Holy:
            default:
                BaseSpellModifier         = solver.BaseHolySpellModifier;
                BaseAdditiveSpellModifier = solver.BaseHolyAdditiveSpellModifier;
                BaseCritRate     = solver.BaseHolyCritRate;
                CritBonus        = solver.BaseHolyCritBonus;
                HitRate          = solver.BaseHolyHitRate;
                ThreatMultiplier = solver.HolyThreatMultiplier;
                realResistance   = calculationOptions.HolyResist;
                break;
            }

            int playerLevel = calculationOptions.PlayerLevel;
            int targetLevel = calculationOptions.TargetLevel;

            /*if (areaEffect)
             * {
             *  targetLevel = calculationOptions.AoeTargetLevel;
             *  float hitRate = ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + calculations.BaseSpellHit;
             *  if (MagicSchool == MagicSchool.Arcane) hitRate += 0.01f * mageTalents.ArcaneFocus;
             *  if (hitRate > Spell.MaxHitRate) hitRate = Spell.MaxHitRate;
             *  HitRate = hitRate;
             * }
             * else
             * {
             *  targetLevel = calculationOptions.TargetLevel;
             * }*/

            RealResistance      = realResistance;
            PartialResistFactor = (realResistance == -1) ? 0 : (1 - StatConversion.GetAverageResistance(playerLevel, targetLevel, realResistance, baseStats.SpellPenetration));
        }
Esempio n. 21
0
        protected override void LoadCalculationOptions()
        {
            //if (Character.MageTalents == null) Character.MageTalents = new MageTalents();
            if (Character.CalculationOptions == null)
            {
                Character.CalculationOptions = new CalculationOptionsMage(Character);
            }
            CalculationOptionsMage calculationOptions = Character.CalculationOptions as CalculationOptionsMage;

            if (calculationOptions.ArcaneResist > 0 && calculationOptions.ArcaneResist <= 1)
            {
                if (calculationOptions.ArcaneResist == 1)
                {
                    calculationOptions.ArcaneResist = -1;
                }
                else
                {
                    calculationOptions.ArcaneResist *= 400;
                }
            }
            if (calculationOptions.FireResist > 0 && calculationOptions.FireResist <= 1)
            {
                if (calculationOptions.FireResist == 1)
                {
                    calculationOptions.FireResist = -1;
                }
                else
                {
                    calculationOptions.FireResist *= 400;
                }
            }
            if (calculationOptions.FrostResist > 0 && calculationOptions.FrostResist <= 1)
            {
                if (calculationOptions.FrostResist == 1)
                {
                    calculationOptions.FrostResist = -1;
                }
                else
                {
                    calculationOptions.FrostResist *= 400;
                }
            }
            if (calculationOptions.ShadowResist > 0 && calculationOptions.ShadowResist <= 1)
            {
                if (calculationOptions.ShadowResist == 1)
                {
                    calculationOptions.ShadowResist = -1;
                }
                else
                {
                    calculationOptions.ShadowResist *= 400;
                }
            }
            if (calculationOptions.NatureResist > 0 && calculationOptions.NatureResist <= 1)
            {
                if (calculationOptions.NatureResist == 1)
                {
                    calculationOptions.NatureResist = -1;
                }
                else
                {
                    calculationOptions.NatureResist *= 400;
                }
            }
            if (calculationOptions.HolyResist > 0 && calculationOptions.HolyResist <= 1)
            {
                if (calculationOptions.HolyResist == 1)
                {
                    calculationOptions.HolyResist = -1;
                }
                else
                {
                    calculationOptions.HolyResist *= 400;
                }
            }

            loading = true;
            calculationOptionsMageBindingSource.DataSource = calculationOptions;

            //BindingSource bs = calculationOptionsMageBindingSource;
            //bs.AddingNew += (s, ev) => System.Diagnostics.Trace.WriteLine("AddingNew");
            //bs.BindingComplete += (s, ev) => System.Diagnostics.Trace.WriteLine("BindingComplete");
            //bs.CurrentChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("CurrentChanged");
            //bs.CurrentItemChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("CurrentItemChanged");
            //bs.DataError += (s, ev) => System.Diagnostics.Trace.WriteLine("DataError");
            //bs.DataMemberChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("DataMemberChanged");
            //bs.DataSourceChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("DataSourceChanged");
            //bs.ListChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("ListChanged");
            //bs.PositionChanged += (s, ev) => System.Diagnostics.Trace.WriteLine("PositionChanged");

            if (cooldownRestrictions != null && !cooldownRestrictions.IsDisposed)
            {
                cooldownRestrictions.Character = Character;
                //cooldownRestrictions.bindingSourceCalculationOptions.DataSource = calculationOptions;
            }

            loading = false;

            SolverLogForm.Instance.ToString(); // force create it on main thread
        }
Esempio n. 22
0
        private void CycleGeneratorComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string armor = "Molten Armor";
            CalculationOptionsMage calculationOptions = character.CalculationOptions as CalculationOptionsMage;
            CalculationsMage       calculations       = (CalculationsMage)Calculations.Instance;
            Solver solver = new Solver(character, calculationOptions, false, false, false, 0, armor, false, false, false, false);

            solver.Initialize(null);

            switch ((string)((ComboBoxItem)CycleGeneratorComboBox.SelectedItem).Content)
            {
            case "Arcane (MB/2T10 duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGenerator(castingState, true, false, true, false, true, true);
                break;

            case "Arcane (Arcane Power, MB/2T10 duration collapsed)":
                castingState = new CastingState(solver, (int)StandardEffect.ArcanePower, false, 0);
                generator    = new ArcaneCycleGenerator(castingState, true, false, true, false, true, true);
                break;

            case "Arcane (ABar on cooldown only, MB/2T10 duration/ABar cooldown collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGenerator(castingState, true, true, true, true, true, true);
                break;

            case "Arcane (no ABar, MB duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneCycleGenerator(castingState, false, true, true, true, false, true);
                break;

            case "Arcane Movement (average 1 per 10 sec for 1 sec)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new ArcaneMovementCycleGenerator(castingState, 0.1f, 1.0f, true, false, true, true, true, true);
                break;

            case "Frost":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator(castingState, true, false);
                break;

            case "Frost (no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator(castingState, false, false);
                break;

            case "Frost+Deep Freeze":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, false, false, false);
                break;

            case "Frost+Deep Freeze (no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, false, false, false);
                break;

            case "Frost+Deep Freeze (2T10 duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, true, false, false);
                break;

            case "Frost+Deep Freeze (2T10 duration collapsed, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, true, false, false);
                break;

            case "Frost+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, true, true, false);
                break;

            case "Frost+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, true, true, false);
                break;

            case "Frost+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, 10 sec Deep Freeze cooldown)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 10.0f, true, true, false);
                break;

            case "Frost+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, 10 sec Deep Freeze cooldown, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 10.0f, true, true, false);
                break;

            case "FrostFFB+Deep Freeze":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, false, false, true);
                break;

            case "FrostFFB+Deep Freeze (no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, false, false, true);
                break;

            case "FrostFFB+Deep Freeze (2T10 duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, true, false, true);
                break;

            case "FrostFFB+Deep Freeze (2T10 duration collapsed, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, true, false, true);
                break;

            case "FrostFFB+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 30.0f, true, true, true);
                break;

            case "FrostFFB+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 30.0f, true, true, true);
                break;

            case "FrostFFB+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, 10 sec Deep Freeze cooldown)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, true, true, 10.0f, true, true, true);
                break;

            case "FrostFFB+Deep Freeze (FOF instants on last charge only, 2T10 duration collapsed, 10 sec Deep Freeze cooldown, no latency combos)":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FrostCycleGenerator2(castingState, false, true, 10.0f, true, true, true);
                break;

            case "Fire":
                castingState = new CastingState(solver, 0, false, 0);
                generator    = new FireCycleGenerator(castingState);
                break;
            }

            if (castingState == null || generator == null)
            {
                return;
            }

            if (character.Ranged != null)
            {
                wand = new WandTemplate(solver, (MagicSchool)character.Ranged.Item.DamageType, character.Ranged.Item.MinDamage, character.Ranged.Item.MaxDamage, character.Ranged.Item.Speed).GetSpell(castingState);
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(generator.StateDescription);

            sb.AppendLine("");
            for (int i = 0; i < generator.ControlOptions.Length; i++)
            {
                sb.Append(i);
                sb.Append(": ");
                sb.Append(generator.StateList[Array.IndexOf(generator.ControlIndex, i)]);
                sb.Append(": ");
                foreach (var kvp in generator.SpellMap[i])
                {
                    sb.Append(kvp.Value);
                    sb.Append("=");
                    sb.Append(kvp.Key);
                    sb.Append("  ");
                }
                sb.AppendLine();
            }

            Description.Text   = sb.ToString();
            ControlString.Text = new string('0', generator.ControlOptions.Length);

            //ControlString.SelectAll();
            ControlString.Focus();

            Calculate_Click(null, null);
        }
Esempio n. 23
0
        public void AccumulateRawStats(Stats stats, Character character, Item additionalItem, CalculationOptionsMage calculationOptions, out List<Buff> autoActivatedBuffs, string armor, out List<Buff> activeBuffs)
        {
            AccumulateItemStats(stats, character, additionalItem);

            bool activeBuffsCloned = false;
            activeBuffs = character.ActiveBuffs;
            autoActivatedBuffs = null;

            if (!character.DisableBuffAutoActivation)
            {
                MageTalents talents = character.MageTalents;
                /*if (talents.CriticalMass > 0)
                {
                    if (!character.ActiveBuffs.Contains(ImprovedScorchBuff) && !character.ActiveBuffs.Contains(WintersChillBuff))
                    {
                        if (!activeBuffsCloned)
                        {
                            activeBuffs = new List<Buff>(character.ActiveBuffs);
                            autoActivatedBuffs = new List<Buff>();
                            activeBuffsCloned = true;
                        }
                        activeBuffs.Add(ImprovedScorchBuff);
                        autoActivatedBuffs.Add(ImprovedScorchBuff);
                        RemoveConflictingBuffs(activeBuffs, ImprovedScorchBuff);
                    }
                }*/
                if (armor != null)
                {
                    Buff armorBuff = null;
                    switch (armor)
                    {
                        case "Molten Armor":
                            armorBuff = MoltenArmorBuff;
                            break;
                        case "Mage Armor":
                            armorBuff = MageArmorBuff;
                            break;
                        case "Ice Armor":
                            armorBuff = IceArmorBuff;
                            break;
                    }
                    if (!character.ActiveBuffs.Contains(armorBuff))
                    {
                        if (!activeBuffsCloned)
                        {
                            activeBuffs = new List<Buff>(character.ActiveBuffs);
                            autoActivatedBuffs = new List<Buff>();
                            activeBuffsCloned = true;
                        }
                        activeBuffs.Add(armorBuff);
                        autoActivatedBuffs.Add(armorBuff);
                        RemoveConflictingBuffs(activeBuffs, armorBuff);
                    }
                }
            }

            AccumulateBuffsStats(stats, activeBuffs);

            // moving away to handling these as normal procs, reevaluate if needed
            /*for (int i = 0; i < stats._rawSpecialEffectDataSize; i++)
            {
                SpecialEffect effect = stats._rawSpecialEffectData[i];
                if (effect.MaxStack > 1 && effect.Chance == 1f && effect.Cooldown == 0f && (effect.Trigger == Trigger.DamageSpellCast || effect.Trigger == Trigger.DamageSpellHit || effect.Trigger == Trigger.SpellCast || effect.Trigger == Trigger.SpellHit))
                {
                    effect.Stats.GenerateSparseData();
                    stats.Accumulate(effect.Stats, effect.MaxStack);
                }                
            }*/
        }
Esempio n. 24
0
 public CharacterCalculationsMage GetCharacterCalculations(Character character, Item additionalItem, CalculationOptionsMage calculationOptions, string armor, bool useIncrementalOptimizations, bool useGlobalOptimizations, bool needsDisplayCalculations, bool needsSolutionVariables, bool solveCycles)
 {
     return Solver.GetCharacterCalculations(character, additionalItem, calculationOptions, this, armor, calculationOptions.ComparisonSegmentCooldowns, calculationOptions.ComparisonSegmentMana, calculationOptions.ComparisonIntegralMana, calculationOptions.ComparisonAdvancedConstraintsLevel, useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, needsSolutionVariables, solveCycles, calculationOptions.SimpleStacking, calculationOptions.SimpleStacking);
 }
Esempio n. 25
0
        public virtual void CalculateDerivedStats(CastingState castingState, bool outOfFiveSecondRule, bool pom, bool spammedDot, bool round, bool forceHit, bool forceMiss, bool dotUptime)
        {
            MageTalents            mageTalents        = castingState.MageTalents;
            Stats                  baseStats          = castingState.BaseStats;
            CalculationOptionsMage calculationOptions = castingState.CalculationOptions;

            if (AreaEffect)
            {
                // do not count debuffs for aoe effects, can't assume it will be up on all
                // do not include molten fury (molten fury relates to boss), instead amplify all by average
                if (castingState.MoltenFury)
                {
                    SpellModifier /= (1 + 0.04f * castingState.MageTalents.MoltenFury);
                }
                if (castingState.MageTalents.MoltenFury > 0)
                {
                    SpellModifier *= (1 + 0.04f * castingState.MageTalents.MoltenFury * castingState.CalculationOptions.MoltenFuryPercentage);
                }
            }

            SpellModifier *= AdditiveSpellModifier;

            if (CritRate < 0.0f)
            {
                CritRate = 0.0f;
            }
            if (CritRate > 1.0f)
            {
                CritRate = 1.0f;
            }

            Ticks     = template.Ticks;
            CastProcs = template.CastProcs;
            HitProcs  = Ticks * HitRate;
            if (AreaEffect)
            {
                TargetProcs = HitProcs * castingState.CalculationOptions.AoeTargets;
            }
            else
            {
                TargetProcs = HitProcs;
            }

            Pom = pom;
            if (Instant)
            {
                InterruptProtection = 1;
            }

            CastTime = template.CalculateCastTime(castingState, InterruptProtection, CritRate, pom, BaseCastTime, out ChannelReduction);

            // add crit rate for on use stacking crit effects (would be better if it was computed
            // on cycle level, but right now the architecture doesn't allow that too well)
            // we'd actually need some iterations of this as cast time can depend on crit etc, just ignore that for now
            for (int i = 0; i < castingState.Solver.StackingNonHasteEffectCooldownsCount; i++)
            {
                EffectCooldown effectCooldown = castingState.Solver.StackingNonHasteEffectCooldowns[i];
                if (castingState.EffectsActive(effectCooldown.Mask))
                {
                    Stats stats = effectCooldown.SpecialEffect.Stats;
                    for (int j = 0; j < stats._rawSpecialEffectDataSize; j++)
                    {
                        SpecialEffect effect = stats._rawSpecialEffectData[j];
                        if (effect.Chance == 1f && effect.Cooldown == 0f && (effect.Trigger == Trigger.DamageSpellCrit || effect.Trigger == Trigger.SpellCrit))
                        {
                            if (effect.Stats.CritRating < 0 && effectCooldown.SpecialEffect.Stats.CritRating > 0)
                            {
                                float critScale = castingState.CalculationOptions.LevelScalingFactor / 1400f;
                                CritRate += SpecialEffect.GetAverageStackingCritRate(CastTime, effectCooldown.SpecialEffect.Duration, HitRate, CritRate, effectCooldown.SpecialEffect.Stats.CritRating * critScale, effect.Stats.CritRating * critScale, effect.MaxStack);
                                if (CritRate > 1.0f)
                                {
                                    CritRate = 1.0f;
                                }
                            }
                        }
                    }
                }
            }

            if (castingState.Frozen)
            {
                CritRate *= (1 + castingState.MageTalents.Shatter);
                if (CritRate > 1.0f)
                {
                    CritRate = 1.0f;
                }
            }

            CritProcs = HitProcs * CritRate;
            if ((MagicSchool == MagicSchool.Fire || MagicSchool == MagicSchool.FrostFire) && mageTalents.Ignite > 0)
            {
                IgniteProcs = CritProcs;
            }
            else
            {
                IgniteProcs = 0;
            }

            if (DotTickInterval > 0)
            {
                // non-spammed we have to take into account haste on dot duration and increase in number of ticks
                // probably don't want to take into account haste procs as that might skew optimization thresholds as we're averaging cast time over procs
                // reevaluate this if needed
                float x = DotTickInterval / DotDuration;
                DotExtraTicks   = (float)Math.Floor((castingState.CastingSpeed - 1) / x + 0.5);
                DotFullDuration = (DotDuration + DotTickInterval * DotExtraTicks) / castingState.CastingSpeed;
                if (spammedDot)
                {
                    // spammed dots no longer clip on reapplication
                    DotProcs = Math.Min(CastTime, DotDuration) / DotTickInterval;
                }
                else
                {
                    DotProcs = DotDuration / DotTickInterval + DotExtraTicks;
                }
            }
            else
            {
                DotProcs        = 0;
                DotFullDuration = 0;
                DotExtraTicks   = 0;
            }

            SpammedDot = spammedDot;
            if ((BaseMinDamage > 0 || BasePeriodicDamage > 0) && !forceMiss)
            {
                if (dotUptime)
                {
                    CalculateDirectAverageDamage(castingState.Solver, RawSpellDamage, forceHit);
                    AverageThreat = AverageDamage * ThreatMultiplier;

                    CalculateDotAverageDamage(castingState.Solver, RawSpellDamage, forceHit);
                    DotAverageThreat = DotAverageDamage * ThreatMultiplier;
                }
                else
                {
                    CalculateAverageDamage(castingState.Solver, RawSpellDamage, spammedDot, forceHit);
                    AverageThreat = AverageDamage * ThreatMultiplier;
                }
            }
            else
            {
                AverageDamage             = 0;
                AverageThreat             = 0;
                DamagePerSpellPower       = 0;
                DamagePerMastery          = 0;
                DamagePerCrit             = 0;
                IgniteDamage              = 0;
                IgniteDamagePerSpellPower = 0;
                IgniteDamagePerMastery    = 0;
                IgniteDamagePerCrit       = 0;
                if (dotUptime)
                {
                    DotAverageDamage       = 0;
                    DotAverageThreat       = 0;
                    DotDamagePerSpellPower = 0;
                    DotDamagePerMastery    = 0;
                    DotDamagePerCrit       = 0;
                }
            }
            if (ChannelReduction != 0)
            {
                Ticks               *= (1 - ChannelReduction);
                HitProcs            *= (1 - ChannelReduction);
                CritProcs           *= (1 - ChannelReduction);
                TargetProcs         *= (1 - ChannelReduction);
                CastProcs            = CastProcs2 + (CastProcs - CastProcs2) * (1 - ChannelReduction);
                AverageDamage       *= (1 - ChannelReduction);
                AverageThreat       *= (1 - ChannelReduction);
                DamagePerSpellPower *= (1 - ChannelReduction);
                DamagePerMastery    *= (1 - ChannelReduction);
                DamagePerCrit       *= (1 - ChannelReduction);
            }
            AverageCost = CalculateCost(castingState.Solver, round);

            Absorb      = 0;
            TotalAbsorb = 0;

            if (outOfFiveSecondRule)
            {
                OO5SR = 1;
            }
            else
            {
                OO5SR = 0;
            }
        }
Esempio n. 26
0
        public void InitializeDamage(Solver solver, bool areaEffect, int range, MagicSchool magicSchool, SpellData spellData, float hitProcs, float castProcs, float dotDuration)
        {
            Stats                  baseStats          = solver.BaseStats;
            MageTalents            mageTalents        = solver.MageTalents;
            CalculationOptionsMage calculationOptions = solver.CalculationOptions;

            AreaEffect             = areaEffect;
            BaseCost               = spellData.Cost - (int)baseStats.SpellsManaReduction;
            MagicSchool            = magicSchool;
            Ticks                  = hitProcs;
            CastProcs              = castProcs;
            CastProcs2             = castProcs;
            BaseMinDamage          = spellData.MinDamage;
            BaseMaxDamage          = spellData.MaxDamage;
            SpellDamageCoefficient = spellData.SpellDamageCoefficient;
            BasePeriodicDamage     = spellData.PeriodicDamage;
            DotDamageCoefficient   = spellData.DotDamageCoefficient;
            DotDuration            = dotDuration;

            BaseDirectDamageModifier = 1.0f;
            BaseDotDamageModifier    = 1.0f;
            BaseCostModifier         = 1.0f;

            float baseCostAmplifier = calculationOptions.EffectCostMultiplier;

            baseCostAmplifier *= (1.0f - 0.01f * mageTalents.Precision);
            if (mageTalents.FrostChanneling > 0)
            {
                baseCostAmplifier *= (1.0f - 0.01f - 0.03f * mageTalents.FrostChanneling);
            }
            if (MagicSchool == MagicSchool.Arcane)
            {
                baseCostAmplifier *= (1.0f - 0.01f * mageTalents.ArcaneFocus);
            }
            BaseCostAmplifier = baseCostAmplifier;

            float baseInterruptProtection = baseStats.InterruptProtection;

            if (MagicSchool == MagicSchool.Fire || MagicSchool == MagicSchool.FrostFire)
            {
                baseInterruptProtection += 0.35f * mageTalents.BurningSoul;
            }
            BaseInterruptProtection = baseInterruptProtection;

            float realResistance;

            switch (MagicSchool)
            {
            case MagicSchool.Arcane:
                BaseSpellModifier         = solver.BaseArcaneSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseArcaneAdditiveSpellModifier;
                BaseCritRate     = solver.BaseArcaneCritRate;
                CritBonus        = solver.BaseArcaneCritBonus;
                HitRate          = solver.BaseArcaneHitRate;
                ThreatMultiplier = solver.ArcaneThreatMultiplier;
                realResistance   = calculationOptions.ArcaneResist;
                if (range != 0)
                {
                    Range = range + mageTalents.MagicAttunement * 3;
                }
                break;

            case MagicSchool.Fire:
                BaseSpellModifier         = solver.BaseFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFireCritRate;
                CritBonus        = solver.BaseFireCritBonus;
                HitRate          = solver.BaseFireHitRate;
                ThreatMultiplier = solver.FireThreatMultiplier;
                realResistance   = calculationOptions.FireResist;
                if (range != 0)
                {
                    Range = range + mageTalents.FlameThrowing * 3;
                }
                break;

            case MagicSchool.FrostFire:
                BaseSpellModifier         = solver.BaseFrostFireSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostFireAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostFireCritRate;
                CritBonus        = solver.BaseFrostFireCritBonus;
                HitRate          = solver.BaseFrostFireHitRate;
                ThreatMultiplier = solver.FrostFireThreatMultiplier;
                if (calculationOptions.FireResist == -1)
                {
                    realResistance = calculationOptions.FrostResist;
                }
                else if (calculationOptions.FrostResist == -1)
                {
                    realResistance = calculationOptions.FireResist;
                }
                else
                {
                    realResistance = Math.Min(calculationOptions.FireResist, calculationOptions.FrostResist);
                }
                Range = range;
                break;

            case MagicSchool.Frost:
                BaseSpellModifier         = solver.BaseFrostSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseFrostAdditiveSpellModifier;
                BaseCritRate     = solver.BaseFrostCritRate;
                CritBonus        = solver.BaseFrostCritBonus;
                HitRate          = solver.BaseFrostHitRate;
                ThreatMultiplier = solver.FrostThreatMultiplier;
                realResistance   = calculationOptions.FrostResist;
                Range            = range * (1 + mageTalents.ArcticReach * 0.1f);
                break;

            case MagicSchool.Nature:
                BaseSpellModifier         = solver.BaseNatureSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseNatureAdditiveSpellModifier;
                BaseCritRate     = solver.BaseNatureCritRate;
                CritBonus        = solver.BaseNatureCritBonus;
                HitRate          = solver.BaseNatureHitRate;
                ThreatMultiplier = solver.NatureThreatMultiplier;
                realResistance   = calculationOptions.NatureResist;
                Range            = range;
                break;

            case MagicSchool.Shadow:
                BaseSpellModifier         = solver.BaseShadowSpellModifier;
                BaseAdditiveSpellModifier = solver.BaseShadowAdditiveSpellModifier;
                BaseCritRate     = solver.BaseShadowCritRate;
                CritBonus        = solver.BaseShadowCritBonus;
                HitRate          = solver.BaseShadowHitRate;
                ThreatMultiplier = solver.ShadowThreatMultiplier;
                realResistance   = calculationOptions.ShadowResist;
                Range            = range;
                break;

            case MagicSchool.Holy:
            default:
                BaseSpellModifier         = solver.BaseHolySpellModifier;
                BaseAdditiveSpellModifier = solver.BaseHolyAdditiveSpellModifier;
                BaseCritRate     = solver.BaseHolyCritRate;
                CritBonus        = solver.BaseHolyCritBonus;
                HitRate          = solver.BaseHolyHitRate;
                ThreatMultiplier = solver.HolyThreatMultiplier;
                realResistance   = calculationOptions.HolyResist;
                Range            = range;
                break;
            }

            int playerLevel = calculationOptions.PlayerLevel;
            int targetLevel;

            if (areaEffect)
            {
                targetLevel = calculationOptions.AoeTargetLevel;
                float hitRate = ((targetLevel <= playerLevel + 2) ? (0.96f - (targetLevel - playerLevel) * 0.01f) : (0.94f - (targetLevel - playerLevel - 2) * 0.11f)) + solver.BaseSpellHit;
                if (MagicSchool == MagicSchool.Arcane)
                {
                    hitRate += 0.01f * mageTalents.ArcaneFocus;
                }
                if (hitRate > Spell.MaxHitRate)
                {
                    hitRate = Spell.MaxHitRate;
                }
                HitRate = hitRate;
            }
            else
            {
                targetLevel = calculationOptions.TargetLevel;
            }

            RealResistance      = realResistance;
            PartialResistFactor = (realResistance == -1) ? 0 : (1 - StatConversion.GetAverageResistance(playerLevel, targetLevel, realResistance, baseStats.SpellPenetration));
        }