diff --git a/apps/openmw/mwbase/statemanager.hpp b/apps/openmw/mwbase/statemanager.hpp index 35435e1430..0ea4103163 100644 --- a/apps/openmw/mwbase/statemanager.hpp +++ b/apps/openmw/mwbase/statemanager.hpp @@ -45,7 +45,7 @@ namespace MWBase virtual void askLoadRecent() = 0; virtual void requestNewGame() = 0; - virtual void requestLoad(const std::filesystem::path& filepath) = 0; + virtual void requestLoad(const MWState::Character* character, const std::filesystem::path& filepath) = 0; virtual State getState() const = 0; diff --git a/apps/openmw/mwlua/menuscripts.cpp b/apps/openmw/mwlua/menuscripts.cpp index c9134201d3..fa6be3b7b7 100644 --- a/apps/openmw/mwlua/menuscripts.cpp +++ b/apps/openmw/mwlua/menuscripts.cpp @@ -53,7 +53,7 @@ namespace MWLua const MWState::Slot* slot = findSlot(character, slotName); if (!slot) throw std::runtime_error("Save game slot not found: " + std::string(dir) + "/" + std::string(slotName)); - MWBase::Environment::get().getStateManager()->requestLoad(slot->mPath); + MWBase::Environment::get().getStateManager()->requestLoad(character, slot->mPath); }; api["deleteGame"] = [](std::string_view dir, std::string_view slotName) { diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index e47bf3e3e0..dbb4c46ee3 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -402,7 +402,7 @@ void MWState::StateManager::loadGame(const std::filesystem::path& filepath) { for (const auto& slot : character) { - if (slot.mPath == filepath) + if (std::filesystem::equivalent(slot.mPath, filepath)) { loadGame(&character, slot.mPath); return; @@ -697,7 +697,7 @@ void MWState::StateManager::quickLoad() if (currentCharacter->begin() == currentCharacter->end()) return; // use requestLoad, otherwise we can crash by loading during the wrong part of the frame - requestLoad(currentCharacter->begin()->mPath); + requestLoad(currentCharacter, currentCharacter->begin()->mPath); } } @@ -763,7 +763,14 @@ void MWState::StateManager::update(float duration) if (mLoadRequest) { MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_MainMenu); - loadGame(*mLoadRequest); + const Character* character = mLoadRequest->first; + // The character may have been deleted after the request was made + const bool validCharacter = std::ranges::find_if(mCharacterManager, [=](const Character& c) { + return &c == character; + }) != mCharacterManager.end(); + if (!validCharacter) + character = getCurrentCharacter(); + loadGame(character, mLoadRequest->second); mLoadRequest = std::nullopt; } } diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index b08584a817..4b8a9b04c0 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "../mwbase/statemanager.hpp" @@ -15,7 +16,7 @@ namespace MWState bool mQuitRequest; bool mAskLoadRecent; bool mNewGameRequest = false; - std::optional mLoadRequest; + std::optional> mLoadRequest; State mState; CharacterManager mCharacterManager; double mTimePlayed; @@ -42,7 +43,10 @@ namespace MWState void askLoadRecent() override; void requestNewGame() override { mNewGameRequest = true; } - void requestLoad(const std::filesystem::path& filepath) override { mLoadRequest = filepath; } + void requestLoad(const Character* character, const std::filesystem::path& filepath) override + { + mLoadRequest.emplace(character, filepath); + } State getState() const override;