Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions sim/core/aura.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type OnReset func(aura *Aura, sim *Simulation)
type OnDoneIteration func(aura *Aura, sim *Simulation)
type OnGain func(aura *Aura, sim *Simulation)
type OnExpire func(aura *Aura, sim *Simulation)
type OnRestore func(aura *Aura, sim *Simulation, stacks int32)
type OnStacksChange func(aura *Aura, sim *Simulation, oldStacks int32, newStacks int32)
type OnEncounterStart func(aura *Aura, sim *Simulation)

Expand Down Expand Up @@ -87,6 +88,7 @@ type Aura struct {
OnDoneIteration OnDoneIteration
OnGain OnGain
OnExpire OnExpire
OnRestore OnRestore
OnStacksChange OnStacksChange // Invoked when the number of stacks of this aura changes.

OnApplyEffects OnApplyEffects // Invoked when a spell cast is completing, before apply effects are called
Expand Down Expand Up @@ -647,6 +649,10 @@ restart:
// Adds a new aura to the simulation. If an aura with the same ID already
// exists it will be replaced with the new one.
func (aura *Aura) Activate(sim *Simulation) {
aura.activate(sim, true)
}

func (aura *Aura) activate(sim *Simulation, triggerOnGain bool) {
if aura == nil {
return
}
Expand Down Expand Up @@ -748,7 +754,7 @@ func (aura *Aura) Activate(sim *Simulation) {
}

// don't invoke possible callbacks until the internal state is consistent
if aura.OnGain != nil {
if triggerOnGain && aura.OnGain != nil {
aura.OnGain(aura, sim)
}
}
Expand Down Expand Up @@ -1148,8 +1154,22 @@ func (aura *Aura) SaveState(sim *Simulation) AuraState {
}

func (aura *Aura) RestoreState(state AuraState, sim *Simulation) {
if !aura.active {
aura.Activate(sim)
// If the aura has an OnRestore callback, we need special handling to properly
// restart any periodic actions without causing issues like double-stacking.
if aura.OnRestore != nil {
// Deactivate first to cancel any existing periodic actions
if aura.active {
aura.Deactivate(sim)
}
// Activate without triggering OnGain's immediate effects
aura.activate(sim, false)
// Then call the restore callback to restart periodic actions properly
// Pass the stacks so it can calculate remaining ticks
aura.OnRestore(aura, sim, state.Stacks)
Comment thread
Saji-Saji marked this conversation as resolved.
Outdated
} else {
if !aura.active {
aura.Activate(sim)
}
}

aura.UpdateExpires(state.RemainingDuration + sim.CurrentTime)
Expand Down
52 changes: 37 additions & 15 deletions sim/core/aura_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,25 @@ func (character *Character) NewTemporaryStatBuffWithStacks(config TemporaryStatB
})

if config.TimePerStack > 0 {
var pa *PendingAction

startStackingAction := func(sim *Simulation, tickImmediately bool, numTicks int) {
pa = StartPeriodicAction(sim, PeriodicActionOptions{
Period: config.TimePerStack,
NumTicks: numTicks,
TickImmediately: tickImmediately,
OnAction: func(sim *Simulation) {
if stackingAura.IsActive() {
if config.DecrementStacks {
stackingAura.RemoveStack(sim)
} else {
stackingAura.AddStack(sim)
}
}
},
})
}

aura := character.RegisterAura(Aura{
Label: config.AuraLabel,
ActionID: config.ActionID,
Expand All @@ -352,21 +371,24 @@ func (character *Character) NewTemporaryStatBuffWithStacks(config TemporaryStatB
stackingAura.SetStacks(sim, config.MaxStacks)
}

StartPeriodicAction(sim, PeriodicActionOptions{
Period: config.TimePerStack,
NumTicks: int(config.MaxStacks),
TickImmediately: config.TickImmediately,
OnAction: func(sim *Simulation) {
// Aura might not be active because of stuff like mage alter time being cast right before this aura being activated
if stackingAura.IsActive() {
if config.DecrementStacks {
stackingAura.RemoveStack(sim)
} else {
stackingAura.AddStack(sim)
}
}
},
})
startStackingAction(sim, config.TickImmediately, int(config.MaxStacks))
},
OnExpire: func(aura *Aura, sim *Simulation) {
if pa != nil {
pa.Cancel(sim)
pa = nil
}
},
OnRestore: func(aura *Aura, sim *Simulation, stacks int32) {
// When restoring (e.g., via Alter Time), we need to restart the periodic action
// but without TickImmediately to avoid adding an extra stack.
// Note: We don't activate the stacking aura here because it will be restored
// separately by Alter Time's restoration loop with the correct duration.

remainingTicks := int(config.MaxStacks - stacks)
if remainingTicks > 0 {
startStackingAction(sim, false, remainingTicks)
}
},
})
return stackingAura, aura
Expand Down
8 changes: 4 additions & 4 deletions sim/mage/arcane/TestArcane.results
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ dps_results: {
dps_results: {
key: "TestArcane-AllItems-BlackBloodofY'Shaarj-105648"
value: {
dps: 250708.14874
tps: 241227.73721
dps: 247368.66106
tps: 238202.20435
}
}
dps_results: {
Expand Down Expand Up @@ -495,8 +495,8 @@ dps_results: {
dps_results: {
key: "TestArcane-AllItems-Wushoolay'sFinalChoice-96785"
value: {
dps: 229530.16406
tps: 221189.14387
dps: 227481.12544
tps: 219192.8406
}
}
dps_results: {
Expand Down
8 changes: 4 additions & 4 deletions sim/mage/fire/TestFire.results
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ dps_results: {
dps_results: {
key: "TestFire-AllItems-BlackBloodofY'Shaarj-105648"
value: {
dps: 168331.6727
tps: 163805.79586
dps: 167197.44883
tps: 162730.59082
}
}
dps_results: {
Expand Down Expand Up @@ -2392,8 +2392,8 @@ dps_results: {
dps_results: {
key: "TestFire-AllItems-Wushoolay'sFinalChoice-96785"
value: {
dps: 151200.99334
tps: 147159.65728
dps: 149762.49072
tps: 145741.62368
}
}
dps_results: {
Expand Down
8 changes: 4 additions & 4 deletions sim/mage/frost/TestFrost.results
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ dps_results: {
dps_results: {
key: "TestFrost-AllItems-BlackBloodofY'Shaarj-105648"
value: {
dps: 175922.50483
tps: 128279.16303
dps: 176451.38176
tps: 128653.32481
}
}
dps_results: {
Expand Down Expand Up @@ -495,8 +495,8 @@ dps_results: {
dps_results: {
key: "TestFrost-AllItems-Wushoolay'sFinalChoice-96785"
value: {
dps: 162929.76163
tps: 119026.63359
dps: 162234.99754
tps: 118586.24646
}
}
dps_results: {
Expand Down
6 changes: 3 additions & 3 deletions sim/monk/brewmaster/TestBrewmaster.results
Original file line number Diff line number Diff line change
Expand Up @@ -2715,10 +2715,10 @@ dps_results: {
dps_results: {
key: "TestBrewmaster-AllItems-TickingEbonDetonator-105612"
value: {
dps: 280443.12765
tps: 1.2080022053e+06
dps: 280460.43133
tps: 1.20812333106e+06
dtps: 13651.61794
hps: 31015.91987
hps: 31018.86531
}
}
dps_results: {
Expand Down
6 changes: 3 additions & 3 deletions sim/monk/windwalker/TestWindwalker.results
Original file line number Diff line number Diff line change
Expand Up @@ -2433,9 +2433,9 @@ dps_results: {
dps_results: {
key: "TestWindwalker-AllItems-TickingEbonDetonator-105612"
value: {
dps: 271886.08025
tps: 259546.47389
hps: 8823.0909
dps: 271907.0088
tps: 259566.55912
hps: 8825.87634
}
}
dps_results: {
Expand Down
4 changes: 2 additions & 2 deletions sim/paladin/retribution/TestRetribution.results
Original file line number Diff line number Diff line change
Expand Up @@ -2393,8 +2393,8 @@ dps_results: {
dps_results: {
key: "TestRetribution-AllItems-TickingEbonDetonator-105612"
value: {
dps: 240898.69088
tps: 229849.35766
dps: 240900.50608
tps: 229851.17286
hps: 22.01849
}
}
Expand Down