From 024ad3276b472e0fc58b681d10566917e4d8d44d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 29 Jun 2021 19:20:01 +1000 Subject: [PATCH 01/17] Partial fix for #6017. The persistence flag of the references are saved but it is not yet possible to modify it via OpenCS. --- apps/opencs/model/doc/savingstages.cpp | 119 ++++++++++++---------- apps/opencs/model/doc/savingstages.hpp | 2 + apps/opencs/model/world/refcollection.cpp | 5 +- components/esm/cellref.cpp | 21 +++- components/esm/cellref.hpp | 6 +- components/esm/loadcell.cpp | 17 ++-- components/esm/loadcell.hpp | 4 +- 7 files changed, 109 insertions(+), 65 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 44698cd2e3..5e94f40b0f 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -253,6 +253,70 @@ int CSMDoc::WriteCellCollectionStage::setup() return mDocument.getData().getCells().getSize(); } +int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum, bool temp) +{ + ESM::ESMWriter& writer = mState.getWriter(); + size_t refCount = 0; + + for (std::deque::const_iterator iter (references.begin()); + iter!=references.end(); ++iter) + { + const CSMWorld::Record& ref = + mDocument.getData().getReferences().getRecord (*iter); + + if (temp && ref.get().mIsPersistent || !temp && !ref.get().mIsPersistent) + continue; + + refCount++; + + if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted) + { + CSMWorld::CellRef refRecord = ref.get(); + + // Check for uninitialized content file + if (!refRecord.mRefNum.hasContentFile()) + refRecord.mRefNum.mContentFile = 0; + + // recalculate the ref's cell location + std::ostringstream stream; + if (!interior) + { + std::pair index = refRecord.getCellIndex(); + stream << "#" << index.first << " " << index.second; + } + + if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 || + (!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly && + refRecord.mCell!=stream.str())) + { + refRecord.mRefNum.mIndex = newRefNum++; + } + else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) + != stream.str() && !interior) + { + // An empty mOriginalCell is meant to indicate that it is the same as + // the current cell. It is possible that a moved ref is moved again. + + ESM::MovedCellRef moved; + moved.mRefNum = refRecord.mRefNum; + + // Need to fill mTarget with the ref's new position. + std::istringstream istream (stream.str().c_str()); + + char ignore; + istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; + + refRecord.mRefNum.save (writer, false, "MVRF"); + writer.writeHNT ("CNDT", moved.mTarget); + } + + refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted); + } + } + + return refCount; +} + void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) { ESM::ESMWriter& writer = mState.getWriter(); @@ -289,7 +353,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (refRecord.mRefNum.mIndex >= newRefNum) newRefNum = refRecord.mRefNum.mIndex + 1; - } } @@ -312,56 +375,10 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) // write references if (references!=mState.getSubRecords().end()) { - for (std::deque::const_iterator iter (references->second.begin()); - iter!=references->second.end(); ++iter) - { - const CSMWorld::Record& ref = - mDocument.getData().getReferences().getRecord (*iter); - - if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted) - { - CSMWorld::CellRef refRecord = ref.get(); - - // Check for uninitialized content file - if (!refRecord.mRefNum.hasContentFile()) - refRecord.mRefNum.mContentFile = 0; - - // recalculate the ref's cell location - std::ostringstream stream; - if (!interior) - { - std::pair index = refRecord.getCellIndex(); - stream << "#" << index.first << " " << index.second; - } - - if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 || - (!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly && - refRecord.mCell!=stream.str())) - { - refRecord.mRefNum.mIndex = newRefNum++; - } - else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) - != stream.str() && !interior) - { - // An empty mOriginalCell is meant to indicate that it is the same as - // the current cell. It is possible that a moved ref is moved again. - - ESM::MovedCellRef moved; - moved.mRefNum = refRecord.mRefNum; - - // Need to fill mTarget with the ref's new position. - std::istringstream istream (stream.str().c_str()); - - char ignore; - istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; - - refRecord.mRefNum.save (writer, false, "MVRF"); - writer.writeHNT ("CNDT", moved.mTarget); - } - - refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted); - } - } + int persistentRefCount = writeReferences(references->second, interior, newRefNum, false/*temp*/); + cellRecord.saveTempMarker(writer, int(references->second.size()) - persistentRefCount); + // FIXME: loops twice, inefficient + writeReferences(references->second, interior, newRefNum, true/*temp*/); } writer.endRecord (cellRecord.sRecordId); diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index d3a0cc9b31..e9497a6064 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -171,6 +171,8 @@ namespace CSMDoc Document& mDocument; SavingState& mState; + int writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum, bool temp); + public: WriteCellCollectionStage (Document& document, SavingState& state); diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index dfdb8e73bf..2f5db65636 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -19,8 +19,9 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool ESM::MovedCellRef mref; mref.mRefNum.mIndex = 0; bool isDeleted = false; + int tempRefCount = cell.get().mRefNumCounter; // if initially non-zero, all refs in cell are temp - while (ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref)) + while (ESM::Cell::getNextRef(reader, ref, isDeleted, &tempRefCount, true, &mref)) { // Keep mOriginalCell empty when in modified (as an indicator that the // original cell will always be equal the current cell). @@ -59,6 +60,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool else ref.mCell = cell2.mId; + // TODO: update cell.get().mRefNumCounter with tempRefCount? + mref.mRefNum.mIndex = 0; // ignore content file number diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index b4d6ac7a72..42bc3d648f 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -31,10 +31,10 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const } -void ESM::CellRef::load (ESMReader& esm, bool &isDeleted, bool wideRefNum) +void ESM::CellRef::load (ESMReader& esm, bool &isDeleted, int *tempRefCount, bool wideRefNum) { loadId(esm, wideRefNum); - loadData(esm, isDeleted); + loadData(esm, isDeleted, tempRefCount); } void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) @@ -57,9 +57,11 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) } } -void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted) +void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted, int *tempRefCount) { isDeleted = false; + mIsPersistent = !tempRefCount // default to persistent + || (tempRefCount && *tempRefCount == -1); bool isLoaded = false; while (!isLoaded && esm.hasMoreSubs()) @@ -121,8 +123,17 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted) esm.getHT(mPos, 24); break; case ESM::FourCC<'N','A','M','0'>::value: - esm.skipHSub(); + { + if (tempRefCount && *tempRefCount == -1) + { + esm.getHT(*tempRefCount); + // TODO: check that there are no more subs following this sub + } + else + esm.skipHSub(); + break; + } case ESM::SREC_DELE: esm.skipHSub(); isDeleted = true; @@ -236,4 +247,6 @@ void ESM::CellRef::blank() mPos.pos[i] = 0; mPos.rot[i] = 0; } + + mIsPersistent = false; } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index c2f7ff6de5..97cfea89d0 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -106,13 +106,15 @@ namespace ESM // Position and rotation of this object within the cell Position mPos; + bool mIsPersistent; + /// Calls loadId and loadData - void load (ESMReader& esm, bool &isDeleted, bool wideRefNum = false); + void load (ESMReader& esm, bool &isDeleted, int *tempRefCount, bool wideRefNum = false); void loadId (ESMReader& esm, bool wideRefNum = false); /// Implicitly called by load - void loadData (ESMReader& esm, bool &isDeleted); + void loadData (ESMReader& esm, bool &isDeleted, int *tempRefCount = nullptr); void save (ESMWriter &esm, bool wideRefNum = false, bool inInventory = false, bool isDeleted = false) const; diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index bf70aad96f..8aeacd5116 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -146,7 +146,7 @@ namespace ESM } } - if (saveContext) + if (saveContext) { mContextList.push_back(esm.getContext()); esm.skipRecord(); @@ -197,9 +197,12 @@ namespace ESM if (mMapColor != 0) esm.writeHNT("NAM5", mMapColor); } + } - if (mRefNumCounter != 0) - esm.writeHNT("NAM0", mRefNumCounter); + void Cell::saveTempMarker(ESMWriter &esm, int tempCount) const + { + if (tempCount != 0) + esm.writeHNT("NAM0", tempCount); } void Cell::restore(ESMReader &esm, int iCtx) const @@ -221,7 +224,7 @@ namespace ESM return region + ' ' + cellGrid; } - bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, bool ignoreMoves, MovedCellRef *mref) + bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, int *tempRefCount, bool ignoreMoves, MovedCellRef *mref) { isDeleted = false; @@ -249,7 +252,9 @@ namespace ESM if (esm.peekNextSub("FRMR")) { - ref.load (esm, isDeleted); + ref.load (esm, isDeleted, tempRefCount); + + // TODO: should count the number of temp refs and validate the number // Identify references belonging to a parent file and adapt the ID accordingly. adjustRefNum (ref.mRefNum, esm); @@ -275,7 +280,7 @@ namespace ESM mWater = 0; mWaterInt = false; mMapColor = 0; - mRefNumCounter = 0; + mRefNumCounter = -1; mData.mFlags = 0; mData.mX = 0; diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index d06b509c5a..ca4ca6e577 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -94,7 +94,7 @@ struct Cell mWater(0), mWaterInt(false), mMapColor(0), - mRefNumCounter(0) + mRefNumCounter(-1) {} // Interior cells are indexed by this (it's the 'id'), for exterior @@ -133,6 +133,7 @@ struct Cell void loadCell(ESMReader &esm, bool saveContext = true); // Load everything, except NAME, DATAstruct and references void save(ESMWriter &esm, bool isDeleted = false) const; + void saveTempMarker(ESMWriter &esm, int tempCount) const; bool isExterior() const { @@ -184,6 +185,7 @@ struct Cell static bool getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, + int *tempRefCount = nullptr, bool ignoreMoves = false, MovedCellRef *mref = nullptr); From f6eab52a1b8fd005d1d55ed9b164f76e225f8735 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 29 Jun 2021 19:45:02 +1000 Subject: [PATCH 02/17] Added "Persistent" column to references table. --- apps/opencs/model/world/columnimp.hpp | 27 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 2 ++ apps/opencs/model/world/columns.hpp | 2 ++ apps/opencs/model/world/data.cpp | 1 + 4 files changed, 32 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 17518937c2..11b47e1a08 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1429,6 +1429,33 @@ namespace CSMWorld } }; + template + struct PersistentColumn : public Column + { + PersistentColumn() + : Column (Columns::ColumnId_Persistent, ColumnBase::Display_Boolean) + {} + + QVariant get (const Record& record) const override + { + return record.get().mIsPersistent; + } + + void set (Record& record, const QVariant& data) override + { + ESXRecordT record2 = record.get(); + + record2.mIsPersistent = data.toInt(); + + record.setModified (record2); + } + + bool isEditable() const override + { + return true; + } + }; + template struct QuestStatusTypeColumn : public Column { diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index eaea66c2f9..1b91997a5f 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -371,6 +371,8 @@ namespace CSMWorld { ColumnId_Skill6, "Skill 6" }, { ColumnId_Skill7, "Skill 7" }, + { ColumnId_Persistent, "Persistent" }, + { -1, 0 } // end marker }; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index c85eaac5f1..b50fb71e04 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -343,6 +343,8 @@ namespace CSMWorld ColumnId_FactionAttrib1 = 311, ColumnId_FactionAttrib2 = 312, + ColumnId_Persistent = 313, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4ccd2a06db..0132584762 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -528,6 +528,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat mRefs.addColumn (new TrapColumn); mRefs.addColumn (new OwnerGlobalColumn); mRefs.addColumn (new RefNumColumn); + mRefs.addColumn (new PersistentColumn); mFilters.addColumn (new StringIdColumn); mFilters.addColumn (new RecordStateColumn); From 2a76634f5f1891792e5f60d16482a08403314253 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 29 Jun 2021 23:25:26 +1000 Subject: [PATCH 03/17] Moved persistence flag from references to the header flags of referenceables (e.g. Static, Weapon, etc). Editing widget is not fully working. --- apps/opencs/model/doc/savingstages.cpp | 7 +- apps/opencs/model/world/columnimp.hpp | 27 ---- apps/opencs/model/world/data.cpp | 1 - apps/opencs/model/world/refidadapterimp.hpp | 20 ++- apps/opencs/model/world/refidcollection.cpp | 2 + apps/opencs/model/world/refiddata.cpp | 133 ++++++++++++++++++++ apps/opencs/model/world/refiddata.hpp | 4 +- components/esm/cellref.cpp | 4 - components/esm/cellref.hpp | 2 - components/esm/loadacti.cpp | 1 + components/esm/loadacti.hpp | 1 + components/esm/loadalch.cpp | 1 + components/esm/loadalch.hpp | 1 + components/esm/loadappa.cpp | 1 + components/esm/loadappa.hpp | 1 + components/esm/loadarmo.cpp | 1 + components/esm/loadarmo.hpp | 1 + components/esm/loadbook.cpp | 1 + components/esm/loadbook.hpp | 1 + components/esm/loadclot.cpp | 1 + components/esm/loadclot.hpp | 1 + components/esm/loadcont.cpp | 1 + components/esm/loadcont.hpp | 1 + components/esm/loadcrea.cpp | 3 +- components/esm/loadcrea.hpp | 1 + components/esm/loaddoor.cpp | 1 + components/esm/loaddoor.hpp | 1 + components/esm/loadingr.cpp | 1 + components/esm/loadingr.hpp | 1 + components/esm/loadlevlist.cpp | 1 + components/esm/loadlevlist.hpp | 1 + components/esm/loadligh.cpp | 1 + components/esm/loadligh.hpp | 1 + components/esm/loadlock.cpp | 1 + components/esm/loadlock.hpp | 1 + components/esm/loadmisc.cpp | 1 + components/esm/loadmisc.hpp | 1 + components/esm/loadnpc.cpp | 3 +- components/esm/loadnpc.hpp | 1 + components/esm/loadprob.cpp | 1 + components/esm/loadprob.hpp | 1 + components/esm/loadrepa.cpp | 1 + components/esm/loadrepa.hpp | 1 + components/esm/loadstat.cpp | 3 + components/esm/loadstat.hpp | 1 + components/esm/loadweap.cpp | 1 + components/esm/loadweap.hpp | 1 + 47 files changed, 205 insertions(+), 39 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 5e94f40b0f..7d6e8fef88 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -257,6 +257,8 @@ int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& re { ESM::ESMWriter& writer = mState.getWriter(); size_t refCount = 0; + const CSMWorld::RefIdCollection& referenceables = mDocument.getData().getReferenceables(); + const CSMWorld::RefIdData& refIdData = referenceables.getDataSet(); for (std::deque::const_iterator iter (references.begin()); iter!=references.end(); ++iter) @@ -264,7 +266,10 @@ int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& re const CSMWorld::Record& ref = mDocument.getData().getReferences().getRecord (*iter); - if (temp && ref.get().mIsPersistent || !temp && !ref.get().mIsPersistent) + unsigned int recordFlags = refIdData.getRecordFlags(ref.get().mId); + bool isPersistent = (recordFlags & 0x00000400) != 0; + + if (temp && isPersistent || !temp && !isPersistent) continue; refCount++; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 11b47e1a08..17518937c2 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -1429,33 +1429,6 @@ namespace CSMWorld } }; - template - struct PersistentColumn : public Column - { - PersistentColumn() - : Column (Columns::ColumnId_Persistent, ColumnBase::Display_Boolean) - {} - - QVariant get (const Record& record) const override - { - return record.get().mIsPersistent; - } - - void set (Record& record, const QVariant& data) override - { - ESXRecordT record2 = record.get(); - - record2.mIsPersistent = data.toInt(); - - record.setModified (record2); - } - - bool isEditable() const override - { - return true; - } - }; - template struct QuestStatusTypeColumn : public Column { diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 0132584762..4ccd2a06db 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -528,7 +528,6 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat mRefs.addColumn (new TrapColumn); mRefs.addColumn (new OwnerGlobalColumn); mRefs.addColumn (new RefNumColumn); - mRefs.addColumn (new PersistentColumn); mFilters.addColumn (new StringIdColumn); mFilters.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 3d784f1b2b..f8ca93fec7 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -114,8 +114,9 @@ namespace CSMWorld struct ModelColumns : public BaseColumns { const RefIdColumn *mModel; + const RefIdColumn *mPersistence; - ModelColumns (const BaseColumns& base) : BaseColumns (base), mModel(nullptr) {} + ModelColumns (const BaseColumns& base) : BaseColumns (base), mModel(nullptr), mPersistence(nullptr) {} }; /// \brief Adapter for IDs with models (all but levelled lists) @@ -151,6 +152,12 @@ namespace CSMWorld if (column==mModel.mModel) return QString::fromUtf8 (record.get().mModel.c_str()); + if (column==mModel.mPersistence) + { + bool isPersistent = (record.get().mRecordFlags & 0x00000400) != 0; + return QString::fromUtf8 (isPersistent ? "Yes" : "No"); + } + return BaseRefIdAdapter::getData (column, data, index); } @@ -164,6 +171,17 @@ namespace CSMWorld RecordT record2 = record.get(); if (column==mModel.mModel) record2.mModel = value.toString().toUtf8().constData(); + else if (column==mModel.mPersistence) + { + unsigned int flag = record2.mRecordFlags; + std::string val = value.toString().toUtf8().constData(); + if (val == "Yes") + flag |= 0x00000400; + else if (val == "No") + flag &= ~0x00000400; + + record2.mRecordFlags = flag; + } else { BaseRefIdAdapter::setData (column, data, index, value); diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index cd2dd89dff..b7370c20da 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -54,6 +54,8 @@ CSMWorld::RefIdCollection::RefIdCollection() mColumns.emplace_back(Columns::ColumnId_Model, ColumnBase::Display_Mesh); modelColumns.mModel = &mColumns.back(); + mColumns.emplace_back(Columns::ColumnId_Persistent, ColumnBase::Display_Boolean); + modelColumns.mPersistence = &mColumns.back(); NameColumns nameColumns (modelColumns); diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp index e2ffbcca6b..4f72bae92e 100644 --- a/apps/opencs/model/world/refiddata.cpp +++ b/apps/opencs/model/world/refiddata.cpp @@ -87,6 +87,139 @@ CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId ( return iter->second; } +unsigned int CSMWorld::RefIdData::getRecordFlags (const std::string& id) const +{ + LocalIndex localIndex = searchId (id); + + switch (localIndex.second) + { + case UniversalId::Type_Activator: + { + const RefIdDataContainer& records = getActivators(); + const ESM::Activator& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Potion: + { + const RefIdDataContainer& records = getPotions(); + const ESM::Potion& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Apparatus: + { + const RefIdDataContainer& records = getApparati(); + const ESM::Apparatus& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Armor: + { + const RefIdDataContainer& records = getArmors(); + const ESM::Armor& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Book: + { + const RefIdDataContainer& records = getBooks(); + const ESM::Book& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Clothing: + { + const RefIdDataContainer& records = getClothing(); + const ESM::Clothing& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Container: + { + const RefIdDataContainer& records = getContainers(); + const ESM::Container& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Creature: + { + const RefIdDataContainer& records = getCreatures(); + const ESM::Creature& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Door: + { + const RefIdDataContainer& records = getDoors(); + const ESM::Door& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Ingredient: + { + const RefIdDataContainer& records = getIngredients(); + const ESM::Ingredient& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_CreatureLevelledList: + { + const RefIdDataContainer& records = getCreatureLevelledLists(); + const ESM::CreatureLevList& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_ItemLevelledList: + { + const RefIdDataContainer& records = getItemLevelledList(); + const ESM::ItemLevList& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Light: + { + const RefIdDataContainer& records = getLights(); + const ESM::Light& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Lockpick: + { + const RefIdDataContainer& records = getLocpicks(); + const ESM::Lockpick& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Miscellaneous: + { + const RefIdDataContainer& records = getMiscellaneous(); + const ESM::Miscellaneous& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Npc: + { + const RefIdDataContainer& records = getNPCs(); + const ESM::NPC& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Probe: + { + const RefIdDataContainer& records = getProbes(); + const ESM::Probe& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Repair: + { + const RefIdDataContainer& records = getRepairs(); + const ESM::Repair& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Static: + { + const RefIdDataContainer& records = getStatics(); + const ESM::Static& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + case UniversalId::Type_Weapon: + { + const RefIdDataContainer& records = getWeapons(); + const ESM::Weapon& record = dynamic_cast(records.getRecord(localIndex.first)); + return record.mRecordFlags; + } + default: + break; + } + + return 0; +} + void CSMWorld::RefIdData::erase (int index, int count) { LocalIndex localIndex = globalToLocalIndex (index); diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index 1480bb71d9..da6ac7b154 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -209,7 +209,7 @@ namespace CSMWorld if (record.isModified() || record.mState == RecordBase::State_Deleted) { RecordT esmRecord = record.get(); - writer.startRecord(esmRecord.sRecordId); + writer.startRecord(esmRecord.sRecordId, esmRecord.mRecordFlags); esmRecord.save(writer, record.mState == RecordBase::State_Deleted); writer.endRecord(esmRecord.sRecordId); } @@ -273,6 +273,8 @@ namespace CSMWorld RecordBase& getRecord (const LocalIndex& index); + unsigned int getRecordFlags(const std::string& id) const; + void appendRecord (UniversalId::Type type, const std::string& id, bool base); int getAppendIndex (UniversalId::Type type) const; diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 42bc3d648f..7d924d9c90 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -60,8 +60,6 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted, int *tempRefCount) { isDeleted = false; - mIsPersistent = !tempRefCount // default to persistent - || (tempRefCount && *tempRefCount == -1); bool isLoaded = false; while (!isLoaded && esm.hasMoreSubs()) @@ -247,6 +245,4 @@ void ESM::CellRef::blank() mPos.pos[i] = 0; mPos.rot[i] = 0; } - - mIsPersistent = false; } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 97cfea89d0..3e7a3a2f28 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -106,8 +106,6 @@ namespace ESM // Position and rotation of this object within the cell Position mPos; - bool mIsPersistent; - /// Calls loadId and loadData void load (ESMReader& esm, bool &isDeleted, int *tempRefCount, bool wideRefNum = false); diff --git a/components/esm/loadacti.cpp b/components/esm/loadacti.cpp index ba35535b8f..34592296ef 100644 --- a/components/esm/loadacti.cpp +++ b/components/esm/loadacti.cpp @@ -11,6 +11,7 @@ namespace ESM void Activator::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; while (esm.hasMoreSubs()) diff --git a/components/esm/loadacti.hpp b/components/esm/loadacti.hpp index 4cc72d5283..5b88ad379f 100644 --- a/components/esm/loadacti.hpp +++ b/components/esm/loadacti.hpp @@ -15,6 +15,7 @@ struct Activator /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string getRecordType() { return "Activator"; } + unsigned int mRecordFlags; std::string mId, mName, mScript, mModel; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadalch.cpp b/components/esm/loadalch.cpp index 85c24dc2d1..e1dd3a358b 100644 --- a/components/esm/loadalch.cpp +++ b/components/esm/loadalch.cpp @@ -11,6 +11,7 @@ namespace ESM void Potion::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); mEffects.mList.clear(); diff --git a/components/esm/loadalch.hpp b/components/esm/loadalch.hpp index 9ef390ebd9..d573531134 100644 --- a/components/esm/loadalch.hpp +++ b/components/esm/loadalch.hpp @@ -30,6 +30,7 @@ struct Potion }; ALDTstruct mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; EffectList mEffects; diff --git a/components/esm/loadappa.cpp b/components/esm/loadappa.cpp index 1bd1f93798..5d8bd61189 100644 --- a/components/esm/loadappa.cpp +++ b/components/esm/loadappa.cpp @@ -11,6 +11,7 @@ namespace ESM void Apparatus::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadappa.hpp b/components/esm/loadappa.hpp index 74f8dd6aea..fcd9100be4 100644 --- a/components/esm/loadappa.hpp +++ b/components/esm/loadappa.hpp @@ -36,6 +36,7 @@ struct Apparatus }; AADTstruct mData; + unsigned int mRecordFlags; std::string mId, mModel, mIcon, mScript, mName; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp index 6743702539..2253285c06 100644 --- a/components/esm/loadarmo.cpp +++ b/components/esm/loadarmo.cpp @@ -41,6 +41,7 @@ namespace ESM void Armor::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); mParts.mParts.clear(); diff --git a/components/esm/loadarmo.hpp b/components/esm/loadarmo.hpp index ef3bb734c0..195230fbf2 100644 --- a/components/esm/loadarmo.hpp +++ b/components/esm/loadarmo.hpp @@ -94,6 +94,7 @@ struct Armor AODTstruct mData; PartReferenceList mParts; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript, mEnchant; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadbook.cpp b/components/esm/loadbook.cpp index ee3c0c4af5..3535608272 100644 --- a/components/esm/loadbook.cpp +++ b/components/esm/loadbook.cpp @@ -11,6 +11,7 @@ namespace ESM void Book::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadbook.hpp b/components/esm/loadbook.hpp index bb2d7912f7..60b03f7a36 100644 --- a/components/esm/loadbook.hpp +++ b/components/esm/loadbook.hpp @@ -26,6 +26,7 @@ struct Book BKDTstruct mData; std::string mName, mModel, mIcon, mScript, mEnchant, mText; + unsigned int mRecordFlags; std::string mId; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 12f0d495d5..cf0b40d699 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -11,6 +11,7 @@ namespace ESM void Clothing::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); mParts.mParts.clear(); diff --git a/components/esm/loadclot.hpp b/components/esm/loadclot.hpp index 4db791c0c1..bbc8449a95 100644 --- a/components/esm/loadclot.hpp +++ b/components/esm/loadclot.hpp @@ -46,6 +46,7 @@ struct Clothing PartReferenceList mParts; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mEnchant, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp index 107aea7cf6..3bb603dbef 100644 --- a/components/esm/loadcont.cpp +++ b/components/esm/loadcont.cpp @@ -32,6 +32,7 @@ namespace ESM void Container::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); mInventory.mList.clear(); diff --git a/components/esm/loadcont.hpp b/components/esm/loadcont.hpp index 0cac580748..ade9004214 100644 --- a/components/esm/loadcont.hpp +++ b/components/esm/loadcont.hpp @@ -46,6 +46,7 @@ struct Container Unknown = 8 }; + unsigned int mRecordFlags; std::string mId, mName, mModel, mScript; float mWeight; // Not sure, might be max total weight allowed? diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 52138e2232..fd358987e0 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -13,8 +13,9 @@ namespace ESM { void Creature::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); - mPersistent = (esm.getRecordFlags() & 0x0400) != 0; + mPersistent = (mRecordFlags & 0x0400) != 0; mAiPackage.mList.clear(); mInventory.mList.clear(); diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 0ab09ee122..aeebeeb217 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -80,6 +80,7 @@ struct Creature float mScale; + unsigned int mRecordFlags; std::string mId, mModel, mName, mScript; std::string mOriginal; // Base creature that this is a modification of diff --git a/components/esm/loaddoor.cpp b/components/esm/loaddoor.cpp index 523d8a1efc..3e3e134112 100644 --- a/components/esm/loaddoor.cpp +++ b/components/esm/loaddoor.cpp @@ -11,6 +11,7 @@ namespace ESM void Door::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; while (esm.hasMoreSubs()) diff --git a/components/esm/loaddoor.hpp b/components/esm/loaddoor.hpp index 3afe5d5e4b..167eda20f5 100644 --- a/components/esm/loaddoor.hpp +++ b/components/esm/loaddoor.hpp @@ -15,6 +15,7 @@ struct Door /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string getRecordType() { return "Door"; } + unsigned int mRecordFlags; std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadingr.cpp b/components/esm/loadingr.cpp index a18e321ff7..6784d7ceac 100644 --- a/components/esm/loadingr.cpp +++ b/components/esm/loadingr.cpp @@ -11,6 +11,7 @@ namespace ESM void Ingredient::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadingr.hpp b/components/esm/loadingr.hpp index c0f4450238..34e05da2c1 100644 --- a/components/esm/loadingr.hpp +++ b/components/esm/loadingr.hpp @@ -29,6 +29,7 @@ struct Ingredient }; IRDTstruct mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadlevlist.cpp b/components/esm/loadlevlist.cpp index 0aed15aa94..c876e3b080 100644 --- a/components/esm/loadlevlist.cpp +++ b/components/esm/loadlevlist.cpp @@ -9,6 +9,7 @@ namespace ESM void LevelledListBase::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasList = false; diff --git a/components/esm/loadlevlist.hpp b/components/esm/loadlevlist.hpp index ed4131c165..d3451b70ae 100644 --- a/components/esm/loadlevlist.hpp +++ b/components/esm/loadlevlist.hpp @@ -22,6 +22,7 @@ struct LevelledListBase { int mFlags; unsigned char mChanceNone; // Chance that none are selected (0-100) + unsigned int mRecordFlags; std::string mId; // Record name used to read references. Must be set before load() is diff --git a/components/esm/loadligh.cpp b/components/esm/loadligh.cpp index 2a6dac14b0..b7c3d64cab 100644 --- a/components/esm/loadligh.cpp +++ b/components/esm/loadligh.cpp @@ -11,6 +11,7 @@ namespace ESM void Light::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index 8509c64b6d..901fe6ec85 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -45,6 +45,7 @@ struct Light LHDTstruct mData; + unsigned int mRecordFlags; std::string mSound, mScript, mModel, mIcon, mName, mId; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadlock.cpp b/components/esm/loadlock.cpp index b14353ec5a..a80760cf45 100644 --- a/components/esm/loadlock.cpp +++ b/components/esm/loadlock.cpp @@ -11,6 +11,7 @@ namespace ESM void Lockpick::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadlock.hpp b/components/esm/loadlock.hpp index 9db41af978..9cd40c0d4f 100644 --- a/components/esm/loadlock.hpp +++ b/components/esm/loadlock.hpp @@ -25,6 +25,7 @@ struct Lockpick }; // Size = 16 Data mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadmisc.cpp b/components/esm/loadmisc.cpp index 3ba6626505..f0ad49c1dc 100644 --- a/components/esm/loadmisc.cpp +++ b/components/esm/loadmisc.cpp @@ -11,6 +11,7 @@ namespace ESM void Miscellaneous::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadmisc.hpp b/components/esm/loadmisc.hpp index e7a3239042..72aaa5de3b 100644 --- a/components/esm/loadmisc.hpp +++ b/components/esm/loadmisc.hpp @@ -30,6 +30,7 @@ struct Miscellaneous }; MCDTstruct mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 2bb0811ac9..678678b5d3 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -11,8 +11,9 @@ namespace ESM void NPC::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); - mPersistent = (esm.getRecordFlags() & 0x0400) != 0; + mPersistent = (mRecordFlags & 0x0400) != 0; mSpells.mList.clear(); mInventory.mList.clear(); diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 687afeaf64..859f9d19e8 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -129,6 +129,7 @@ struct NPC AIPackageList mAiPackage; + unsigned int mRecordFlags; std::string mId, mName, mModel, mRace, mClass, mFaction, mScript; // body parts diff --git a/components/esm/loadprob.cpp b/components/esm/loadprob.cpp index 6307df3298..6460b793a0 100644 --- a/components/esm/loadprob.cpp +++ b/components/esm/loadprob.cpp @@ -11,6 +11,7 @@ namespace ESM void Probe::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadprob.hpp b/components/esm/loadprob.hpp index da203b456b..930e31a971 100644 --- a/components/esm/loadprob.hpp +++ b/components/esm/loadprob.hpp @@ -25,6 +25,7 @@ struct Probe }; // Size = 16 Data mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadrepa.cpp b/components/esm/loadrepa.cpp index c04691c12f..7bd98329ce 100644 --- a/components/esm/loadrepa.cpp +++ b/components/esm/loadrepa.cpp @@ -11,6 +11,7 @@ namespace ESM void Repair::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadrepa.hpp b/components/esm/loadrepa.hpp index 2537c53cb6..312c87b7b4 100644 --- a/components/esm/loadrepa.hpp +++ b/components/esm/loadrepa.hpp @@ -25,6 +25,7 @@ struct Repair }; // Size = 16 Data mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mScript; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 6c9de22bd1..0c97662d7e 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -11,6 +11,9 @@ namespace ESM void Static::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); + //bool isBlocked = (mRecordFlags & 0x00002000) != 0; + //bool isPersistent = (mRecordFlags & 0x00000400) != 0; bool hasName = false; while (esm.hasMoreSubs()) diff --git a/components/esm/loadstat.hpp b/components/esm/loadstat.hpp index 3d91440402..038fb9f52b 100644 --- a/components/esm/loadstat.hpp +++ b/components/esm/loadstat.hpp @@ -26,6 +26,7 @@ struct Static /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string getRecordType() { return "Static"; } + unsigned int mRecordFlags; std::string mId, mModel; void load(ESMReader &esm, bool &isDeleted); diff --git a/components/esm/loadweap.cpp b/components/esm/loadweap.cpp index 4a77ff6a00..79d1a8c5e5 100644 --- a/components/esm/loadweap.cpp +++ b/components/esm/loadweap.cpp @@ -11,6 +11,7 @@ namespace ESM void Weapon::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; + mRecordFlags = esm.getRecordFlags(); bool hasName = false; bool hasData = false; diff --git a/components/esm/loadweap.hpp b/components/esm/loadweap.hpp index 90431756d7..8d1591854b 100644 --- a/components/esm/loadweap.hpp +++ b/components/esm/loadweap.hpp @@ -73,6 +73,7 @@ struct Weapon WPDTstruct mData; + unsigned int mRecordFlags; std::string mId, mName, mModel, mIcon, mEnchant, mScript; void load(ESMReader &esm, bool &isDeleted); From f2a301653ce6ec92378ada0abbf88b0dc6f83be6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 30 Jun 2021 08:20:29 +1000 Subject: [PATCH 04/17] Remove redundant mPersistent member from ESM::NPC and ESM::Creature, replaced by mRecordFlags. Fixed the editing of the persistence flag value. --- apps/opencs/model/world/columns.cpp | 1 - apps/opencs/model/world/columns.hpp | 2 +- apps/opencs/model/world/refidadapterimp.cpp | 4 ---- apps/opencs/model/world/refidadapterimp.hpp | 17 +++++------------ apps/opencs/model/world/refidcollection.cpp | 2 -- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- components/esm/loadcrea.cpp | 2 -- components/esm/loadcrea.hpp | 2 -- components/esm/loadnpc.cpp | 2 -- components/esm/loadnpc.hpp | 2 -- 11 files changed, 8 insertions(+), 30 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 1b91997a5f..cf04d96753 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -294,7 +294,6 @@ namespace CSMWorld { ColumnId_NpcReputation, "Reputation" }, { ColumnId_NpcRank, "NPC Rank" }, { ColumnId_Gold, "Gold" }, - { ColumnId_NpcPersistence, "Persistent" }, { ColumnId_RaceAttributes, "Race Attributes" }, { ColumnId_Male, "Male" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b50fb71e04..16482d4898 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -280,7 +280,7 @@ namespace CSMWorld ColumnId_NpcReputation = 258, ColumnId_NpcRank = 259, ColumnId_Gold = 260, - ColumnId_NpcPersistence = 261, + // unused ColumnId_RaceAttributes = 262, ColumnId_Male = 263, diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 644092f164..4013b3d00c 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1108,7 +1108,6 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column case 5: return static_cast(record.get().mNpdt.mReputation); case 6: return static_cast(record.get().mNpdt.mRank); case 7: return record.get().mNpdt.mGold; - case 8: return record.get().mPersistent == true; default: return QVariant(); // throw an exception here? } else @@ -1122,7 +1121,6 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column case 5: return static_cast(record.get().mNpdt.mReputation); case 6: return static_cast(record.get().mNpdt.mRank); case 7: return record.get().mNpdt.mGold; - case 8: return record.get().mPersistent == true; default: return QVariant(); // throw an exception here? } } @@ -1147,7 +1145,6 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column, case 5: npc.mNpdt.mReputation = static_cast(value.toInt()); break; case 6: npc.mNpdt.mRank = static_cast(value.toInt()); break; case 7: npc.mNpdt.mGold = value.toInt(); break; - case 8: npc.mPersistent = value.toBool(); break; default: return; // throw an exception here? } else @@ -1161,7 +1158,6 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column, case 5: npc.mNpdt.mReputation = static_cast(value.toInt()); break; case 6: npc.mNpdt.mRank = static_cast(value.toInt()); break; case 7: npc.mNpdt.mGold = value.toInt(); break; - case 8: npc.mPersistent = value.toBool(); break; default: return; // throw an exception here? } diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index f8ca93fec7..210deca69b 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -153,10 +153,7 @@ namespace CSMWorld return QString::fromUtf8 (record.get().mModel.c_str()); if (column==mModel.mPersistence) - { - bool isPersistent = (record.get().mRecordFlags & 0x00000400) != 0; - return QString::fromUtf8 (isPersistent ? "Yes" : "No"); - } + return (record.get().mRecordFlags & 0x00000400) != 0; return BaseRefIdAdapter::getData (column, data, index); } @@ -173,14 +170,10 @@ namespace CSMWorld record2.mModel = value.toString().toUtf8().constData(); else if (column==mModel.mPersistence) { - unsigned int flag = record2.mRecordFlags; - std::string val = value.toString().toUtf8().constData(); - if (val == "Yes") - flag |= 0x00000400; - else if (val == "No") - flag &= ~0x00000400; - - record2.mRecordFlags = flag; + if (value.toInt() != 0) + record2.mRecordFlags |= 0x00000400; + else + record2.mRecordFlags &= ~0x00000400; } else { diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index b7370c20da..0cf9a4e6dc 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -551,8 +551,6 @@ CSMWorld::RefIdCollection::RefIdCollection() new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_UnsignedInteger8)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); - mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean)); WeaponColumns weaponColumns (enchantableColumns); diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index acf969bd3a..0a40139d36 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -588,7 +588,7 @@ namespace MWClass bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const { const MWWorld::LiveCellRef* ref = actor.get(); - return ref->mBase->mPersistent; + return (ref->mBase->mRecordFlags & 0x0400) != 0; } std::string Creature::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 933ba5cd38..1951f964bc 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -403,7 +403,7 @@ namespace MWClass bool Npc::isPersistent(const MWWorld::ConstPtr &actor) const { const MWWorld::LiveCellRef* ref = actor.get(); - return ref->mBase->mPersistent; + return (ref->mBase->mRecordFlags & 0x0400) != 0; } std::string Npc::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index fd358987e0..2c1cc69a7b 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -15,8 +15,6 @@ namespace ESM { isDeleted = false; mRecordFlags = esm.getRecordFlags(); - mPersistent = (mRecordFlags & 0x0400) != 0; - mAiPackage.mList.clear(); mInventory.mList.clear(); mSpells.mList.clear(); diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index aeebeeb217..f6b188d96e 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -76,8 +76,6 @@ struct Creature int mBloodType; unsigned char mFlags; - bool mPersistent; - float mScale; unsigned int mRecordFlags; diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 678678b5d3..80cd2e9623 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -13,8 +13,6 @@ namespace ESM isDeleted = false; mRecordFlags = esm.getRecordFlags(); - mPersistent = (mRecordFlags & 0x0400) != 0; - mSpells.mList.clear(); mInventory.mList.clear(); mTransport.mList.clear(); diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 859f9d19e8..ba9f415760 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -116,8 +116,6 @@ struct NPC int mBloodType; unsigned char mFlags; - bool mPersistent; - InventoryList mInventory; SpellList mSpells; From 47ef98ca1b2d622dd9b8b2dc8b27c4b8616b256b Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 30 Jun 2021 10:09:56 +1000 Subject: [PATCH 05/17] Clean up RefIdData code for better legibility. --- apps/opencs/model/world/refiddata.cpp | 140 ++++---------------------- apps/opencs/model/world/refiddata.hpp | 10 ++ 2 files changed, 30 insertions(+), 120 deletions(-) diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp index 4f72bae92e..79a2efdcc8 100644 --- a/apps/opencs/model/world/refiddata.cpp +++ b/apps/opencs/model/world/refiddata.cpp @@ -93,126 +93,26 @@ unsigned int CSMWorld::RefIdData::getRecordFlags (const std::string& id) const switch (localIndex.second) { - case UniversalId::Type_Activator: - { - const RefIdDataContainer& records = getActivators(); - const ESM::Activator& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Potion: - { - const RefIdDataContainer& records = getPotions(); - const ESM::Potion& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Apparatus: - { - const RefIdDataContainer& records = getApparati(); - const ESM::Apparatus& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Armor: - { - const RefIdDataContainer& records = getArmors(); - const ESM::Armor& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Book: - { - const RefIdDataContainer& records = getBooks(); - const ESM::Book& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Clothing: - { - const RefIdDataContainer& records = getClothing(); - const ESM::Clothing& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Container: - { - const RefIdDataContainer& records = getContainers(); - const ESM::Container& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Creature: - { - const RefIdDataContainer& records = getCreatures(); - const ESM::Creature& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Door: - { - const RefIdDataContainer& records = getDoors(); - const ESM::Door& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Ingredient: - { - const RefIdDataContainer& records = getIngredients(); - const ESM::Ingredient& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_CreatureLevelledList: - { - const RefIdDataContainer& records = getCreatureLevelledLists(); - const ESM::CreatureLevList& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_ItemLevelledList: - { - const RefIdDataContainer& records = getItemLevelledList(); - const ESM::ItemLevList& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Light: - { - const RefIdDataContainer& records = getLights(); - const ESM::Light& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Lockpick: - { - const RefIdDataContainer& records = getLocpicks(); - const ESM::Lockpick& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Miscellaneous: - { - const RefIdDataContainer& records = getMiscellaneous(); - const ESM::Miscellaneous& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Npc: - { - const RefIdDataContainer& records = getNPCs(); - const ESM::NPC& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Probe: - { - const RefIdDataContainer& records = getProbes(); - const ESM::Probe& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Repair: - { - const RefIdDataContainer& records = getRepairs(); - const ESM::Repair& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Static: - { - const RefIdDataContainer& records = getStatics(); - const ESM::Static& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } - case UniversalId::Type_Weapon: - { - const RefIdDataContainer& records = getWeapons(); - const ESM::Weapon& record = dynamic_cast(records.getRecord(localIndex.first)); - return record.mRecordFlags; - } + case UniversalId::Type_Activator: return mActivators.getRecordFlags(localIndex.first); + case UniversalId::Type_Potion: return mPotions.getRecordFlags(localIndex.first); + case UniversalId::Type_Apparatus: return mApparati.getRecordFlags(localIndex.first); + case UniversalId::Type_Armor: return mArmors.getRecordFlags(localIndex.first); + case UniversalId::Type_Book: return mBooks.getRecordFlags(localIndex.first); + case UniversalId::Type_Clothing: return mClothing.getRecordFlags(localIndex.first); + case UniversalId::Type_Container: return mContainers.getRecordFlags(localIndex.first); + case UniversalId::Type_Creature: return mCreatures.getRecordFlags(localIndex.first); + case UniversalId::Type_Door: return mDoors.getRecordFlags(localIndex.first); + case UniversalId::Type_Ingredient: return mIngredients.getRecordFlags(localIndex.first); + case UniversalId::Type_CreatureLevelledList: return mCreatureLevelledLists.getRecordFlags(localIndex.first); + case UniversalId::Type_ItemLevelledList: return mItemLevelledLists.getRecordFlags(localIndex.first); + case UniversalId::Type_Light: return mLights.getRecordFlags(localIndex.first); + case UniversalId::Type_Lockpick: return mLockpicks.getRecordFlags(localIndex.first); + case UniversalId::Type_Miscellaneous: return mMiscellaneous.getRecordFlags(localIndex.first); + case UniversalId::Type_Npc: return mNpcs.getRecordFlags(localIndex.first); + case UniversalId::Type_Probe: return mProbes.getRecordFlags(localIndex.first); + case UniversalId::Type_Repair: return mRepairs.getRecordFlags(localIndex.first); + case UniversalId::Type_Static: return mStatics.getRecordFlags(localIndex.first); + case UniversalId::Type_Weapon: return mWeapons.getRecordFlags(localIndex.first); default: break; } diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index da6ac7b154..ab5269b390 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -47,6 +47,8 @@ namespace CSMWorld virtual RecordBase& getRecord (int index)= 0; + virtual unsigned int getRecordFlags (int index) const = 0; + virtual void appendRecord (const std::string& id, bool base) = 0; virtual void insertRecord (RecordBase& record) = 0; @@ -72,6 +74,8 @@ namespace CSMWorld RecordBase& getRecord (int index) override; + unsigned int getRecordFlags (int index) const override; + void appendRecord (const std::string& id, bool base) override; void insertRecord (RecordBase& record) override; @@ -111,6 +115,12 @@ namespace CSMWorld return mContainer.at (index); } + template + unsigned int RefIdDataContainer::getRecordFlags (int index) const + { + return mContainer.at (index).get().mRecordFlags; + } + template void RefIdDataContainer::appendRecord (const std::string& id, bool base) { From 2d8dd9be329fb796c6f81c6d498fa7ca28046c73 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 30 Jun 2021 10:46:51 +1000 Subject: [PATCH 06/17] Fix using incorrect id to search for record flags. Eliminate inefficient double-loop in saving cell references. --- apps/opencs/model/doc/savingstages.cpp | 35 +++++++++++++------------- apps/opencs/model/doc/savingstages.hpp | 2 +- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 7d6e8fef88..edf319db6c 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -253,12 +253,9 @@ int CSMDoc::WriteCellCollectionStage::setup() return mDocument.getData().getCells().getSize(); } -int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum, bool temp) +void CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum) { ESM::ESMWriter& writer = mState.getWriter(); - size_t refCount = 0; - const CSMWorld::RefIdCollection& referenceables = mDocument.getData().getReferenceables(); - const CSMWorld::RefIdData& refIdData = referenceables.getDataSet(); for (std::deque::const_iterator iter (references.begin()); iter!=references.end(); ++iter) @@ -266,14 +263,6 @@ int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& re const CSMWorld::Record& ref = mDocument.getData().getReferences().getRecord (*iter); - unsigned int recordFlags = refIdData.getRecordFlags(ref.get().mId); - bool isPersistent = (recordFlags & 0x00000400) != 0; - - if (temp && isPersistent || !temp && !isPersistent) - continue; - - refCount++; - if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted) { CSMWorld::CellRef refRecord = ref.get(); @@ -318,14 +307,17 @@ int CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque& re refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted); } } - - return refCount; } void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) { ESM::ESMWriter& writer = mState.getWriter(); const CSMWorld::Record& cell = mDocument.getData().getCells().getRecord (stage); + const CSMWorld::RefIdCollection& referenceables = mDocument.getData().getReferenceables(); + const CSMWorld::RefIdData& refIdData = referenceables.getDataSet(); + + std::deque tempRefs; + std::deque persistentRefs; std::map >::const_iterator references = mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId)); @@ -350,6 +342,14 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) CSMWorld::CellRef refRecord = ref.get(); + unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID); + bool isPersistent = (recordFlags & 0x00000400) != 0; + + if (isPersistent) + persistentRefs.push_back(*iter); + else + tempRefs.push_back(*iter); + if (refRecord.mNew || (!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly && /// \todo consider worldspace @@ -380,10 +380,9 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) // write references if (references!=mState.getSubRecords().end()) { - int persistentRefCount = writeReferences(references->second, interior, newRefNum, false/*temp*/); - cellRecord.saveTempMarker(writer, int(references->second.size()) - persistentRefCount); - // FIXME: loops twice, inefficient - writeReferences(references->second, interior, newRefNum, true/*temp*/); + writeReferences(persistentRefs, interior, newRefNum); + cellRecord.saveTempMarker(writer, int(references->second.size()) - persistentRefs.size()); + writeReferences(tempRefs, interior, newRefNum); } writer.endRecord (cellRecord.sRecordId); diff --git a/apps/opencs/model/doc/savingstages.hpp b/apps/opencs/model/doc/savingstages.hpp index e9497a6064..d59a1efe5e 100644 --- a/apps/opencs/model/doc/savingstages.hpp +++ b/apps/opencs/model/doc/savingstages.hpp @@ -171,7 +171,7 @@ namespace CSMDoc Document& mDocument; SavingState& mState; - int writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum, bool temp); + void writeReferences (const std::deque& references, bool interior, unsigned int& newRefNum); public: From 42bcbe34de75b2e631020ff5b7496daafdaa2a98 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 4 Jul 2021 16:18:47 +1000 Subject: [PATCH 07/17] Cell references that teleport (Doors) should be placed in the "persistent" group when saving. --- apps/opencs/model/doc/savingstages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index edf319db6c..27b31251e5 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -343,7 +343,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) CSMWorld::CellRef refRecord = ref.get(); unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID); - bool isPersistent = (recordFlags & 0x00000400) != 0; + bool isPersistent = ((recordFlags & 0x00000400) != 0) || refRecord.mTeleport; if (isPersistent) persistentRefs.push_back(*iter); From 0a15d7740a66d1a920c6cf86dbd37b0614c6a9de Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Fri, 5 Mar 2021 22:21:53 +0100 Subject: [PATCH 08/17] Delay physics for objects created by scripts --- apps/openmw/mwclass/activator.cpp | 5 +++++ apps/openmw/mwclass/activator.hpp | 2 ++ apps/openmw/mwclass/container.cpp | 5 +++++ apps/openmw/mwclass/container.hpp | 1 + apps/openmw/mwclass/door.cpp | 9 ++++++-- apps/openmw/mwclass/door.hpp | 1 + apps/openmw/mwclass/light.cpp | 11 +++++++--- apps/openmw/mwclass/light.hpp | 1 + apps/openmw/mwclass/static.cpp | 5 +++++ apps/openmw/mwclass/static.hpp | 1 + apps/openmw/mwphysics/physicssystem.cpp | 2 ++ apps/openmw/mwscript/miscextensions.cpp | 2 ++ .../mwscript/transformationextensions.cpp | 3 +++ apps/openmw/mwworld/class.cpp | 3 +++ apps/openmw/mwworld/class.hpp | 1 + apps/openmw/mwworld/refdata.cpp | 7 ++++--- apps/openmw/mwworld/refdata.hpp | 2 ++ apps/openmw/mwworld/scene.cpp | 21 +++++++++++++++++++ 18 files changed, 74 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 0b4d9ef836..2e8553920f 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -39,6 +39,11 @@ namespace MWClass } void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + { + insertObjectPhysics(ptr, model, rotation, physics, skipAnimated); + } + + void Activator::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 7af47680b3..4dc85bd507 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -19,6 +19,8 @@ namespace MWClass void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; + void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const override; + std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index b88d756cbc..5c1ddd8bd1 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -107,6 +107,11 @@ namespace MWClass } void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + { + insertObjectPhysics(ptr, model, rotation, physics, skipAnimated); + } + + void Container::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 02ec9b1012..1cbc5a6142 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -43,6 +43,7 @@ namespace MWClass ///< Add reference into a cell for rendering void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; + void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 1407d6a0d5..e608c27000 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -57,8 +57,7 @@ namespace MWClass void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { - if(!model.empty()) - physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated); + insertObjectPhysics(ptr, model, rotation, physics, skipAnimated); // Resume the door's opening/closing animation if it wasn't finished if (ptr.getRefData().getCustomData()) @@ -71,6 +70,12 @@ namespace MWClass } } + void Door::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + { + if(!model.empty()) + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated); + } + bool Door::isDoor() const { return true; diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index f80c9bb416..5882842e91 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -19,6 +19,7 @@ namespace MWClass ///< Add reference into a cell for rendering void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; + void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; bool isDoor() const override; diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index ca744be7bc..ad5eb4e737 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -39,9 +39,7 @@ namespace MWClass ptr.get(); assert (ref->mBase != nullptr); - // TODO: add option somewhere to enable collision for placeable objects - if (!model.empty() && (ref->mBase->mData.mFlags & ESM::Light::Carry) == 0) - physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); + insertObjectPhysics(ptr, model, rotation, physics, skipAnimated); if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault)) MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0, @@ -49,6 +47,13 @@ namespace MWClass MWSound::PlayMode::Loop); } + void Light::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + { + // TODO: add option somewhere to enable collision for placeable objects + if (!model.empty() && (ptr.get()->mBase->mData.mFlags & ESM::Light::Carry) == 0) + physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); + } + bool Light::useAnim() const { return true; diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 7641722788..55fef759aa 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -15,6 +15,7 @@ namespace MWClass ///< Add reference into a cell for rendering void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; + void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; bool useAnim() const override; diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 323e482bf0..25029528ea 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -24,6 +24,11 @@ namespace MWClass } void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + { + insertObjectPhysics(ptr, model, rotation, physics, skipAnimated); + } + + void Static::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const { if(!model.empty()) physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated); diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 211b93de2a..d1991d0550 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -15,6 +15,7 @@ namespace MWClass ///< Add reference into a cell for rendering void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; + void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override; std::string getName (const MWWorld::ConstPtr& ptr) const override; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 034a35f38e..e5bd936abb 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -463,6 +463,8 @@ namespace MWPhysics void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType, bool skipAnimated) { + if (ptr.mRef->mData.mPhysicsPostponed) + return; osg::ref_ptr shapeInstance = mShapeManager->getInstance(mesh); if (!shapeInstance || !shapeInstance->getCollisionShape()) return; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 5538e8536f..c28f2b8951 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -168,6 +168,8 @@ namespace MWScript void execute (Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = R()(runtime); + if(!ptr.isEmpty() && !ptr.mRef->mData.isEnabled()) + ptr.mRef->mData.mPhysicsPostponed = false; MWBase::Environment::get().getWorld()->enable (ptr); } }; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index dbd8e905aa..825306d650 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -501,6 +501,7 @@ namespace MWScript pos.rot[0] = pos.rot[1] = 0; pos.rot[2] = osg::DegreesToRadians(zRotDegrees); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID); + ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor(); ref.getPtr().getCellRef().setPosition(pos); MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos); placed.getClass().adjustPosition(placed, true); @@ -548,6 +549,7 @@ namespace MWScript pos.rot[0] = pos.rot[1] = 0; pos.rot[2] = osg::DegreesToRadians(zRotDegrees); MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID); + ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor(); ref.getPtr().getCellRef().setPosition(pos); MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos); placed.getClass().adjustPosition(placed, true); @@ -588,6 +590,7 @@ namespace MWScript { // create item MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1); + ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor(); MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance); MWBase::Environment::get().getWorld()->scaleObject(ptr, actor.getCellRef().getScale()); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 04dfba6b97..96f03af6c3 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -35,6 +35,9 @@ namespace MWWorld } + void Class::insertObjectPhysics(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const + {} + bool Class::apply (const MWWorld::Ptr& ptr, const std::string& id, const MWWorld::Ptr& actor) const { return false; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index e225e0187c..7937209c6e 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -80,6 +80,7 @@ namespace MWWorld virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const; virtual void insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const; ///< Add reference into a cell for rendering (default implementation: don't render anything). + virtual void insertObjectPhysics(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const; virtual std::string getName (const ConstPtr& ptr) const = 0; ///< \return name or ID; can return an empty string. diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index f6a445d619..29c669caf9 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -31,6 +31,7 @@ namespace MWWorld mChanged = refData.mChanged; mDeletedByContentFile = refData.mDeletedByContentFile; mFlags = refData.mFlags; + mPhysicsPostponed = refData.mPhysicsPostponed; mAnimationState = refData.mAnimationState; @@ -44,7 +45,7 @@ namespace MWWorld } RefData::RefData() - : mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (nullptr), mChanged(false), mFlags(0) + : mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (nullptr), mChanged(false), mFlags(0), mPhysicsPostponed(false) { for (int i=0; i<3; ++i) { @@ -57,7 +58,7 @@ namespace MWWorld : mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true), mCount (1), mPosition (cellRef.mPos), mCustomData (nullptr), - mChanged(false), mFlags(0) // Loading from ESM/ESP files -> assume unchanged + mChanged(false), mFlags(0), mPhysicsPostponed(false) // Loading from ESM/ESP files -> assume unchanged { } @@ -68,7 +69,7 @@ namespace MWWorld mPosition (objectState.mPosition), mAnimationState(objectState.mAnimationState), mCustomData (nullptr), - mChanged(true), mFlags(objectState.mFlags) // Loading from a savegame -> assume changed + mChanged(true), mFlags(objectState.mFlags), mPhysicsPostponed(false) // Loading from a savegame -> assume changed { // "Note that the ActivationFlag_UseEnabled is saved to the reference, // which will result in permanently suppressed activation if the reference script is removed. diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 8979c8505d..e2f77d09e0 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -58,6 +58,8 @@ namespace MWWorld public: + bool mPhysicsPostponed; + RefData(); /// @param cellRef Used to copy constant data such as position into this class where it can diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 45b0c5d9f8..d3b381d2af 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -343,7 +343,10 @@ namespace MWWorld cell->forEach(visitor); for (const auto& ptr : visitor.mObjects) + { mPhysics->remove(ptr); + ptr.mRef->mData.mPhysicsPostponed = false; + } if (cell->getCell()->isExterior()) { @@ -626,6 +629,24 @@ namespace MWWorld } return cellsPositionsToLoad; }; + + for(const auto& cell : mActiveCells) + { + cell->forEach([&](const MWWorld::Ptr& ptr) + { + if(ptr.mRef->mData.mPhysicsPostponed) + { + ptr.mRef->mData.mPhysicsPostponed = false; + if(ptr.mRef->mData.isEnabled() && ptr.mRef->mData.getCount() > 0) { + std::string model = getModel(ptr, MWBase::Environment::get().getResourceSystem()->getVFS()); + const auto rotation = makeNodeRotation(ptr, RotationOrder::direct); + ptr.getClass().insertObjectPhysics(ptr, model, rotation, *mPhysics); + } + } + return true; + }); + } + auto cellsPositionsToLoad = cellsToLoad(mActiveCells,mHalfGridSize); auto cellsPositionsToLoadInactive = cellsToLoad(mInactiveCells,mHalfGridSize+1); From 18f297a4e052b51d914e0158462021cda9602815 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 11 Mar 2021 20:37:38 +0100 Subject: [PATCH 09/17] Allow a missing implicit argument for GetDistance --- apps/openmw/mwscript/transformationextensions.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 825306d650..096e78d34b 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -42,10 +42,19 @@ namespace MWScript void execute (Interpreter::Runtime& runtime) override { - MWWorld::Ptr from = R()(runtime); + MWWorld::Ptr from = R()(runtime, !R::implicit); std::string name = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); + if (from.isEmpty()) + { + std::string error = "Missing implicit ref"; + runtime.getContext().report(error); + Log(Debug::Error) << error; + runtime.push(0.f); + return; + } + if (from.getContainerStore()) // is the object contained? { MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(from); From d138602bd390c7c0d704cdeef7406dd2b62222cd Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 5 Jul 2021 18:41:43 +0200 Subject: [PATCH 10/17] Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 705cc21bf0..cf7caabdc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions) Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes + Bug #3905: Great House Dagoth issues + Bug #5120: Scripted object spawning updates physics system Bug #5379: Wandering NPCs falling through cantons Bug #5453: Magic effect VFX are offset for creatures Bug #5483: AutoCalc flag is not used to calculate spells cost From f8aefc7f0b591619c17a7f4b56575d4936dcf192 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 07:02:41 +1000 Subject: [PATCH 11/17] Update the changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23814425a8..3b389dd7d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Bug #5453: Magic effect VFX are offset for creatures Bug #5483: AutoCalc flag is not used to calculate spells cost Bug #6101: Disarming trapped unlocked owned objects isn't considered a crime + Task #6017: Separate persistent and temporary cell references when saving 0.47.0 ------ From 1f5b20ef7de8880a3eb9a32a2b7ca1fb3649b0c0 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 11:43:30 +1000 Subject: [PATCH 12/17] test fix for missing refs --- apps/openmw/mwworld/cellstore.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 051273f21d..e8d46b1574 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -610,9 +610,17 @@ namespace MWWorld ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile; // Get each reference in turn + ESM::MovedCellRef cMRef; + cMRef.mRefNum.mIndex = 0; bool deleted = false; - while(mCell->getNextRef(esm[index], ref, deleted)) + while(mCell->getNextRef(esm[index], ref, deleted, /*ignoreMoves*/true, &cMRef)) { + if (cMRef.mRefNum.mIndex) + { + cMRef.mRefNum.mIndex = 0; + continue; // ignore refs that are moved + } + // 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); From 4b3de46bfa23c3f9bc9ecdf4798b33d5d6af8828 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 12:37:02 +1000 Subject: [PATCH 13/17] Use enums in place of magic numbers. Ensure Creature and NPC cell references are always saved as persistent. --- apps/opencs/model/doc/savingstages.cpp | 6 +++++- apps/opencs/model/world/refidadapterimp.hpp | 6 +++--- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- components/esm/esmcommon.hpp | 5 +++++ components/esm/loadstat.cpp | 4 ++-- 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 27b31251e5..8c17a3b8c1 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -342,8 +342,12 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) CSMWorld::CellRef refRecord = ref.get(); + CSMWorld::RefIdData::LocalIndex localIndex = refIdData.searchId(refRecord.mRefID); unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID); - bool isPersistent = ((recordFlags & 0x00000400) != 0) || refRecord.mTeleport; + bool isPersistent = ((recordFlags & ESM::FLAG_Persistent) != 0) + || refRecord.mTeleport + || localIndex.second == CSMWorld::UniversalId::Type_Creature + || localIndex.second == CSMWorld::UniversalId::Type_Npc; if (isPersistent) persistentRefs.push_back(*iter); diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 210deca69b..1d1b5a94a6 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -153,7 +153,7 @@ namespace CSMWorld return QString::fromUtf8 (record.get().mModel.c_str()); if (column==mModel.mPersistence) - return (record.get().mRecordFlags & 0x00000400) != 0; + return (record.get().mRecordFlags & ESM::FLAG_Persistent) != 0; return BaseRefIdAdapter::getData (column, data, index); } @@ -171,9 +171,9 @@ namespace CSMWorld else if (column==mModel.mPersistence) { if (value.toInt() != 0) - record2.mRecordFlags |= 0x00000400; + record2.mRecordFlags |= ESM::FLAG_Persistent; else - record2.mRecordFlags &= ~0x00000400; + record2.mRecordFlags &= ~ESM::FLAG_Persistent; } else { diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 0a40139d36..141bf99e92 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -588,7 +588,7 @@ namespace MWClass bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const { const MWWorld::LiveCellRef* ref = actor.get(); - return (ref->mBase->mRecordFlags & 0x0400) != 0; + return (ref->mBase->mRecordFlags & ESM::FLAG_Persistent) != 0; } std::string Creature::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 1951f964bc..6131f86269 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -403,7 +403,7 @@ namespace MWClass bool Npc::isPersistent(const MWWorld::ConstPtr &actor) const { const MWWorld::LiveCellRef* ref = actor.get(); - return (ref->mBase->mRecordFlags & 0x0400) != 0; + return (ref->mBase->mRecordFlags & ESM::FLAG_Persistent) != 0; } std::string Npc::getModel(const MWWorld::ConstPtr &ptr) const diff --git a/components/esm/esmcommon.hpp b/components/esm/esmcommon.hpp index 749e9a85d6..10e05de905 100644 --- a/components/esm/esmcommon.hpp +++ b/components/esm/esmcommon.hpp @@ -16,6 +16,11 @@ enum Version VER_13 = 0x3fa66666 }; +enum RecordFlag + { + FLAG_Persistent = 0x00000400, + FLAG_Blocked = 0x00002000 + }; // CRTP for FIXED_STRING class, a structure used for holding fixed-length strings template< template class DERIVED, size_t SIZE> diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 0c97662d7e..543e76bc85 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -12,8 +12,8 @@ namespace ESM { isDeleted = false; mRecordFlags = esm.getRecordFlags(); - //bool isBlocked = (mRecordFlags & 0x00002000) != 0; - //bool isPersistent = (mRecordFlags & 0x00000400) != 0; + //bool isBlocked = (mRecordFlags & ESM::FLAG_Blocked) != 0; + //bool isPersistent = (mRecordFlags & ESM::FLAG_Persistent) != 0; bool hasName = false; while (esm.hasMoreSubs()) From ec457a09c3263c09d632b2719960d149b7434f86 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 13:45:58 +1000 Subject: [PATCH 14/17] Fix Npc edit widget index out of bounds due to a removed column. --- apps/opencs/model/world/refidadapterimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 4013b3d00c..0dfc9945f7 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -1166,7 +1166,7 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column, int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const { - return 9; // Level, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold, Persist + return 8; // Level, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold } int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const From fea1ac2c0ff10f357ff54c6bb8a8176540fff8db Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 14:21:17 +1000 Subject: [PATCH 15/17] Remove dead code from commit 024ad3276b472e0fc58b681d10566917e4d8d44d. --- components/esm/cellref.cpp | 15 ++++----------- components/esm/cellref.hpp | 4 ++-- components/esm/loadcell.cpp | 4 ++-- components/esm/loadcell.hpp | 3 +-- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index dbe5828289..3628bac1b7 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -31,10 +31,10 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const } -void ESM::CellRef::load (ESMReader& esm, bool &isDeleted, int *tempRefCount, bool wideRefNum) +void ESM::CellRef::load (ESMReader& esm, bool &isDeleted, bool wideRefNum) { loadId(esm, wideRefNum); - loadData(esm, isDeleted, tempRefCount); + loadData(esm, isDeleted); } void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) @@ -57,7 +57,7 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) } } -void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted, int *tempRefCount) +void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted) { isDeleted = false; @@ -119,14 +119,7 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted, int *tempRefCount) break; case ESM::FourCC<'N','A','M','0'>::value: { - if (tempRefCount && *tempRefCount == -1) - { - esm.getHT(*tempRefCount); - // TODO: check that there are no more subs following this sub - } - else - esm.skipHSub(); - + esm.skipHSub(); break; } case ESM::SREC_DELE: diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 3e7a3a2f28..c2f7ff6de5 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -107,12 +107,12 @@ namespace ESM Position mPos; /// Calls loadId and loadData - void load (ESMReader& esm, bool &isDeleted, int *tempRefCount, bool wideRefNum = false); + void load (ESMReader& esm, bool &isDeleted, bool wideRefNum = false); void loadId (ESMReader& esm, bool wideRefNum = false); /// Implicitly called by load - void loadData (ESMReader& esm, bool &isDeleted, int *tempRefCount = nullptr); + void loadData (ESMReader& esm, bool &isDeleted); void save (ESMWriter &esm, bool wideRefNum = false, bool inInventory = false, bool isDeleted = false) const; diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 8aeacd5116..2cb8761938 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -224,7 +224,7 @@ namespace ESM return region + ' ' + cellGrid; } - bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, int *tempRefCount, bool ignoreMoves, MovedCellRef *mref) + bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool &isDeleted, bool ignoreMoves, MovedCellRef *mref) { isDeleted = false; @@ -252,7 +252,7 @@ namespace ESM if (esm.peekNextSub("FRMR")) { - ref.load (esm, isDeleted, tempRefCount); + ref.load (esm, isDeleted); // TODO: should count the number of temp refs and validate the number diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index ca4ca6e577..c49dc20c59 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -184,8 +184,7 @@ struct Cell /// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef. static bool getNextRef(ESMReader &esm, CellRef &ref, - bool &isDeleted, - int *tempRefCount = nullptr, + bool &isDeleted, bool ignoreMoves = false, MovedCellRef *mref = nullptr); From ae4ddd810fac1d19d077bf8ae0b90dcb93432024 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 14:45:45 +1000 Subject: [PATCH 16/17] More dead code removal. --- apps/opencs/model/world/refcollection.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 2f5db65636..dfdb8e73bf 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -19,9 +19,8 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool ESM::MovedCellRef mref; mref.mRefNum.mIndex = 0; bool isDeleted = false; - int tempRefCount = cell.get().mRefNumCounter; // if initially non-zero, all refs in cell are temp - while (ESM::Cell::getNextRef(reader, ref, isDeleted, &tempRefCount, true, &mref)) + while (ESM::Cell::getNextRef(reader, ref, isDeleted, true, &mref)) { // Keep mOriginalCell empty when in modified (as an indicator that the // original cell will always be equal the current cell). @@ -60,8 +59,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool else ref.mCell = cell2.mId; - // TODO: update cell.get().mRefNumCounter with tempRefCount? - mref.mRefNum.mIndex = 0; // ignore content file number From a47ebf5c9eb517453ec1fa6b436c0ec328dfc245 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 6 Jul 2021 14:57:58 +1000 Subject: [PATCH 17/17] For consistency with TES CS, force DELE record writes to be 4 bytes (currently writes 1 byte). --- CHANGELOG.md | 1 + components/esm/cellref.cpp | 2 +- components/esm/debugprofile.cpp | 2 +- components/esm/filter.cpp | 2 +- components/esm/loadacti.cpp | 2 +- components/esm/loadalch.cpp | 2 +- components/esm/loadappa.cpp | 2 +- components/esm/loadarmo.cpp | 2 +- components/esm/loadbody.cpp | 2 +- components/esm/loadbook.cpp | 2 +- components/esm/loadbsgn.cpp | 2 +- components/esm/loadcell.cpp | 2 +- components/esm/loadclas.cpp | 2 +- components/esm/loadclot.cpp | 2 +- components/esm/loadcont.cpp | 2 +- components/esm/loadcrea.cpp | 2 +- components/esm/loaddial.cpp | 2 +- components/esm/loaddoor.cpp | 2 +- components/esm/loadench.cpp | 2 +- components/esm/loadfact.cpp | 2 +- components/esm/loadinfo.cpp | 2 +- components/esm/loadingr.cpp | 2 +- components/esm/loadland.cpp | 2 +- components/esm/loadlevlist.cpp | 2 +- components/esm/loadligh.cpp | 2 +- components/esm/loadlock.cpp | 2 +- components/esm/loadltex.cpp | 2 +- components/esm/loadmisc.cpp | 2 +- components/esm/loadnpc.cpp | 2 +- components/esm/loadpgrd.cpp | 2 +- components/esm/loadprob.cpp | 2 +- components/esm/loadrace.cpp | 2 +- components/esm/loadregn.cpp | 2 +- components/esm/loadrepa.cpp | 2 +- components/esm/loadscpt.cpp | 2 +- components/esm/loadsndg.cpp | 2 +- components/esm/loadsoun.cpp | 2 +- components/esm/loadspel.cpp | 2 +- components/esm/loadsscr.cpp | 2 +- components/esm/loadstat.cpp | 2 +- components/esm/loadweap.cpp | 2 +- 41 files changed, 41 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 705cc21bf0..b711a20b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Bug #6129: Player avatar not displayed correctly for large window sizes when GUI scaling active Bug #6131: Item selection in the avatar window not working correctly for large window sizes Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player + Editor: For consistency with TES CS make DELE records 4 bytes long 0.47.0 ------ diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 20edf00a8b..733547216b 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -145,7 +145,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool esm.writeHNCString("NAME", mRefID); if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/debugprofile.cpp b/components/esm/debugprofile.cpp index 17249d8a3b..1dcf661fc9 100644 --- a/components/esm/debugprofile.cpp +++ b/components/esm/debugprofile.cpp @@ -44,7 +44,7 @@ void ESM::DebugProfile::save (ESMWriter& esm, bool isDeleted) const if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/filter.cpp b/components/esm/filter.cpp index 4f0519f80b..5bae1ed03e 100644 --- a/components/esm/filter.cpp +++ b/components/esm/filter.cpp @@ -42,7 +42,7 @@ void ESM::Filter::save (ESMWriter& esm, bool isDeleted) const if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadacti.cpp b/components/esm/loadacti.cpp index ba35535b8f..57c55d6760 100644 --- a/components/esm/loadacti.cpp +++ b/components/esm/loadacti.cpp @@ -50,7 +50,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadalch.cpp b/components/esm/loadalch.cpp index 85c24dc2d1..ba904f5037 100644 --- a/components/esm/loadalch.cpp +++ b/components/esm/loadalch.cpp @@ -65,7 +65,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadappa.cpp b/components/esm/loadappa.cpp index 1bd1f93798..b448e778cf 100644 --- a/components/esm/loadappa.cpp +++ b/components/esm/loadappa.cpp @@ -61,7 +61,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp index 6743702539..9e2eca9a2c 100644 --- a/components/esm/loadarmo.cpp +++ b/components/esm/loadarmo.cpp @@ -99,7 +99,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadbody.cpp b/components/esm/loadbody.cpp index 3e5895c2c6..4ddefc92c7 100644 --- a/components/esm/loadbody.cpp +++ b/components/esm/loadbody.cpp @@ -55,7 +55,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadbook.cpp b/components/esm/loadbook.cpp index ee3c0c4af5..c6d1d618de 100644 --- a/components/esm/loadbook.cpp +++ b/components/esm/loadbook.cpp @@ -66,7 +66,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadbsgn.cpp b/components/esm/loadbsgn.cpp index e3b2f76a3a..1f679af39a 100644 --- a/components/esm/loadbsgn.cpp +++ b/components/esm/loadbsgn.cpp @@ -56,7 +56,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } esm.writeHNOCString("FNAM", mName); diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index bf70aad96f..0356cc646b 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -167,7 +167,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index 1e18bc0540..b76fc57067 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -86,7 +86,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 12f0d495d5..9546eec2dd 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -69,7 +69,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp index 107aea7cf6..077fc2145a 100644 --- a/components/esm/loadcont.cpp +++ b/components/esm/loadcont.cpp @@ -95,7 +95,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 52138e2232..ecb080f75e 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -115,7 +115,7 @@ namespace ESM { if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index d7e0a6ee17..59fb13484b 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -61,7 +61,7 @@ namespace ESM esm.writeHNCString("NAME", mId); if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); } else { diff --git a/components/esm/loaddoor.cpp b/components/esm/loaddoor.cpp index 523d8a1efc..d99418add2 100644 --- a/components/esm/loaddoor.cpp +++ b/components/esm/loaddoor.cpp @@ -57,7 +57,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadench.cpp b/components/esm/loadench.cpp index 8c4dd8c644..3c1a2f1eda 100644 --- a/components/esm/loadench.cpp +++ b/components/esm/loadench.cpp @@ -53,7 +53,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index ff2fbf66d1..bd0962721b 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -90,7 +90,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadinfo.cpp b/components/esm/loadinfo.cpp index 38bb163e61..15921249f4 100644 --- a/components/esm/loadinfo.cpp +++ b/components/esm/loadinfo.cpp @@ -100,7 +100,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadingr.cpp b/components/esm/loadingr.cpp index a18e321ff7..a19a9d5dd9 100644 --- a/components/esm/loadingr.cpp +++ b/components/esm/loadingr.cpp @@ -84,7 +84,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index d23452d76e..1fac79082d 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -123,7 +123,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadlevlist.cpp b/components/esm/loadlevlist.cpp index 0aed15aa94..26751b8925 100644 --- a/components/esm/loadlevlist.cpp +++ b/components/esm/loadlevlist.cpp @@ -80,7 +80,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadligh.cpp b/components/esm/loadligh.cpp index 2a6dac14b0..2e3f711eb7 100644 --- a/components/esm/loadligh.cpp +++ b/components/esm/loadligh.cpp @@ -63,7 +63,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadlock.cpp b/components/esm/loadlock.cpp index b14353ec5a..6f02909b98 100644 --- a/components/esm/loadlock.cpp +++ b/components/esm/loadlock.cpp @@ -61,7 +61,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadltex.cpp b/components/esm/loadltex.cpp index 3e150f9c0c..6bdc40e5fc 100644 --- a/components/esm/loadltex.cpp +++ b/components/esm/loadltex.cpp @@ -53,7 +53,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); } } diff --git a/components/esm/loadmisc.cpp b/components/esm/loadmisc.cpp index 3ba6626505..90fcd618e8 100644 --- a/components/esm/loadmisc.cpp +++ b/components/esm/loadmisc.cpp @@ -61,7 +61,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 2bb0811ac9..34d806072d 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -135,7 +135,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index 9abeba2605..7bf60ca5fc 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -156,7 +156,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadprob.cpp b/components/esm/loadprob.cpp index 6307df3298..ceb19a77b6 100644 --- a/components/esm/loadprob.cpp +++ b/components/esm/loadprob.cpp @@ -61,7 +61,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index fbdf22fb6d..ce3cc95bf8 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -68,7 +68,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadregn.cpp b/components/esm/loadregn.cpp index ada33dc3f8..91ea92e305 100644 --- a/components/esm/loadregn.cpp +++ b/components/esm/loadregn.cpp @@ -89,7 +89,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadrepa.cpp b/components/esm/loadrepa.cpp index c04691c12f..c86227a045 100644 --- a/components/esm/loadrepa.cpp +++ b/components/esm/loadrepa.cpp @@ -61,7 +61,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index 1ad90dbc31..19602fef62 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -155,7 +155,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadsndg.cpp b/components/esm/loadsndg.cpp index 9bd806641b..c6ea930a20 100644 --- a/components/esm/loadsndg.cpp +++ b/components/esm/loadsndg.cpp @@ -54,7 +54,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadsoun.cpp b/components/esm/loadsoun.cpp index 3b3dc1eacd..ccb5f6fdce 100644 --- a/components/esm/loadsoun.cpp +++ b/components/esm/loadsoun.cpp @@ -52,7 +52,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadspel.cpp b/components/esm/loadspel.cpp index 947e6c9ec8..34e146501c 100644 --- a/components/esm/loadspel.cpp +++ b/components/esm/loadspel.cpp @@ -59,7 +59,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; } diff --git a/components/esm/loadsscr.cpp b/components/esm/loadsscr.cpp index f8854493b9..f436c32a1c 100644 --- a/components/esm/loadsscr.cpp +++ b/components/esm/loadsscr.cpp @@ -47,7 +47,7 @@ namespace ESM esm.writeHNCString("NAME", mId); if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); } else { diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 6c9de22bd1..14bac10f95 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -43,7 +43,7 @@ namespace ESM esm.writeHNCString("NAME", mId); if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); } else { diff --git a/components/esm/loadweap.cpp b/components/esm/loadweap.cpp index 4a77ff6a00..b57359e29d 100644 --- a/components/esm/loadweap.cpp +++ b/components/esm/loadweap.cpp @@ -62,7 +62,7 @@ namespace ESM if (isDeleted) { - esm.writeHNCString("DELE", ""); + esm.writeHNString("DELE", "", 3); return; }