public static void solve(CharacterCalculationsElemental calculatedStats, CalculationOptionsElemental calcOpts, BossOptions bossOpts) { Stats stats = calculatedStats.BasicStats; Character character = calculatedStats.LocalCharacter; ShamanTalents talents = character.ShamanTalents; /* Effects: * Clearcasting (-40% mana cost next 2 spells) * Glyph of flame shock or not * Clearcasting (5/10% more total damage) * Elemental Mastery (+15% haste chance, 15 sec/3 min cd) * Trinkets * * Assume LvB used on CD and FS either after LvB, on dot drop or before LvB * Filler: LB * NYI Optional: use of CL */ Estimation e; Rotation rot; float damage; Stats procStats; float FightDuration = bossOpts.BerserkTimer; // WITHOUT PROCS e = new Estimation(stats, new Stats{}, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); // WITH PROCS int nPasses = 2, k; for (k = 0; k < nPasses; k++) { procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); e.Update(stats, procStats, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); } // Thunderstorm usage float thunderstormRegen = 0f; #region Thunderstorm if (calcOpts.UseThunderstorm) { float procsPerSecond = Thunderstorm.getProcsPerSecond(talents.GlyphofThunder, (int)FightDuration); thunderstormRegen += (talents.GlyphofThunderstorm ? .1f : .08f) * stats.Mana * procsPerSecond * 5; } #endregion /* Regen variables: (divide by 5 for regen per second) * While casting: ManaRegInFSR * During regen: ManaRegOutFSR */ #region Calculate Regen float spiRegen = 5 * StatConversion.GetSpiritRegenSec(stats.Spirit, stats.Intellect); float replenishRegen = 5 * stats.Mana * stats.ManaRestoreFromMaxManaPerSecond; float judgementRegen = 0;// 5 * rot.GetBaseCastTime() / rot.Duration * stats.ManaRestoreFromBaseManaPPM / 60f * BaseStats.GetBaseStats(character).Mana; float ManaRegInFSR = /*spiRegen * stats.SpellCombatManaRegeneration +*/ stats.Mp5 + replenishRegen + judgementRegen + thunderstormRegen; float ManaRegOutFSR = spiRegen + stats.Mp5 + replenishRegen + thunderstormRegen; float ManaRegen = ManaRegInFSR; #endregion // TotalDamage, CastFraction, TimeUntilOOM #region Calculate total damage in the fight float TimeUntilOOM = 0; float effectiveMPS = rot.MPS - ManaRegen / 5f; if (effectiveMPS <= 0) TimeUntilOOM = FightDuration; else TimeUntilOOM = (calculatedStats.BasicStats.Mana) / effectiveMPS; if (TimeUntilOOM > FightDuration) TimeUntilOOM = FightDuration; #region SpecialEffects from procs etc. procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); //damage procs (Thunder Capacitor etc.) are effected by spellcrit and damage debuffs damage = procStats.ArcaneDamage * (1 + stats.BonusArcaneDamageMultiplier) + procStats.NatureDamage * (1 + stats.BonusNatureDamageMultiplier) + procStats.FireDamage * (1 + stats.BonusFireDamageMultiplier) + procStats.ShadowDamage * (1 + stats.BonusShadowDamageMultiplier); if (damage > 0) { damage *= (1 + stats.SpellCrit * .5f); // but only with the normal 50% dmg bonus rot.DPS += damage; } #endregion float TotalDamage = TimeUntilOOM * rot.DPS; float TimeToRegenFull = 5f * calculatedStats.BasicStats.Mana / ManaRegOutFSR; float TimeToBurnAll = calculatedStats.BasicStats.Mana / effectiveMPS; float CastFraction = 1f; if (ManaRegOutFSR > 0 && FightDuration > TimeUntilOOM) { float timeLeft = FightDuration - TimeUntilOOM; if (TimeToRegenFull + TimeToBurnAll == 0) CastFraction = 0; else CastFraction = TimeToBurnAll / (TimeToRegenFull + TimeToBurnAll); TotalDamage += timeLeft * rot.DPS * CastFraction; } #endregion float bsRatio = ((float)calcOpts.BSRatio) * 0.01f; calculatedStats.BurstPoints = (1f - bsRatio) * 2f * rot.DPS; calculatedStats.SustainedPoints = bsRatio * 2f * TotalDamage / FightDuration; calculatedStats.OverallPoints = calculatedStats.BurstPoints + calculatedStats.SustainedPoints; calculatedStats.CombatStats = stats.Clone(); calculatedStats.CombatStats.Accumulate(procStats); calculatedStats.ManaRegenInFSR = ManaRegInFSR; calculatedStats.ReplenishMP5 = replenishRegen; calculatedStats.LightningBolt = rot.LB; calculatedStats.ChainLightning = rot.CL; calculatedStats.FlameShock = rot.FS; calculatedStats.LavaBurst = rot.LvB; calculatedStats.EarthShock = rot.ES; calculatedStats.FrostShock = rot.FrS; // asd calculatedStats.FireNova = rot.FN; calculatedStats.SearingTotem = rot.ST; calculatedStats.MagmaTotem = rot.MT; calculatedStats.TimeToOOM = TimeUntilOOM; calculatedStats.CastRegenFraction = CastFraction; calculatedStats.CastsPerSecond = rot.getCastsPerSecond(); calculatedStats.CritsPerSecond = rot.getWeightedCritchance() * rot.getCastsPerSecond(); calculatedStats.MissesPerSecond = rot.getCastsPerSecond() * (1f - rot.getWeightedHitchance()); calculatedStats.LvBPerSecond = rot.getCastsPerSecond(typeof(LavaBurst)); calculatedStats.LBPerSecond = rot.getCastsPerSecond(typeof(LightningBolt)); calculatedStats.FSPerSecond = rot.getCastsPerSecond(typeof(FlameShock)); calculatedStats.LatencyPerSecond = rot.LatencyPerSecond; calculatedStats.RotationDPS = rot.DPS; calculatedStats.RotationMPS = rot.MPS; calculatedStats.TotalDPS = TotalDamage / FightDuration; rot.ClearCasting.TryGetValue(typeof(FlameShock), out calculatedStats.ClearCast_FlameShock); rot.ClearCasting.TryGetValue(typeof(LavaBurst), out calculatedStats.ClearCast_LavaBurst); rot.ClearCasting.TryGetValue(typeof(LightningBolt), out calculatedStats.ClearCast_LightningBolt); calculatedStats.Rotation = rot.ToString(); calculatedStats.RotationDetails = rot.ToDetailedString(); }
public static void solve(CharacterCalculationsElemental calculatedStats, CalculationOptionsElemental calcOpts, BossOptions bossOpts) { Stats stats = calculatedStats.BasicStats; Character character = calculatedStats.LocalCharacter; ShamanTalents talents = character.ShamanTalents; /* Effects: * Clearcasting (-40% mana cost next 2 spells) * Glyph of flame shock or not * Clearcasting (5/10% more total damage) * Elemental Mastery (+15% haste chance, 15 sec/3 min cd) * Trinkets * * Assume LvB used on CD and FS either after LvB, on dot drop or before LvB * Filler: LB * NYI Optional: use of CL */ Estimation e; Rotation rot; float damage; Stats procStats; #if RAWR3 || SILVERLIGHT float FightDuration = bossOpts.BerserkTimer; #else float FightDuration = calcOpts.FightDuration; #endif // WITHOUT PROCS e = new Estimation(stats, new Stats { }, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); // WITH PROCS int nPasses = 2, k; for (k = 0; k < nPasses; k++) { procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); e.Update(stats, procStats, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); } // Thunderstorm usage float thunderstormRegen = 0f; #region Thunderstorm if (calcOpts.UseThunderstorm) { float procsPerSecond = Thunderstorm.getProcsPerSecond(talents.GlyphofThunder, (int)FightDuration); thunderstormRegen += (talents.GlyphofThunderstorm ? .1f : .08f) * stats.Mana * procsPerSecond * 5; } #endregion /* Regen variables: (divide by 5 for regen per second) * While casting: ManaRegInFSR * During regen: ManaRegOutFSR */ #region Calculate Regen float spiRegen = 5 * StatConversion.GetSpiritRegenSec(stats.Spirit, stats.Intellect); float replenishRegen = 5 * stats.Mana * stats.ManaRestoreFromMaxManaPerSecond; float judgementRegen = 5 * rot.GetBaseCastTime() / rot.Duration * stats.ManaRestoreFromBaseManaPPM / 60f * BaseStats.GetBaseStats(character).Mana; float ManaRegInFSR = spiRegen * stats.SpellCombatManaRegeneration + stats.Mp5 + replenishRegen + judgementRegen + thunderstormRegen; float ManaRegOutFSR = spiRegen + stats.Mp5 + replenishRegen + thunderstormRegen; float ManaRegen = ManaRegInFSR; #endregion // TotalDamage, CastFraction, TimeUntilOOM #region Calculate total damage in the fight float TimeUntilOOM = 0; float effectiveMPS = rot.MPS - ManaRegen / 5f; if (effectiveMPS <= 0) { TimeUntilOOM = FightDuration; } else { TimeUntilOOM = (calculatedStats.BasicStats.Mana) / effectiveMPS; } if (TimeUntilOOM > FightDuration) { TimeUntilOOM = FightDuration; } #region SpecialEffects from procs etc. procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); //damage procs (Thunder Capacitor etc.) are effected by spellcrit and damage debuffs damage = procStats.ArcaneDamage * (1 + stats.BonusArcaneDamageMultiplier) + procStats.NatureDamage * (1 + stats.BonusNatureDamageMultiplier) + procStats.FireDamage * (1 + stats.BonusFireDamageMultiplier) + procStats.ShadowDamage * (1 + stats.BonusShadowDamageMultiplier); if (damage > 0) { damage *= (1 + stats.SpellCrit * .5f); // but only with the normal 50% dmg bonus rot.DPS += damage; } #endregion float TotalDamage = TimeUntilOOM * rot.DPS; float TimeToRegenFull = 5f * calculatedStats.BasicStats.Mana / ManaRegOutFSR; float TimeToBurnAll = calculatedStats.BasicStats.Mana / effectiveMPS; float CastFraction = 1f; if (ManaRegOutFSR > 0 && FightDuration > TimeUntilOOM) { float timeLeft = FightDuration - TimeUntilOOM; if (TimeToRegenFull + TimeToBurnAll == 0) { CastFraction = 0; } else { CastFraction = TimeToBurnAll / (TimeToRegenFull + TimeToBurnAll); } TotalDamage += timeLeft * rot.DPS * CastFraction; } #endregion float bsRatio = ((float)calcOpts.BSRatio) * 0.01f; calculatedStats.BurstPoints = (1f - bsRatio) * 2f * rot.DPS; calculatedStats.SustainedPoints = bsRatio * 2f * TotalDamage / FightDuration; calculatedStats.OverallPoints = calculatedStats.BurstPoints + calculatedStats.SustainedPoints; calculatedStats.CombatStats = stats.Clone(); calculatedStats.CombatStats.Accumulate(procStats); calculatedStats.ManaRegenInFSR = ManaRegInFSR; calculatedStats.ManaRegenOutFSR = ManaRegOutFSR; calculatedStats.ReplenishMP5 = replenishRegen; calculatedStats.LightningBolt = rot.LB; calculatedStats.ChainLightning = rot.CL; calculatedStats.FlameShock = rot.FS; calculatedStats.LavaBurst = rot.LvB; calculatedStats.EarthShock = rot.ES; calculatedStats.FrostShock = rot.FrS; calculatedStats.FireNova = rot.FN; calculatedStats.SearingTotem = rot.ST; calculatedStats.MagmaTotem = rot.MT; calculatedStats.TimeToOOM = TimeUntilOOM; calculatedStats.CastRegenFraction = CastFraction; calculatedStats.CastsPerSecond = rot.getCastsPerSecond(); calculatedStats.CritsPerSecond = rot.getWeightedCritchance() * rot.getCastsPerSecond(); calculatedStats.MissesPerSecond = rot.getCastsPerSecond() * (1f - rot.getWeightedHitchance()); calculatedStats.LvBPerSecond = rot.getCastsPerSecond(typeof(LavaBurst)); calculatedStats.LBPerSecond = rot.getCastsPerSecond(typeof(LightningBolt)); calculatedStats.FSPerSecond = rot.getCastsPerSecond(typeof(FlameShock)); calculatedStats.LatencyPerSecond = rot.LatencyPerSecond; calculatedStats.RotationDPS = rot.DPS; calculatedStats.RotationMPS = rot.MPS; calculatedStats.TotalDPS = TotalDamage / FightDuration; rot.ClearCasting.TryGetValue(typeof(FlameShock), out calculatedStats.ClearCast_FlameShock); rot.ClearCasting.TryGetValue(typeof(LavaBurst), out calculatedStats.ClearCast_LavaBurst); rot.ClearCasting.TryGetValue(typeof(LightningBolt), out calculatedStats.ClearCast_LightningBolt); calculatedStats.Rotation = rot.ToString(); calculatedStats.RotationDetails = rot.ToDetailedString(); }