From 68be9a95446f04e5db335e37debd5c0204ac9526 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 25 Jul 2024 22:22:23 +0200 Subject: [PATCH] Rebuild ESMStore indices before loading any cell or player state --- apps/openmw/mwworld/worldimp.cpp | 26 +++++++++++++++++++------- apps/openmw/mwworld/worldimp.hpp | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0bd686ce7f..57fe28ed58 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -436,6 +436,7 @@ namespace MWWorld mLevitationEnabled = true; mPlayerTraveling = false; mPlayerInJail = false; + mIdsRebuilt = false; fillGlobalVariables(); } @@ -507,11 +508,13 @@ namespace MWWorld } break; case ESM::REC_PLAY: - // World::write always puts `ESM::REC_PLAY` between ESMStore (that contains dynamic records) - // and WorldModel (that can contain instances of dynamic records). Here we need to rebuild - // ESMStore index in order to be able to lookup dynamic records while loading the player and - // WorldModel. - mStore.rebuildIdsIndex(); + if (!mIdsRebuilt) + { + // FIME this can be removed when MinSupportedSaveGameFormatVersion > 32 + // Older saves have the player before the WorldModel. + mStore.rebuildIdsIndex(); + mIdsRebuilt = true; + } mStore.checkPlayer(); mPlayer->readRecord(reader, type); @@ -523,10 +526,19 @@ namespace MWWorld mWorldScene->preloadCellWithSurroundings(*getPlayerPtr().getCell()); } break; + case ESM::REC_CSTA: + // We need to rebuild the ESMStore index in order to be able to lookup dynamic records while loading the + // WorldModel and, afterwards, the player. + if (!mIdsRebuilt) + { + mStore.rebuildIdsIndex(); + mIdsRebuilt = true; + } + mWorldModel.readRecord(reader, type); + break; default: if (!mStore.readRecord(reader, type) && !mGlobalVariables.readRecord(reader, type) - && !mWeatherManager->readRecord(reader, type) && !mWorldModel.readRecord(reader, type) - && !mProjectileManager->readRecord(reader, type)) + && !mWeatherManager->readRecord(reader, type) && !mProjectileManager->readRecord(reader, type)) { throw std::runtime_error("unknown record in saved game"); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 20e33ad66c..f4c22e94d3 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -134,6 +134,7 @@ namespace MWWorld ///< only holds doors that are currently moving. 1 = opening, 2 = closing uint32_t mRandomSeed{}; + bool mIdsRebuilt{}; // not implemented World(const World&) = delete;