diff --git a/sim/core/pet.go b/sim/core/pet.go index 5021e082d8..4a20f78546 100644 --- a/sim/core/pet.go +++ b/sim/core/pet.go @@ -162,6 +162,14 @@ func (pet *Pet) Enable(sim *Simulation, petAgent PetAgent) { //reset current mana after applying stats pet.manaBar.reset() + // Call onEnable callbacks before enabling auto swing + // to not have to reorder PAs multiple times + pet.enabled = true + + if pet.OnPetEnable != nil { + pet.OnPetEnable(sim) + } + pet.SetGCDTimer(sim, MaxDuration(0, sim.CurrentTime)) if sim.CurrentTime >= 0 { pet.AutoAttacks.EnableAutoSwing(sim) @@ -172,12 +180,6 @@ func (pet *Pet) Enable(sim *Simulation, petAgent PetAgent) { }) } - pet.enabled = true - - if pet.OnPetEnable != nil { - pet.OnPetEnable(sim) - } - if sim.Log != nil { pet.Log(sim, "Pet stats: %s", pet.GetStats()) pet.Log(sim, "Pet inherited stats: %s", pet.ApplyStatDependencies(pet.inheritedStats)) diff --git a/sim/deathknight/dps/TestUnholy.results b/sim/deathknight/dps/TestUnholy.results index fa35246995..62506e45e5 100644 --- a/sim/deathknight/dps/TestUnholy.results +++ b/sim/deathknight/dps/TestUnholy.results @@ -734,9 +734,9 @@ dps_results: { dps_results: { key: "TestUnholy-AllItems-SigilofVirulence-47673" value: { - dps: 8046.96581 - tps: 5128.16517 - hps: 266.55313 + dps: 8245.23172 + tps: 5205.95757 + hps: 238.66172 } } dps_results: { diff --git a/sim/deathknight/dps/rotation_unholy.go b/sim/deathknight/dps/rotation_unholy.go index 6dea9adaa7..6300e621c9 100644 --- a/sim/deathknight/dps/rotation_unholy.go +++ b/sim/deathknight/dps/rotation_unholy.go @@ -28,26 +28,29 @@ func (dk *DpsDeathknight) setupUnholyRotations() { NewAction(dk.getSecondDiseaseAction()). NewAction(dk.uhBloodRuneAction(true)) + fuStrikeAction := dk.RotationActionCallback_DS if dk.Talents.ScourgeStrike { - if dk.ur.sigil == Sigil_Virulence { - dk.RotationSequence. - NewAction(dk.RotationActionCallback_SS). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionUH_SS_Sigil). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionUH_SS_Sigil). - NewAction(dk.RotationActionUH_BS) - } else if dk.ur.sigil == Sigil_HangedMan { - dk.RotationSequence. - NewAction(dk.RotationActionCallback_SS). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_DC). - NewAction(dk.RotationActionCallback_ERW). - NewAction(dk.RotationActionCallback_SS). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_SS). - NewAction(dk.RotationActionUH_BS) - } + fuStrikeAction = dk.RotationActionCallback_SS + } + + if dk.ur.sigil == Sigil_Virulence { + dk.RotationSequence. + NewAction(fuStrikeAction). + NewAction(dk.RotationActionUH_BS). + NewAction(dk.RotationActionUH_SS_Sigil). + NewAction(dk.RotationActionUH_BS). + NewAction(dk.RotationActionUH_SS_Sigil). + NewAction(dk.RotationActionUH_BS) + } else if dk.ur.sigil == Sigil_HangedMan { + dk.RotationSequence. + NewAction(fuStrikeAction). + NewAction(dk.RotationActionUH_BS). + NewAction(dk.RotationActionCallback_DC). + NewAction(dk.RotationActionCallback_ERW). + NewAction(fuStrikeAction). + NewAction(dk.RotationActionUH_BS). + NewAction(fuStrikeAction). + NewAction(dk.RotationActionUH_BS) } if dk.Rotation.UseDeathAndDecay || (!dk.Talents.ScourgeStrike && dk.Talents.Annihilation == 0) { @@ -131,19 +134,19 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholyDndRotation(sim *core.Sim } cast := false - prioSs, _ := dk.bonusProcRotationChecks(sim) - if dk.uhDiseaseCheck(sim, target, dk.DeathAndDecay, true, 1) { - if prioSs { + if dk.uhVirulenceRotationCheck(sim, true) { if dk.uhGargoyleCheck(sim, target, core.GCDDefault*2+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } - cast = dk.ScourgeStrike.Cast(sim, target) + cast = dk.uhCastVirulenceStrike(sim, target) if cast { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_UnholyDndRotation) + if dk.LastOutcome.Matches(core.OutcomeLanded) { + dk.RotationSequence.Clear(). + NewAction(dk.RotationActionUH_BS). + NewAction(dk.RotationActionCallback_UnholyDndRotation) + } } } else { if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { @@ -164,16 +167,18 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholyDndRotation(sim *core.Sim if !cast { if dk.uhDiseaseCheck(sim, target, dk.ScourgeStrike, true, 1) { if !dk.uhShouldWaitForDnD(sim, true, true, true) { - if dk.Talents.ScourgeStrike && dk.ScourgeStrike.IsReady(sim) { + if dk.uhVirulenceRotationCheck(sim, false) && dk.DeathStrike.IsReady(sim) { if dk.uhGargoyleCheck(sim, target, core.GCDDefault*2+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } - cast = dk.ScourgeStrike.Cast(sim, target) + cast = dk.uhCastVirulenceStrike(sim, target) if cast { - dk.RotationSequence.Clear(). - NewAction(dk.RotationActionUH_BS). - NewAction(dk.RotationActionCallback_UnholyDndRotation) + if dk.LastOutcome.Matches(core.OutcomeLanded) { + dk.RotationSequence.Clear(). + NewAction(dk.RotationActionUH_BS). + NewAction(dk.RotationActionCallback_UnholyDndRotation) + } } } else if dk.IcyTouch.CanCast(sim, nil) && dk.PlagueStrike.CanCast(sim, nil) { if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { @@ -189,9 +194,10 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholyDndRotation(sim *core.Sim return sim.CurrentTime } if !cast { + gargCheck := dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) if dk.shShouldSpreadDisease(sim) { if !dk.uhShouldWaitForDnD(sim, true, false, false) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -200,14 +206,14 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholyDndRotation(sim *core.Sim } if !cast { if dk.uhDeathCoilCheck(sim) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } cast = dk.DeathCoil.Cast(sim, target) } if !cast { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -258,13 +264,13 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholySsRotation(sim *core.Simu fuStrike = dk.Obliterate } if dk.uhDiseaseCheck(sim, target, fuStrike, true, 1) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if dk.uhGargoyleCheck(sim, target, core.GCDDefault+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } casted = fuStrike.Cast(sim, target) } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()*2+50*time.Millisecond) { + if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -272,15 +278,16 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholySsRotation(sim *core.Simu return sim.CurrentTime } if !casted { + gargCheck := dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) if dk.shShouldSpreadDisease(sim) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } casted = dk.uhSpreadDiseases(sim, target, s) } else { if dk.uhDiseaseCheck(sim, target, dk.BloodStrike, true, 1) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if dk.uhGargoyleCheck(sim, target, core.GCDDefault+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -290,7 +297,7 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholySsRotation(sim *core.Simu casted = dk.BloodBoil.Cast(sim, target) } } else { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()*2+50*time.Millisecond) { + if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+core.GCDDefault*2+50*time.Millisecond) { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -300,14 +307,14 @@ func (dk *DpsDeathknight) RotationActionCallback_UnholySsRotation(sim *core.Simu } if !casted { if dk.uhDeathCoilCheck(sim) { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } casted = dk.DeathCoil.Cast(sim, target) } if !casted { - if dk.uhGargoyleCheck(sim, target, dk.SpellGCD()+50*time.Millisecond) { + if gargCheck { dk.uhAfterGargoyleSequence(sim) return sim.CurrentTime } @@ -500,7 +507,7 @@ func (dk *DpsDeathknight) RotationActionUH_BS(sim *core.Simulation, target *core s.ConditionalAdvance(casted && advance) } else { bloodSpell := dk.BloodBoil - _, prioBs := dk.bonusProcRotationChecks(sim) + prioBs := dk.unholyMightRotationChecks(sim) if dk.desolationAuraCheck(sim) || prioBs { bloodSpell = dk.BloodStrike } @@ -528,7 +535,7 @@ func (dk *DpsDeathknight) RotationActionUH_SS_Sigil(sim *core.Simulation, target dk.EmpowerRuneWeapon.Cast(sim, target) } - casted := dk.ScourgeStrike.Cast(sim, target) + casted := dk.uhCastVirulenceStrike(sim, target) advance := dk.LastOutcome.Matches(core.OutcomeLanded) s.ConditionalAdvance(casted && advance) diff --git a/sim/deathknight/dps/rotation_unholy_helper.go b/sim/deathknight/dps/rotation_unholy_helper.go index c834b639f9..dcb44211cf 100644 --- a/sim/deathknight/dps/rotation_unholy_helper.go +++ b/sim/deathknight/dps/rotation_unholy_helper.go @@ -45,6 +45,13 @@ type UnholyRotation struct { sigil SigilType unholyMight bool + + virulenceAura *core.Aura + unholyMightAura *core.Aura + blackMagicProc *core.Aura + fallenCrusaderProc *core.Aura + berserkingMh *core.Aura + berserkingOh *core.Aura } func (ur *UnholyRotation) Reset(sim *core.Simulation) { @@ -75,16 +82,22 @@ func (ur *UnholyRotation) Initialize(dk *DpsDeathknight) { if dk.Talents.SummonGargoyle && dk.Rotation.UseGargoyle { dk.setupWeaponSwap() + ur.blackMagicProc = dk.GetAura("Black Magic Proc") + ur.fallenCrusaderProc = dk.GetAura("Rune Of The Fallen Crusader Proc") + ur.berserkingMh = dk.GetAura("Berserking MH Proc") + ur.berserkingOh = dk.GetAura("Berserking OH Proc") } // Init Sigil of Virulence Rotation - if dk.Talents.ScourgeStrike && dk.Equip[core.ItemSlotRanged].ID == 47673 { + if dk.Equip[core.ItemSlotRanged].ID == 47673 { ur.sigil = Sigil_Virulence + ur.virulenceAura = dk.GetAura("Sigil of Virulence Proc") } // Init T9 2P Proc if dk.HasSetBonus(deathknight.ItemSetThassariansBattlegear, 2) { ur.unholyMight = true + ur.unholyMightAura = dk.GetAura("Unholy Might Proc") } } @@ -114,22 +127,31 @@ func (dk *DpsDeathknight) uhBloodRuneAction(isFirst bool) deathknight.RotationAc } } -func (dk *DpsDeathknight) bonusProcRotationChecks(sim *core.Simulation) (bool, bool) { +func (dk *DpsDeathknight) uhCastVirulenceStrike(sim *core.Simulation, target *core.Unit) bool { + if dk.Talents.ScourgeStrike { + return dk.ScourgeStrike.Cast(sim, target) + } else { + return dk.DeathStrike.Cast(sim, target) + } +} + +func (dk *DpsDeathknight) uhVirulenceRotationCheck(sim *core.Simulation, gargCheck bool) bool { // If we have sigil of virulence // Higher prio SS then Dnd when gargoyle is ready - prioSs := false - if dk.Talents.ScourgeStrike && dk.ur.sigil == Sigil_Virulence && (dk.SummonGargoyle.IsReady(sim) || dk.SummonGargoyle.CD.TimeToReady(sim) < 10*time.Second) { - virulenceAura := dk.GetAura("Sigil of Virulence Proc") - prioSs = !virulenceAura.IsActive() || virulenceAura.RemainingDuration(sim) < 10*time.Second + prioVirulenceStrike := false + if dk.ur.sigil == Sigil_Virulence && (!gargCheck || (dk.SummonGargoyle.IsReady(sim) || dk.SummonGargoyle.CD.TimeToReady(sim) < 10*time.Second)) { + prioVirulenceStrike = !dk.ur.virulenceAura.IsActive() || dk.ur.virulenceAura.RemainingDuration(sim) < 10*time.Second } + return prioVirulenceStrike +} +func (dk *DpsDeathknight) unholyMightRotationChecks(sim *core.Simulation) bool { // If we have T9 2P we prio BS over BB for refreshing the buff when out of ICD prioBs := false if dk.ur.unholyMight { - unholyMightAura := dk.GetAura("Unholy Might Proc") - prioBs = unholyMightAura.StartedAt() == 0 || unholyMightAura.StartedAt() < sim.CurrentTime-45*time.Second + prioBs = dk.ur.unholyMightAura.StartedAt() == 0 || dk.ur.unholyMightAura.StartedAt() < sim.CurrentTime-45*time.Second } - return prioSs, prioBs + return prioBs } func (dk *DpsDeathknight) weaponSwapCheck(sim *core.Simulation) bool { @@ -139,22 +161,16 @@ func (dk *DpsDeathknight) weaponSwapCheck(sim *core.Simulation) bool { // Swap if gargoyle will still be on CD for full ICD or if gargoyle is already active shouldSwapBm := dk.ur.bmIcd < sim.CurrentTime && (dk.SummonGargoyle.CD.TimeToReady(sim) > 45*time.Second || dk.SummonGargoyleAura.IsActive()) - shouldSwapBackFromBm := dk.HasActiveAura("Black Magic Proc") // || dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) < 5*time.Second + shouldSwapBackFromBm := dk.ur.blackMagicProc.IsActive() // || dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) < 5*time.Second if dk.ur.mhSwap == WeaponSwap_BlackMagic { if !dk.ur.mhSwapped && shouldSwapBm { // Swap to BM - if sim.Log != nil { - sim.Log("Swapping MH to BM") - } dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}, true) dk.ur.mhSwapped = true } else if dk.ur.mhSwapped && shouldSwapBackFromBm { // Swap to Normal set and set BM Icd tracker - if sim.Log != nil { - sim.Log("Swapping MH to Normal") - } - dk.ur.bmIcd = dk.GetAura("Black Magic Proc").ExpiresAt() + 35*time.Second + dk.ur.bmIcd = dk.ur.blackMagicProc.ExpiresAt() + 35*time.Second dk.ur.mhSwapped = false dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}, true) } @@ -163,58 +179,40 @@ func (dk *DpsDeathknight) weaponSwapCheck(sim *core.Simulation) bool { if dk.ur.ohSwap == WeaponSwap_BlackMagic { if !dk.ur.ohSwapped && shouldSwapBm { // Swap to BM - if sim.Log != nil { - sim.Log("Swapping OH to BM") - } dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}, true) dk.ur.ohSwapped = true } else if dk.ur.ohSwapped && shouldSwapBackFromBm { // Swap to Normal set and set BM Icd tracker - if sim.Log != nil { - sim.Log("Swapping OH to Normal") - } - dk.ur.bmIcd = dk.GetAura("Black Magic Proc").ExpiresAt() + 35*time.Second + dk.ur.bmIcd = dk.ur.blackMagicProc.ExpiresAt() + 35*time.Second dk.ur.ohSwapped = false dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}, true) } } - shouldSwapBerserking := dk.HasActiveAura("Rune Of The Fallen Crusader Proc") && - dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) > time.Second*10 + shouldSwapBerserking := dk.ur.fallenCrusaderProc.IsActive() && + dk.ur.fallenCrusaderProc.RemainingDuration(sim) > time.Second*10 shouldSwapBackfromBerserking := false //dk.GetAura("Rune Of The Fallen Crusader Proc").RemainingDuration(sim) < 5*time.Second if dk.ur.mhSwap == WeaponSwap_Berserking { - if !dk.ur.mhSwapped && !dk.HasActiveAura("Berserking MH Proc") && shouldSwapBerserking { + if !dk.ur.mhSwapped && !dk.ur.berserkingMh.IsActive() && shouldSwapBerserking { // Swap to Berserking - if sim.Log != nil { - sim.Log("Swapping MH to Berserking") - } dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}, true) dk.ur.mhSwapped = true - } else if dk.ur.mhSwapped && (dk.HasActiveAura("Berserking MH Proc") || shouldSwapBackfromBerserking) { + } else if dk.ur.mhSwapped && (dk.ur.berserkingMh.IsActive() || shouldSwapBackfromBerserking) { // Swap to Normal set - if sim.Log != nil { - sim.Log("Swapping MH to Normal") - } dk.ur.mhSwapped = false dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotMainHand}, true) } } if dk.ur.ohSwap == WeaponSwap_Berserking { - if !dk.ur.ohSwapped && !dk.HasActiveAura("Berserking OH Proc") && shouldSwapBerserking { + if !dk.ur.ohSwapped && !dk.ur.berserkingOh.IsActive() && shouldSwapBerserking { // Swap to Berserking - if sim.Log != nil { - sim.Log("Swapping OH to Berserking") - } dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}, true) dk.ur.ohSwapped = true - } else if dk.ur.ohSwapped && (dk.HasActiveAura("Berserking OH Proc") || shouldSwapBackfromBerserking) { + } else if dk.ur.ohSwapped && (dk.ur.berserkingOh.IsActive() || shouldSwapBackfromBerserking) { // Swap to Normal set - if sim.Log != nil { - sim.Log("Swapping OH to Normal") - } dk.ur.ohSwapped = false dk.ItemSwap.SwapItems(sim, []proto.ItemSlot{proto.ItemSlot_ItemSlotOffHand}, true) } diff --git a/sim/deathknight/rune_strike.go b/sim/deathknight/rune_strike.go index 51593e950b..46f0295274 100644 --- a/sim/deathknight/rune_strike.go +++ b/sim/deathknight/rune_strike.go @@ -65,6 +65,10 @@ func (dk *Deathknight) newRuneStrikeSpell(isMH bool) *core.Spell { baseDamage *= dk.RoRTSBonus(target) result := spell.CalcAndDealDamage(sim, target, baseDamage, outcomeApplier) + if result.Damage > 0 && dk.Talents.Necrosis > 0 { + dk.necrosisDamage(result.Damage, sim, target) + } + if isMH { dk.threatOfThassarianProc(sim, result, dk.RuneStrikeOh) dk.RuneStrikeAura.Deactivate(sim) diff --git a/sim/deathknight/scourge_strike.go b/sim/deathknight/scourge_strike.go index daba30162e..0594f57e74 100644 --- a/sim/deathknight/scourge_strike.go +++ b/sim/deathknight/scourge_strike.go @@ -35,6 +35,10 @@ func (dk *Deathknight) registerScourgeStrikeShadowDamageSpell() *core.Spell { } func (dk *Deathknight) registerScourgeStrikeSpell() { + if !dk.Talents.ScourgeStrike { + return + } + shadowDamageSpell := dk.registerScourgeStrikeShadowDamageSpell() bonusBaseDamage := dk.sigilOfAwarenessBonus() + dk.sigilOfArthriticBindingBonus() hasGlyph := dk.HasMajorGlyph(proto.DeathknightMajorGlyph_GlyphOfScourgeStrike) @@ -57,9 +61,6 @@ func (dk *Deathknight) registerScourgeStrikeSpell() { }, IgnoreHaste: true, }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return dk.Talents.ScourgeStrike - }, BonusCritRating: (dk.subversionCritBonus() + dk.viciousStrikesCritChanceBonus() + dk.scourgeborneBattlegearCritBonus()) * core.CritRatingPerCritChance, diff --git a/sim/deathknight/talents_unholy.go b/sim/deathknight/talents_unholy.go index 1e7f42ff60..c0dd8df8d0 100644 --- a/sim/deathknight/talents_unholy.go +++ b/sim/deathknight/talents_unholy.go @@ -107,12 +107,16 @@ func (dk *Deathknight) applyNecrosis() { dk.AutoAttacks.OHConfig.ApplyEffects = dk.necrosisOHAuto } +func (dk *Deathknight) necrosisDamage(damage float64, sim *core.Simulation, target *core.Unit) { + dk.Necrosis.SpellMetrics[target.UnitIndex].Casts++ + dk.Necrosis.CalcAndDealDamage(sim, target, damage*dk.NecrosisCoeff, dk.Necrosis.OutcomeAlwaysHit) +} func (dk *Deathknight) necrosisOHAuto(sim *core.Simulation, target *core.Unit, spell *core.Spell) { baseDamage := spell.Unit.OHWeaponDamage(sim, spell.MeleeAttackPower()) + spell.BonusWeaponDamage() if result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWhite); result.Damage > 0 { - dk.Necrosis.CalcAndDealDamage(sim, target, result.Damage*dk.NecrosisCoeff, dk.Necrosis.OutcomeAlwaysHit) + dk.necrosisDamage(result.Damage, sim, target) } } func (dk *Deathknight) necrosisMHAuto(sim *core.Simulation, target *core.Unit, spell *core.Spell) { @@ -120,7 +124,7 @@ func (dk *Deathknight) necrosisMHAuto(sim *core.Simulation, target *core.Unit, s spell.BonusWeaponDamage() if result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWhite); result.Damage > 0 { - dk.Necrosis.CalcAndDealDamage(sim, target, result.Damage*dk.NecrosisCoeff, dk.Necrosis.OutcomeAlwaysHit) + dk.necrosisDamage(result.Damage, sim, target) } }