Merge branch 'characterguide' into 'master'

Compare saves passed on the command line using file equivalence

Closes #8842

See merge request OpenMW/openmw!5034
This commit is contained in:
Alexei Kotov 2025-12-16 12:07:30 +03:00
commit 8b92f68537
4 changed files with 18 additions and 7 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -3,6 +3,7 @@
#include <filesystem>
#include <map>
#include <utility>
#include "../mwbase/statemanager.hpp"
@ -15,7 +16,7 @@ namespace MWState
bool mQuitRequest;
bool mAskLoadRecent;
bool mNewGameRequest = false;
std::optional<std::filesystem::path> mLoadRequest;
std::optional<std::pair<const Character*, std::filesystem::path>> 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;