From 531e55e04c5440b23897ec954ecca4e30715645b Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 27 Jan 2023 01:13:17 +0100 Subject: [PATCH] Better handling of the esm3 vs esm4 cell problem Common attribute are in one structure that has two constructors, one for ESM3 vs ESM4 Cell Mood part of MWWorld::Cell --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 3 +- apps/openmw/mwclass/door.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- apps/openmw/mwlua/localscripts.cpp | 2 +- apps/openmw/mwmechanics/aicombat.cpp | 8 +- apps/openmw/mwmechanics/aipackage.cpp | 7 +- apps/openmw/mwmechanics/aiwander.cpp | 16 ++-- apps/openmw/mwmechanics/pathfinding.cpp | 2 +- apps/openmw/mwmechanics/pathgrid.cpp | 4 +- apps/openmw/mwrender/fogmanager.cpp | 9 ++- apps/openmw/mwrender/fogmanager.hpp | 6 +- apps/openmw/mwrender/pathgrid.cpp | 7 +- apps/openmw/mwrender/renderingmanager.cpp | 14 ++-- apps/openmw/mwrender/renderingmanager.hpp | 5 +- apps/openmw/mwsound/soundmanagerimp.cpp | 4 +- apps/openmw/mwworld/cell.cpp | 66 ++++++++++++++++ apps/openmw/mwworld/cell.hpp | 67 ++++++++++++++++ apps/openmw/mwworld/cellstore.cpp | 81 +++++++++----------- apps/openmw/mwworld/cellstore.hpp | 12 +-- apps/openmw/mwworld/scene.cpp | 24 +++--- apps/openmw/mwworld/worldimp.cpp | 31 ++++---- apps/openmw/mwworld/worldimp.hpp | 2 +- apps/openmw/mwworld/worldmodel.cpp | 10 +-- components/detournavigator/navigatorimpl.cpp | 2 +- components/esm/esm3esm4bridge.cpp | 8 -- components/esm/esm3esm4bridge.hpp | 16 ---- components/esm3/loadcell.hpp | 19 ++--- components/esm4/loadcell.cpp | 6 -- components/esm4/loadcell.hpp | 17 +--- components/misc/coordinateconverter.hpp | 8 +- 31 files changed, 268 insertions(+), 194 deletions(-) create mode 100644 apps/openmw/mwworld/cell.cpp create mode 100644 apps/openmw/mwworld/cell.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e9683cc40a..cf9d76be4e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -78,7 +78,7 @@ add_openmw_dir (mwworld actionequip timestamp actionalchemy cellstore actionapply actioneat store esmstore fallback actionrepair actionsoulgem livecellref actiondoor contentloader esmloader actiontrap cellreflist cellref weather projectilemanager - cellpreloader datetimemanager groundcoverstore magiceffects + cellpreloader datetimemanager groundcoverstore magiceffects cell ) add_openmw_dir (mwphysics diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 202af249f5..5219ab72cc 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -94,6 +94,7 @@ namespace MWWorld class TimeStamp; class ESMStore; class RefData; + struct Cell; typedef std::vector> PtrMovementList; } @@ -181,7 +182,7 @@ namespace MWBase /// /// \note If cell==0, the cell the player is currently in will be used instead to /// generate a name. - virtual std::string_view getCellName(const ESM::CellVariant& cell) const = 0; + virtual std::string_view getCellName(const MWWorld::Cell& cell) const = 0; virtual void removeRefScript(MWWorld::RefData* ref) = 0; //< Remove the script attached to ref from mLocalScripts diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 56fbdeabe6..2035ac3507 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -307,7 +307,7 @@ namespace MWClass const osg::Vec2i index = MWWorld::positionToCellIndex(door.mRef.getDoorDest().pos[0], door.mRef.getDoorDest().pos[1]); const ESM::Cell* cell = world->getStore().get().search(index.x(), index.y()); - dest = world->getCellName(ESM::CellVariant(cell)); + dest = world->getCellName(MWWorld::Cell(cell)); } return "#{sCell=" + std::string{ dest } + "}"; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b31b0adaf2..e22d1302b1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -954,7 +954,7 @@ namespace MWGui mMap->setCellName(name); mHud->setCellName(name); - auto cellCommon = cell->getCellVariant().getCommon(); + auto cellCommon = cell->getCell(); if (cellCommon->isExterior()) { diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 6cdfff0fea..88c824cc59 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -176,7 +176,7 @@ namespace MWLua // TODO: change AiEscort implementation to accept ptr instead of a non-unique refId. const ESM::RefId& refId = target.ptr().getCellRef().getRefId(); int gameHoursDuration = static_cast(std::ceil(duration / 3600.0)); - const ESM::CellCommon* esmCell = cell.mStore->getCell(); + auto* esmCell = cell.mStore->getCell(); if (esmCell->isExterior()) ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), false), ptr); else diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index bf5f7cebc0..e558eedc66 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -357,13 +357,13 @@ namespace MWMechanics case AiCombatStorage::FleeState_Idle: { float triggerDist = getMaxAttackDistance(target); - auto cellVariant = storage.mCell->getCellVariant(); - if (!cellVariant.isEsm4() && storage.mLOS + auto cellVariant = storage.mCell->getCell(); + if (!cellVariant->isEsm4() && storage.mLOS && (triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist)) { const ESM::Pathgrid* pathgrid = MWBase::Environment::get().getWorld()->getStore().get().search( - cellVariant.getEsm3()); + cellVariant->getEsm3()); bool runFallback = true; @@ -371,7 +371,7 @@ namespace MWMechanics && !actor.getClass().isPureWaterCreature(actor)) { ESM::Pathgrid::PointList points; - Misc::CoordinateConverter coords(storage.mCell->getCell()); + Misc::CoordinateConverter coords(*storage.mCell->getCell()); osg::Vec3f localPos = actor.getRefData().getPosition().asVec3(); coords.toLocal(localPos); diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index ac96765a3a..5abc99dac9 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -411,11 +411,14 @@ bool MWMechanics::AiPackage::doesPathNeedRecalc(const osg::Vec3f& newDest, const bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position) { - const ESM::Cell* playerCell(&getPlayer().getCell()->getCellVariant().getEsm3()); + if (getPlayer().getCell()->getCell()->isEsm4()) + return false; + + const ESM::Cell* playerCell(&getPlayer().getCell()->getCell()->getEsm3()); if (playerCell->isExterior()) { // get actor's distance from origin of center cell - Misc::CoordinateConverter(playerCell).toLocal(position); + Misc::CoordinateConverter(ESM::CellVariant(playerCell)).toLocal(position); // currently assumes 3 x 3 grid for exterior cells, with player at center cell. // AI shuts down actors before they reach edges of 3 x 3 grid. diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 1ff9cf0c54..3631cfb776 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -271,9 +271,9 @@ namespace MWMechanics } // Initialization to discover & store allowed node points for this actor. - if (!actor.getCell()->getCellVariant().isEsm4() && storage.mPopulateAvailableNodes) + if (!actor.getCell()->getCell()->isEsm4() && storage.mPopulateAvailableNodes) { - getAllowedNodes(actor, &actor.getCell()->getCellVariant().getEsm3(), storage); + getAllowedNodes(actor, &actor.getCell()->getCell()->getEsm3(), storage); } auto& prng = MWBase::Environment::get().getWorld()->getPrng(); @@ -721,8 +721,8 @@ namespace MWMechanics return; AiWanderStorage& storage = state.get(); - if (!actor.getCell()->getCellVariant().isEsm4() && storage.mPopulateAvailableNodes) - getAllowedNodes(actor, &actor.getCell()->getCellVariant().getEsm3(), storage); + if (!actor.getCell()->getCell()->isEsm4() && storage.mPopulateAvailableNodes) + getAllowedNodes(actor, &actor.getCell()->getCell()->getEsm3(), storage); if (storage.mAllowedNodes.empty()) return; @@ -730,7 +730,7 @@ namespace MWMechanics auto& prng = MWBase::Environment::get().getWorld()->getPrng(); int index = Misc::Rng::rollDice(storage.mAllowedNodes.size(), prng); ESM::Pathgrid::Point worldDest = storage.mAllowedNodes[index]; - auto converter = Misc::CoordinateConverter(actor.getCell()->getCell()); + auto converter = Misc::CoordinateConverter(*actor.getCell()->getCell()); ESM::Pathgrid::Point dest = converter.toLocalPoint(worldDest); bool isPathGridOccupied = MWBase::Environment::get().getMechanicsManager()->isAnyActorInRange( @@ -800,9 +800,9 @@ namespace MWMechanics void AiWander::getNeighbouringNodes( ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points) { - if (currentCell->getCellVariant().isEsm4()) + if (currentCell->getCell()->isEsm4()) return; - auto cell3 = currentCell->getCellVariant().getEsm3(); + auto cell3 = currentCell->getCell()->getEsm3(); const ESM::Pathgrid* pathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(cell3); @@ -839,7 +839,7 @@ namespace MWMechanics if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor)) { // get NPC's position in local (i.e. cell) coordinates - auto converter = Misc::CoordinateConverter(cell); + auto converter = Misc::CoordinateConverter(ESM::CellVariant(cell)); const osg::Vec3f npcPos = converter.toLocalVec3(mInitialActorPosition); // Find closest pathgrid point diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 6e9ea28f93..0180323ddd 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -196,7 +196,7 @@ namespace MWMechanics return; // NOTE: getClosestPoint expects local coordinates - Misc::CoordinateConverter converter(mCell->getCell()); + Misc::CoordinateConverter converter(*mCell->getCell()); // NOTE: It is possible that getClosestPoint returns a pathgrind point index // that is unreachable in some situations. e.g. actor is standing diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index 282ac4e381..ad1be1a94d 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -98,13 +98,13 @@ namespace MWMechanics */ bool PathgridGraph::load(const MWWorld::CellStore* cell) { - if (!cell || !cell->getCellVariant().isValid()) + if (!cell) return false; if (mIsGraphConstructed) return true; - mCell = cell->getCellVariant().isEsm4() ? nullptr : &cell->getCellVariant().getEsm3(); + mCell = cell->getCell()->isEsm4() ? nullptr : &cell->getCell()->getEsm3(); if (!mCell) return false; mPathgrid = MWBase::Environment::get().getWorld()->getStore().get().search(*mCell); diff --git a/apps/openmw/mwrender/fogmanager.cpp b/apps/openmw/mwrender/fogmanager.cpp index 8752196dc6..bb4abc3fa9 100644 --- a/apps/openmw/mwrender/fogmanager.cpp +++ b/apps/openmw/mwrender/fogmanager.cpp @@ -9,6 +9,8 @@ #include #include +#include + namespace { float DLLandFogStart; @@ -40,12 +42,11 @@ namespace MWRender DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog"); } - void FogManager::configure(float viewDistance, const ESM::CellVariant& cell) + void FogManager::configure(float viewDistance, const MWWorld::Cell& cell) { - osg::Vec4f color - = SceneUtil::colourFromRGB(cell.isEsm4() ? cell.getEsm4().mLighting.fogColor : cell.getEsm3().mAmbi.mFog); + osg::Vec4f color = SceneUtil::colourFromRGB(cell.getMood().mFogColor); - const float fogDensity = !cell.isEsm4() ? cell.getEsm3().mAmbi.mFogDensity : cell.getEsm4().mLighting.fogPower; + const float fogDensity = cell.getMood().mFogDensity; if (mDistantFog) { float density = std::max(0.2f, fogDensity); diff --git a/apps/openmw/mwrender/fogmanager.hpp b/apps/openmw/mwrender/fogmanager.hpp index a1759d5963..258371bc9e 100644 --- a/apps/openmw/mwrender/fogmanager.hpp +++ b/apps/openmw/mwrender/fogmanager.hpp @@ -3,9 +3,9 @@ #include -namespace ESM +namespace MWWorld { - struct CellVariant; + struct Cell; } namespace MWRender @@ -15,7 +15,7 @@ namespace MWRender public: FogManager(); - void configure(float viewDistance, const ESM::CellVariant& cell); + void configure(float viewDistance, const MWWorld::Cell& cell); void configure(float viewDistance, float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& color); diff --git a/apps/openmw/mwrender/pathgrid.cpp b/apps/openmw/mwrender/pathgrid.cpp index f449861a07..8e4db52726 100644 --- a/apps/openmw/mwrender/pathgrid.cpp +++ b/apps/openmw/mwrender/pathgrid.cpp @@ -102,15 +102,14 @@ namespace MWRender void Pathgrid::enableCellPathgrid(const MWWorld::CellStore* store) { MWBase::World* world = MWBase::Environment::get().getWorld(); - if (store->getCellVariant().isEsm4()) + if (store->getCell()->isEsm4()) return; - const ESM::Pathgrid* pathgrid - = world->getStore().get().search(store->getCellVariant().getEsm3()); + const ESM::Pathgrid* pathgrid = world->getStore().get().search(store->getCell()->getEsm3()); if (!pathgrid) return; osg::Vec3f cellPathGridPos(0, 0, 0); - Misc::CoordinateConverter(store->getCell()).toWorld(cellPathGridPos); + Misc::CoordinateConverter(*store->getCell()).toWorld(cellPathGridPos); osg::ref_ptr cellPathGrid = new osg::PositionAttitudeTransform; cellPathGrid->setPosition(cellPathGridPos); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ef09d38df0..c1aa3055a6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -740,15 +740,14 @@ namespace MWRender mSky->setMoonColour(red); } - void RenderingManager::configureAmbient(const ESM::CellVariant& cell) + void RenderingManager::configureAmbient(const MWWorld::Cell& cell) { - bool isInterior = !cell.getCommon()->isExterior() && !cell.getCommon()->isQuasiExterior(); + bool isInterior = !cell.isExterior() && !cell.isQuasiExterior(); bool needsAdjusting = false; if (mResourceSystem->getSceneManager()->getLightingMethod() != SceneUtil::LightingMethod::FFP) needsAdjusting = isInterior; - osg::Vec4f ambient = SceneUtil::colourFromRGB( - cell.isEsm4() ? cell.getEsm4().mLighting.ambient : cell.getEsm3().mAmbi.mAmbient); + osg::Vec4f ambient = SceneUtil::colourFromRGB(cell.getMood().mAmbiantColor); if (needsAdjusting) { @@ -772,8 +771,7 @@ namespace MWRender setAmbientColour(ambient); - osg::Vec4f diffuse = SceneUtil::colourFromRGB( - !cell.isEsm4() ? cell.getEsm3().mAmbi.mSunlight : cell.getEsm4().mLighting.directional); + osg::Vec4f diffuse = SceneUtil::colourFromRGB(cell.getMood().mDirectionalColor); setSunColour(diffuse, diffuse, 1.f); @@ -894,7 +892,7 @@ namespace MWRender return false; } - void RenderingManager::configureFog(const ESM::CellVariant& cell) + void RenderingManager::configureFog(const MWWorld::Cell& cell) { mFog->configure(mViewDistance, cell); } @@ -1428,7 +1426,7 @@ namespace MWRender mMinimumAmbientLuminance = std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f); if (MWMechanics::getPlayer().isInCell()) - configureAmbient(MWMechanics::getPlayer().getCell()->getCellVariant()); + configureAmbient(*MWMechanics::getPlayer().getCell()->getCell()); } else if (it->first == "Shaders" && (it->second == "light bounds multiplier" || it->second == "maximum light distance" diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index e4791df71a..70b40f6f67 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -74,6 +74,7 @@ namespace DetourNavigator namespace MWWorld { class GroundcoverStore; + struct Cell; } namespace Debug @@ -141,8 +142,8 @@ namespace MWRender void setSunColour(const osg::Vec4f& diffuse, const osg::Vec4f& specular, float sunVis); void setNight(bool isNight) { mNight = isNight; } - void configureAmbient(const ESM::CellVariant& cell); - void configureFog(const ESM::CellVariant& cell); + void configureAmbient(const MWWorld::Cell& cell); + void configureFog(const MWWorld::Cell& cell); void configureFog( float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour); diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index a54b3e40d7..3ef3a19353 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -781,10 +781,10 @@ namespace MWSound { MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); - if (player.getCell()->getCellVariant().isEsm4()) + if (player.getCell()->getCell()->isEsm4()) return; - const ESM::Cell* curcell = &player.getCell()->getCellVariant().getEsm3(); + const ESM::Cell* curcell = &player.getCell()->getCell()->getEsm3(); const auto update = mWaterSoundUpdater.update(player, *world); WaterSoundAction action; diff --git a/apps/openmw/mwworld/cell.cpp b/apps/openmw/mwworld/cell.cpp new file mode 100644 index 0000000000..6fdc5c4041 --- /dev/null +++ b/apps/openmw/mwworld/cell.cpp @@ -0,0 +1,66 @@ +#include "cell.hpp" + +#include +#include +#include + +namespace MWWorld +{ + Cell::Cell(const ESM4::Cell* cell) + : ESM::CellVariant(cell) + { + assert(cell != nullptr); + + mNameID = cell->mEditorId; + mDisplayname = cell->mFullName; + mGridPos.x() = cell->mX; + mGridPos.y() = cell->mY; + + mRegion = ESM::RefId::sEmpty; // Unimplemented for now + + mFlags.hasWater = (cell->mCellFlags & ESM4::CELL_HasWater) != 0; + mFlags.isExterior = !(cell->mCellFlags & ESM4::CELL_Interior); + mFlags.isQuasiExterior = (cell->mCellFlags & ESM4::CELL_QuasiExt) != 0; + mFlags.noSleep = false; // No such notion in ESM4 + + mCellId.mWorldspace = Misc::StringUtils::lowerCase(cell->mEditorId); + mCellId.mWorld = ESM::RefId::sEmpty; + mCellId.mIndex.mX = cell->getGridX(); + mCellId.mIndex.mX = cell->getGridY(); + mCellId.mPaged = isExterior(); + + mMood.mAmbiantColor = cell->mLighting.ambient; + mMood.mFogColor = cell->mLighting.fogColor; + mMood.mDirectionalColor = cell->mLighting.directional; + mMood.mFogDensity = cell->mLighting.fogPower; + } + + Cell::Cell(const ESM::Cell* cell) + : ESM::CellVariant(cell) + { + assert(cell != nullptr); + mNameID = cell->mName; + mDisplayname = cell->mName; + mGridPos.x() = cell->getGridX(); + mGridPos.y() = cell->getGridY(); + + mRegion = ESM::RefId::sEmpty; // Unimplemented for now + + mFlags.hasWater = (cell->mData.mFlags & ESM::Cell::HasWater) != 0; + mFlags.isExterior = !(cell->mData.mFlags & ESM::Cell::Interior); + mFlags.isQuasiExterior = (cell->mData.mFlags & ESM::Cell::QuasiEx) != 0; + mFlags.noSleep = (cell->mData.mFlags & ESM::Cell::NoSleep) != 0; + + mCellId = cell->getCellId(); + + mMood.mAmbiantColor = cell->mAmbi.mAmbient; + mMood.mFogColor = cell->mAmbi.mFog; + mMood.mDirectionalColor = cell->mAmbi.mSunlight; + mMood.mFogDensity = cell->mAmbi.mFogDensity; + } + + std::string Cell::getDescription() const + { + return isEsm4() ? mNameID : getEsm3().getDescription(); + } +} diff --git a/apps/openmw/mwworld/cell.hpp b/apps/openmw/mwworld/cell.hpp new file mode 100644 index 0000000000..6761485f29 --- /dev/null +++ b/apps/openmw/mwworld/cell.hpp @@ -0,0 +1,67 @@ +#ifndef OPENW_MWORLD_CELL +#define OPENW_MWORLD_CELL + +#include +#include +#include + +namespace ESM +{ + struct Cell; + struct CellId; +} + +namespace ESM4 +{ + struct Cell; +} + +namespace MWWorld +{ + struct Cell : public ESM::CellVariant + { + + struct MoodData + { + uint32_t mAmbiantColor; + uint32_t mDirectionalColor; + uint32_t mFogColor; + float mFogDensity; + }; + + public: + explicit Cell(const ESM4::Cell* cell); + explicit Cell(const ESM::Cell* cell); + + int getGridX() const { return mGridPos.x(); } + int getGridY() const { return mGridPos.y(); } + bool isExterior() const { return mFlags.isExterior; } + bool isQuasiExterior() const { return mFlags.isQuasiExterior; } + bool hasWater() const { return mFlags.hasWater; } + bool noSleep() const { return mFlags.noSleep; } + const ESM::CellId& getCellId() const { return mCellId; }; + const ESM::RefId& getRegion() const { return mRegion; } + std::string_view getEditorName() const { return mNameID; } + std::string getDescription() const; + const MoodData& getMood() const { return mMood; } + + private: + struct + { + uint8_t isExterior : 1; + uint8_t isQuasiExterior : 1; + uint8_t hasWater : 1; + uint8_t noSleep : 1; + uint8_t _free : 4; + } mFlags; + + osg::Vec2i mGridPos; + std::string mDisplayname; // How the game displays it + std::string mNameID; // The name that will be used by the script and console commands + ESM::RefId mRegion; + ESM::CellId mCellId; + MoodData mMood; + }; +} + +#endif diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 29c05e72b5..f820d551ab 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -536,10 +536,10 @@ namespace MWWorld return false; } - CellStore::CellStore(ESM::CellVariant cell, const MWWorld::ESMStore& esmStore, ESM::ReadersCache& readers) + CellStore::CellStore(MWWorld::Cell cell, const MWWorld::ESMStore& esmStore, ESM::ReadersCache& readers) : mStore(esmStore) , mReaders(readers) - , mCellVariant(cell) + , mCellVariant(std::move(cell)) , mState(State_Unloaded) , mHasState(false) , mLastRespawn(0, 0) @@ -547,36 +547,17 @@ namespace MWWorld , mRechargingItemsUpToDate(false) { - mCell = mCellVariant.isEsm4() ? nullptr : &mCellVariant.getEsm3(); - std::apply([this](auto&... x) { (CellStoreImp::assignStoreToIndex(*this, x), ...); }, mCellStoreImp->mRefLists); - if (mCell) - mWaterLevel = mCell->mWater; + if (!mCellVariant.isEsm4()) + mWaterLevel = mCellVariant.getEsm3().mWater; } CellStore::~CellStore() = default; CellStore::CellStore(CellStore&&) = default; - const ESM::CellCommon* CellStore::getCell() const + const MWWorld::Cell* CellStore::getCell() const { - return mCellVariant.getCommon(); - } - - ESM::CellVariant CellStore::getCellVariant() const - { - return mCellVariant; - } - - std::string_view CellStore::getEditorName() const - { - if (mCellVariant.isEsm4()) - { - return mCellVariant.getEsm4().mEditorId; - } - else - { - return mCellVariant.getEsm3().mName; - } + return &mCellVariant; } CellStore::State CellStore::getState() const @@ -732,20 +713,24 @@ namespace MWWorld void CellStore::listRefs() { - assert(mCell); - if (mCell->mContextList.empty()) + if (mCellVariant.isEsm4()) + return; + + auto cell3 = mCellVariant.getEsm3(); + + if (cell3.mContextList.empty()) return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. - for (size_t i = 0; i < mCell->mContextList.size(); i++) + for (size_t i = 0; i < cell3.mContextList.size(); i++) { try { // Reopen the ESM reader and seek to the right position. - const std::size_t index = static_cast(mCell->mContextList[i].index); + const std::size_t index = static_cast(cell3.mContextList[i].index); const ESM::ReadersCache::BusyItem reader = mReaders.get(index); - mCell->restore(*reader, i); + cell3.restore(*reader, i); ESM::CellRef ref; @@ -761,8 +746,8 @@ namespace MWWorld // Don't list reference if it was moved to a different cell. ESM::MovedCellRefTracker::const_iterator iter - = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum); - if (iter != mCell->mMovedRefs.end()) + = std::find(cell3.mMovedRefs.begin(), cell3.mMovedRefs.end(), ref.mRefNum); + if (iter != cell3.mMovedRefs.end()) { continue; } @@ -778,7 +763,7 @@ namespace MWWorld } // List moved references, from separately tracked list. - for (const auto& [ref, deleted] : mCell->mLeasedRefs) + for (const auto& [ref, deleted] : cell3.mLeasedRefs) { if (!deleted) mIds.push_back(ref.mRefID); @@ -809,18 +794,19 @@ namespace MWWorld } else { - if (mCell->mContextList.empty()) + auto cell3 = mCellVariant.getEsm3(); + if (cell3.mContextList.empty()) return; // this is a dynamically generated cell -> skipping. // Load references from all plugins that do something with this cell. - for (size_t i = 0; i < mCell->mContextList.size(); i++) + for (size_t i = 0; i < cell3.mContextList.size(); i++) { try { // Reopen the ESM reader and seek to the right position. - const std::size_t index = static_cast(mCell->mContextList[i].index); + const std::size_t index = static_cast(cell3.mContextList[i].index); const ESM::ReadersCache::BusyItem reader = mReaders.get(index); - mCell->restore(*reader, i); + cell3.restore(*reader, i); ESM::CellRef ref; // Get each reference in turn @@ -835,8 +821,8 @@ namespace MWWorld // Don't load reference if it was moved to a different cell. ESM::MovedCellRefTracker::const_iterator iter - = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum); - if (iter != mCell->mMovedRefs.end()) + = std::find(cell3.mMovedRefs.begin(), cell3.mMovedRefs.end(), ref.mRefNum); + if (iter != cell3.mMovedRefs.end()) { continue; } @@ -851,7 +837,7 @@ namespace MWWorld } } // Load moved references, from separately tracked list. - for (const auto& leasedRef : mCell->mLeasedRefs) + for (const auto& leasedRef : cell3.mLeasedRefs) { ESM::CellRef& ref = const_cast(leasedRef.first); bool deleted = leasedRef.second; @@ -865,12 +851,12 @@ namespace MWWorld bool CellStore::isExterior() const { - return mCellVariant.getCommon()->isExterior(); + return mCellVariant.isExterior(); } bool CellStore::isQuasiExterior() const { - return mCellVariant.getCommon()->isExterior(); + return mCellVariant.isQuasiExterior(); } Ptr CellStore::searchInContainer(const ESM::RefId& id) @@ -954,9 +940,12 @@ namespace MWWorld void CellStore::loadState(const ESM::CellState& state) { + if (mCellVariant.isEsm4()) + return; + mHasState = true; - if (mCell->mData.mFlags & ESM::Cell::Interior && mCell->mData.mFlags & ESM::Cell::HasWater) + if (!mCellVariant.isExterior() && mCellVariant.hasWater()) mWaterLevel = state.mWaterLevel; mLastRespawn = MWWorld::TimeStamp(state.mLastRespawn); @@ -964,9 +953,9 @@ namespace MWWorld void CellStore::saveState(ESM::CellState& state) const { - state.mId = mCell->getCellId(); + state.mId = mCellVariant.getCellId(); - if (mCell->mData.mFlags & ESM::Cell::Interior && mCell->mData.mFlags & ESM::Cell::HasWater) + if (!mCellVariant.isExterior() && mCellVariant.hasWater()) state.mWaterLevel = mWaterLevel; state.mHasFogOfWar = (mFogState.get() ? 1 : 0); @@ -977,7 +966,7 @@ namespace MWWorld { if (mFogState.get()) { - mFogState->save(writer, mCell->mData.mFlags & ESM::Cell::Interior); + mFogState->save(writer, !mCellVariant.isExterior()); } } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 736470f15b..eaeeec42d3 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -12,10 +12,10 @@ #include #include +#include "cell.hpp" #include "cellreflist.hpp" #include "livecellref.hpp" -#include #include #include #include @@ -98,8 +98,7 @@ namespace MWWorld // Note this is nullptr until the cell is explored to save some memory std::unique_ptr mFogState; - const ESM::Cell* mCell; - ESM::CellVariant mCellVariant; + MWWorld::Cell mCellVariant; State mState; bool mHasState; std::vector mIds; @@ -194,14 +193,11 @@ namespace MWWorld } /// @param readerList The readers to use for loading of the cell on-demand. - CellStore(ESM::CellVariant cell, const MWWorld::ESMStore& store, ESM::ReadersCache& readers); + CellStore(MWWorld::Cell cell, const MWWorld::ESMStore& store, ESM::ReadersCache& readers); CellStore(CellStore&&); ~CellStore(); - const ESM::CellCommon* getCell() const; - ESM::CellVariant getCellVariant() const; - - std::string_view getEditorName() const; + const MWWorld::Cell* getCell() const; State getState() const; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 0c5f72b107..089428fd26 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -355,9 +355,9 @@ namespace MWWorld if (cell->getCell()->hasWater()) mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); - if (!cell->getCellVariant().isEsm4()) + if (!cell->getCell()->isEsm4()) { - if (const auto pathgrid = mWorld.getStore().get().search(cell->getCellVariant().getEsm3())) + if (const auto pathgrid = mWorld.getStore().get().search(cell->getCell()->getEsm3())) mNavigator.removePathgrid(*pathgrid); } @@ -383,11 +383,11 @@ namespace MWWorld assert(mActiveCells.find(cell) == mActiveCells.end()); mActiveCells.insert(cell); - Log(Debug::Info) << "Loading cell " << cell->getEditorName(); + Log(Debug::Info) << "Loading cell " << cell->getCell()->getEditorName(); - const int cellX = cell->getCellVariant().getCommon()->getGridX(); - const int cellY = cell->getCellVariant().getCommon()->getGridY(); - auto cellVariant = cell->getCellVariant(); + const int cellX = cell->getCell()->getGridX(); + const int cellY = cell->getCell()->getGridY(); + auto cellVariant = *cell->getCell(); if (!cellVariant.isEsm4()) { auto cell3 = cellVariant.getEsm3(); @@ -450,7 +450,7 @@ namespace MWWorld mRendering.addCell(cell); MWBase::Environment::get().getWindowManager()->addCell(cell); - bool waterEnabled = (!cellVariant.isEsm4()) && (cellVariant.getEsm3().hasWater() || cell->isExterior()); + bool waterEnabled = (!cellVariant.isEsm4()) && (cellVariant.hasWater() || cell->isExterior()); float waterLevel = cell->getWaterLevel(); mRendering.setWaterEnabled(waterEnabled); if (waterEnabled) @@ -473,7 +473,7 @@ namespace MWWorld else mPhysics->disableWater(); - if (!cell->isExterior() && !cellVariant.getCommon()->isQuasiExterior()) + if (!cell->isExterior() && !cellVariant.isQuasiExterior()) mRendering.configureAmbient(cellVariant); mPreloader->notifyLoaded(cell); @@ -887,7 +887,8 @@ namespace MWWorld loadingListener->setProgressRange(cell->count()); - mNavigator.setWorldspace(Misc::StringUtils::lowerCase(cell->getEditorName()), navigatorUpdateGuard.get()); + mNavigator.setWorldspace( + Misc::StringUtils::lowerCase(cell->getCell()->getEditorName()), navigatorUpdateGuard.get()); mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get()); // Load cell. @@ -899,7 +900,7 @@ namespace MWWorld changePlayerCell(cell, position, adjustPlayerPos); // adjust fog - mRendering.configureFog(mCurrentCell->getCellVariant()); + mRendering.configureFog(*mCurrentCell->getCell()); // Sky system mWorld.adjustSky(); @@ -914,8 +915,7 @@ namespace MWWorld MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - MWBase::Environment::get().getWorld()->getPostProcessor()->setExteriorFlag( - cell->getCellVariant().getCommon()->isQuasiExterior()); + MWBase::Environment::get().getWorld()->getPostProcessor()->setExteriorFlag(cell->getCell()->isQuasiExterior()); } void Scene::changeToExteriorCell(const ESM::Position& position, bool adjustPlayerPos, bool changeEvent) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 5bee6c554a..c7ec164348 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -634,22 +634,18 @@ namespace MWWorld { if (!cell) cell = mWorldScene->getCurrentCell(); - return getCellName(cell->getCellVariant()); + return getCellName(*cell->getCell()); } - std::string_view World::getCellName(const ESM::CellVariant& cell) const + std::string_view World::getCellName(const MWWorld::Cell& cell) const { - auto cellCommon = cell.getCommon(); - if (cellCommon) - { - if (!cellCommon->isExterior() || !cellCommon->getEditorName().empty()) - return cellCommon->getEditorName(); + if (!cell.isExterior() || !cell.getEditorName().empty()) + return cell.getEditorName(); - if (!cell.isEsm4()) - { - const ESM::Region* region = mStore.get().search(cell.getEsm3().mRegion); - return region->mName; - } + if (!cell.isEsm4()) + { + const ESM::Region* region = mStore.get().search(cell.getEsm3().mRegion); + return region->mName; } return mStore.get().find("sDefaultCellname")->mValue.getString(); @@ -2313,7 +2309,7 @@ namespace MWWorld if (!cell) return false; - if (!(cell->getCellVariant().getCommon()->hasWater())) + if (!(cell->getCell()->hasWater())) { return false; } @@ -2840,7 +2836,7 @@ namespace MWWorld { pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; - const ESM::CellCommon* ext = nullptr; + const MWWorld::Cell* ext = nullptr; try { ext = mWorldModel.getCell(nameId)->getCell(); @@ -3247,9 +3243,8 @@ namespace MWWorld } else { - auto cellVariant = cell->getCellVariant(); - uint32_t ambient = !cellVariant.isEsm4() ? cellVariant.getEsm3().mAmbi.mAmbient - : cellVariant.getEsm4().mLighting.ambient; + auto cellVariant = *cell->getCell(); + uint32_t ambient = cellVariant.getMood().mAmbiantColor; int ambientTotal = (ambient & 0xff) + ((ambient >> 8) & 0xff) + ((ambient >> 16) & 0xff); return !cell->getCell()->noSleep() && ambientTotal <= 201; } @@ -3275,7 +3270,7 @@ namespace MWWorld std::set checkedCells; std::set currentCells; std::set nextCells; - nextCells.insert(cell->getEditorName()); + nextCells.insert(cell->getCell()->getEditorName()); while (!nextCells.empty()) { diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 809daf95d8..0d3a45e656 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -269,7 +269,7 @@ namespace MWWorld /// /// \note If cell==0, the cell the player is currently in will be used instead to /// generate a name. - std::string_view getCellName(const ESM::CellVariant& cell) const override; + std::string_view getCellName(const MWWorld::Cell& cell) const override; void removeRefScript(MWWorld::RefData* ref) override; //< Remove the script attached to ref from mLocalScripts diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index 1dc935af3b..7b89e12ff4 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -67,7 +67,7 @@ MWWorld::CellStore* MWWorld::WorldModel::getCellStore(const ESM::Cell* cell) auto result = mInteriors.find(cell->mName); if (result == mInteriors.end()) - result = mInteriors.emplace(cell->mName, CellStore(ESM::CellVariant(cell), mStore, mReaders)).first; + result = mInteriors.emplace(cell->mName, CellStore(MWWorld::Cell(cell), mStore, mReaders)).first; return &result->second; } @@ -79,7 +79,7 @@ MWWorld::CellStore* MWWorld::WorldModel::getCellStore(const ESM::Cell* cell) if (result == mExteriors.end()) result = mExteriors .emplace(std::make_pair(cell->getGridX(), cell->getGridY()), - CellStore(ESM::CellVariant(cell), mStore, mReaders)) + CellStore(MWWorld::Cell(cell), mStore, mReaders)) .first; return &result->second; @@ -186,7 +186,7 @@ MWWorld::CellStore* MWWorld::WorldModel::getExterior(int x, int y) cell = MWBase::Environment::get().getWorld()->createRecord(record); } - result = mExteriors.emplace(std::make_pair(x, y), CellStore(ESM::CellVariant(cell), mStore, mReaders)).first; + result = mExteriors.emplace(std::make_pair(x, y), CellStore(MWWorld::Cell(cell), mStore, mReaders)).first; } if (result->second.getState() != CellStore::State_Loaded) @@ -208,11 +208,11 @@ MWWorld::CellStore* MWWorld::WorldModel::getInterior(std::string_view name) if (!cell4) { const ESM::Cell* cell = mStore.get().find(name); - result = mInteriors.emplace(name, CellStore(ESM::CellVariant(cell), mStore, mReaders)).first; + result = mInteriors.emplace(name, CellStore(MWWorld::Cell(cell), mStore, mReaders)).first; } else { - result = mInteriors.emplace(name, CellStore(ESM::CellVariant(cell4), mStore, mReaders)).first; + result = mInteriors.emplace(name, CellStore(MWWorld::Cell(cell4), mStore, mReaders)).first; } } diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 0978f69c24..542818a151 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -134,7 +134,7 @@ namespace DetourNavigator void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) { - Misc::CoordinateConverter converter(&cell); + Misc::CoordinateConverter converter = Misc::CoordinateConverter(ESM::CellVariant(&cell)); for (const auto& edge : pathgrid.mEdges) { const auto src = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV0])); diff --git a/components/esm/esm3esm4bridge.cpp b/components/esm/esm3esm4bridge.cpp index ec76b19fc6..f804f437bc 100644 --- a/components/esm/esm3esm4bridge.cpp +++ b/components/esm/esm3esm4bridge.cpp @@ -4,14 +4,6 @@ namespace ESM { - const ESM::CellCommon* CellVariant::getCommon() const - { - if (isEsm4()) - return &getEsm4(); - else - return &getEsm3(); - } - const ESM4::Cell& CellVariant::getEsm4() const { auto cell4 = std::get<0>(mVariant); diff --git a/components/esm/esm3esm4bridge.hpp b/components/esm/esm3esm4bridge.hpp index 4c6eaf5875..6152b0e610 100644 --- a/components/esm/esm3esm4bridge.hpp +++ b/components/esm/esm3esm4bridge.hpp @@ -16,20 +16,6 @@ namespace ESM struct Cell; struct CellId; struct RefId; - // Common interface for esm3 and esm4 cells - struct CellCommon - { - virtual int getGridX() const = 0; - virtual int getGridY() const = 0; - virtual bool isExterior() const = 0; - virtual bool isQuasiExterior() const = 0; - virtual bool hasWater() const = 0; - virtual bool noSleep() const { return false; } - virtual const ESM::CellId& getCellId() const = 0; - virtual const ESM::RefId& getRegion() const = 0; - virtual std::string_view getEditorName() const = 0; - virtual std::string getDescription() const = 0; - }; struct CellVariant { @@ -61,8 +47,6 @@ namespace ESM const ESM4::Cell& getEsm4() const; const ESM::Cell& getEsm3() const; - - const ESM::CellCommon* getCommon() const; }; } diff --git a/components/esm3/loadcell.hpp b/components/esm3/loadcell.hpp index c957dc493a..8bd707d825 100644 --- a/components/esm3/loadcell.hpp +++ b/components/esm3/loadcell.hpp @@ -8,7 +8,6 @@ #include "cellid.hpp" #include "cellref.hpp" #include "components/esm/defs.hpp" -#include "components/esm/esm3esm4bridge.hpp" #include "components/esm/esmcommon.hpp" #include "components/esm/refid.hpp" @@ -66,7 +65,7 @@ namespace ESM (using ESMReader::getContext()) and jumping back into place whenever we need to load a given cell. */ - struct Cell : public CellCommon + struct Cell { constexpr static RecNameInts sRecordId = REC_CELL; @@ -151,14 +150,11 @@ namespace ESM void save(ESMWriter& esm, bool isDeleted = false) const; void saveTempMarker(ESMWriter& esm, int tempCount) const; - bool isExterior() const override { return !(mData.mFlags & Interior); } - bool isQuasiExterior() const override { return mData.mFlags & QuasiEx; } + bool isExterior() const { return !(mData.mFlags & Interior); } - int getGridX() const override { return mData.mX; } + int getGridX() const { return mData.mX; } - int getGridY() const override { return mData.mY; } - - bool hasWater() const override { return ((mData.mFlags & HasWater) != 0) || isExterior(); } + int getGridY() const { return mData.mY; } bool hasAmbient() const { return mHasAmbi; } @@ -171,7 +167,7 @@ namespace ESM // exactly. void restore(ESMReader& esm, int iCtx) const; - std::string getDescription() const override; + std::string getDescription() const; ///< Return a short string describing the cell (mostly used for debugging/logging purpose) /* Get the next reference in this cell, if any. Returns false when @@ -193,10 +189,7 @@ namespace ESM void blank(); ///< Set record to default state (does not touch the ID/index). - const CellId& getCellId() const override; - const ESM::RefId& getRegion() const override { return mRegion; } - bool noSleep() const override { return mData.mFlags & ESM::Cell::NoSleep; } - std::string_view getEditorName() const override { return mName; } + const CellId& getCellId() const; }; } #endif diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index fed031ed16..09eef41679 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -241,12 +241,6 @@ void ESM4::Cell::load(ESM4::Reader& reader) throw std::runtime_error("ESM4::CELL::load - Unknown subrecord " + ESM::printName(subHdr.typeId)); } } - - mCellId.mWorldspace = Misc::StringUtils::lowerCase(mEditorId); - mCellId.mWorld = ESM::RefId::sEmpty; - mCellId.mIndex.mX = getGridX(); - mCellId.mIndex.mX = getGridY(); - mCellId.mPaged = isExterior(); } // void ESM4::Cell::save(ESM4::Writer& writer) const diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index 631aa1c94a..2573c08ae7 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -35,7 +35,6 @@ #include "lighting.hpp" #include -#include #include #include @@ -62,7 +61,7 @@ namespace ESM4 // Unlike TES3, multiple cells can have the same exterior co-ordinates. // The cells need to be organised under world spaces. - struct Cell final : public ESM::CellCommon + struct Cell { FormId mParent; // world formId (for grouping cells), from the loading sequence @@ -96,8 +95,6 @@ namespace ESM4 CellGroup* mCellGroup; - ESM::CellId mCellId; - void load(ESM4::Reader& reader); // void save(ESM4::Writer& writer) const; @@ -105,15 +102,9 @@ namespace ESM4 static constexpr ESM::RecNameInts sRecordId = ESM::REC_CELL4; - int getGridX() const override { return mX; } - int getGridY() const override { return mY; } - bool isExterior() const override { return !(mCellFlags & CELL_Interior); } - virtual bool isQuasiExterior() const override { return mCellFlags & CELL_QuasiExt; } - virtual bool hasWater() const override { return false; /*unimplemented for now*/ } - const ESM::CellId& getCellId() const override { return mCellId; } - const ESM::RefId& getRegion() const override { return ESM::RefId::sEmpty; } - std::string_view getEditorName() const override { return mEditorId; } - std::string getDescription() const override { return mEditorId; } + int getGridX() const { return mX; } + int getGridY() const { return mY; } + bool isExterior() const { return !(mCellFlags & CELL_Interior); } }; } diff --git a/components/misc/coordinateconverter.hpp b/components/misc/coordinateconverter.hpp index bc9ef6d427..12ea2d8c40 100644 --- a/components/misc/coordinateconverter.hpp +++ b/components/misc/coordinateconverter.hpp @@ -1,9 +1,11 @@ #ifndef OPENMW_COMPONENTS_MISC_COORDINATECONVERTER_H #define OPENMW_COMPONENTS_MISC_COORDINATECONVERTER_H +#include #include #include #include +#include namespace Misc { @@ -17,8 +19,10 @@ namespace Misc { } - explicit CoordinateConverter(const ESM::CellCommon* cell) - : CoordinateConverter(cell->isExterior(), cell->getGridX(), cell->getGridY()) + explicit CoordinateConverter(const ESM::CellVariant& cell) + : CoordinateConverter(cell.isEsm4() ? cell.getEsm4().isExterior() : cell.getEsm3().isExterior(), + cell.isEsm4() ? cell.getEsm4().getGridX() : cell.getEsm3().getGridX(), + cell.isEsm4() ? cell.getEsm4().getGridY() : cell.getEsm3().getGridY()) { }