mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-05-09 20:17:54 +03:00
Avoids a lot a special cases for ESM3 vs ESM4 cells.
This commit is contained in:
parent
f3d5f6345e
commit
084207af64
19 changed files with 137 additions and 101 deletions
|
@ -357,13 +357,11 @@ namespace MWMechanics
|
||||||
case AiCombatStorage::FleeState_Idle:
|
case AiCombatStorage::FleeState_Idle:
|
||||||
{
|
{
|
||||||
float triggerDist = getMaxAttackDistance(target);
|
float triggerDist = getMaxAttackDistance(target);
|
||||||
auto cellVariant = storage.mCell->getCell();
|
const MWWorld::Cell* cellVariant = storage.mCell->getCell();
|
||||||
if (!cellVariant->isEsm4() && storage.mLOS
|
if (storage.mLOS && (triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist))
|
||||||
&& (triggerDist >= 1000 || getDistanceMinusHalfExtents(actor, target) <= triggerDist))
|
|
||||||
{
|
{
|
||||||
const ESM::Pathgrid* pathgrid
|
const ESM::Pathgrid* pathgrid
|
||||||
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(
|
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cellVariant);
|
||||||
cellVariant->getEsm3());
|
|
||||||
|
|
||||||
bool runFallback = true;
|
bool runFallback = true;
|
||||||
|
|
||||||
|
|
|
@ -411,14 +411,11 @@ bool MWMechanics::AiPackage::doesPathNeedRecalc(const osg::Vec3f& newDest, const
|
||||||
|
|
||||||
bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position)
|
bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position)
|
||||||
{
|
{
|
||||||
if (getPlayer().getCell()->getCell()->isEsm4())
|
const MWWorld::Cell* playerCell = getPlayer().getCell()->getCell();
|
||||||
return false;
|
|
||||||
|
|
||||||
const ESM::Cell* playerCell(&getPlayer().getCell()->getCell()->getEsm3());
|
|
||||||
if (playerCell->isExterior())
|
if (playerCell->isExterior())
|
||||||
{
|
{
|
||||||
// get actor's distance from origin of center cell
|
// get actor's distance from origin of center cell
|
||||||
Misc::CoordinateConverter(playerCell).toLocal(position);
|
Misc::CoordinateConverter(*playerCell).toLocal(position);
|
||||||
|
|
||||||
// currently assumes 3 x 3 grid for exterior cells, with player at center cell.
|
// 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.
|
// AI shuts down actors before they reach edges of 3 x 3 grid.
|
||||||
|
|
|
@ -271,9 +271,9 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization to discover & store allowed node points for this actor.
|
// Initialization to discover & store allowed node points for this actor.
|
||||||
if (!actor.getCell()->getCell()->isEsm4() && storage.mPopulateAvailableNodes)
|
if (storage.mPopulateAvailableNodes)
|
||||||
{
|
{
|
||||||
getAllowedNodes(actor, &actor.getCell()->getCell()->getEsm3(), storage);
|
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||||
|
@ -721,8 +721,8 @@ namespace MWMechanics
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
AiWanderStorage& storage = state.get<AiWanderStorage>();
|
||||||
if (!actor.getCell()->getCell()->isEsm4() && storage.mPopulateAvailableNodes)
|
if (storage.mPopulateAvailableNodes)
|
||||||
getAllowedNodes(actor, &actor.getCell()->getCell()->getEsm3(), storage);
|
getAllowedNodes(actor, actor.getCell()->getCell(), storage);
|
||||||
|
|
||||||
if (storage.mAllowedNodes.empty())
|
if (storage.mAllowedNodes.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -800,12 +800,8 @@ namespace MWMechanics
|
||||||
void AiWander::getNeighbouringNodes(
|
void AiWander::getNeighbouringNodes(
|
||||||
ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points)
|
ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points)
|
||||||
{
|
{
|
||||||
if (currentCell->getCell()->isEsm4())
|
|
||||||
return;
|
|
||||||
auto cell3 = currentCell->getCell()->getEsm3();
|
|
||||||
|
|
||||||
const ESM::Pathgrid* pathgrid
|
const ESM::Pathgrid* pathgrid
|
||||||
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(cell3);
|
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*currentCell->getCell());
|
||||||
|
|
||||||
if (pathgrid == nullptr || pathgrid->mPoints.empty())
|
if (pathgrid == nullptr || pathgrid->mPoints.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -815,7 +811,7 @@ namespace MWMechanics
|
||||||
getPathGridGraph(currentCell).getNeighbouringPoints(index, points);
|
getPathGridGraph(currentCell).getNeighbouringPoints(index, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage)
|
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const MWWorld::Cell* cell, AiWanderStorage& storage)
|
||||||
{
|
{
|
||||||
// infrequently used, therefore no benefit in caching it as a member
|
// infrequently used, therefore no benefit in caching it as a member
|
||||||
const ESM::Pathgrid* pathgrid
|
const ESM::Pathgrid* pathgrid
|
||||||
|
@ -839,7 +835,7 @@ namespace MWMechanics
|
||||||
if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor))
|
if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor))
|
||||||
{
|
{
|
||||||
// get NPC's position in local (i.e. cell) coordinates
|
// get NPC's position in local (i.e. cell) coordinates
|
||||||
auto converter = Misc::CoordinateConverter(cell);
|
auto converter = Misc::CoordinateConverter(*cell);
|
||||||
const osg::Vec3f npcPos = converter.toLocalVec3(mInitialActorPosition);
|
const osg::Vec3f npcPos = converter.toLocalVec3(mInitialActorPosition);
|
||||||
|
|
||||||
// Find closest pathgrid point
|
// Find closest pathgrid point
|
||||||
|
|
|
@ -23,6 +23,10 @@ namespace Misc
|
||||||
class CoordinateConverter;
|
class CoordinateConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Cell;
|
||||||
|
}
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
||||||
|
@ -147,7 +151,7 @@ namespace MWMechanics
|
||||||
void getNeighbouringNodes(
|
void getNeighbouringNodes(
|
||||||
ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points);
|
ESM::Pathgrid::Point dest, const MWWorld::CellStore* currentCell, ESM::Pathgrid::PointList& points);
|
||||||
|
|
||||||
void getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell, AiWanderStorage& storage);
|
void getAllowedNodes(const MWWorld::Ptr& actor, const MWWorld::Cell* cell, AiWanderStorage& storage);
|
||||||
|
|
||||||
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes, const PathFinder& pathfinder);
|
void trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes, const PathFinder& pathfinder);
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,7 @@ namespace MWMechanics
|
||||||
if (mIsGraphConstructed)
|
if (mIsGraphConstructed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (cell->getCell()->isEsm4())
|
mCell = cell->getCell();
|
||||||
return false;
|
|
||||||
mCell = &cell->getCell()->getEsm3();
|
|
||||||
|
|
||||||
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell);
|
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*mCell);
|
||||||
if (!mPathgrid)
|
if (!mPathgrid)
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace ESM
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class CellStore;
|
class CellStore;
|
||||||
|
class Cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -41,7 +42,7 @@ namespace MWMechanics
|
||||||
std::deque<ESM::Pathgrid::Point> aStarSearch(const int start, const int end) const;
|
std::deque<ESM::Pathgrid::Point> aStarSearch(const int start, const int end) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ESM::Cell* mCell;
|
const MWWorld::Cell* mCell;
|
||||||
const ESM::Pathgrid* mPathgrid;
|
const ESM::Pathgrid* mPathgrid;
|
||||||
|
|
||||||
struct ConnectedPoint // edge
|
struct ConnectedPoint // edge
|
||||||
|
|
|
@ -102,9 +102,8 @@ namespace MWRender
|
||||||
void Pathgrid::enableCellPathgrid(const MWWorld::CellStore* store)
|
void Pathgrid::enableCellPathgrid(const MWWorld::CellStore* store)
|
||||||
{
|
{
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
if (store->getCell()->isEsm4())
|
|
||||||
return;
|
const ESM::Pathgrid* pathgrid = world->getStore().get<ESM::Pathgrid>().search(*store->getCell());
|
||||||
const ESM::Pathgrid* pathgrid = world->getStore().get<ESM::Pathgrid>().search(store->getCell()->getEsm3());
|
|
||||||
if (!pathgrid)
|
if (!pathgrid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -781,10 +781,8 @@ namespace MWSound
|
||||||
{
|
{
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
const MWWorld::ConstPtr player = world->getPlayerPtr();
|
const MWWorld::ConstPtr player = world->getPlayerPtr();
|
||||||
if (player.getCell()->getCell()->isEsm4())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ESM::Cell* curcell = &player.getCell()->getCell()->getEsm3();
|
const MWWorld::Cell* curcell = player.getCell()->getCell();
|
||||||
const auto update = mWaterSoundUpdater.update(player, *world);
|
const auto update = mWaterSoundUpdater.update(player, *world);
|
||||||
|
|
||||||
WaterSoundAction action;
|
WaterSoundAction action;
|
||||||
|
@ -813,7 +811,7 @@ namespace MWSound
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SoundManager::WaterSoundAction, Sound_Buffer*> SoundManager::getWaterSoundAction(
|
std::pair<SoundManager::WaterSoundAction, Sound_Buffer*> SoundManager::getWaterSoundAction(
|
||||||
const WaterSoundUpdate& update, const ESM::Cell* cell) const
|
const WaterSoundUpdate& update, const MWWorld::Cell* cell) const
|
||||||
{
|
{
|
||||||
if (mNearWaterSound)
|
if (mNearWaterSound)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,11 @@ namespace ESM
|
||||||
struct Cell;
|
struct Cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Cell;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound_Output;
|
class Sound_Output;
|
||||||
|
@ -107,7 +112,7 @@ namespace MWSound
|
||||||
|
|
||||||
float mTimePassed;
|
float mTimePassed;
|
||||||
|
|
||||||
const ESM::Cell* mLastCell;
|
const MWWorld::Cell* mLastCell;
|
||||||
|
|
||||||
Sound* mCurrentRegionSound;
|
Sound* mCurrentRegionSound;
|
||||||
|
|
||||||
|
@ -143,7 +148,7 @@ namespace MWSound
|
||||||
};
|
};
|
||||||
|
|
||||||
std::pair<WaterSoundAction, Sound_Buffer*> getWaterSoundAction(
|
std::pair<WaterSoundAction, Sound_Buffer*> getWaterSoundAction(
|
||||||
const WaterSoundUpdate& update, const ESM::Cell* cell) const;
|
const WaterSoundUpdate& update, const MWWorld::Cell* cell) const;
|
||||||
|
|
||||||
SoundManager(const SoundManager& rhs);
|
SoundManager(const SoundManager& rhs);
|
||||||
SoundManager& operator=(const SoundManager& rhs);
|
SoundManager& operator=(const SoundManager& rhs);
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace MWWorld
|
||||||
.mDirectionalColor = cell.mLighting.directional,
|
.mDirectionalColor = cell.mLighting.directional,
|
||||||
.mFogColor = cell.mLighting.fogColor,
|
.mFogColor = cell.mLighting.fogColor,
|
||||||
.mFogDensity = cell.mLighting.fogPower,}
|
.mFogDensity = cell.mLighting.fogPower,}
|
||||||
|
,mWaterHeight(cell.mWaterHeight)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +46,16 @@ namespace MWWorld
|
||||||
.mFogColor = cell.mAmbi.mFog,
|
.mFogColor = cell.mAmbi.mFog,
|
||||||
.mFogDensity = cell.mAmbi.mFogDensity,
|
.mFogDensity = cell.mAmbi.mFogDensity,
|
||||||
}
|
}
|
||||||
|
,mWaterHeight(cell.mWater)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Cell::getDescription() const
|
std::string Cell::getDescription() const
|
||||||
{
|
{
|
||||||
return isEsm4() ? mNameID : getEsm3().getDescription();
|
return ESM::visit(ESM::VisitOverload{
|
||||||
|
[&](const ESM::Cell& cell) { return cell.getDescription(); },
|
||||||
|
[&](const ESM4::Cell& cell) { return cell.mEditorId; },
|
||||||
|
},
|
||||||
|
*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace MWWorld
|
||||||
std::string_view getDisplayName() const { return mDisplayname; }
|
std::string_view getDisplayName() const { return mDisplayname; }
|
||||||
std::string getDescription() const;
|
std::string getDescription() const;
|
||||||
const MoodData& getMood() const { return mMood; }
|
const MoodData& getMood() const { return mMood; }
|
||||||
|
float getWaterHeight() const { return mWaterHeight; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mIsExterior;
|
bool mIsExterior;
|
||||||
|
@ -61,6 +62,8 @@ namespace MWWorld
|
||||||
ESM::RefId mRegion;
|
ESM::RefId mRegion;
|
||||||
ESM::CellId mCellId;
|
ESM::CellId mCellId;
|
||||||
MoodData mMood;
|
MoodData mMood;
|
||||||
|
|
||||||
|
float mWaterHeight;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,6 @@
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
// makes it easier to use std visit with a variant
|
|
||||||
template <class... Ts>
|
|
||||||
struct RefVisit : Ts...
|
|
||||||
{
|
|
||||||
using Ts::operator()...;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class... Ts>
|
|
||||||
RefVisit(Ts...) -> RefVisit<Ts...>;
|
|
||||||
|
|
||||||
CellRef::CellRef(const ESM::CellRef& ref)
|
CellRef::CellRef(const ESM::CellRef& ref)
|
||||||
: mCellRef(ESM::ReferenceVariant(ref))
|
: mCellRef(ESM::ReferenceVariant(ref))
|
||||||
{
|
{
|
||||||
|
@ -31,7 +21,7 @@ namespace MWWorld
|
||||||
|
|
||||||
const ESM::RefNum& CellRef::getRefNum() const
|
const ESM::RefNum& CellRef::getRefNum() const
|
||||||
{
|
{
|
||||||
return std::visit(RefVisit{
|
return std::visit(ESM::VisitOverload{
|
||||||
[&](const ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
|
[&](const ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
|
||||||
[&](const ESM::CellRef& ref) -> const ESM::RefNum& { return ref.mRefNum; },
|
[&](const ESM::CellRef& ref) -> const ESM::RefNum& { return ref.mRefNum; },
|
||||||
},
|
},
|
||||||
|
@ -59,7 +49,7 @@ namespace MWWorld
|
||||||
return ref.mRefNum;
|
return ref.mRefNum;
|
||||||
};
|
};
|
||||||
return std::visit(
|
return std::visit(
|
||||||
RefVisit{
|
ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
|
[&](ESM4::Reference& /*ref*/) -> const ESM::RefNum& { return emptyRefNum; },
|
||||||
esm3Visit,
|
esm3Visit,
|
||||||
},
|
},
|
||||||
|
@ -68,7 +58,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellRef::unsetRefNum()
|
void CellRef::unsetRefNum()
|
||||||
{
|
{
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mRefNum = emptyRefNum; },
|
[&](ESM::CellRef& ref) { ref.mRefNum = emptyRefNum; },
|
||||||
},
|
},
|
||||||
|
@ -79,7 +69,11 @@ namespace MWWorld
|
||||||
|
|
||||||
const std::string& CellRef::getDestCell() const
|
const std::string& CellRef::getDestCell() const
|
||||||
{
|
{
|
||||||
return mCellRef.isESM4() ? emptyString : mCellRef.getEsm3().mDestCell;
|
return std::visit(ESM::VisitOverload{
|
||||||
|
[&](const ESM4::Reference& /*ref*/) -> const std::string& { return emptyString; },
|
||||||
|
[&](const ESM::CellRef& ref) -> const std::string& { return ref.mDestCell; },
|
||||||
|
},
|
||||||
|
mCellRef.mVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellRef::setScale(float scale)
|
void CellRef::setScale(float scale)
|
||||||
|
@ -99,7 +93,7 @@ namespace MWWorld
|
||||||
|
|
||||||
float CellRef::getEnchantmentCharge() const
|
float CellRef::getEnchantmentCharge() const
|
||||||
{
|
{
|
||||||
return std::visit(RefVisit{
|
return std::visit(ESM::VisitOverload{
|
||||||
[&](const ESM4::Reference& /*ref*/) { return 0.f; },
|
[&](const ESM4::Reference& /*ref*/) { return 0.f; },
|
||||||
[&](const ESM::CellRef& ref) { return ref.mEnchantmentCharge; },
|
[&](const ESM::CellRef& ref) { return ref.mEnchantmentCharge; },
|
||||||
},
|
},
|
||||||
|
@ -128,7 +122,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
|
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mEnchantmentCharge = charge; },
|
[&](ESM::CellRef& ref) { ref.mEnchantmentCharge = charge; },
|
||||||
},
|
},
|
||||||
|
@ -138,7 +132,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellRef::setCharge(int charge)
|
void CellRef::setCharge(int charge)
|
||||||
{
|
{
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mChargeInt = charge; },
|
[&](ESM::CellRef& ref) { ref.mChargeInt = charge; },
|
||||||
},
|
},
|
||||||
|
@ -164,7 +158,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::visit(
|
std::visit(
|
||||||
RefVisit{
|
ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
esm3Visit,
|
esm3Visit,
|
||||||
},
|
},
|
||||||
|
@ -173,7 +167,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellRef::setChargeFloat(float charge)
|
void CellRef::setChargeFloat(float charge)
|
||||||
{
|
{
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mChargeFloat = charge; },
|
[&](ESM::CellRef& ref) { ref.mChargeFloat = charge; },
|
||||||
},
|
},
|
||||||
|
@ -182,7 +176,7 @@ namespace MWWorld
|
||||||
|
|
||||||
const std::string& CellRef::getGlobalVariable() const
|
const std::string& CellRef::getGlobalVariable() const
|
||||||
{
|
{
|
||||||
return std::visit(RefVisit{
|
return std::visit(ESM::VisitOverload{
|
||||||
[&](const ESM4::Reference& /*ref*/) -> const std::string& { return emptyString; },
|
[&](const ESM4::Reference& /*ref*/) -> const std::string& { return emptyString; },
|
||||||
[&](const ESM::CellRef& ref) -> const std::string& { return ref.mGlobalVariable; },
|
[&](const ESM::CellRef& ref) -> const std::string& { return ref.mGlobalVariable; },
|
||||||
},
|
},
|
||||||
|
@ -194,7 +188,7 @@ namespace MWWorld
|
||||||
if (!getGlobalVariable().empty())
|
if (!getGlobalVariable().empty())
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mGlobalVariable.erase(); },
|
[&](ESM::CellRef& ref) { ref.mGlobalVariable.erase(); },
|
||||||
},
|
},
|
||||||
|
@ -215,7 +209,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
if (owner != getOwner())
|
if (owner != getOwner())
|
||||||
{
|
{
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mOwner = owner; },
|
[&](ESM::CellRef& ref) { ref.mOwner = owner; },
|
||||||
},
|
},
|
||||||
|
@ -228,7 +222,7 @@ namespace MWWorld
|
||||||
if (soul != getSoul())
|
if (soul != getSoul())
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mSoul = soul; },
|
[&](ESM::CellRef& ref) { ref.mSoul = soul; },
|
||||||
},
|
},
|
||||||
|
@ -241,7 +235,7 @@ namespace MWWorld
|
||||||
if (faction != getFaction())
|
if (faction != getFaction())
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mFaction = faction; },
|
[&](ESM::CellRef& ref) { ref.mFaction = faction; },
|
||||||
},
|
},
|
||||||
|
@ -276,7 +270,7 @@ namespace MWWorld
|
||||||
if (trap != getTrap())
|
if (trap != getTrap())
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mTrap = trap; },
|
[&](ESM::CellRef& ref) { ref.mTrap = trap; },
|
||||||
},
|
},
|
||||||
|
@ -289,7 +283,7 @@ namespace MWWorld
|
||||||
if (value != getGoldValue())
|
if (value != getGoldValue())
|
||||||
{
|
{
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](ESM4::Reference& /*ref*/) {},
|
[&](ESM4::Reference& /*ref*/) {},
|
||||||
[&](ESM::CellRef& ref) { ref.mGoldValue = value; },
|
[&](ESM::CellRef& ref) { ref.mGoldValue = value; },
|
||||||
},
|
},
|
||||||
|
@ -299,7 +293,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellRef::writeState(ESM::ObjectState& state) const
|
void CellRef::writeState(ESM::ObjectState& state) const
|
||||||
{
|
{
|
||||||
std::visit(RefVisit{
|
std::visit(ESM::VisitOverload{
|
||||||
[&](const ESM4::Reference& /*ref*/) {},
|
[&](const ESM4::Reference& /*ref*/) {},
|
||||||
[&](const ESM::CellRef& ref) { state.mRef = ref; },
|
[&](const ESM::CellRef& ref) { state.mRef = ref; },
|
||||||
},
|
},
|
||||||
|
|
|
@ -540,8 +540,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
std::apply([this](auto&... x) { (CellStoreImp::assignStoreToIndex(*this, x), ...); }, mCellStoreImp->mRefLists);
|
std::apply([this](auto&... x) { (CellStoreImp::assignStoreToIndex(*this, x), ...); }, mCellStoreImp->mRefLists);
|
||||||
if (!mCellVariant.isEsm4())
|
mWaterLevel = mCellVariant.getWaterHeight();
|
||||||
mWaterLevel = mCellVariant.getEsm3().mWater;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CellStore::~CellStore() = default;
|
CellStore::~CellStore() = default;
|
||||||
|
@ -703,26 +702,20 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellStore::listRefs()
|
void CellStore::listRefs(const ESM::Cell& cell)
|
||||||
{
|
{
|
||||||
|
if (cell.mContextList.empty())
|
||||||
if (mCellVariant.isEsm4())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ESM::Cell& cell3 = mCellVariant.getEsm3();
|
|
||||||
|
|
||||||
if (cell3.mContextList.empty())
|
|
||||||
return; // this is a dynamically generated cell -> skipping.
|
return; // this is a dynamically generated cell -> skipping.
|
||||||
|
|
||||||
// Load references from all plugins that do something with this cell.
|
// Load references from all plugins that do something with this cell.
|
||||||
for (size_t i = 0; i < cell3.mContextList.size(); i++)
|
for (size_t i = 0; i < cell.mContextList.size(); i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Reopen the ESM reader and seek to the right position.
|
// Reopen the ESM reader and seek to the right position.
|
||||||
const std::size_t index = static_cast<std::size_t>(cell3.mContextList[i].index);
|
const std::size_t index = static_cast<std::size_t>(cell.mContextList[i].index);
|
||||||
const ESM::ReadersCache::BusyItem reader = mReaders.get(index);
|
const ESM::ReadersCache::BusyItem reader = mReaders.get(index);
|
||||||
cell3.restore(*reader, i);
|
cell.restore(*reader, i);
|
||||||
|
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
|
|
||||||
|
@ -738,8 +731,8 @@ namespace MWWorld
|
||||||
|
|
||||||
// Don't list reference if it was moved to a different cell.
|
// Don't list reference if it was moved to a different cell.
|
||||||
ESM::MovedCellRefTracker::const_iterator iter
|
ESM::MovedCellRefTracker::const_iterator iter
|
||||||
= std::find(cell3.mMovedRefs.begin(), cell3.mMovedRefs.end(), ref.mRefNum);
|
= std::find(cell.mMovedRefs.begin(), cell.mMovedRefs.end(), ref.mRefNum);
|
||||||
if (iter != cell3.mMovedRefs.end())
|
if (iter != cell.mMovedRefs.end())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -755,12 +748,29 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
// List moved references, from separately tracked list.
|
// List moved references, from separately tracked list.
|
||||||
for (const auto& [ref, deleted] : cell3.mLeasedRefs)
|
for (const auto& [ref, deleted] : cell.mLeasedRefs)
|
||||||
{
|
{
|
||||||
if (!deleted)
|
if (!deleted)
|
||||||
mIds.push_back(ref.mRefID);
|
mIds.push_back(ref.mRefID);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CellStore::listRefs(const ESM4::Cell& cell)
|
||||||
|
{
|
||||||
|
auto& refs = MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>();
|
||||||
|
|
||||||
|
for (const auto& ref : refs)
|
||||||
|
{
|
||||||
|
if (ref.mParent == cell.mId)
|
||||||
|
{
|
||||||
|
mIds.push_back(ref.mBaseObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CellStore::listRefs()
|
||||||
|
{
|
||||||
|
ESM::visit([&](auto&& cell) { listRefs(cell); }, mCellVariant);
|
||||||
std::sort(mIds.begin(), mIds.end());
|
std::sort(mIds.begin(), mIds.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,7 +844,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
std::map<ESM::RefNum, ESM::RefId> refNumToID; // used to detect refID modifications
|
std::map<ESM::RefNum, ESM::RefId> refNumToID; // used to detect refID modifications
|
||||||
|
|
||||||
ESM::visit([&refNumToID, this](auto&& cell) { this->loadRefs(cell, refNumToID); }, mCellVariant);
|
ESM::visit([&](auto&& cell) { loadRefs(cell, refNumToID); }, mCellVariant);
|
||||||
|
|
||||||
updateMergedRefs();
|
updateMergedRefs();
|
||||||
}
|
}
|
||||||
|
@ -930,9 +940,6 @@ namespace MWWorld
|
||||||
|
|
||||||
void CellStore::loadState(const ESM::CellState& state)
|
void CellStore::loadState(const ESM::CellState& state)
|
||||||
{
|
{
|
||||||
if (mCellVariant.isEsm4())
|
|
||||||
return;
|
|
||||||
|
|
||||||
mHasState = true;
|
mHasState = true;
|
||||||
|
|
||||||
if (!mCellVariant.isExterior() && mCellVariant.hasWater())
|
if (!mCellVariant.isExterior() && mCellVariant.hasWater())
|
||||||
|
|
|
@ -383,6 +383,8 @@ namespace MWWorld
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Run through references and store IDs
|
/// Run through references and store IDs
|
||||||
|
void listRefs(const ESM::Cell& cell);
|
||||||
|
void listRefs(const ESM4::Cell& cell);
|
||||||
void listRefs();
|
void listRefs();
|
||||||
|
|
||||||
void loadRefs(const ESM::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID);
|
void loadRefs(const ESM::Cell& cell, std::map<ESM::RefNum, ESM::RefId>& refNumToID);
|
||||||
|
|
|
@ -354,11 +354,14 @@ namespace MWWorld
|
||||||
if (cell->getCell()->hasWater())
|
if (cell->getCell()->hasWater())
|
||||||
mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard);
|
mNavigator.removeWater(osg::Vec2i(cellX, cellY), navigatorUpdateGuard);
|
||||||
|
|
||||||
if (!cell->getCell()->isEsm4())
|
ESM::visit(ESM::VisitOverload{
|
||||||
{
|
[&](const ESM::Cell& cell) {
|
||||||
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(cell->getCell()->getEsm3()))
|
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(cell))
|
||||||
mNavigator.removePathgrid(*pathgrid);
|
mNavigator.removePathgrid(*pathgrid);
|
||||||
}
|
},
|
||||||
|
[&](const ESM4::Cell& cell) {},
|
||||||
|
},
|
||||||
|
*cell->getCell());
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->drop(cell);
|
MWBase::Environment::get().getMechanicsManager()->drop(cell);
|
||||||
|
|
||||||
|
@ -430,12 +433,14 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cellVariant.isEsm4())
|
ESM::visit(ESM::VisitOverload{
|
||||||
{
|
[&](const ESM::Cell& cell) {
|
||||||
const ESM::Cell& cell3 = cellVariant.getEsm3();
|
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(cell))
|
||||||
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(cell3))
|
mNavigator.addPathgrid(cell, *pathgrid);
|
||||||
mNavigator.addPathgrid(cell3, *pathgrid);
|
},
|
||||||
}
|
[&](const ESM4::Cell& cell) {},
|
||||||
|
},
|
||||||
|
*cell->getCell());
|
||||||
|
|
||||||
// register local scripts
|
// register local scripts
|
||||||
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
||||||
|
@ -449,7 +454,7 @@ namespace MWWorld
|
||||||
mRendering.addCell(cell);
|
mRendering.addCell(cell);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
||||||
bool waterEnabled = (!cellVariant.isEsm4()) && (cellVariant.hasWater() || cell->isExterior());
|
bool waterEnabled = cellVariant.hasWater() || cell->isExterior();
|
||||||
float waterLevel = cell->getWaterLevel();
|
float waterLevel = cell->getWaterLevel();
|
||||||
mRendering.setWaterEnabled(waterEnabled);
|
mRendering.setWaterEnabled(waterEnabled);
|
||||||
if (waterEnabled)
|
if (waterEnabled)
|
||||||
|
@ -457,7 +462,7 @@ namespace MWWorld
|
||||||
mPhysics->enableWater(waterLevel);
|
mPhysics->enableWater(waterLevel);
|
||||||
mRendering.setWaterHeight(waterLevel);
|
mRendering.setWaterHeight(waterLevel);
|
||||||
|
|
||||||
if (cellVariant.getEsm3().isExterior())
|
if (cellVariant.isExterior())
|
||||||
{
|
{
|
||||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
mNavigator.addWater(
|
mNavigator.addWater(
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <components/loadinglistener/loadinglistener.hpp>
|
#include <components/loadinglistener/loadinglistener.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
|
#include <apps/openmw/mwworld/cell.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// TODO: Switch to C++23 to get a working version of std::unordered_map::erase
|
// TODO: Switch to C++23 to get a working version of std::unordered_map::erase
|
||||||
|
@ -961,6 +963,14 @@ namespace MWWorld
|
||||||
else
|
else
|
||||||
return search(ESM::RefId::stringRefId(cell.mName));
|
return search(ESM::RefId::stringRefId(cell.mName));
|
||||||
}
|
}
|
||||||
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::search(const MWWorld::Cell& cellVariant) const
|
||||||
|
{
|
||||||
|
return ESM::visit(ESM::VisitOverload{
|
||||||
|
[&](const ESM::Cell& cell) { return search(cell); },
|
||||||
|
[&](const ESM4::Cell& cell) -> const ESM::Pathgrid* { return nullptr; },
|
||||||
|
},
|
||||||
|
cellVariant);
|
||||||
|
}
|
||||||
const ESM::Pathgrid* Store<ESM::Pathgrid>::find(const ESM::Cell& cell) const
|
const ESM::Pathgrid* Store<ESM::Pathgrid>::find(const ESM::Cell& cell) const
|
||||||
{
|
{
|
||||||
if (!(cell.mData.mFlags & ESM::Cell::Interior))
|
if (!(cell.mData.mFlags & ESM::Cell::Interior))
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace Loading
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
class Cell;
|
||||||
struct RecordId
|
struct RecordId
|
||||||
{
|
{
|
||||||
ESM::RefId mId;
|
ESM::RefId mId;
|
||||||
|
@ -430,6 +431,7 @@ namespace MWWorld
|
||||||
const ESM::Pathgrid* find(int x, int y) const;
|
const ESM::Pathgrid* find(int x, int y) const;
|
||||||
const ESM::Pathgrid* find(const ESM::RefId& name) const;
|
const ESM::Pathgrid* find(const ESM::RefId& name) const;
|
||||||
const ESM::Pathgrid* search(const ESM::Cell& cell) const;
|
const ESM::Pathgrid* search(const ESM::Cell& cell) const;
|
||||||
|
const ESM::Pathgrid* search(const MWWorld::Cell& cell) const;
|
||||||
const ESM::Pathgrid* find(const ESM::Cell& cell) const;
|
const ESM::Pathgrid* find(const ESM::Cell& cell) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -642,11 +642,13 @@ namespace MWWorld
|
||||||
if (!cell.isExterior() || !cell.getNameId().empty())
|
if (!cell.isExterior() || !cell.getNameId().empty())
|
||||||
return cell.getNameId();
|
return cell.getNameId();
|
||||||
|
|
||||||
if (!cell.isEsm4())
|
return ESM::visit(ESM::VisitOverload{
|
||||||
{
|
[&](const ESM::Cell& cellIn) -> std::string_view { return getCellName(&cellIn); },
|
||||||
return getCellName(&cell.getEsm3());
|
[&](const ESM4::Cell& cellIn) -> std::string_view {
|
||||||
}
|
return mStore.get<ESM::GameSetting>().find("sDefaultCellname")->mValue.getString();
|
||||||
return mStore.get<ESM::GameSetting>().find("sDefaultCellname")->mValue.getString();
|
},
|
||||||
|
},
|
||||||
|
cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view World::getCellName(const ESM::Cell* cell) const
|
std::string_view World::getCellName(const ESM::Cell* cell) const
|
||||||
|
|
|
@ -70,5 +70,14 @@ namespace ESM
|
||||||
{
|
{
|
||||||
return std::visit([&](auto*... ptr) { return std::forward<F>(f)(*ptr...); }, std::forward<T>(v).mVariant...);
|
return std::visit([&](auto*... ptr) { return std::forward<F>(f)(*ptr...); }, std::forward<T>(v).mVariant...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class... Ts>
|
||||||
|
struct VisitOverload : Ts...
|
||||||
|
{
|
||||||
|
using Ts::operator()...;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class... Ts>
|
||||||
|
VisitOverload(Ts...) -> VisitOverload<Ts...>;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue