diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index d9358a0e56..bf5f7cebc0 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -357,12 +357,13 @@ namespace MWMechanics case AiCombatStorage::FleeState_Idle: { float triggerDist = getMaxAttackDistance(target); - auto cell3 = storage.mCell->getCellVariant().getEsm3(); - if (cell3 && storage.mLOS + auto cellVariant = storage.mCell->getCellVariant(); + if (!cellVariant.isEsm4() && storage.mLOS && (triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist)) { const ESM::Pathgrid* pathgrid - = MWBase::Environment::get().getWorld()->getStore().get().search(*cell3); + = MWBase::Environment::get().getWorld()->getStore().get().search( + cellVariant.getEsm3()); bool runFallback = true; diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 1233e16a39..ac96765a3a 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -411,7 +411,7 @@ bool MWMechanics::AiPackage::doesPathNeedRecalc(const osg::Vec3f& newDest, const bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position) { - const ESM::Cell* playerCell(getPlayer().getCell()->getCellVariant().getEsm3()); + const ESM::Cell* playerCell(&getPlayer().getCell()->getCellVariant().getEsm3()); if (playerCell->isExterior()) { // get actor's distance from origin of center cell diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 6043759b3e..1ff9cf0c54 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -271,10 +271,9 @@ namespace MWMechanics } // Initialization to discover & store allowed node points for this actor. - auto cell3 = actor.getCell()->getCellVariant().getEsm3(); - if (cell3 && storage.mPopulateAvailableNodes) + if (!actor.getCell()->getCellVariant().isEsm4() && storage.mPopulateAvailableNodes) { - getAllowedNodes(actor, cell3, storage); + getAllowedNodes(actor, &actor.getCell()->getCellVariant().getEsm3(), storage); } auto& prng = MWBase::Environment::get().getWorld()->getPrng(); @@ -722,9 +721,8 @@ namespace MWMechanics return; AiWanderStorage& storage = state.get(); - auto cell3 = actor.getCell()->getCellVariant().getEsm3(); - if (cell3 && storage.mPopulateAvailableNodes) - getAllowedNodes(actor, cell3, storage); + if (!actor.getCell()->getCellVariant().isEsm4() && storage.mPopulateAvailableNodes) + getAllowedNodes(actor, &actor.getCell()->getCellVariant().getEsm3(), storage); if (storage.mAllowedNodes.empty()) return; @@ -802,11 +800,12 @@ namespace MWMechanics void AiWander::getNeighbouringNodes( ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points) { - auto cell3 = currentCell->getCellVariant().getEsm3(); - if (!cell3) + if (currentCell->getCellVariant().isEsm4()) return; + auto cell3 = currentCell->getCellVariant().getEsm3(); + const ESM::Pathgrid* pathgrid - = MWBase::Environment::get().getWorld()->getStore().get().search(*cell3); + = MWBase::Environment::get().getWorld()->getStore().get().search(cell3); if (pathgrid == nullptr || pathgrid->mPoints.empty()) return; diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index ceaf513937..282ac4e381 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) + if (!cell || !cell->getCellVariant().isValid()) return false; if (mIsGraphConstructed) return true; - mCell = cell->getCellVariant().getEsm3(); + mCell = cell->getCellVariant().isEsm4() ? nullptr : &cell->getCellVariant().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 6b56bc81a2..c87ef8757f 100644 --- a/apps/openmw/mwrender/fogmanager.cpp +++ b/apps/openmw/mwrender/fogmanager.cpp @@ -45,9 +45,10 @@ namespace MWRender auto cell3 = cell.getEsm3(); auto cell4 = cell.getEsm4(); - osg::Vec4f color = SceneUtil::colourFromRGB(cell3 ? cell3->mAmbi.mFog : cell4->mLighting.fogColor); + osg::Vec4f color + = SceneUtil::colourFromRGB(cell.isEsm4() ? cell.getEsm4().mLighting.fogColor : cell.getEsm3().mAmbi.mFog); - const float fogDensity = cell3 ? cell3->mAmbi.mFogDensity : cell4->mLighting.fogPower; + const float fogDensity = !cell.isEsm4() ? cell.getEsm3().mAmbi.mFogDensity : cell.getEsm4().mLighting.fogPower; if (mDistantFog) { float density = std::max(0.2f, fogDensity); diff --git a/apps/openmw/mwrender/pathgrid.cpp b/apps/openmw/mwrender/pathgrid.cpp index 85d8f7a295..f449861a07 100644 --- a/apps/openmw/mwrender/pathgrid.cpp +++ b/apps/openmw/mwrender/pathgrid.cpp @@ -102,10 +102,10 @@ namespace MWRender void Pathgrid::enableCellPathgrid(const MWWorld::CellStore* store) { MWBase::World* world = MWBase::Environment::get().getWorld(); - auto cell3 = store->getCellVariant().getEsm3(); - if (!cell3) + if (store->getCellVariant().isEsm4()) return; - const ESM::Pathgrid* pathgrid = world->getStore().get().search(*cell3); + const ESM::Pathgrid* pathgrid + = world->getStore().get().search(store->getCellVariant().getEsm3()); if (!pathgrid) return; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7f03d4707c..ef09d38df0 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -747,17 +747,8 @@ namespace MWRender if (mResourceSystem->getSceneManager()->getLightingMethod() != SceneUtil::LightingMethod::FFP) needsAdjusting = isInterior; - osg::Vec4f ambient; - auto cell3 = cell.getEsm3(); - auto cell4 = cell.getEsm4(); - if (cell3) - { - ambient = SceneUtil::colourFromRGB(cell3->mAmbi.mAmbient); - } - else - { - ambient = SceneUtil::colourFromRGB(cell4->mLighting.ambient); - } + osg::Vec4f ambient = SceneUtil::colourFromRGB( + cell.isEsm4() ? cell.getEsm4().mLighting.ambient : cell.getEsm3().mAmbi.mAmbient); if (needsAdjusting) { @@ -781,8 +772,8 @@ namespace MWRender setAmbientColour(ambient); - osg::Vec4f diffuse = cell3 ? SceneUtil::colourFromRGB(cell3->mAmbi.mSunlight) - : SceneUtil::colourFromRGB(cell4->mLighting.directional); + osg::Vec4f diffuse = SceneUtil::colourFromRGB( + !cell.isEsm4() ? cell.getEsm3().mAmbi.mSunlight : cell.getEsm4().mLighting.directional); setSunColour(diffuse, diffuse, 1.f); diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 06f889d58a..e0b905a228 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -781,7 +781,7 @@ namespace MWSound { MWBase::World* world = MWBase::Environment::get().getWorld(); const MWWorld::ConstPtr player = world->getPlayerPtr(); - const ESM::Cell* curcell = player.getCell()->getCellVariant().getEsm3(); + const ESM::Cell* curcell = &player.getCell()->getCellVariant().getEsm3(); const auto update = mWaterSoundUpdater.update(player, *world); WaterSoundAction action; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 0fe281dcc6..8e09c7953b 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -516,7 +516,7 @@ namespace MWWorld , mRechargingItemsUpToDate(false) { - mCell = mCellVariant.getEsm3(); + mCell = mCellVariant.isEsm4() ? nullptr : &mCellVariant.getEsm3(); std::apply([this](auto&... x) { (CellStoreImp::assignStoreToIndex(*this, x), ...); }, mCellStoreImp->mRefLists); if (mCell) @@ -538,14 +538,13 @@ namespace MWWorld std::string_view CellStore::getEditorName() const { - const ESM4::Cell* cell4 = mCellVariant.getEsm4(); - if (cell4) + if (mCellVariant.isEsm4()) { - return cell4->mEditorId; + return mCellVariant.getEsm4().mEditorId; } else { - return mCellVariant.getEsm3()->mName; + return mCellVariant.getEsm3().mName; } } @@ -759,17 +758,17 @@ namespace MWWorld void CellStore::loadRefs() { - assert(mCellVariant.getEsm4() || mCellVariant.getEsm3()); - const ESM4::Cell* cell4 = mCellVariant.getEsm4(); - if (cell4) - { + assert(mCellVariant.isValid()); + if (mCellVariant.isEsm4()) + { + auto cell4 = mCellVariant.getEsm4(); auto& refs = MWBase::Environment::get().getWorld()->getStore().get(); auto it = refs.begin(); while (it != refs.end()) { - if (it->mParent == cell4->mId) + if (it->mParent == cell4.mId) { loadRef(*it, false); } @@ -836,15 +835,12 @@ namespace MWWorld bool CellStore::isExterior() const { - auto cell3 = mCellVariant.getEsm3(); - return cell3 ? cell3->isExterior() : false; + return mCellVariant.getCommon()->isExterior(); } bool CellStore::isQuasiExterior() const { - auto cell3 = mCellVariant.getEsm3(); - - return cell3 ? (mCell->mData.mFlags & ESM::Cell::QuasiEx) != 0 : false; + return mCellVariant.getCommon()->isExterior(); } Ptr CellStore::searchInContainer(const ESM::RefId& id) @@ -1084,16 +1080,14 @@ namespace MWWorld bool CellStore::operator==(const CellStore& right) const { - auto cell4Left = mCellVariant.getEsm4(); - auto cell4Right = right.mCellVariant.getEsm4(); - auto cell3Left = mCellVariant.getEsm3(); - auto cell3Right = right.mCellVariant.getEsm3(); + bool bothCell4 = mCellVariant.isEsm4() && right.mCellVariant.isEsm4(); + bool bothCell3 = !mCellVariant.isEsm4() && !right.mCellVariant.isEsm4(); - if (!cell4Left && !cell4Right) - return cell3Left->getCellId() == cell3Right->getCellId(); - else if (cell4Left && cell4Right) - return cell4Left->mId == cell4Right->mId; + if (bothCell3) + return mCellVariant.getEsm3().getCellId() == right.mCellVariant.getEsm3().getCellId(); + else if (bothCell4) + return mCellVariant.getEsm4().mId == right.mCellVariant.getEsm4().mId; else return false; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 6c817f3b56..0c5f72b107 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -355,10 +355,9 @@ namespace MWWorld if (cell->getCell()->hasWater()) mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); - auto cell3 = cell->getCellVariant().getEsm3(); - if (cell3) + if (!cell->getCellVariant().isEsm4()) { - if (const auto pathgrid = mWorld.getStore().get().search(*cell3)) + if (const auto pathgrid = mWorld.getStore().get().search(cell->getCellVariant().getEsm3())) mNavigator.removePathgrid(*pathgrid); } @@ -386,13 +385,14 @@ namespace MWWorld Log(Debug::Info) << "Loading cell " << cell->getEditorName(); - auto cell3 = cell->getCellVariant().getEsm3(); const int cellX = cell->getCellVariant().getCommon()->getGridX(); const int cellY = cell->getCellVariant().getCommon()->getGridY(); - if (cell3 != nullptr) + auto cellVariant = cell->getCellVariant(); + if (!cellVariant.isEsm4()) { + auto cell3 = cellVariant.getEsm3(); - if (cell3->isExterior()) + if (cell3.isExterior()) { osg::ref_ptr land = mRendering.getLandManager()->getLand(cellX, cellY); const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr; @@ -434,8 +434,8 @@ namespace MWWorld } } - if (const auto pathgrid = mWorld.getStore().get().search(*cell3)) - mNavigator.addPathgrid(*cell3, *pathgrid); + if (const auto pathgrid = mWorld.getStore().get().search(cell3)) + mNavigator.addPathgrid(cell3, *pathgrid); } // register local scripts @@ -450,7 +450,7 @@ namespace MWWorld mRendering.addCell(cell); MWBase::Environment::get().getWindowManager()->addCell(cell); - bool waterEnabled = cell3 && (cell3->hasWater() || cell->isExterior()); + bool waterEnabled = (!cellVariant.isEsm4()) && (cellVariant.getEsm3().hasWater() || cell->isExterior()); float waterLevel = cell->getWaterLevel(); mRendering.setWaterEnabled(waterEnabled); if (waterEnabled) @@ -458,7 +458,7 @@ namespace MWWorld mPhysics->enableWater(waterLevel); mRendering.setWaterHeight(waterLevel); - if (cell3->isExterior()) + if (cellVariant.getEsm3().isExterior()) { if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) mNavigator.addWater( @@ -473,8 +473,6 @@ namespace MWWorld else mPhysics->disableWater(); - const auto cellVariant = cell->getCellVariant(); - if (!cell->isExterior() && !cellVariant.getCommon()->isQuasiExterior()) mRendering.configureAmbient(cellVariant); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 1b4a37b1eb..5bee6c554a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -645,9 +645,9 @@ namespace MWWorld if (!cellCommon->isExterior() || !cellCommon->getEditorName().empty()) return cellCommon->getEditorName(); - if (cell.getEsm3()) + if (!cell.isEsm4()) { - const ESM::Region* region = mStore.get().search(cell.getEsm3()->mRegion); + const ESM::Region* region = mStore.get().search(cell.getEsm3().mRegion); return region->mName; } } @@ -3248,8 +3248,8 @@ namespace MWWorld else { auto cellVariant = cell->getCellVariant(); - uint32_t ambient = cellVariant.getEsm3() ? cellVariant.getEsm3()->mAmbi.mAmbient - : cellVariant.getEsm4()->mLighting.ambient; + uint32_t ambient = !cellVariant.isEsm4() ? cellVariant.getEsm3().mAmbi.mAmbient + : cellVariant.getEsm4().mLighting.ambient; int ambientTotal = (ambient & 0xff) + ((ambient >> 8) & 0xff) + ((ambient >> 16) & 0xff); return !cell->getCell()->noSleep() && ambientTotal <= 201; } diff --git a/components/esm/cellcommon.cpp b/components/esm/cellcommon.cpp index 42c93f0b83..ce3f50c726 100644 --- a/components/esm/cellcommon.cpp +++ b/components/esm/cellcommon.cpp @@ -7,9 +7,25 @@ namespace ESM const ESM::CellCommon* CellVariant::getCommon() const { auto cell3 = getEsm3(); - if (cell3) - return cell3; + if (isEsm4()) + return &getEsm4(); else - return getEsm4(); + return &getEsm3(); + } + + const ESM4::Cell& CellVariant::getEsm4() const + { + auto cell4 = std::get<0>(mVariant); + if (!cell4) + throw std::runtime_error("invalid variant acess"); + return *cell4; + } + + const ESM::Cell& CellVariant::getEsm3() const + { + auto cell = std::get<1>(mVariant); + if (!cell) + throw std::runtime_error("invalid variant acess"); + return *cell; } } diff --git a/components/esm/cellcommon.hpp b/components/esm/cellcommon.hpp index ec2d0559ec..a8067c11a1 100644 --- a/components/esm/cellcommon.hpp +++ b/components/esm/cellcommon.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace ESM4 { struct Cell; @@ -31,7 +33,12 @@ namespace ESM struct CellVariant { - std::variant mVariant; + std::variant mVariant; + + CellVariant() + : mVariant((void*)(nullptr)) + { + } explicit CellVariant(const ESM4::Cell* cell) : mVariant(cell) @@ -43,23 +50,17 @@ namespace ESM { } - bool isEsm4() const { return getEsm4(); } - - const ESM4::Cell* getEsm4() const + bool isValid() const { - auto cell4 = std::get_if(&mVariant); - if (cell4) - return *cell4; - return nullptr; + return std::holds_alternative(mVariant) + || std::holds_alternative(mVariant); } - const ESM::Cell* getEsm3() const - { - auto cell3 = std::get_if(&mVariant); - if (cell3) - return *cell3; - return nullptr; - } + bool isEsm4() const { return std::holds_alternative(mVariant); } + + const ESM4::Cell& getEsm4() const; + + const ESM::Cell& getEsm3() const; const ESM::CellCommon* getCommon() const; };