예제 #1
0
        public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem)
        {
            CharacterCalculationsMoonkin calcs = new CharacterCalculationsMoonkin();
            Stats stats = GetCharacterStats(character, additionalItem);

            calcs.BasicStats = stats;

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

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

            CalculationOptionsMoonkin calcOpts = character.CalculationOptions as CalculationOptionsMoonkin;

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

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

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

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

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

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

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

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

            return(calcs);
        }
예제 #2
0
        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);
        }