public override Dictionary <string, string> GetCharacterDisplayCalculationValues() { if (CalculationOptions.DisplaySegmentCooldowns != CalculationOptions.ComparisonSegmentCooldowns || CalculationOptions.DisplayIntegralMana != CalculationOptions.ComparisonIntegralMana) { bool savedIncrementalOptimizations = CalculationOptions.IncrementalOptimizations; CalculationOptions.IncrementalOptimizations = false; CharacterCalculationsMage smp = Solver.GetCharacterCalculations(Character, null, CalculationOptions, Calculations, MageArmor, CalculationOptions.DisplaySegmentCooldowns, CalculationOptions.DisplayIntegralMana); Dictionary <string, string> ret = smp.GetCharacterDisplayCalculationValuesInternal(); ret["Dps"] = String.Format("{0:F}*{1:F}% Error margin", smp.DpsRating, Math.Abs(DpsRating - smp.DpsRating) / DpsRating * 100); CalculationOptions.IncrementalOptimizations = savedIncrementalOptimizations; return(ret); } else { return(GetCharacterDisplayCalculationValuesInternal()); } }
public SolverLP(int baseRows, int maximumColumns, CharacterCalculationsMage calculations, int segments) { if (baseRows > maxRows || maximumColumns > maxCols) { maxRows = Math.Max(baseRows, maxRows); maxCols = Math.Max(maximumColumns, maxCols); RecreateArrays(); } this.calculations = calculations; this.segments = segments; cRows = baseRows; cCols = 0; for (int i = 0; i <= cRows; i++) { rowScale[i] = 1.0; } lp = new LP(cRows, maximumColumns); }
public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, bool referenceCalculation, bool significantChange, bool needsDisplayCalculations) { // First things first, we need to ensure that we aren't using bad data CharacterCalculationsMage calcs = new CharacterCalculationsMage(); if (character == null) { return calcs; } CalculationOptionsMage calcOpts = character.CalculationOptions as CalculationOptionsMage; if (calcOpts == null) { return calcs; } // bool computeIncrementalSet = referenceCalculation && calcOpts.IncrementalOptimizations; bool useGlobalOptimizations = calcOpts.SmartOptimization && !significantChange; bool useIncrementalOptimizations = calcOpts.IncrementalOptimizations && (!significantChange || calcOpts.ForceIncrementalOptimizations); bool solveCycles = referenceCalculation || significantChange; if (useIncrementalOptimizations && calcOpts.IncrementalSetStateIndexes == null) computeIncrementalSet = true; if (computeIncrementalSet) { useIncrementalOptimizations = false; needsDisplayCalculations = true; } if (useIncrementalOptimizations && !character.DisableBuffAutoActivation) { return GetCharacterCalculations(character, additionalItem, calcOpts, calcOpts.IncrementalSetArmor, useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, computeIncrementalSet, solveCycles); } else if (calcOpts.AutomaticArmor && !calcOpts.ArmorSwapping && !character.DisableBuffAutoActivation) { CharacterCalculationsMage mage = GetCharacterCalculations(character, additionalItem, calcOpts, "Mage Armor", useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, computeIncrementalSet, solveCycles); CharacterCalculationsMage molten = GetCharacterCalculations(character, additionalItem, calcOpts, "Molten Armor", useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, computeIncrementalSet, solveCycles); CharacterCalculationsMage calc = (mage.OverallPoints > molten.OverallPoints) ? mage : molten; if (calcOpts.MeleeDps + calcOpts.MeleeDot + calcOpts.PhysicalDps + calcOpts.PhysicalDot > 0) { CharacterCalculationsMage ice = GetCharacterCalculations(character, additionalItem, calcOpts, "Ice Armor", useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, computeIncrementalSet, solveCycles); if (ice.OverallPoints > calc.OverallPoints) calc = ice; } if (computeIncrementalSet) StoreIncrementalSet(character, calc.DisplayCalculations); if (referenceCalculation) StoreCycleSolutions(character, calc.DisplayCalculations); return calc; } else { CharacterCalculationsMage calc = GetCharacterCalculations(character, additionalItem, calcOpts, null, useIncrementalOptimizations, useGlobalOptimizations, needsDisplayCalculations, computeIncrementalSet, solveCycles); if (computeIncrementalSet) StoreIncrementalSet(character, calc.DisplayCalculations); if (referenceCalculation) StoreCycleSolutions(character, calc.DisplayCalculations); return calc; } }
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; }