Add effect add/remove scheduling #51952
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Bugfixes "Explicitly order effects map changes"
Purpose of change
Fixes #51812. Fixes #51839. Fixes #51900.
Describe the solution
Introduce functions
schedule_effect_removal
andschedule_effect
to the Creature class that can schedule effects to be added/removed after the effects processing step.Previously effects could be added or removed immediately during the
process_effects
loop using a "laissez-faire" approach. The iterator might or might not process a newly added effect and effects might be removed before or after being processed. A typical bug I would expect to occur without this PR would be foreffect_valium
to be applied, create a neweffect_downed
which would also be processed, then maybe processed again depending on how the iterator would update. Crashes seem to only occur when the current iterator being used is removed due to the effect it is pointing to being removed as part of its own processing.To the best of my ability to spot the cases, whenever the previous solution tried to immediately add or remove effects the scheduled variants are now used instead. This means that pre-existing effects should always be fully processed before any changes occur to the effects map. The expected order of events is:
To facilitate the scheduling two static
std::queue<T>
objects were introduced to theCreature
class. The queues hold new struct objects that simply store theadd_effect
andremove_effect
function arguments.After the effects processing loops are completed, the effect additions are performed from the
scheduled_effects
queue until it is empty. After that, theterminating_effects
queue is likewise used to perform any scheduled effect removals. Both queues are emptied by calling the originaladd_effect
andremove_effect
functions using the function arguments stored previously.The
schedule_effect
functions do not support passing theeffect_source
as I had some issues with storing the function argument reference during implementation and cut it out during testing. It may be possible to support them, though no current functionality seems to use it.Reverts #51827.
Describe alternatives you've considered
process_effects
loop. Replicating the intended behavior through other means would require changes to multiple systems that likely would break a lot of things.Testing
avatar::wake_up()
immediately removingeffect_alarm_clock
; does not cause a crash in this PR.Testing suggestions:
It is possible that systems that previously "worked" relied on the old behavior and so may behave strangely in this PR.
Additional context
This acts as an alternative solution to the issues resolved by PR #51947.
This is my second PR submitted and while I hope the solution presented is roughly reasonable, I am sure I could benefit from a couple of critical eyes here.