Cataclysm-DDA icon indicating copy to clipboard operation
Cataclysm-DDA copied to clipboard

Update events to account for ability to swap avatars (debug or upon death)

Open cake-pie opened this issue 2 years ago • 2 comments

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 from game_start and game_avatar_death from game_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.
  • [x] adjust existing event emissions (split into two events accordingly)
  • [x] emit game_avatar_new at the end of avatar::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 recent game_avatar_new event
  • [x] memorial logger logs game_avatar_death instead of game_over
  • [x] memorial logger logs game_avatar_new instead of game_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 many game_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 no game_avatar_new entries, it will fall back on the legacy approach and pull the starting character name from game_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

  1. 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.

  2. 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.

  3. Switch back to the original character. Check score screen, which should list 6 kills.

  4. Fire up a recent experimental build and load up the original save file again. Verify that the score screen shows 5 monsters killed.

  5. Switch to the follower NPC. Check that score screen; it shows 5 kills. Spawn water strider; kill; check the count, which did not increase.

  6. Save the game and transfer it to the PR build. The score screen should reflect Antonia's 1 kill.

  7. Spawn water strider; kill; check count increased to 2.

  8. Switch back to the original character. The score screen should reflect their 5 kills.

cake-pie avatar Feb 08 '23 10:02 cake-pie

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.

cake-pie avatar Feb 09 '23 07:02 cake-pie

Rebased to resolve conflicts.

E: test failure unrelated, fixed in #63911

cake-pie avatar Mar 03 '23 13:03 cake-pie