From 5043e67e06942bcf40d12bc9a36b7508497d8d39 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Mon, 1 Jan 2024 13:22:11 +0300 Subject: [PATCH] Replicate recent save loading prompt behavior (bug #7617) --- CHANGELOG.md | 1 + apps/openmw/mwstate/statemanagerimp.cpp | 38 ++++++++++++++++++++----- apps/openmw/mwstate/statemanagerimp.hpp | 1 + 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dbd4e463f..00795b34cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ Bug #7604: Goblins Grunt becomes idle once injured Bug #7609: ForceGreeting should not open dialogue for werewolves Bug #7611: Beast races' idle animations slide after turning or jumping in place + Bug #7617: The death prompt asks the player if they wanted to load the character's last created save Bug #7619: Long map notes may get cut off Bug #7630: Charm can be cast on creatures Bug #7631: Cannot trade with/talk to Creeper or Mudcrab Merchant when they're fleeing diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 89b63c35e4..4358c4094e 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -64,6 +64,7 @@ void MWState::StateManager::cleanup(bool force) mState = State_NoGame; mCharacterManager.setCurrentCharacter(nullptr); mTimePlayed = 0; + mLastSavegame.clear(); MWMechanics::CreatureStats::cleanup(); } @@ -119,14 +120,27 @@ void MWState::StateManager::askLoadRecent() if (!mAskLoadRecent) { - const MWState::Character* character = getCurrentCharacter(); - if (!character || character->begin() == character->end()) // no saves + if (mLastSavegame.empty()) // no saves { MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu); } else { - MWState::Slot lastSave = *character->begin(); + std::string saveName = Files::pathToUnicodeString(mLastSavegame.filename()); + // Assume the last saved game belongs to the current character's slot list. + const Character* character = getCurrentCharacter(); + if (character) + { + for (const auto& slot : *character) + { + if (slot.mPath == mLastSavegame) + { + saveName = slot.mProfile.mDescription; + break; + } + } + } + std::vector buttons; buttons.emplace_back("#{Interface:Yes}"); buttons.emplace_back("#{Interface:No}"); @@ -134,7 +148,7 @@ void MWState::StateManager::askLoadRecent() = MWBase::Environment::get().getL10nManager()->getMessage("OMWEngine", "AskLoadLastSave"); std::string_view tag = "%s"; size_t pos = message.find(tag); - message.replace(pos, tag.length(), lastSave.mProfile.mDescription); + message.replace(pos, tag.length(), saveName); MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); mAskLoadRecent = true; } @@ -322,6 +336,7 @@ void MWState::StateManager::saveGame(std::string_view description, const Slot* s throw std::runtime_error("Write operation failed (file stream)"); Settings::saves().mCharacter.set(Files::pathToUnicodeString(slot->mPath.parent_path().filename())); + mLastSavegame = slot->mPath; const auto finish = std::chrono::steady_clock::now(); @@ -561,6 +576,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file if (character) Settings::saves().mCharacter.set(Files::pathToUnicodeString(character->getPath().filename())); + mLastSavegame = filepath; MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWorld()->saveLoaded(); @@ -639,7 +655,15 @@ void MWState::StateManager::quickLoad() void MWState::StateManager::deleteGame(const MWState::Character* character, const MWState::Slot* slot) { + const std::filesystem::path savePath = slot->mPath; mCharacterManager.deleteSlot(character, slot); + if (mLastSavegame == savePath) + { + if (character->begin() != character->end()) + mLastSavegame = character->begin()->mPath; + else + mLastSavegame.clear(); + } } MWState::Character* MWState::StateManager::getCurrentCharacter() @@ -670,9 +694,9 @@ void MWState::StateManager::update(float duration) { mAskLoadRecent = false; // Load last saved game for current character - - MWState::Slot lastSave = *curCharacter->begin(); - loadGame(curCharacter, lastSave.mPath); + // loadGame resets the game state along with mLastSavegame so we want to preserve it + const std::filesystem::path filePath = std::move(mLastSavegame); + loadGame(curCharacter, filePath); } else if (iButton == 1) { diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index c293209f34..a76b829e38 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -17,6 +17,7 @@ namespace MWState State mState; CharacterManager mCharacterManager; double mTimePlayed; + std::filesystem::path mLastSavegame; private: void cleanup(bool force = false);