mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +00:00
Cannot load a cell yet, but getting more necessary parts in
This commit is contained in:
parent
cddf6f29d6
commit
08b68fcd48
@ -47,5 +47,7 @@ namespace MWClass
|
||||
Repair::registerSelf();
|
||||
Static::registerSelf();
|
||||
BodyPart::registerSelf();
|
||||
|
||||
ESM4Static::registerSelf();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "static.hpp"
|
||||
|
||||
#include <components/esm3/loadstat.hpp>
|
||||
#include <components/esm4/loadstat.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
|
||||
#include "../mwphysics/physicssystem.hpp"
|
||||
@ -63,4 +64,53 @@ namespace MWClass
|
||||
|
||||
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||
}
|
||||
|
||||
ESM4Static::ESM4Static()
|
||||
: MWWorld::RegisteredClass<ESM4Static>(ESM4::Static::sRecordId)
|
||||
{
|
||||
}
|
||||
|
||||
void ESM4Static ::insertObjectRendering(
|
||||
const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
if (!model.empty())
|
||||
{
|
||||
renderingInterface.getObjects().insertModel(ptr, model);
|
||||
ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Static);
|
||||
}
|
||||
}
|
||||
|
||||
void ESM4Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
|
||||
MWPhysics::PhysicsSystem& physics) const
|
||||
{
|
||||
insertObjectPhysics(ptr, model, rotation, physics);
|
||||
}
|
||||
|
||||
void ESM4Static::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
|
||||
MWPhysics::PhysicsSystem& physics) const
|
||||
{
|
||||
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World);
|
||||
}
|
||||
|
||||
std::string ESM4Static::getModel(const MWWorld::ConstPtr& ptr) const
|
||||
{
|
||||
return getClassModel<ESM4::Static>(ptr);
|
||||
}
|
||||
|
||||
std::string_view ESM4Static ::getName(const MWWorld::ConstPtr& ptr) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ESM4Static::hasToolTip(const MWWorld::ConstPtr& ptr) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MWWorld::Ptr ESM4Static::copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const
|
||||
{
|
||||
const MWWorld::LiveCellRef<ESM4::Static>* ref = ptr.get<ESM4::Static>();
|
||||
|
||||
return MWWorld::Ptr(cell.insert(ref), &cell);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,33 @@ namespace MWClass
|
||||
|
||||
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
|
||||
};
|
||||
|
||||
class ESM4Static : public MWWorld::RegisteredClass<ESM4Static>
|
||||
{
|
||||
friend MWWorld::RegisteredClass<ESM4Static>;
|
||||
|
||||
ESM4Static();
|
||||
|
||||
MWWorld::Ptr copyToCellImpl(const MWWorld::ConstPtr& ptr, MWWorld::CellStore& cell) const override;
|
||||
|
||||
public:
|
||||
void insertObjectRendering(const MWWorld::Ptr& ptr, const std::string& model,
|
||||
MWRender::RenderingInterface& renderingInterface) const override;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
|
||||
MWPhysics::PhysicsSystem& physics) const override;
|
||||
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, const osg::Quat& rotation,
|
||||
MWPhysics::PhysicsSystem& physics) const override;
|
||||
|
||||
std::string_view getName(const MWWorld::ConstPtr& ptr) const override;
|
||||
///< \return name or ID; can return an empty string.
|
||||
|
||||
bool hasToolTip(const MWWorld::ConstPtr& ptr) const override;
|
||||
///< @return true if this object has a tooltip when focused (default implementation: true)
|
||||
|
||||
std::string getModel(const MWWorld::ConstPtr& ptr) const override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <components/esm3/npcstate.hpp>
|
||||
#include <components/esm3/objectstate.hpp>
|
||||
#include <components/esm3/readerscache.hpp>
|
||||
#include <components/esm4/loadrefr.hpp>
|
||||
#include <components/esm4/loadstat.hpp>
|
||||
#include <components/misc/tuplehelpers.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
@ -503,18 +505,22 @@ namespace MWWorld
|
||||
return false;
|
||||
}
|
||||
|
||||
CellStore::CellStore(const ESM::Cell* cell, const MWWorld::ESMStore& esmStore, ESM::ReadersCache& readers)
|
||||
CellStore::CellStore(CellVariant cell, const MWWorld::ESMStore& esmStore, ESM::ReadersCache& readers)
|
||||
: mStore(esmStore)
|
||||
, mReaders(readers)
|
||||
, mCell(cell)
|
||||
, mCellVariant(cell)
|
||||
, mState(State_Unloaded)
|
||||
, mHasState(false)
|
||||
, mLastRespawn(0, 0)
|
||||
, mCellStoreImp(std::make_unique<CellStoreImp>())
|
||||
, mRechargingItemsUpToDate(false)
|
||||
{
|
||||
|
||||
mCell = mCellVariant.getEsm3();
|
||||
|
||||
std::apply([this](auto&... x) { (CellStoreImp::assignStoreToIndex(*this, x), ...); }, mCellStoreImp->mRefLists);
|
||||
mWaterLevel = cell->mWater;
|
||||
if (mCell)
|
||||
mWaterLevel = mCell->mWater;
|
||||
}
|
||||
|
||||
CellStore::~CellStore() = default;
|
||||
@ -525,6 +531,24 @@ namespace MWWorld
|
||||
return mCell;
|
||||
}
|
||||
|
||||
CellVariant CellStore::getCellVariant() const
|
||||
{
|
||||
return mCellVariant;
|
||||
}
|
||||
|
||||
std::string_view CellStore::getEditorName() const
|
||||
{
|
||||
const ESM4::Cell* cell4 = mCellVariant.getEsm4();
|
||||
if (cell4)
|
||||
{
|
||||
return cell4->mEditorId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mCellVariant.getEsm3()->mName;
|
||||
}
|
||||
}
|
||||
|
||||
CellStore::State CellStore::getState() const
|
||||
{
|
||||
return mState;
|
||||
@ -735,7 +759,24 @@ namespace MWWorld
|
||||
|
||||
void CellStore::loadRefs()
|
||||
{
|
||||
assert(mCell);
|
||||
assert(mCellVariant.getEsm4() || mCellVariant.getEsm3());
|
||||
const ESM4::Cell* cell4 = mCellVariant.getEsm4();
|
||||
if (cell4)
|
||||
{
|
||||
|
||||
auto& refs = MWBase::Environment::get().getWorld()->getStore().get<ESM4::Reference>();
|
||||
auto it = refs.begin();
|
||||
|
||||
while (it != refs.end())
|
||||
{
|
||||
if (it->mParent == cell4->mId)
|
||||
{
|
||||
loadRef(*it, false);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCell->mContextList.empty())
|
||||
return; // this is a dynamically generated cell -> skipping.
|
||||
@ -795,12 +836,15 @@ namespace MWWorld
|
||||
|
||||
bool CellStore::isExterior() const
|
||||
{
|
||||
return mCell->isExterior();
|
||||
auto cell3 = mCellVariant.getEsm3();
|
||||
return cell3 ? cell3->isExterior() : false;
|
||||
}
|
||||
|
||||
bool CellStore::isQuasiExterior() const
|
||||
{
|
||||
return (mCell->mData.mFlags & ESM::Cell::QuasiEx) != 0;
|
||||
auto cell3 = mCellVariant.getEsm3();
|
||||
|
||||
return cell3 ? (mCell->mData.mFlags & ESM::Cell::QuasiEx) != 0 : false;
|
||||
}
|
||||
|
||||
Ptr CellStore::searchInContainer(const ESM::RefId& id)
|
||||
@ -823,6 +867,28 @@ namespace MWWorld
|
||||
return Ptr();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void loadRefESM4(
|
||||
const MWWorld::ESMStore& store, const ESM4::Reference& ref, MWWorld::CellRefList<T>& storeIn, bool deleted)
|
||||
{
|
||||
if constexpr (ESM::isESM4Rec(T::sRecordId))
|
||||
{
|
||||
// storeIn.load(ref, deleted, store);
|
||||
}
|
||||
}
|
||||
|
||||
void CellStore::loadRef(const ESM4::Reference& ref, bool deleted)
|
||||
{
|
||||
const MWWorld::ESMStore& store = mStore;
|
||||
|
||||
ESM::RecNameInts foundType = static_cast<ESM::RecNameInts>(store.find(ref.mBaseObj));
|
||||
|
||||
Misc::tupleForEach(this->mCellStoreImp->mRefLists, [&ref, &deleted, &store, foundType](auto& x) {
|
||||
recNameSwitcher(
|
||||
x, foundType, [&ref, &deleted, &store](auto& storeIn) { loadRefESM4(store, ref, storeIn, deleted); });
|
||||
});
|
||||
}
|
||||
|
||||
void CellStore::loadRef(ESM::CellRef& ref, bool deleted, std::map<ESM::RefNum, ESM::RefId>& refNumToID)
|
||||
{
|
||||
const MWWorld::ESMStore& store = mStore;
|
||||
@ -999,8 +1065,8 @@ namespace MWWorld
|
||||
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << movedRef.getCellRef().getRefId()
|
||||
<< " (target cell " << movedTo.mWorldspace
|
||||
<< " no longer exists). Reference moved back to its original location.";
|
||||
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially
|
||||
// at inapproriate coordinates. Restore original coordinates:
|
||||
// Note by dropping tag the object will automatically re-appear in its original cell, though
|
||||
// potentially at inapproriate coordinates. Restore original coordinates:
|
||||
movedRef.getRefData().setPosition(movedRef.getCellRef().getPosition());
|
||||
continue;
|
||||
}
|
||||
@ -1016,14 +1082,17 @@ namespace MWWorld
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const CellStore& left, const CellStore& right)
|
||||
bool CellStore::operator==(const CellStore& right) const
|
||||
{
|
||||
return left.getCell()->getCellId() == right.getCell()->getCellId();
|
||||
}
|
||||
auto cell4Left = mCellVariant.getEsm4();
|
||||
auto cell4Right = right.mCellVariant.getEsm4();
|
||||
|
||||
bool operator!=(const CellStore& left, const CellStore& right)
|
||||
{
|
||||
return !(left == right);
|
||||
if (!cell4Left && !cell4Right)
|
||||
return getCell()->getCellId() == right.getCell()->getCellId();
|
||||
else if (cell4Left && cell4Right)
|
||||
return cell4Left->mId == cell4Right->mId;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CellStore::setFog(std::unique_ptr<ESM::FogState>&& fog)
|
||||
|
@ -55,20 +55,56 @@ namespace ESM4
|
||||
{
|
||||
class Reader;
|
||||
struct Cell;
|
||||
struct Reference;
|
||||
struct Static;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class ESMStore;
|
||||
struct CellStoreImp;
|
||||
typedef std::variant<const ESM4::Cell*, const ESM::Cell*> CellVariant;
|
||||
|
||||
struct CellVariant
|
||||
{
|
||||
std::variant<const ESM4::Cell*, const ESM::Cell*> mVariant;
|
||||
|
||||
CellVariant(const ESM4::Cell* cell)
|
||||
: mVariant(cell)
|
||||
{
|
||||
}
|
||||
|
||||
CellVariant(const ESM::Cell* cell)
|
||||
: mVariant(cell)
|
||||
{
|
||||
}
|
||||
|
||||
bool isEsm4() const { return getEsm4(); }
|
||||
|
||||
const ESM4::Cell* getEsm4() const
|
||||
{
|
||||
auto cell4 = std::get_if<const ESM4::Cell*>(&mVariant);
|
||||
if (cell4)
|
||||
return *cell4;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ESM::Cell* getEsm3() const
|
||||
{
|
||||
auto cell3 = std::get_if<const ESM::Cell*>(&mVariant);
|
||||
if (cell3)
|
||||
return *cell3;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
using CellStoreTuple = std::tuple<CellRefList<ESM::Activator>, CellRefList<ESM::Potion>,
|
||||
CellRefList<ESM::Apparatus>, CellRefList<ESM::Armor>, CellRefList<ESM::Book>, CellRefList<ESM::Clothing>,
|
||||
CellRefList<ESM::Container>, CellRefList<ESM::Creature>, CellRefList<ESM::Door>, CellRefList<ESM::Ingredient>,
|
||||
CellRefList<ESM::CreatureLevList>, CellRefList<ESM::ItemLevList>, CellRefList<ESM::Light>,
|
||||
CellRefList<ESM::Lockpick>, CellRefList<ESM::Miscellaneous>, CellRefList<ESM::NPC>, CellRefList<ESM::Probe>,
|
||||
CellRefList<ESM::Repair>, CellRefList<ESM::Static>, CellRefList<ESM::Weapon>, CellRefList<ESM::BodyPart>>;
|
||||
CellRefList<ESM::Repair>, CellRefList<ESM::Static>, CellRefList<ESM::Weapon>, CellRefList<ESM::BodyPart>,
|
||||
|
||||
CellRefList<ESM4::Static>>;
|
||||
|
||||
/// \brief Mutable state of a cell
|
||||
class CellStore
|
||||
@ -188,11 +224,14 @@ namespace MWWorld
|
||||
}
|
||||
|
||||
/// @param readerList The readers to use for loading of the cell on-demand.
|
||||
CellStore(const ESM::Cell* cell, const MWWorld::ESMStore& store, ESM::ReadersCache& readers);
|
||||
CellStore(CellVariant cell, const MWWorld::ESMStore& store, ESM::ReadersCache& readers);
|
||||
CellStore(CellStore&&);
|
||||
~CellStore();
|
||||
|
||||
const ESM::Cell* getCell() const;
|
||||
CellVariant getCellVariant() const;
|
||||
|
||||
std::string_view getEditorName() const;
|
||||
|
||||
State getState() const;
|
||||
|
||||
@ -339,6 +378,7 @@ namespace MWWorld
|
||||
// Should be phased out when we have const version of forEach
|
||||
inline const CellRefList<ESM::Door>& getReadOnlyDoors() const { return get<ESM::Door>(); }
|
||||
inline const CellRefList<ESM::Static>& getReadOnlyStatics() const { return get<ESM::Static>(); }
|
||||
inline const CellRefList<ESM4::Static>& getReadOnlyEsm4Statics() const { return get<ESM4::Static>(); }
|
||||
|
||||
bool isExterior() const;
|
||||
|
||||
@ -374,20 +414,22 @@ namespace MWWorld
|
||||
|
||||
Ptr getMovedActor(int actorId) const;
|
||||
|
||||
bool operator==(const CellStore& right) const;
|
||||
|
||||
private:
|
||||
/// Run through references and store IDs
|
||||
void listRefs();
|
||||
|
||||
void loadRefs();
|
||||
|
||||
void loadRef(const ESM4::Reference& ref, bool deleted);
|
||||
void loadRef(ESM::CellRef& ref, bool deleted, std::map<ESM::RefNum, ESM::RefId>& refNumToID);
|
||||
///< Make case-adjustments to \a ref and insert it into the respective container.
|
||||
///
|
||||
/// Invalid \a ref objects are silently dropped.
|
||||
///
|
||||
};
|
||||
|
||||
bool operator==(const CellStore& left, const CellStore& right);
|
||||
bool operator!=(const CellStore& left, const CellStore& right);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -87,7 +87,8 @@ namespace MWWorld
|
||||
{
|
||||
if (const LiveCellRef<T>* ref = dynamic_cast<const LiveCellRef<T>*>(value))
|
||||
return ref;
|
||||
throw std::runtime_error(makeDynamicCastErrorMessage(value, T::getRecordType()));
|
||||
throw std::runtime_error(
|
||||
makeDynamicCastErrorMessage(value, ESM::getRecNameString(T::sRecordId).toStringView()));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -95,7 +96,8 @@ namespace MWWorld
|
||||
{
|
||||
if (LiveCellRef<T>* ref = dynamic_cast<LiveCellRef<T>*>(value))
|
||||
return ref;
|
||||
throw std::runtime_error(makeDynamicCastErrorMessage(value, T::getRecordType()));
|
||||
throw std::runtime_error(
|
||||
makeDynamicCastErrorMessage(value, ESM::getRecNameString(T::sRecordId).toStringView()));
|
||||
}
|
||||
|
||||
/// A reference to one object (of any type) in a cell.
|
||||
@ -130,7 +132,13 @@ namespace MWWorld
|
||||
void save(ESM::ObjectState& state) const override;
|
||||
///< Save LiveCellRef state into \a state.
|
||||
|
||||
std::string_view getTypeDescription() const override { return X::getRecordType(); }
|
||||
std::string_view getTypeDescription() const override
|
||||
{
|
||||
if constexpr (ESM::isESM4Rec(X::sRecordId))
|
||||
return ESM::getRecNameString(X::sRecordId).toStringView();
|
||||
else
|
||||
return X::getRecordType();
|
||||
}
|
||||
|
||||
static bool checkState(const ESM::ObjectState& state);
|
||||
///< Check if state is valid and report errors.
|
||||
|
@ -380,55 +380,62 @@ namespace MWWorld
|
||||
assert(mActiveCells.find(cell) == mActiveCells.end());
|
||||
mActiveCells.insert(cell);
|
||||
|
||||
Log(Debug::Info) << "Loading cell " << cell->getCell()->getDescription();
|
||||
Log(Debug::Info) << "Loading cell " << cell->getEditorName();
|
||||
|
||||
const int cellX = cell->getCell()->getGridX();
|
||||
const int cellY = cell->getCell()->getGridY();
|
||||
|
||||
if (cell->getCell()->isExterior())
|
||||
auto cell3 = cell->getCellVariant().getEsm3();
|
||||
int cellX = 0;
|
||||
int cellY = 0;
|
||||
if (cell3 != nullptr)
|
||||
{
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
const int verts = ESM::Land::LAND_SIZE;
|
||||
const int worldsize = ESM::Land::REAL_SIZE;
|
||||
if (data)
|
||||
{
|
||||
mPhysics->addHeightField(
|
||||
data->mHeights, cellX, cellY, worldsize, verts, data->mMinHeight, data->mMaxHeight, land.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
static std::vector<float> defaultHeight;
|
||||
defaultHeight.resize(verts * verts, ESM::Land::DEFAULT_HEIGHT);
|
||||
mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts,
|
||||
ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
|
||||
}
|
||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||
{
|
||||
const osg::Vec2i cellPosition(cellX, cellY);
|
||||
const btVector3& origin = heightField->getCollisionObject()->getWorldTransform().getOrigin();
|
||||
const osg::Vec3f shift(origin.x(), origin.y(), origin.z());
|
||||
const HeightfieldShape shape = [&]() -> HeightfieldShape {
|
||||
if (data == nullptr)
|
||||
{
|
||||
return DetourNavigator::HeightfieldPlane{ static_cast<float>(ESM::Land::DEFAULT_HEIGHT) };
|
||||
}
|
||||
else
|
||||
{
|
||||
DetourNavigator::HeightfieldSurface heights;
|
||||
heights.mHeights = data->mHeights;
|
||||
heights.mSize = static_cast<std::size_t>(ESM::Land::LAND_SIZE);
|
||||
heights.mMinHeight = data->mMinHeight;
|
||||
heights.mMaxHeight = data->mMaxHeight;
|
||||
return heights;
|
||||
}
|
||||
}();
|
||||
mNavigator.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, shape, navigatorUpdateGuard);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
||||
mNavigator.addPathgrid(*cell->getCell(), *pathgrid);
|
||||
int cellX = cell3->getGridX();
|
||||
int cellY = cell3->getGridY();
|
||||
|
||||
if (cell3->isExterior())
|
||||
{
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
const int verts = ESM::Land::LAND_SIZE;
|
||||
const int worldsize = ESM::Land::REAL_SIZE;
|
||||
if (data)
|
||||
{
|
||||
mPhysics->addHeightField(
|
||||
data->mHeights, cellX, cellY, worldsize, verts, data->mMinHeight, data->mMaxHeight, land.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
static std::vector<float> defaultHeight;
|
||||
defaultHeight.resize(verts * verts, ESM::Land::DEFAULT_HEIGHT);
|
||||
mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts,
|
||||
ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
|
||||
}
|
||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||
{
|
||||
const osg::Vec2i cellPosition(cellX, cellY);
|
||||
const btVector3& origin = heightField->getCollisionObject()->getWorldTransform().getOrigin();
|
||||
const osg::Vec3f shift(origin.x(), origin.y(), origin.z());
|
||||
const HeightfieldShape shape = [&]() -> HeightfieldShape {
|
||||
if (data == nullptr)
|
||||
{
|
||||
return DetourNavigator::HeightfieldPlane{ static_cast<float>(ESM::Land::DEFAULT_HEIGHT) };
|
||||
}
|
||||
else
|
||||
{
|
||||
DetourNavigator::HeightfieldSurface heights;
|
||||
heights.mHeights = data->mHeights;
|
||||
heights.mSize = static_cast<std::size_t>(ESM::Land::LAND_SIZE);
|
||||
heights.mMinHeight = data->mMinHeight;
|
||||
heights.mMaxHeight = data->mMaxHeight;
|
||||
return heights;
|
||||
}
|
||||
}();
|
||||
mNavigator.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, shape, navigatorUpdateGuard);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto pathgrid = mWorld.getStore().get<ESM::Pathgrid>().search(*cell3))
|
||||
mNavigator.addPathgrid(*cell3, *pathgrid);
|
||||
}
|
||||
|
||||
// register local scripts
|
||||
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
||||
@ -442,7 +449,7 @@ namespace MWWorld
|
||||
mRendering.addCell(cell);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->addCell(cell);
|
||||
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
|
||||
bool waterEnabled = cell3 && (cell3->hasWater() || cell->isExterior());
|
||||
float waterLevel = cell->getWaterLevel();
|
||||
mRendering.setWaterEnabled(waterEnabled);
|
||||
if (waterEnabled)
|
||||
@ -450,7 +457,7 @@ namespace MWWorld
|
||||
mPhysics->enableWater(waterLevel);
|
||||
mRendering.setWaterHeight(waterLevel);
|
||||
|
||||
if (cell->getCell()->isExterior())
|
||||
if (cell3->isExterior())
|
||||
{
|
||||
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||
mNavigator.addWater(
|
||||
@ -465,8 +472,8 @@ namespace MWWorld
|
||||
else
|
||||
mPhysics->disableWater();
|
||||
|
||||
if (!cell->isExterior() && !(cell->getCell()->mData.mFlags & ESM::Cell::QuasiEx))
|
||||
mRendering.configureAmbient(cell->getCell());
|
||||
if (cell3 && !cell->isExterior() && !(cell3->mData.mFlags & ESM::Cell::QuasiEx))
|
||||
mRendering.configureAmbient(cell3);
|
||||
|
||||
mPreloader->notifyLoaded(cell);
|
||||
}
|
||||
@ -879,8 +886,7 @@ namespace MWWorld
|
||||
|
||||
loadingListener->setProgressRange(cell->count());
|
||||
|
||||
mNavigator.setWorldspace(
|
||||
Misc::StringUtils::lowerCase(cell->getCell()->mCellId.mWorldspace), navigatorUpdateGuard.get());
|
||||
mNavigator.setWorldspace(Misc::StringUtils::lowerCase(cell->getEditorName()), navigatorUpdateGuard.get());
|
||||
mNavigator.updateBounds(position.asVec3(), navigatorUpdateGuard.get());
|
||||
|
||||
// Load cell.
|
||||
|
@ -1170,20 +1170,6 @@ namespace MWWorld
|
||||
return mKeywordSearch;
|
||||
}
|
||||
|
||||
ESM::FixedString<6> getRecNameString(ESM::RecNameInts recName)
|
||||
{
|
||||
ESM::FixedString<6> name;
|
||||
name.assign("");
|
||||
ESM::NAME fourCCName(recName & ~ESM::sEsm4RecnameFlag);
|
||||
for (int i = 0; i < 4; i++)
|
||||
name.mData[i] = fourCCName.mData[i];
|
||||
if (ESM::isESM4Rec(recName))
|
||||
{
|
||||
name.mData[4] = '4';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// ESM4 Cell
|
||||
//=========================================================================
|
||||
|
||||
|
@ -533,8 +533,6 @@ namespace MWWorld
|
||||
const MWDialogue::KeywordSearch<std::string, int>& getDialogIdKeywordSearch() const;
|
||||
};
|
||||
|
||||
ESM::FixedString<6> getRecNameString(ESM::RecNameInts recName);
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <components/esm3/loadregn.hpp>
|
||||
#include <components/esm3/loadstat.hpp>
|
||||
|
||||
#include <components/esm4/loadstat.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/convert.hpp>
|
||||
#include <components/misc/mathutil.hpp>
|
||||
@ -2804,6 +2806,24 @@ namespace MWWorld
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const MWWorld::LiveCellRef<ESM4::Static>& stat4 : cellStore->getReadOnlyEsm4Statics().mList)
|
||||
{
|
||||
if (Misc::StringUtils::lowerCase(stat4.mBase->mEditorId) == "cocmarkerheading")
|
||||
{
|
||||
// found the COC position?
|
||||
pos = stat4.mRef.getPosition();
|
||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Fall back to the first static location.
|
||||
const MWWorld::CellRefList<ESM4::Static>::List& statics4 = cellStore->getReadOnlyEsm4Statics().mList;
|
||||
if (!statics4.empty())
|
||||
{
|
||||
pos = statics4.begin()->mRef.getPosition();
|
||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||
return true;
|
||||
}
|
||||
// Fall back to the first static location.
|
||||
const MWWorld::CellRefList<ESM::Static>::List& statics = cellStore->getReadOnlyStatics().mList;
|
||||
if (!statics.empty())
|
||||
@ -3253,7 +3273,7 @@ namespace MWWorld
|
||||
std::set<std::string_view> checkedCells;
|
||||
std::set<std::string_view> currentCells;
|
||||
std::set<std::string_view> nextCells;
|
||||
nextCells.insert(cell->getCell()->mName);
|
||||
nextCells.insert(cell->getEditorName());
|
||||
|
||||
while (!nextCells.empty())
|
||||
{
|
||||
|
@ -202,9 +202,17 @@ MWWorld::CellStore* MWWorld::WorldModel::getInterior(std::string_view name)
|
||||
|
||||
if (result == mInteriors.end())
|
||||
{
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().find(name);
|
||||
const ESM4::Cell* cell4 = mStore.get<ESM4::Cell>().searchCellName(name);
|
||||
|
||||
result = mInteriors.emplace(name, CellStore(cell, mStore, mReaders)).first;
|
||||
if (!cell4)
|
||||
{
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().find(name);
|
||||
result = mInteriors.emplace(name, CellStore(cell, mStore, mReaders)).first;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mInteriors.emplace(name, CellStore(cell4, mStore, mReaders)).first;
|
||||
}
|
||||
}
|
||||
|
||||
if (result->second.getState() != CellStore::State_Loaded)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include "components/esm/fourcc.hpp"
|
||||
#include <components/esm/esmcommon.hpp>
|
||||
#include <components/esm4/common.hpp>
|
||||
|
||||
namespace ESM
|
||||
@ -338,6 +339,20 @@ namespace ESM
|
||||
return RecName & sEsm4RecnameFlag;
|
||||
}
|
||||
|
||||
inline FixedString<6> getRecNameString(ESM::RecNameInts recName)
|
||||
{
|
||||
ESM::FixedString<6> name;
|
||||
name.assign("");
|
||||
ESM::NAME fourCCName(recName & ~ESM::sEsm4RecnameFlag);
|
||||
for (int i = 0; i < 4; i++)
|
||||
name.mData[i] = fourCCName.mData[i];
|
||||
if (ESM::isESM4Rec(recName))
|
||||
{
|
||||
name.mData[4] = '4';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/// Common subrecords
|
||||
enum SubRecNameInts
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user