diff --git a/sim/common/sod/item_effects/phase_8.go b/sim/common/sod/item_effects/phase_8.go index 795639e20c..48f8cebadd 100644 --- a/sim/common/sod/item_effects/phase_8.go +++ b/sim/common/sod/item_effects/phase_8.go @@ -748,13 +748,16 @@ func init() { // https://www.wowhead.com/classic/item=240919/ravagane // Chance on hit: You attack all nearby enemies for 9 sec causing weapon damage plus an additional 200 every 1.5 sec. // Confirmed PPM 0.8 - itemhelpers.CreateWeaponProcAura(Ravagane, "Ravagane", 0.8, func(character *core.Character) *core.Aura { + core.NewItemEffect(Ravagane, func(agent core.Agent) { + character := agent.GetCharacter() + actionID := core.ActionID{SpellID: 1231547} + tickSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1231546}, + ActionID: actionID, SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, + Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagSuppressEquipProcs, DamageMultiplier: 1, ThreatMultiplier: 1, @@ -769,12 +772,27 @@ func init() { }) whirlwindSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 1231547}, SpellSchool: core.SpellSchoolPhysical, ProcMask: core.ProcMaskMeleeMHSpecial, Dot: core.DotConfig{ Aura: core.Aura{ - Label: "Ravagane Whirlwind", + ActionID: actionID, + Label: "Ravagane Whirlwind", + OnGain: func(aura *core.Aura, sim *core.Simulation) { + // In-game testing shows that there is a slight delay before auto attacks are disablecd. + // Extra attacks are able to proc during this time. + core.StartDelayedAction(sim, core.DelayedActionOptions{ + DoAt: sim.CurrentTime + time.Millisecond*50, // Exact amount of time unknown + OnAction: func(sim *core.Simulation) { + if aura.IsActive() { + character.AutoAttacks.AllowAutoSwing(sim, false) + } + }, + }) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + character.AutoAttacks.AllowAutoSwing(sim, true) + }, }, NumberOfTicks: 6, TickLength: time.Millisecond * 1500, @@ -785,36 +803,20 @@ func init() { }, }) - return character.RegisterAura(core.Aura{ - Label: "Ravagane Bladestorm", - Duration: time.Second * 9, - Icd: &core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Second * 8, - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if !aura.Icd.IsReady(sim) { - return - } - aura.Icd.Use(sim) - + triggerAura := core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Ravagane Bladestorm Trigger", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskMelee, + SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, // Trigger is Chance on Hit so suppress if triggering spell does not proc Chance on Hit + PPM: 0.8, + ICD: 8 * time.Second, + Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { whirlwindSpell.AOEDot().Apply(sim) - character.AutoAttacks.CancelAutoSwing(sim) - }, - OnRefresh: func(aura *core.Aura, sim *core.Simulation) { - if !aura.Icd.IsReady(sim) { - return - } - aura.Icd.Use(sim) - - whirlwindSpell.AOEDot().ApplyOrReset(sim) - character.AutoAttacks.CancelAutoSwing(sim) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - whirlwindSpell.AOEDot().Cancel(sim) - character.AutoAttacks.EnableAutoSwing(sim) }, }) + + character.ItemSwap.RegisterProc(Ravagane, triggerAura) }) // https://www.wowhead.com/classic/item=241002/remnants-of-the-red diff --git a/sim/core/attack.go b/sim/core/attack.go index c7378e8ac6..299fd1c739 100644 --- a/sim/core/attack.go +++ b/sim/core/attack.go @@ -293,6 +293,7 @@ type WeaponAttack struct { curSwingSpeed float64 curSwingDuration time.Duration enabled bool + allowed bool } func (wa *WeaponAttack) getWeapon() *Weapon { @@ -330,6 +331,10 @@ func (wa *WeaponAttack) setWeapon(sim *Simulation, weapon Weapon) { func (wa *WeaponAttack) trySwing(sim *Simulation) time.Duration { if sim.CurrentTime < wa.swingAt { return wa.swingAt + } else if !wa.allowed { + wa.swingAt = sim.CurrentTime + wa.curSwingDuration // Auto Attack Fails due to being disabled by an item or effect (e.g. Ravagane) + sim.rescheduleWeaponAttack(wa.swingAt) + return wa.swingAt } return wa.swing(sim) } @@ -467,6 +472,8 @@ type AutoAttacks struct { AutoSwingMelee bool AutoSwingRanged bool + AutoSwingDisabled bool + IsDualWielding bool character *Character @@ -676,6 +683,10 @@ func (aa *AutoAttacks) reset(sim *Simulation) { aa.oh.enabled = false aa.ranged.enabled = false + aa.mh.allowed = true + aa.oh.allowed = true + aa.ranged.allowed = true + aa.mh.swingAt = NeverExpires aa.oh.swingAt = NeverExpires @@ -798,6 +809,13 @@ func (aa *AutoAttacks) EnableAutoSwing(sim *Simulation) { aa.EnableRangedSwing(sim) } +// Allow the auto swing action for the iteration +func (aa *AutoAttacks) AllowAutoSwing(sim *Simulation, isAllowed bool) { + aa.mh.allowed = isAllowed + aa.oh.allowed = isAllowed + aa.ranged.allowed = isAllowed +} + func (aa *AutoAttacks) EnableMeleeSwing(sim *Simulation) { if !aa.AutoSwingMelee { return @@ -821,7 +839,7 @@ func (aa *AutoAttacks) EnableMeleeSwing(sim *Simulation) { } } - if !aa.IsDualWielding && aa.oh.enabled { + if (!aa.IsDualWielding && aa.oh.enabled) { sim.removeWeaponAttack(&aa.oh) aa.oh.enabled = false }