From d0677c3f07678a5eb351572c4eb9b14b0e1f03e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Wed, 28 Jul 2021 21:31:41 +0200 Subject: [PATCH] Move reference to the right cell according to its geographical position --- apps/openmw/mwrender/objectpaging.cpp | 10 ++++++++++ apps/openmw/mwworld/store.cpp | 12 ++++++++++++ components/esm/loadcell.hpp | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 2cbffbc6eb..aae8f2e4f1 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -434,6 +434,7 @@ namespace MWRender continue; if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue; + if (std::find(cell->mMovedRefsByPos.begin(), cell->mMovedRefsByPos.end(), ref.mRefNum) != cell->mMovedRefsByPos.end()) continue; Misc::StringUtils::lowerCaseInPlace(ref.mRefID); int type = store.findStatic(ref.mRefID); if (!typeFilter(type,size>=2)) continue; @@ -455,6 +456,15 @@ namespace MWRender if (!typeFilter(type,size>=2)) continue; refs[ref.mRefNum] = std::move(ref); } + + for (auto [ref, deleted] : cell->mLeasedRefsByPos) + { + if (deleted) { refs.erase(ref.mRefNum); continue; } + Misc::StringUtils::lowerCaseInPlace(ref.mRefID); + int type = store.findStatic(ref.mRefID); + if (!typeFilter(type, size >= 2)) continue; + refs[ref.mRefNum] = std::move(ref); + } } } diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 125239e9a3..add8b541e0 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -478,6 +478,15 @@ namespace MWWorld // implementation when the oher implementation works as well. while (cell->getNextRef(esm, ref, deleted, cMRef, moved)) { + + auto x = static_cast(std::floor(ref.mPos.pos[0] / float(ESM::Land::REAL_SIZE))); + auto y = static_cast(std::floor(ref.mPos.pos[1] / float(ESM::Land::REAL_SIZE))); + if (x != cell->getGridX() || y != cell->getGridY()) + { + ESM::Cell* cellAlt = const_cast(searchOrCreate(x, y)); + cellAlt->mLeasedRefsByPos.emplace_back(ref, deleted); + cell->mMovedRefsByPos.push_back(ref.mRefNum); + } if (!moved) continue; @@ -678,6 +687,9 @@ namespace MWWorld oldcell->mMovedRefs.push_back(*it); } + oldcell->mLeasedRefsByPos.splice(oldcell->mLeasedRefsByPos.end(), cell.mLeasedRefsByPos); + oldcell->mMovedRefsByPos.splice(oldcell->mMovedRefsByPos.end(), cell.mMovedRefsByPos); + // We don't need to merge mLeasedRefs of cell / oldcell. This list is filled when another cell moves a // reference to this cell, so the list for the new cell should be empty. The list for oldcell, // however, could have leased refs in it and so should be kept. diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 3a8133d881..7770f719e3 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -124,6 +124,11 @@ struct Cell CellRefTracker mLeasedRefs; MovedCellRefTracker mMovedRefs; + // References "adopted" from another cell (i.e. a different cell + // introduced this ref, and it has been moved here as it geographically in this cell) + CellRefTracker mLeasedRefsByPos; + std::list mMovedRefsByPos; + void postLoad(ESMReader &esm); // This method is left in for compatibility with esmtool. Parsing moved references currently requires