diff --git a/sim/core/dot.go b/sim/core/dot.go index 9daa26db49..afd3f81693 100644 --- a/sim/core/dot.go +++ b/sim/core/dot.go @@ -494,3 +494,46 @@ func (dot *Dot) RestoreState(state DotState, sim *Simulation) { dot.tickAction = pa sim.AddPendingAction(dot.tickAction) } + +type ExpectedTickConfig struct { + UseSnapshot bool + BaseDmgFn func(*Spell) float64 // for non-snapshot damage calc + SnapshotOutcome OutcomeApplier + NormalOutcome OutcomeApplier + ModifyDamage func(*SpellResult) // Modifies Damage before hasteNormalization + SkipHasteNormalization bool // disables haste normalization + ModifyResult func(*SpellResult) // optional final tweaks, apply multipliers, add crit mods +} + +func (dot *Dot) CalcExpectedTickDamage(sim *Simulation, target *Unit, cfg ExpectedTickConfig) *SpellResult { + if cfg.UseSnapshot { + result := dot.CalcSnapshotDamage(sim, target, cfg.SnapshotOutcome) + if cfg.ModifyDamage != nil { + cfg.ModifyDamage(result) + } + if !cfg.SkipHasteNormalization { + result.Damage /= dot.TickPeriod().Seconds() + } + if cfg.ModifyResult != nil { + cfg.ModifyResult(result) + } + return result + } + + baseDamage := 0.0 + if cfg.BaseDmgFn != nil { + baseDamage = cfg.BaseDmgFn(dot.Spell) + } + + result := dot.Spell.CalcPeriodicDamage(sim, target, baseDamage, cfg.NormalOutcome) + if cfg.ModifyDamage != nil { + cfg.ModifyDamage(result) + } + if !cfg.SkipHasteNormalization { + result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() + } + if cfg.ModifyResult != nil { + cfg.ModifyResult(result) + } + return result +} diff --git a/sim/druid/balance/sunfire.go b/sim/druid/balance/sunfire.go index 4dae04321c..0b8ca0a911 100644 --- a/sim/druid/balance/sunfire.go +++ b/sim/druid/balance/sunfire.go @@ -69,15 +69,14 @@ func (moonkin *BalanceDruid) registerSunfireDoTSpell() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, moonkin.CalcScalingSpellDmg(SunfireDotCoeff), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return moonkin.CalcScalingSpellDmg(SunfireDotCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/druid/moonfire.go b/sim/druid/moonfire.go index b2c3803b7e..c8b4c3cbec 100644 --- a/sim/druid/moonfire.go +++ b/sim/druid/moonfire.go @@ -68,15 +68,14 @@ func (druid *Druid) registerMoonfireDoTSpell() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, druid.CalcScalingSpellDmg(MoonfireDotCoeff), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return druid.CalcScalingSpellDmg(MoonfireDotCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/druid/rake.go b/sim/druid/rake.go index 36549e0e19..c9dbbaca40 100644 --- a/sim/druid/rake.go +++ b/sim/druid/rake.go @@ -74,20 +74,22 @@ func (druid *Druid) registerRakeSpell() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - } else { - tickBase := flatBaseDamage + bonusCoefficientFromAP*spell.MeleeAttackPower() - ticks := spell.CalcPeriodicDamage(sim, target, tickBase, spell.OutcomeExpectedMagicAlwaysHit) - - attackTable := spell.Unit.AttackTables[target.UnitIndex] - critChance := spell.PhysicalCritChance(attackTable) - critMod := (critChance * (spell.CritMultiplier - 1)) - ticks.Damage *= 1 + critMod - - return ticks - } + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return flatBaseDamage + bonusCoefficientFromAP*spell.MeleeAttackPower() + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicAlwaysHit, + SkipHasteNormalization: true, + ModifyResult: func(sr *core.SpellResult) { + attackTable := spell.Unit.AttackTables[target.UnitIndex] + critChance := spell.PhysicalCritChance(attackTable) + critMod := (critChance * (spell.CritMultiplier - 1)) + sr.Damage *= 1 + critMod + }, + }) }, }) diff --git a/sim/druid/rip.go b/sim/druid/rip.go index d189ad5195..c3a94ec5d7 100644 --- a/sim/druid/rip.go +++ b/sim/druid/rip.go @@ -83,20 +83,26 @@ func (druid *Druid) registerRipSpell() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - } else { - cp := 5.0 // Hard-code this so that snapshotting calculations can be performed at any CP value. - ap := spell.MeleeAttackPower() - baseTickDamage := baseDamage + comboPointCoeff*cp + attackPowerCoeff*cp*ap - result := spell.CalcPeriodicDamage(sim, target, baseTickDamage, spell.OutcomeExpectedMagicAlwaysHit) - attackTable := spell.Unit.AttackTables[target.UnitIndex] - critChance := spell.PhysicalCritChance(attackTable) - critMod := critChance * (spell.CritMultiplier - 1) - result.Damage *= 1 + critMod - return result - } + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + cp := 5.0 // Hard-code this so that snapshotting calculations can be performed at any CP value. + ap := spell.MeleeAttackPower() + return baseDamage + comboPointCoeff*cp + attackPowerCoeff*cp*ap + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicAlwaysHit, + SkipHasteNormalization: true, + ModifyResult: func(sr *core.SpellResult) { + if !useSnapshot { + attackTable := spell.Unit.AttackTables[target.UnitIndex] + critChance := spell.PhysicalCritChance(attackTable) + critMod := critChance * (spell.CritMultiplier - 1) + sr.Damage *= 1 + critMod + } + }, + }) }, }) diff --git a/sim/druid/thrash.go b/sim/druid/thrash.go index 3f8bc89adb..bd76c52554 100644 --- a/sim/druid/thrash.go +++ b/sim/druid/thrash.go @@ -139,13 +139,16 @@ func (druid *Druid) registerThrashCatSpell() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - } else { - baseTickDamage := flatTickDamage + 0.141*spell.MeleeAttackPower() - return spell.CalcPeriodicDamage(sim, target, baseTickDamage, spell.OutcomeExpectedPhysicalCrit) - } + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return flatTickDamage + 0.141*spell.MeleeAttackPower() + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedPhysicalCrit, + SkipHasteNormalization: true, + }) }, RelatedAuraArrays: druid.WeakenedBlowsAuras.ToMap(), diff --git a/sim/hunter/pet_abilities.go b/sim/hunter/pet_abilities.go index ce2172afa7..b8cc8dcb75 100644 --- a/sim/hunter/pet_abilities.go +++ b/sim/hunter/pet_abilities.go @@ -349,8 +349,14 @@ func (hp *HunterPet) newFrostStormBreath() *core.Spell { } }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - baseDamage := 206 + (spell.MeleeAttackPower() * 0.40) - return spell.CalcPeriodicDamage(sim, target, baseDamage, spell.OutcomeExpectedMagicCrit) + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + BaseDmgFn: func(s *core.Spell) float64 { + return 206 + (spell.MeleeAttackPower() * 0.40) + }, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + SkipHasteNormalization: true, + }) }, }) return hp.frostStormBreath diff --git a/sim/mage/fire/combustion.go b/sim/mage/fire/combustion.go index bf1d5a41a0..fc979bb5d1 100644 --- a/sim/mage/fire/combustion.go +++ b/sim/mage/fire/combustion.go @@ -90,13 +90,19 @@ func (fire *FireMage) registerCombustionSpell() { }, }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - tickBase := calculatedDotTick(sim, target) - result := spell.CalcPeriodicDamage(sim, target, tickBase, spell.OutcomeExpectedMagicAlwaysHit) - critChance := spell.SpellCritChance(target) - critMod := (critChance * (spell.CritMultiplier - 1)) - result.Damage *= 1 + critMod - - return result + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + BaseDmgFn: func(s *core.Spell) float64 { + return calculatedDotTick(sim, target) + }, + NormalOutcome: spell.OutcomeExpectedMagicAlwaysHit, + SkipHasteNormalization: true, + ModifyResult: func(sr *core.SpellResult) { + critChance := spell.SpellCritChance(target) + critMod := (critChance * (spell.CritMultiplier - 1)) + sr.Damage *= 1 + critMod + }, + }) }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { spell.Dot(target).Apply(sim) diff --git a/sim/priest/_shadow_word_pain.go b/sim/priest/_shadow_word_pain.go index 73714233fb..145d9d2ea5 100644 --- a/sim/priest/_shadow_word_pain.go +++ b/sim/priest/_shadow_word_pain.go @@ -63,13 +63,15 @@ func (priest *Priest) registerShadowWordPainSpell() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedMagicSnapshotCrit) - } else { - baseDamage := 194.709 - return spell.CalcPeriodicDamage(sim, target, baseDamage, spell.OutcomeExpectedMagicCrit) - } + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return priest.CalcScalingSpellDmg(SwpScaleCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/priest/shadow/mind_flay.go b/sim/priest/shadow/mind_flay.go index a90f12f12f..a84491de6a 100644 --- a/sim/priest/shadow/mind_flay.go +++ b/sim/priest/shadow/mind_flay.go @@ -55,7 +55,14 @@ func (shadow *ShadowPriest) registerMindFlaySpell() *core.Spell { } }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - return spell.CalcPeriodicDamage(sim, target, shadow.CalcScalingSpellDmg(MfScale), spell.OutcomeExpectedMagicCrit) + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + BaseDmgFn: func(s *core.Spell) float64 { + return shadow.CalcScalingSpellDmg(MfScale) + }, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + SkipHasteNormalization: true, + }) }, }) } diff --git a/sim/priest/shadow/talents.go b/sim/priest/shadow/talents.go index 35401d2f6e..a6868f223a 100644 --- a/sim/priest/shadow/talents.go +++ b/sim/priest/shadow/talents.go @@ -106,7 +106,14 @@ func (shadow *ShadowPriest) registerSolaceAndInstanity() { } }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - return spell.CalcPeriodicDamage(sim, target, shadow.CalcScalingSpellDmg(MfScale), spell.OutcomeExpectedMagicCrit) + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + BaseDmgFn: func(s *core.Spell) float64 { + return shadow.CalcScalingSpellDmg(MfScale) + }, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + SkipHasteNormalization: true, + }) }, ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { return shadow.DevouringPlague.Dot(target).IsActive() diff --git a/sim/priest/shadow_word_pain.go b/sim/priest/shadow_word_pain.go index 9ad476e994..db19973f31 100644 --- a/sim/priest/shadow_word_pain.go +++ b/sim/priest/shadow_word_pain.go @@ -62,15 +62,14 @@ func (priest *Priest) registerShadowWordPainSpell() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, priest.CalcScalingSpellDmg(SwpScaleCoeff), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return priest.CalcScalingSpellDmg(SwpScaleCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/priest/vampiric_touch.go b/sim/priest/vampiric_touch.go index b88472e237..d39312ab6b 100644 --- a/sim/priest/vampiric_touch.go +++ b/sim/priest/vampiric_touch.go @@ -61,15 +61,14 @@ func (priest *Priest) registerVampiricTouchSpell() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, priest.CalcScalingSpellDmg(VtScaleCoeff), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return priest.CalcScalingSpellDmg(VtScaleCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/warlock/affliction/agony.go b/sim/warlock/affliction/agony.go index 424804f2b1..9c40f2a4a1 100644 --- a/sim/warlock/affliction/agony.go +++ b/sim/warlock/affliction/agony.go @@ -72,19 +72,18 @@ func (affliction *AfflictionWarlock) registerAgony() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - - // Always compare fully stacked agony damage - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage *= 10 - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, affliction.CalcScalingSpellDmg(agonyScale), spell.OutcomeExpectedMagicCrit) - result.Damage *= 10 - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return affliction.CalcScalingSpellDmg(agonyScale) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + ModifyDamage: func(sr *core.SpellResult) { + // Always compare fully stacked agony damage + sr.Damage *= 10 + }, + }) }, }) } diff --git a/sim/warlock/affliction/unstable_affliction.go b/sim/warlock/affliction/unstable_affliction.go index ba096556af..94e30f0460 100644 --- a/sim/warlock/affliction/unstable_affliction.go +++ b/sim/warlock/affliction/unstable_affliction.go @@ -55,15 +55,14 @@ func (affliction *AfflictionWarlock) registerUnstableAffliction() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, affliction.CalcScalingSpellDmg(uaScale), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return affliction.CalcScalingSpellDmg(uaScale) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/warlock/corruption.go b/sim/warlock/corruption.go index ab2dfda2ec..0469a09a5a 100644 --- a/sim/warlock/corruption.go +++ b/sim/warlock/corruption.go @@ -57,15 +57,14 @@ func (warlock *Warlock) RegisterCorruption(callback WarlockSpellCastedCallback) }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, warlock.CalcScalingSpellDmg(corruptionScale), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return warlock.CalcScalingSpellDmg(corruptionScale) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) diff --git a/sim/warlock/demonology/doom.go b/sim/warlock/demonology/doom.go index 786fe70525..e37eb18c5c 100644 --- a/sim/warlock/demonology/doom.go +++ b/sim/warlock/demonology/doom.go @@ -56,15 +56,14 @@ func (demonology *DemonologyWarlock) registerDoom() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, demonology.CalcScalingSpellDmg(doomScale), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return demonology.CalcScalingSpellDmg(doomScale) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/warlock/destruction/immolate.go b/sim/warlock/destruction/immolate.go index d00b58c45d..49f65b716e 100644 --- a/sim/warlock/destruction/immolate.go +++ b/sim/warlock/destruction/immolate.go @@ -100,15 +100,14 @@ func (destruction *DestructionWarlock) registerImmolate() { ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { dot := spell.Dot(target) - if useSnapshot { - result := dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - result.Damage /= dot.TickPeriod().Seconds() - return result - } else { - result := spell.CalcPeriodicDamage(sim, target, destruction.CalcScalingSpellDmg(immolateCoeff), spell.OutcomeExpectedMagicCrit) - result.Damage /= dot.CalcTickPeriod().Round(time.Millisecond).Seconds() - return result - } + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return destruction.CalcScalingSpellDmg(immolateCoeff) + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedMagicCrit, + }) }, }) } diff --git a/sim/warrior/passives.go b/sim/warrior/passives.go index 7ba4c26cec..b465f44fea 100644 --- a/sim/warrior/passives.go +++ b/sim/warrior/passives.go @@ -91,14 +91,16 @@ func (warrior *Warrior) registerDeepWounds() { }, ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.OutcomeExpectedSnapshotCrit) - } else { - baseDamage := warrior.CalcScalingSpellDmg(deepWoundsCoeff) - baseDamage += deepWoundsBonusCoeff * spell.MeleeAttackPower() - return spell.CalcPeriodicDamage(sim, target, baseDamage, spell.OutcomeExpectedPhysicalCrit) - } + dot := spell.Dot(target) + return dot.CalcExpectedTickDamage(sim, target, core.ExpectedTickConfig{ + UseSnapshot: useSnapshot, + BaseDmgFn: func(s *core.Spell) float64 { + return warrior.CalcScalingSpellDmg(deepWoundsCoeff) + deepWoundsBonusCoeff*s.MeleeAttackPower() + }, + SnapshotOutcome: dot.OutcomeExpectedSnapshotCrit, + NormalOutcome: spell.OutcomeExpectedPhysicalCrit, + SkipHasteNormalization: true, + }) }, })