diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index e0b589c408..ac9cf7a3ee 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -3,7 +3,9 @@ #include +#include #include +#include namespace ESM { @@ -20,9 +22,19 @@ namespace MWWorld CellRef(const ESM::CellRef& ref) : mCellRef(ref) { + mIsEsm4 = false; mChanged = false; } + CellRef(const ESM4::Reference& ref) + : mCellRef4(ref) + { + mRefrPos = { { mCellRef4.mPlacement.pos.x, mCellRef4.mPlacement.pos.y, mCellRef4.mPlacement.pos.z }, + { mCellRef4.mPlacement.rot.x, mCellRef4.mPlacement.rot.y, mCellRef4.mPlacement.rot.z } }; + mChanged = false; + mIsEsm4 = true; + } + // Note: Currently unused for items in containers const ESM::RefNum& getRefNum() const { return mCellRef.mRefNum; } @@ -50,12 +62,24 @@ namespace MWWorld const std::string& getDestCell() const { return mCellRef.mDestCell; } // Scale applied to mesh - float getScale() const { return mCellRef.mScale; } + float getScale() const + { + if (mIsEsm4) + return mCellRef4.mScale; + else + return mCellRef.mScale; + } void setScale(float scale); // The *original* position and rotation as it was given in the Construction Set. // Current position and rotation of the object is stored in RefData. - const ESM::Position& getPosition() const { return mCellRef.mPos; } + const ESM::Position& getPosition() const + { + if (mIsEsm4) + return mRefrPos; + else + return mCellRef.mPos; + } void setPosition(const ESM::Position& position); // Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full). @@ -124,6 +148,9 @@ namespace MWWorld private: bool mChanged; ESM::CellRef mCellRef; + ESM4::Reference mCellRef4; + ESM::Position mRefrPos; + bool mIsEsm4; }; } diff --git a/apps/openmw/mwworld/cellreflist.hpp b/apps/openmw/mwworld/cellreflist.hpp index 8f0a31b5e3..51e1d7df05 100644 --- a/apps/openmw/mwworld/cellreflist.hpp +++ b/apps/openmw/mwworld/cellreflist.hpp @@ -28,6 +28,8 @@ namespace MWWorld /// all methods are known. void load(ESM::CellRef& ref, bool deleted, const MWWorld::ESMStore& esmStore); + void load(const ESM4::Reference& ref, bool deleted, const MWWorld::ESMStore& esmStore); + LiveRef& insert(const LiveRef& item) { mList.push_back(item); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 8e09c7953b..88d076a8f9 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -371,6 +371,37 @@ namespace MWWorld } } + template + void CellRefList::load(const ESM4::Reference& ref, bool deleted, const MWWorld::ESMStore& esmStore) + { + + if constexpr (!ESM::isESM4Rec(X::sRecordId)) + return; + + const MWWorld::Store& store = esmStore.get(); + + if (const X* ptr = store.search(ref.mBaseObj)) + { + // typename std::list::iterator iter = std::find(mList.begin(), mList.end(), ref.); + + LiveRef liveCellRef(ref, ptr); + + if (deleted) + liveCellRef.mData.setDeletedByContentFile(true); + + /*if (iter != mList.end()) + *iter = liveCellRef; + else + */ + mList.push_back(liveCellRef); + } + else + { + Log(Debug::Warning) << "Warning: could not resolve cell reference '" << ref.mId << "'" + << " (dropping reference)"; + } + } + template bool operator==(const LiveCellRef& ref, int pRefnum) { @@ -863,16 +894,6 @@ namespace MWWorld return Ptr(); } - template - static void loadRefESM4( - const MWWorld::ESMStore& store, const ESM4::Reference& ref, MWWorld::CellRefList& 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; @@ -881,7 +902,7 @@ namespace MWWorld Misc::tupleForEach(this->mCellStoreImp->mRefLists, [&ref, &deleted, &store, foundType](auto& x) { recNameSwitcher( - x, foundType, [&ref, &deleted, &store](auto& storeIn) { loadRefESM4(store, ref, storeIn, deleted); }); + x, foundType, [&ref, &deleted, &store](auto& storeIn) { storeIn.load(ref, deleted, store); }); }); } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index aa5185149b..7d9fda7273 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -210,8 +210,8 @@ namespace MWWorld static bool readRecord(ESM4::Reader& reader, ESMStore& store) { - return std::apply([&reader](auto&... x) { return (ESMStoreImp::typedReadRecordESM4(reader, x) || ...); }, - store.mStoreImp->mStores); + return std::apply( + [&reader](auto&... x) { return (typedReadRecordESM4(reader, x) || ...); }, store.mStoreImp->mStores); } }; @@ -278,6 +278,7 @@ namespace MWWorld case ESM::REC_STAT: case ESM::REC_WEAP: case ESM::REC_BODY: + case ESM::REC_STAT4: return true; break; } @@ -595,8 +596,8 @@ namespace MWWorld removeMissingObjects(getWritable()); } - // Leveled lists can be modified by scripts. This removes items that no longer exist (presumably because the plugin - // was removed) from modified lists + // Leveled lists can be modified by scripts. This removes items that no longer exist (presumably because the + // plugin was removed) from modified lists template void ESMStore::removeMissingObjects(Store& store) { diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index 66e31be635..88218429e1 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -22,6 +22,13 @@ MWWorld::LiveCellRefBase::LiveCellRefBase(unsigned int type, const ESM::CellRef& { } +MWWorld::LiveCellRefBase::LiveCellRefBase(unsigned int type, const ESM4::Reference& cref) + : mClass(&Class::get(type)) + , mRef(cref) + , mData(cref) +{ +} + void MWWorld::LiveCellRefBase::loadImp(const ESM::ObjectState& state) { mRef = state.mRef; diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 4e3cb322cc..dc38ff9830 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -35,6 +35,7 @@ namespace MWWorld RefData mData; LiveCellRefBase(unsigned int type, const ESM::CellRef& cref = ESM::CellRef()); + LiveCellRefBase(unsigned int type, const ESM4::Reference& cref); /* Need this for the class to be recognized as polymorphic */ virtual ~LiveCellRefBase() {} @@ -115,6 +116,12 @@ namespace MWWorld { } + LiveCellRef(const ESM4::Reference& cref, const X* b = nullptr) + : LiveCellRefBase(X::sRecordId, cref) + , mBase(b) + { + } + LiveCellRef(const X* b = nullptr) : LiveCellRefBase(X::sRecordId) , mBase(b) diff --git a/apps/openmw/mwworld/manualref.cpp b/apps/openmw/mwworld/manualref.cpp index ec5a3f5e77..741e036154 100644 --- a/apps/openmw/mwworld/manualref.cpp +++ b/apps/openmw/mwworld/manualref.cpp @@ -1,5 +1,6 @@ #include "manualref.hpp" #include +#include #include "esmstore.hpp" @@ -89,7 +90,9 @@ MWWorld::ManualRef::ManualRef(const MWWorld::ESMStore& store, const ESM::RefId& case ESM::REC_BODY: create(store.get(), name, mRef, mPtr); break; - + case ESM::REC_STAT4: + create(store.get(), name, mRef, mPtr); + break; case 0: throw std::logic_error("failed to create manual cell ref for " + name.getRefIdString() + " (unknown ID)"); diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index ffc5af7ff9..b1e03a5722 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -85,6 +85,20 @@ namespace MWWorld { } + RefData::RefData(const ESM4::Reference& cellRef) + : mBaseNode(nullptr) + , mDeletedByContentFile(false) + , mEnabled(true) + , mPhysicsPostponed(false) + , mCount(1) + , mPosition{ { cellRef.mPlacement.pos.x, cellRef.mPlacement.pos.y, cellRef.mPlacement.pos.z }, + { cellRef.mPlacement.rot.x, cellRef.mPlacement.rot.y, cellRef.mPlacement.rot.z } } + , mCustomData(nullptr) + , mChanged(false) + , mFlags(0) + { + } + RefData::RefData(const ESM::ObjectState& objectState, bool deletedByContentFile) : mBaseNode(nullptr) , mDeletedByContentFile(deletedByContentFile) diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 1abc2264bf..0ceb951335 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -25,6 +25,11 @@ namespace ESM struct ObjectState; } +namespace ESM4 +{ + struct Reference; +} + namespace MWLua { class LocalScripts; @@ -76,6 +81,7 @@ namespace MWWorld /// be altered without affecting the original data. This makes it possible /// to reset the position as the original data is still held in the CellRef RefData(const ESM::CellRef& cellRef); + RefData(const ESM4::Reference& cellRef); RefData(const ESM::ObjectState& objectState, bool deletedByContentFile); ///< Ignores local variables and custom data (not enough context available here to diff --git a/components/esm/esm3esm4bridge.hpp b/components/esm/esm3esm4bridge.hpp index a8067c11a1..4c6eaf5875 100644 --- a/components/esm/esm3esm4bridge.hpp +++ b/components/esm/esm3esm4bridge.hpp @@ -1,5 +1,5 @@ -#ifndef COMPONENTS_ESM_CELLCOMMON -#define COMPONENTS_ESM_CELLCOMMON +#ifndef COMPONENTS_ESM_ESMBRIDGE +#define COMPONENTS_ESM_ESMBRIDGE #include #include #include