From d59a993351ef5b3d9656a65e751458e873f1dae6 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 26 Jul 2023 21:26:37 +0200 Subject: [PATCH] Treat ESM4 exterior cells as exterior Prevent adding exterior cells to WorldModel::mInteriors. Otherwise CellStore might be created twice because it's not present in mExteriors but present in mCells. This happens on teleport to a cell using its name (e.g. --start "AnvilMainGate" flag). --- apps/openmw/mwworld/worldmodel.cpp | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index 20067afefe..10073152d0 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -38,6 +38,19 @@ namespace MWWorld return it->second; } + CellStore* emplaceInteriorCellStore(std::string_view name, ESMStore& store, ESM::ReadersCache& readers, + std::unordered_map& cells) + { + if (const ESM::Cell* cell = store.get().search(name)) + return &emplaceCellStore(cell->mId, *cell, store, readers, cells); + if (const ESM4::Cell* cell = store.get().searchCellName(name); + cell != nullptr && !cell->isExterior()) + { + return &emplaceCellStore(cell->mId, *cell, store, readers, cells); + } + return nullptr; + } + const ESM::Cell* createEsmCell(ESM::ExteriorCellLocation location, ESMStore& store) { ESM::Cell record; @@ -199,12 +212,9 @@ namespace MWWorld if (it == mInteriors.end()) { - if (const ESM::Cell* cell = mStore.get().search(name)) - cellStore = &emplaceCellStore(cell->mId, *cell, mStore, mReaders, mCells); - else if (const ESM4::Cell* cell4 = mStore.get().searchCellName(name)) - cellStore = &emplaceCellStore(cell4->mId, *cell4, mStore, mReaders, mCells); - else - return nullptr; + cellStore = emplaceInteriorCellStore(name, mStore, mReaders, mCells); + if (cellStore == nullptr) + return cellStore; mInteriors.emplace(name, cellStore); } else @@ -309,11 +319,18 @@ namespace MWWorld cell = mStore.get().searchExtByRegion(region->mId); } - if (cell == nullptr) - return nullptr; + if (cell != nullptr) + return &getExterior( + ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId), + forceLoad); - return &getExterior( - ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId), forceLoad); + if (const ESM4::Cell* cell4 = mStore.get().searchCellName(name); + cell4 != nullptr && cell4->isExterior()) + { + return &getExterior(cell4->getExteriorCellLocation(), forceLoad); + } + + return nullptr; } CellStore& WorldModel::getCell(std::string_view name, bool forceLoad) const