public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem) { CharacterCalculationsMoonkin calcs = new CharacterCalculationsMoonkin(); Stats stats = GetCharacterStats(character, additionalItem); calcs.BasicStats = stats; float hitRatingMultiplier = 1.0f / CalculationsMoonkin.hitRatingConversionFactor; float critRatingMultiplier = 1.0f / CalculationsMoonkin.critRatingConversionFactor; calcs.SpellCrit = stats.SpellCritRating * critRatingMultiplier; calcs.SpellHit = stats.SpellHitRating * hitRatingMultiplier; CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin; // All spells: Damage +((0.08/0.16/0.25) * Int) switch (calcOpts.LunarGuidance) { case 1: stats.SpellDamageFromIntellectPercentage += 0.08f; break; case 2: stats.SpellDamageFromIntellectPercentage += 0.16f; break; case 3: stats.SpellDamageFromIntellectPercentage += 0.25f; break; default: stats.SpellDamageFromIntellectPercentage += 0.0f; break; } calcs.ArcaneDamage = stats.SpellDamageRating + stats.SpellArcaneDamageRating + stats.SpellDamageFromIntellectPercentage * stats.Intellect + stats.SpellDamageFromSpiritPercentage * stats.Spirit; calcs.NatureDamage = stats.SpellDamageRating + stats.SpellNatureDamageRating + stats.SpellDamageFromIntellectPercentage * stats.Intellect + stats.SpellDamageFromSpiritPercentage * stats.Spirit; calcs.Latency = calcOpts.Latency; calcs.FightLength = calcOpts.FightLength; calcs.TargetLevel = calcOpts.TargetLevel; calcs.Scryer = calcOpts.AldorScryer == "Scryer"; // 2.4 spirit regen float baseRegenConstant = 0.00932715221261f; float spiritRegen = 0.001f + baseRegenConstant * (float)Math.Sqrt(calcs.BasicStats.Intellect) * calcs.BasicStats.Spirit; calcs.ManaRegen = spiritRegen + stats.Mp5 / 5f; calcs.ManaRegen5SR = spiritRegen * stats.SpellCombatManaRegeneration + stats.Mp5 / 5f; // Run the solver to do final calculations MoonkinSolver.Solve(character, ref calcs); return(calcs); }
private float DoEclipseCalcs(DruidTalents talents, CharacterCalculationsMoonkin calcs, MoonkinSolver solver, float spellPower, float spellHit, float spellCrit, float spellHaste) { float latency = calcs.Latency; float omenOfClarityProcChance = talents.OmenOfClarity * 0.06f; float moonkinFormProc = (talents.MoonkinForm == 1) ? 0.02f * calcs.BasicStats.Mana : 0.0f; bool starfireGlyph = talents.GlyphOfStarfire; int impInsectSwarm = talents.ImprovedInsectSwarm; float moonfireCasts = SpellsUsed.Contains("MF") ? 1.0f : 0.0f; float insectSwarmCasts = SpellsUsed.Contains("IS") ? 1.0f : 0.0f; Spell moonfire = moonfireCasts > 0 ? solver.FindSpell("MF") : null; Spell insectSwarm = insectSwarmCasts > 0 ? solver.FindSpell("IS") : null; // Do SF glyph if (starfireGlyph && moonfire != null) { moonfire.DotEffect.Duration += 9.0f; } float eclipseMultiplier = 0.4f + calcs.BasicStats.EclipseBonus; float eclipseDuration = 15.0f; //float eclipseCooldown = 30.0f; Spell preLunarCast = solver.FindSpell("W"); // Do improved Insect Swarm if (insectSwarm != null) { preLunarCast.AllDamageModifier *= 1 + 0.01f * impInsectSwarm; } Spell solarEclipseCast = new Spell(preLunarCast); // Eclipse bonus and improved Insect Swarm // NOTE: Eclipse bonus additive with Moonfury and 4T9; multiplicative with everything else solarEclipseCast.AllDamageModifier = 1 + (float)Math.Floor(talents.Moonfury * 10 / 3.0f) / 100.0f + calcs.BasicStats.BonusMoonkinNukeDamage + eclipseMultiplier; if (insectSwarm != null) { solarEclipseCast.AllDamageModifier *= 1 + 0.01f * impInsectSwarm; } Spell preSolarCast = solver.FindSpell("SF"); if (moonfire != null) { preSolarCast.CriticalChanceModifier += 0.01f * impInsectSwarm; } Spell lunarEclipseCast = new Spell(preSolarCast); lunarEclipseCast.CriticalChanceModifier = (float)Math.Min(1.0f - spellCrit, lunarEclipseCast.CriticalChanceModifier + eclipseMultiplier); DoMainNuke(talents, calcs, ref preSolarCast, spellPower, spellHit, spellCrit, spellHaste); DoMainNuke(talents, calcs, ref solarEclipseCast, spellPower, spellHit, spellCrit, spellHaste); DoMainNuke(talents, calcs, ref preLunarCast, spellPower, spellHit, spellCrit, spellHaste); DoMainNuke(talents, calcs, ref lunarEclipseCast, spellPower, spellHit, spellCrit, spellHaste); float moonfireRatio = 0.0f; float insectSwarmRatio = 0.0f; if (moonfire != null) { DoDotSpell(talents, calcs, ref moonfire, spellPower, spellHit, spellCrit, spellHaste); moonfireRatio = moonfire.CastTime / moonfire.DotEffect.Duration; } if (insectSwarm != null) { DoDotSpell(talents, calcs, ref insectSwarm, spellPower, spellHit, spellCrit, spellHaste); insectSwarmRatio = insectSwarm.CastTime / insectSwarm.DotEffect.Duration; } float castRatio = moonfireRatio + (1 - moonfireRatio) * insectSwarmRatio; float lunarProcChance = (spellCrit + preLunarCast.CriticalChanceModifier) * spellHit * talents.Eclipse / 3.0f * 0.6f; float castsToProcLunar = 1.0f / lunarProcChance; float timeToProcLunar = preLunarCast.CastTime * (castsToProcLunar - 0.5f); float solarProcChance = (spellCrit + preSolarCast.CriticalChanceModifier) * spellHit * talents.Eclipse / 3.0f; float castsToProcSolar = 1.0f / solarProcChance; float timeToProcSolar = preSolarCast.CastTime * (castsToProcSolar - 0.5f); float preLunarTime = timeToProcLunar + (preLunarCast.CastTime * 0.5f) + preLunarCast.NGCastTime * 1.5f; float preLunarDPS = preLunarCast.DamagePerHit / preLunarCast.CastTime; float preLunarManaUsed = preLunarCast.BaseManaCost / preLunarCast.CastTime * preLunarTime; float preLunarManaGained = (preLunarCast.BaseManaCost * omenOfClarityProcChance) + ((spellCrit + preLunarCast.CriticalChanceModifier) * spellHit * moonkinFormProc) + (preLunarCast.BaseCastTime / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana); float lunarTime = (eclipseDuration - (preLunarCast.NGCastTime * 1.5f) - lunarEclipseCast.CastTime * 0.5f) * (1.0f - castRatio); float lunarDPS = lunarEclipseCast.DamagePerHit / lunarEclipseCast.CastTime; float lunarManaUsed = lunarEclipseCast.BaseManaCost / lunarEclipseCast.CastTime * lunarTime; float lunarManaGained = (lunarEclipseCast.BaseManaCost * omenOfClarityProcChance) + ((spellCrit + lunarEclipseCast.CriticalChanceModifier) * spellHit * moonkinFormProc) + (lunarEclipseCast.BaseCastTime / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana); float preSolarTime = timeToProcSolar + (lunarEclipseCast.CastTime * 0.5f) + preSolarCast.NGCastTime; float preSolarDPS = preSolarCast.DamagePerHit / preSolarCast.CastTime; float preSolarManaUsed = preSolarCast.BaseManaCost / preSolarCast.CastTime * preSolarTime; float preSolarManaGained = (preSolarCast.BaseManaCost * omenOfClarityProcChance) + ((spellCrit + preSolarCast.CriticalChanceModifier) * spellHit * moonkinFormProc) + (preSolarCast.BaseCastTime / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana); float solarTime = (eclipseDuration - (preSolarCast.NGCastTime) - (preLunarCast.CastTime * 0.5f)) * (1.0f - castRatio); float solarDPS = solarEclipseCast.DamagePerHit / solarEclipseCast.CastTime; float solarManaUsed = solarEclipseCast.BaseManaCost / solarEclipseCast.CastTime * solarTime; float solarManaGained = (solarEclipseCast.BaseManaCost * omenOfClarityProcChance) + ((spellCrit + solarEclipseCast.CriticalChanceModifier) * spellHit * moonkinFormProc) + (solarEclipseCast.BaseCastTime / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana); float rotationLength = (solarTime + lunarTime + preSolarTime + preLunarTime) / (1 - castRatio); float etSpentOnMFMFPriority = rotationLength * moonfireRatio; float etSpentOnISMFPriority = rotationLength * castRatio - etSpentOnMFMFPriority; float etSpentOnISISPriority = rotationLength * insectSwarmRatio; float etSpentOnMFISPriority = rotationLength * castRatio - etSpentOnISISPriority; float moonfireDamagePerCastTime = moonfireRatio > 0 ? (moonfire.DamagePerHit + moonfire.DotEffect.DamagePerHit) / moonfire.CastTime : 0.0f; float insectSwarmDamagePerCastTime = insectSwarmRatio > 0 ? insectSwarm.DotEffect.DamagePerHit / insectSwarm.CastTime : 0.0f; float dotDamageMoonfirePriority = etSpentOnMFMFPriority * moonfireDamagePerCastTime + etSpentOnISMFPriority * insectSwarmDamagePerCastTime; float dotDamageInsectSwarmPriority = etSpentOnISISPriority * insectSwarmDamagePerCastTime + etSpentOnMFISPriority * moonfireDamagePerCastTime; float totalDotDamage = 0.0f; if (dotDamageMoonfirePriority > dotDamageInsectSwarmPriority) { moonfireCasts = moonfireRatio > 0 ? etSpentOnMFMFPriority / moonfire.CastTime : 0.0f; insectSwarmCasts = insectSwarmRatio > 0 ? etSpentOnISMFPriority / insectSwarm.CastTime : 0.0f; totalDotDamage = dotDamageMoonfirePriority; } else { moonfireCasts = moonfireRatio > 0 ? etSpentOnMFISPriority / moonfire.CastTime : 0.0f; insectSwarmCasts = insectSwarmRatio > 0 ? etSpentOnISISPriority / insectSwarm.CastTime : 0.0f; totalDotDamage = dotDamageInsectSwarmPriority; } float moonfireTicks = moonfire != null ? moonfireCasts * moonfire.DotEffect.NumberOfTicks : 0.0f; float insectSwarmTicks = insectSwarm != null ? insectSwarmCasts * insectSwarm.DotEffect.NumberOfTicks : 0.0f; float moonfireManaUsed = moonfire != null ? moonfireCasts * moonfire.BaseManaCost : 0.0f; float insectSwarmManaUsed = insectSwarm != null ? insectSwarmCasts * insectSwarm.BaseManaCost : 0.0f; float damageDone = preSolarTime * preSolarDPS + solarTime * solarDPS + preLunarTime * preLunarDPS + lunarTime * lunarDPS + totalDotDamage; Duration = rotationLength; DotTicks = moonfireTicks + insectSwarmTicks; InsectSwarmTicks = insectSwarmTicks; MoonfireTicks = moonfireTicks; MoonfireCasts = moonfireCasts; InsectSwarmCasts = insectSwarmCasts; CastCount = castsToProcLunar + (lunarTime / lunarEclipseCast.CastTime) + castsToProcSolar + (solarTime / solarEclipseCast.CastTime) + moonfireCasts + insectSwarmCasts; WrathCount = castsToProcLunar + (solarTime / solarEclipseCast.CastTime); StarfireCount = castsToProcSolar + (lunarTime / lunarEclipseCast.CastTime); ManaUsed = preSolarManaUsed + solarManaUsed + preLunarManaUsed + lunarManaUsed + moonfireManaUsed + insectSwarmManaUsed; ManaGained = castsToProcSolar * preSolarManaGained + (solarTime / solarEclipseCast.CastTime) * solarManaGained + castsToProcLunar * preLunarManaGained + (lunarTime / lunarEclipseCast.CastTime) * lunarManaGained; if (spellCrit + lunarEclipseCast.CriticalChanceModifier > StarfireEclipseCrit) { StarfireEclipseCrit = spellCrit + lunarEclipseCast.CriticalChanceModifier; } if (spellCrit + preSolarCast.CriticalChanceModifier > StarfireNonEclipseCrit) { StarfireNonEclipseCrit = spellCrit + preSolarCast.CriticalChanceModifier; } InsectSwarmDuration = insectSwarm != null ? insectSwarm.DotEffect.Duration : 0.0f; MoonfireDuration = moonfire != null ? moonfire.DotEffect.Duration : 0.0f; float mfSavingsFromOoC = moonfire != null ? (moonfire.BaseManaCost - (moonfire.BaseManaCost * (1 - StarfireCount / WrathCount * 0.06f - (1 - StarfireCount / WrathCount) * 0.06f))) : 0.0f; float isSavingsFromOoC = insectSwarm != null ? (insectSwarm.BaseManaCost - (insectSwarm.BaseManaCost * (1 - StarfireCount / WrathCount * 0.06f - (1 - StarfireCount / WrathCount) * 0.06f))) : 0.0f; ManaGained += moonfire != null ? (moonfireCasts * (mfSavingsFromOoC + ((spellCrit + moonfire.CriticalChanceModifier) * moonkinFormProc * spellHit) + 1.5f / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana)) : 0.0f; ManaGained += insectSwarm != null ? (insectSwarmCasts * (isSavingsFromOoC + 1.5f / 60.0f * calcs.BasicStats.ManaRestoreFromBaseManaPPM * CalculationsMoonkin.BaseMana)) : 0.0f; RotationData.ManaGained = ManaGained; RotationData.DPM = damageDone / ManaUsed; ManaUsed -= ManaGained; RotationData.ManaUsed = ManaUsed; // Undo SF glyph if (starfireGlyph && moonfire != null) { moonfire.DotEffect.Duration -= 9.0f; } // Undo improved Insect Swarm if (insectSwarm != null) { preLunarCast.AllDamageModifier /= 1 + 0.01f * impInsectSwarm; } if (moonfire != null) { preSolarCast.CriticalChanceModifier -= 0.01f * impInsectSwarm; } return(damageDone); }