Cataclysm-DDA
Cataclysm-DDA copied to clipboard
Update events to account for ability to swap avatars (debug or upon death)
Summary
Bugfixes "Update events to account for ability to swap avatars (debug or upon death)"
Purpose of change
Resolves #63455
#51450 and #53606 gave the ability to switch to another character.
Preexisting game events (that feed into memorial, stats, achievements, conducts, scores) are not equipped to handle this, as they only recorded the starting character in event_type::game_start
and then death and last words in event_type::game_over
. This oversight causes some things to break.
Describe the solution
- [x] split
game_avatar_new
off fromgame_start
andgame_avatar_death
fromgame_over
- [x] add migration for existing saves that retroactively populates
game_avatar_new
from available information- where
game_start
is available, get starting character information from it- if current character is different from starting character, add it as well, treating current turn as the time they took over
- if
game_start
is also not available (pretty old save!) treat current character as starting character.
- where
- [x] adjust existing event emissions (split into two events accordingly)
- [x] emit
game_avatar_new
at the end ofavatar::control_npc()
when new avatar takes over - [x] show the "tombstone" screen and prompt for last words on death of all player characters (not just the final one when you run out of "continues" or choose not to do so)
- [x] emit
game_avatar_death
to record last words of all dead PCs - [x] change
avatar_id
event statistic to pull its value from the most recentgame_avatar_new
event - [x] memorial logger logs
game_avatar_death
instead ofgame_over
- [x] memorial logger logs
game_avatar_new
instead ofgame_start
, and will have different text for a character swap rather than a brand new game - [x] past games info will try to account for multiple characters over the course of a save, insofar as the information is available. It will pull the starting character name from the first
game_avatar_new
entry. Depending on how manygame_avatar_new
entries there are, it will append "et. al." to indicate that there was/were subsequent character(s) that took over from the starting character due to death or debug. If there are nogame_avatar_new
entries, it will fall back on the legacy approach and pull the starting character name fromgame_start
.
Behavior of stats after this PR
- any statistic that doesn't rely on comparison against the
avatar_id
statistic continue working as they did - any statistic that depends on
avatar_id
will switch to the "lifetime" stats of the new avatar when switching to them- this includes things they did as an NPC, e.g. any kills, skill gain etc that was captured by the events system
This is imperfect, but now we are at least capturing an event whenever player control switches from one character to another. This ensures that save games will contain the information needed when a fuller solution is developed.
Subsequent work can look into a different way for event transformation to filter events (e.g. kills) to match them against the player character avatar_id
at the time the event occurred rather than the current avatar, so that the affected scores, achievements and conducts are on the basis of player action.
Additional context
I can't do anything about information that was lost between #51450 / #53606 and now, because it wasn't able to be captured.
~This will probably break some achievements in existing saves, because they'd look for avatar_id
but be unable to resolve a value for it when there are no game_avatar_new
events yet. There's no way in the event statistics system to "union" two event streams (game_start
with game_avatar_new
) and implementing such a feature looks like it will get really complex, so I don't think it's worth it just for the sake of this one unusual case. Perhaps some other migration strategy could be devised? In any case, the affected achievements are already broken anyway ( #63455 ) so I'd be satisfied with fixing things so that they work correctly for new saves henceforth.~
Describe alternatives you've considered
Hijack the existing game_start
and game_over
so that they are also emitted whenever there is a character swap, but that seems weird esp. with respect to the game version and total play time fields.
Testing
Simple test case: TestLand.zip
-
Build this PR, load the save in and verify that the score screen shows 5 monsters killed as the first stat on top. Spawn a slow, harmless monster e.g. water strider and kill it; check that the count has increased to 6.
-
Using the debug menu,
p
,x
to switch to the follower NPC. Check the score screen, which should now shows 0 kills (Antonia Boswell's lifetime stats). Spawn water strider; kill; check that the count has increased to 1. -
Switch back to the original character. Check score screen, which should list 6 kills.
-
Fire up a recent experimental build and load up the original save file again. Verify that the score screen shows 5 monsters killed.
-
Switch to the follower NPC. Check that score screen; it shows 5 kills. Spawn water strider; kill; check the count, which did not increase.
-
Save the game and transfer it to the PR build. The score screen should reflect Antonia's 1 kill.
-
Spawn water strider; kill; check count increased to 2.
-
Switch back to the original character. The score screen should reflect their 5 kills.
Added migration from existing saves that makes best-effort attempt to populate game_avatar_new
retroactively with what information is available. Imperfect but better than nothing.
Ready for testing and review.
Rebased to resolve conflicts.
E: test failure unrelated, fixed in #63911