private float RotationMultiplier(SpellRotation rot) { if (rot == null) { return(0); } float manaCostPerCycle = rot.manaPerCycle - rot.currentCycleDuration * (calculatedStats.Mp5Points / 5 + InnervateManaPerSecond(rot) + MementoManaPerSecond(rot) + LessManaPerCastInManaPerSecond(rot) + ManaPerCastInManaPerSecond(rot) + BlueDragonInManaPerSecond(rot) + BangleInManaPerSecond(rot) ); float HPSMultiplier = 1.0f; if (manaCostPerCycle > 0) { HPSMultiplier = (rot.currentCycleDuration * calculatedStats.BasicStats.Mana / manaCostPerCycle) / (calcOpts.FightLength * 60); if (HPSMultiplier > 1.0f) { HPSMultiplier = 1.0f; } } return(HPSMultiplier); }
private float BangleInManaPerSecond(SpellRotation rot) { // Bangle of Endless Blessings - x% mana regen for 15 sec with 10% proc, 45 sec internal cooldown float secondsPerSpell = rot.currentCycleDuration / rot.numberOfSpells; float secondsPerProc = secondsPerSpell / 0.1f + 45f; return(0.15f * calculatedStats.BasicStats.BangleProc * calculatedStats.OS5SRRegen / secondsPerProc); }
private float BlueDragonInManaPerSecond(SpellRotation rot) { // Darkmoon Card: Blue Dragon - let's assume no internal cooldown, no proc while the effect is up and no proc during innervate float secondsPerSpell = rot.currentCycleDuration / rot.numberOfSpells; float secondsPerProc = 100f * secondsPerSpell / calculatedStats.BasicStats.FullManaRegenFor15SecOnSpellcast + 15f; return(15f * (calculatedStats.OS5SRRegen - calculatedStats.IS5SRRegen) / secondsPerProc); }
private float ManaPerCastInManaPerSecond(SpellRotation rot) { float secondsPerSpell = rot.currentCycleDuration / rot.numberOfSpells; // IED 5% proc-rate, 15 sec cooldown // Source: http://elitistjerks.com/f31/t19181-shaman_how_heal_like_pro/p53/#post759589 float secondsPerProc = secondsPerSpell * 20f + 15f; return(calculatedStats.BasicStats.ManaRestorePerCast_5_15 / secondsPerProc); }
private float InnervateManaPerSecond(SpellRotation rot) { float innervateMana = 0f; if (calcOpts.InnervateSelf) { float manaGain = calculatedStats.OS5SRRegen * 5 * 20 - calculatedStats.IS5SRRegen * 20; float manaUsed = rot.manaPerCycle / rot.currentCycleDuration * 20; if (manaGain > calculatedStats.BasicStats.Mana + manaUsed) { manaGain = calculatedStats.BasicStats.Mana + manaUsed; } innervateMana = manaGain / (calcOpts.InnervateDelay * 60); } return(innervateMana); }
private SpellRotation GetBestRotation() { SpellRotation bestRotation = null; float bestScore = 0f; foreach (SpellRotation rot in baseRotations) { float maxLength = calcOpts.MaxCycleDuration * calcOpts.NumCyclesPerRotation; float bestLocalScore = 0f; float granularity = 0.1f; rot.currentCycleDuration = ((float)Math.Ceiling(rot.tightCycleDuration * 10)) / 10f; // No use trying all combinations if we already have a better score than the theoretical max if (bestLocalScore > rot.healPerCycle / rot.tightCycleDuration) { continue; } float multiplier; do { multiplier = RotationMultiplier(rot); float score = rot.healPerCycle / rot.currentCycleDuration * multiplier; if (score > bestLocalScore) { bestLocalScore = score; rot.bestCycleDuration = rot.currentCycleDuration; } rot.currentCycleDuration += granularity; } while (rot.currentCycleDuration < maxLength && multiplier < 1f); if (bestLocalScore > bestScore) { bestRotation = rot; bestScore = bestLocalScore; } } bestRotation.currentCycleDuration = bestRotation.bestCycleDuration; return(bestRotation); }
private float LessManaPerCastInManaPerSecond(SpellRotation rot) { float secondsPerSpell = rot.currentCycleDuration / rot.numberOfSpells; return(calculatedStats.BasicStats.ManacostReduceWithin15OnUse1Min / (4 * secondsPerSpell)); }
private float MementoManaPerSecond(SpellRotation rot) { return(calculatedStats.BasicStats.MementoProc * 3 / (45 + rot.currentCycleDuration / rot.numberOfSpells * 5)); }