diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index 27980096e..3bbdaef35 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -244,7 +244,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info) if(quiet) continue; - std::cout << " Refnum: " << ref.mRefnum << std::endl; + std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl; std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " Owner: '" << ref.mOwner << "'\n"; std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n"; diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 0c145ab60..06ae083ce 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -38,7 +38,7 @@ namespace MWWorld void CellRefList::load(ESM::CellRef &ref, const MWWorld::ESMStore &esmStore) { // Get existing reference, in case we need to overwrite it. - typename std::list::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefnum); + typename std::list::iterator iter = std::find(mList.begin(), mList.end(), ref.mRefNum); // Skip this when reference was deleted. // TODO: Support respawning references, in this case, we need to track it somehow. @@ -148,13 +148,14 @@ namespace MWWorld mCell->restore (esm[index], i); ESM::CellRef ref; + ref.mRefNum.mContentFile = -1; // Get each reference in turn while(mCell->getNextRef(esm[index], ref)) { // Don't load reference if it was moved to a different cell. std::string lowerCase = Misc::StringUtils::lowerCase(ref.mRefID); - ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefnum); + ESM::MovedCellRefTracker::const_iterator iter = std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum); if (iter != mCell->mMovedRefs.end()) { continue; } diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 415351e78..558639a3b 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -31,6 +31,11 @@ namespace MWWorld virtual ~LiveCellRefBase() { } }; + inline bool operator== (const LiveCellRefBase& cellRef, const ESM::CellRef::RefNum refNum) + { + return cellRef.mRef.mRefNum==refNum; + } + /// A reference to one object (of any type) in a cell. /// /// Constructing this with a CellRef instance in the constructor means that @@ -51,8 +56,6 @@ namespace MWWorld // The object that this instance is based on. const X* mBase; }; - -// template bool operator==(const LiveCellRef& ref, int pRefnum); } #endif diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp index 1cdcd8484..f138e3732 100644 --- a/apps/openmw/mwworld/manualref.hpp +++ b/apps/openmw/mwworld/manualref.hpp @@ -25,6 +25,8 @@ namespace MWWorld { LiveCellRef ref; ref.mBase = instance; + ref.mRef.mRefNum.mIndex = 0; + ref.mRef.mRefNum.mContentFile = -1; mRef = ref; mPtr = Ptr (&boost::any_cast&> (mRef), 0); @@ -65,7 +67,8 @@ namespace MWWorld // initialise ESM::CellRef& cellRef = mPtr.getCellRef(); cellRef.mRefID = name; - cellRef.mRefnum = -1; + cellRef.mRefNum.mIndex = 0; + cellRef.mRefNum.mContentFile = -1; cellRef.mScale = 1; cellRef.mFactIndex = 0; cellRef.mCharge = -1; diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 512883f1a..9ba2d8133 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -10,7 +10,7 @@ void Store::load(ESM::ESMReader &esm, const std::string &id) // and we merge all this data into one Cell object. However, we can't simply search for the cell id, // as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they // are not available until both cells have been loaded! So first, proceed as usual. - + // All cells have a name record, even nameless exterior cells. std::string idLower = Misc::StringUtils::lowerCase(id); ESM::Cell *cell = new ESM::Cell; @@ -40,7 +40,7 @@ void Store::load(ESM::ESMReader &esm, const std::string &id) // We should not need to test for duplicates, as this part of the code is pre-cell merge. cell->mMovedRefs.push_back(cMRef); // But there may be duplicates here! - ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum); + ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefNum); if (iter == cellAlt->mLeasedRefs.end()) cellAlt->mLeasedRefs.push_back(ref); else @@ -76,11 +76,11 @@ void Store::load(ESM::ESMReader &esm, const std::string &id) // merge lists of leased references, use newer data in case of conflict for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); ++it) { // remove reference from current leased ref tracker and add it to new cell - ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefnum); + ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefNum); if (itold != oldcell->mMovedRefs.end()) { ESM::MovedCellRef target0 = *itold; ESM::Cell *wipecell = const_cast(search(target0.mTarget[0], target0.mTarget[1])); - ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefnum); + ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefNum); wipecell->mLeasedRefs.erase(it_lease); *itold = *it; } diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index e91059b26..23a95a4ab 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -5,7 +5,8 @@ void ESM::CellRef::save(ESMWriter &esm) const { - esm.writeHNT("FRMR", mRefnum); + esm.writeHNT("FRMR", mRefNum.mIndex); + /// \todo read content file index (if present) esm.writeHNCString("NAME", mRefID); if (mScale != 1.0) { @@ -58,7 +59,8 @@ void ESM::CellRef::save(ESMWriter &esm) const void ESM::CellRef::blank() { - mRefnum = 0; + mRefNum.mIndex = 0; + mRefNum.mContentFile = -1; mRefID.clear(); mScale = 1; mOwner.clear(); @@ -84,4 +86,9 @@ void ESM::CellRef::blank() mPos.pos[i] = 0; mPos.rot[i] = 0; } +} + +bool ESM::operator== (const CellRef::RefNum& left, const CellRef::RefNum& right) +{ + return left.mIndex==right.mIndex && left.mContentFile==right.mContentFile; } \ No newline at end of file diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 47cb0b99e..ef2523869 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -19,7 +19,13 @@ namespace ESM { public: - int mRefnum; // Reference number + struct RefNum + { + int mIndex; + int mContentFile; // -1 no content file + }; + + RefNum mRefNum; // Reference number std::string mRefID; // ID of object being referenced float mScale; // Scale applied to mesh @@ -87,6 +93,8 @@ namespace ESM void blank(); }; + + bool operator== (const CellRef::RefNum& left, const CellRef::RefNum& right); } #endif \ No newline at end of file diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index c22c1b22b..ba4195370 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -9,20 +9,42 @@ #include "esmwriter.hpp" #include "defs.hpp" -namespace ESM +namespace { - unsigned int Cell::sRecordId = REC_CELL; + ///< Translate 8bit/24bit code (stored in refNum.mIndex) into a proper refNum + void adjustRefNum (ESM::CellRef::RefNum& refNum, ESM::ESMReader& reader) + { + int local = (refNum.mIndex & 0xff000000) >> 24; -/// Some overloaded compare operators. -bool operator==(const MovedCellRef& ref, int pRefnum) -{ - return (ref.mRefnum == pRefnum); + if (local) + { + // If the most significant 8 bits are used, then this reference already exists. + // In this case, do not spawn a new reference, but overwrite the old one. + refNum.mIndex &= 0x00ffffff; // delete old plugin ID + refNum.mContentFile = reader.getGameFiles()[local-1].index; + } + else + { + // This is an addition by the present plugin. Set the corresponding plugin index. + refNum.mContentFile = reader.getIndex(); + } + } } -bool operator==(const CellRef& ref, int pRefnum) +namespace ESM { - return (ref.mRefnum == pRefnum); -} + unsigned int Cell::sRecordId = REC_CELL; + + // Some overloaded compare operators. + bool operator== (const MovedCellRef& ref, const CellRef::RefNum& refNum) + { + return ref.mRefNum == refNum; + } + + bool operator== (const CellRef& ref, const CellRef::RefNum& refNum) + { + return ref.mRefNum == refNum; + } void Cell::load(ESMReader &esm, bool saveContext) @@ -163,49 +185,17 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) //esm.getHNOT(NAM0, "NAM0"); } - esm.getHNT(ref.mRefnum, "FRMR"); + esm.getHNT (ref.mRefNum.mIndex, "FRMR"); ref.mRefID = esm.getHNString("NAME"); // Identify references belonging to a parent file and adapt the ID accordingly. - int local = (ref.mRefnum & 0xff000000) >> 24; - size_t global = esm.getIndex() + 1; - if (local) - { - // If the most significant 8 bits are used, then this reference already exists. - // In this case, do not spawn a new reference, but overwrite the old one. - ref.mRefnum &= 0x00ffffff; // delete old plugin ID - const std::vector &masters = esm.getGameFiles(); - global = masters[local-1].index + 1; - ref.mRefnum |= global << 24; // insert global plugin ID - } - else - { - // This is an addition by the present plugin. Set the corresponding plugin index. - ref.mRefnum |= global << 24; // insert global plugin ID - } + adjustRefNum (ref.mRefNum, esm); // getHNOT will not change the existing value if the subrecord is // missing ref.mScale = 1.0; esm.getHNOT(ref.mScale, "XSCL"); - // TODO: support loading references from saves, there are tons of keys not recognized yet. - // The following is just an incomplete list. - if (esm.isNextSub("ACTN")) - esm.skipHSub(); - if (esm.isNextSub("STPR")) - esm.skipHSub(); - if (esm.isNextSub("ACDT")) - esm.skipHSub(); - if (esm.isNextSub("ACSC")) - esm.skipHSub(); - if (esm.isNextSub("ACSL")) - esm.skipHSub(); - if (esm.isNextSub("CHRD")) - esm.skipHSub(); - else if (esm.isNextSub("CRED")) // ??? - esm.skipHSub(); - ref.mOwner = esm.getHNOString("ANAM"); ref.mGlob = esm.getHNOString("BNAM"); ref.mSoul = esm.getHNOString("XSOL"); @@ -271,16 +261,10 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref) { - esm.getHT(mref.mRefnum); + esm.getHT(mref.mRefNum.mIndex); esm.getHNOT(mref.mTarget, "CNDT"); - // Identify references belonging to a parent file and adapt the ID accordingly. - int local = (mref.mRefnum & 0xff000000) >> 24; - size_t global = esm.getIndex() + 1; - mref.mRefnum &= 0x00ffffff; // delete old plugin ID - const std::vector &masters = esm.getGameFiles(); - global = masters[local-1].index + 1; - mref.mRefnum |= global << 24; // insert global plugin ID + adjustRefNum (mref.mRefNum, esm); return true; } diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 61d586b9d..b0340e945 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -27,7 +27,7 @@ class ESMWriter; class MovedCellRef { public: - int mRefnum; + CellRef::RefNum mRefNum; // Target cell (if exterior) int mTarget[2]; @@ -37,9 +37,9 @@ public: // introduces a henchman (which no one uses), so we may need this as well. }; -/// Overloaded copare operator used to search inside a list of cell refs. -bool operator==(const MovedCellRef& ref, int pRefnum); -bool operator==(const CellRef& ref, int pRefnum); +/// Overloaded compare operator used to search inside a list of cell refs. +bool operator==(const MovedCellRef& ref, const CellRef::RefNum& refNum); +bool operator==(const CellRef& ref, const CellRef::RefNum& refNum); typedef std::list MovedCellRefTracker; typedef std::list CellRefTracker;