diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index e49835f41..667f2d4ca 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -43,30 +43,30 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) cellStore.containers.list.begin()); iter!=cellStore.containers.list.end(); ++iter) { - Ptr container (&*iter, &cellStore); + Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->base->mInventory, mStore); + iter->second.base->mInventory, mStore); } for (CellRefList::List::iterator iter ( cellStore.creatures.list.begin()); iter!=cellStore.creatures.list.end(); ++iter) { - Ptr container (&*iter, &cellStore); + Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->base->mInventory, mStore); + iter->second.base->mInventory, mStore); } for (CellRefList::List::iterator iter ( cellStore.npcs.list.begin()); iter!=cellStore.npcs.list.end(); ++iter) { - Ptr container (&*iter, &cellStore); + Ptr container (&iter->second, &cellStore); Class::get (container).getContainerStore (container).fill ( - iter->base->mInventory, mStore); + iter->second.base->mInventory, mStore); } } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 91c0afe26..0af886124 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -65,8 +65,7 @@ namespace MWWorld std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); - // TODO: Fully support deletion / moving references out of the cell. no simple "push_back", - // but make sure that the reference exists only once. + // TODO: Fully support deletion of references. mIds.push_back (lowerCase); } } @@ -98,8 +97,7 @@ namespace MWWorld std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); - // TODO: Fully support deletion / moving references out of the cell. No simple loading, - // but make sure that the reference exists only once. Current code clones references. + // TODO: Fully support deletion of references. int rec = store.find(ref.mRefID); ref.mRefID = lowerCase; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 69c4cf9b4..236f67231 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -47,6 +47,47 @@ namespace MWWorld /// A list of cell references template struct CellRefList + { + typedef LiveCellRef LiveRef; + typedef std::map List; + List list; + + // Search for the given reference in the given reclist from + // ESMStore. Insert the reference into the list if a match is + // found. If not, throw an exception. + template + void find(ESM::CellRef &ref, const Y& recList) + { + const X* obj = recList.find(ref.mRefID); + if(obj == NULL) + throw std::runtime_error("Error resolving cell reference " + ref.mRefID); + + list[ref.mRefnum] = LiveRef(ref, obj); + } + + LiveRef *find (const std::string& name) + { + for (typename std::map::iterator iter (list.begin()); iter!=list.end(); ++iter) + { + if (iter->second.mData.getCount() > 0 && iter->second.ref.mRefID == name) + return &iter->second; + } + + return 0; + } + + LiveRef &insert(const LiveRef &item) { + list[item.ref.mRefnum] = item; + return list[item.ref.mRefnum]; + } + }; + + /// A list of container references. These references do not track their mRefnumber. + /// Otherwise, taking 1 of 20 instances of an object would produce multiple objects + /// with the same reference. + // TODO: Check how Morrowind does this! Maybe auto-generate references on drop. + template + struct ContainerRefList { typedef LiveCellRef LiveRef; typedef std::list List; @@ -62,10 +103,6 @@ namespace MWWorld if(obj == NULL) throw std::runtime_error("Error resolving cell reference " + ref.mRefID); - // TODO: this line must be modified for multiple plugins and moved references. - // This means: no simple "push back", but search for an existing reference with - // this ID first! If it exists, merge data into this list instead of just adding it. - // I'll probably generate a separate method jist for this. list.push_back(LiveRef(ref, obj)); } @@ -180,7 +217,7 @@ namespace MWWorld { for (typename List::List::iterator iter (list.list.begin()); iter!=list.list.end(); ++iter) - if (!functor (iter->ref, iter->mData)) + if (!functor (iter->second.ref, iter->second.mData)) return false; return true; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 5c4dd03a4..035f79310 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -19,11 +19,11 @@ namespace { template - float getTotalWeight (const MWWorld::CellRefList& cellRefList) + float getTotalWeight (const MWWorld::ContainerRefList& cellRefList) { float sum = 0; - for (typename MWWorld::CellRefList::List::const_iterator iter ( + for (typename MWWorld::ContainerRefList::List::const_iterator iter ( cellRefList.list.begin()); iter!=cellRefList.list.end(); ++iter) @@ -270,29 +270,29 @@ MWWorld::ContainerStoreIterator::ContainerStoreIterator (int mask, ContainerStor ++*this; } -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Potion), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mPotion(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Apparatus), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mApparatus(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Armor), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mArmor(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Book), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mBook(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Clothing), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mClothing(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Ingredient), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mIngredient(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Light), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLight(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Lockpick), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mLockpick(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Miscellaneous), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mMiscellaneous(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Probe), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mProbe(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Repair), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mRepair(iterator){} -MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator iterator) +MWWorld::ContainerStoreIterator::ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator iterator) : mType(MWWorld::ContainerStore::Type_Weapon), mMask(MWWorld::ContainerStore::Type_All), mContainer(container), mWeapon(iterator){} void MWWorld::ContainerStoreIterator::incType() diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index ae27fad3d..9611b9c21 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -37,18 +37,18 @@ namespace MWWorld private: - MWWorld::CellRefList potions; - MWWorld::CellRefList appas; - MWWorld::CellRefList armors; - MWWorld::CellRefList books; - MWWorld::CellRefList clothes; - MWWorld::CellRefList ingreds; - MWWorld::CellRefList lights; - MWWorld::CellRefList lockpicks; - MWWorld::CellRefList miscItems; - MWWorld::CellRefList probes; - MWWorld::CellRefList repairs; - MWWorld::CellRefList weapons; + MWWorld::ContainerRefList potions; + MWWorld::ContainerRefList appas; + MWWorld::ContainerRefList armors; + MWWorld::ContainerRefList books; + MWWorld::ContainerRefList clothes; + MWWorld::ContainerRefList ingreds; + MWWorld::ContainerRefList lights; + MWWorld::ContainerRefList lockpicks; + MWWorld::ContainerRefList miscItems; + MWWorld::ContainerRefList probes; + MWWorld::ContainerRefList repairs; + MWWorld::ContainerRefList weapons; int mStateId; mutable float mCachedWeight; mutable bool mWeightUpToDate; @@ -119,18 +119,18 @@ namespace MWWorld ContainerStore *mContainer; mutable Ptr mPtr; - MWWorld::CellRefList::List::iterator mPotion; - MWWorld::CellRefList::List::iterator mApparatus; - MWWorld::CellRefList::List::iterator mArmor; - MWWorld::CellRefList::List::iterator mBook; - MWWorld::CellRefList::List::iterator mClothing; - MWWorld::CellRefList::List::iterator mIngredient; - MWWorld::CellRefList::List::iterator mLight; - MWWorld::CellRefList::List::iterator mLockpick; - MWWorld::CellRefList::List::iterator mMiscellaneous; - MWWorld::CellRefList::List::iterator mProbe; - MWWorld::CellRefList::List::iterator mRepair; - MWWorld::CellRefList::List::iterator mWeapon; + MWWorld::ContainerRefList::List::iterator mPotion; + MWWorld::ContainerRefList::List::iterator mApparatus; + MWWorld::ContainerRefList::List::iterator mArmor; + MWWorld::ContainerRefList::List::iterator mBook; + MWWorld::ContainerRefList::List::iterator mClothing; + MWWorld::ContainerRefList::List::iterator mIngredient; + MWWorld::ContainerRefList::List::iterator mLight; + MWWorld::ContainerRefList::List::iterator mLockpick; + MWWorld::ContainerRefList::List::iterator mMiscellaneous; + MWWorld::ContainerRefList::List::iterator mProbe; + MWWorld::ContainerRefList::List::iterator mRepair; + MWWorld::ContainerRefList::List::iterator mWeapon; private: @@ -141,18 +141,18 @@ namespace MWWorld ///< Begin-iterator // construct iterator using a CellRefList iterator - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); - ContainerStoreIterator (ContainerStore *container, MWWorld::CellRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); + ContainerStoreIterator (ContainerStore *container, MWWorld::ContainerRefList::List::iterator); void incType(); diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index d0d698feb..1ef1cdeaf 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -15,9 +15,9 @@ namespace cellRefList.list.begin()); iter!=cellRefList.list.end(); ++iter) { - if (!iter->base->mScript.empty() && iter->mData.getCount()) + if (!iter->second.base->mScript.empty() && iter->second.mData.getCount()) { - localScripts.add (iter->base->mScript, MWWorld::Ptr (&*iter, cell)); + localScripts.add (iter->second.base->mScript, MWWorld::Ptr (&iter->second, cell)); } } } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 881b090fa..b6add7fbf 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -23,7 +23,7 @@ namespace if (!cellRefList.list.empty()) { const MWWorld::Class& class_ = - MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.list.begin(), &cell)); + MWWorld::Class::get (MWWorld::Ptr (&cellRefList.list.begin()->second, &cell)); int numRefs = cellRefList.list.size(); int current = 0; @@ -33,9 +33,9 @@ namespace MWBase::Environment::get().getWindowManager ()->setLoadingProgress ("Loading cells", 1, current, numRefs); ++current; - if (it->mData.getCount() || it->mData.isEnabled()) + if (it->second.mData.getCount() || it->second.mData.isEnabled()) { - MWWorld::Ptr ptr (&*it, &cell); + MWWorld::Ptr ptr (&it->second, &cell); try { diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3e23679b1..e999100f0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -28,13 +28,13 @@ namespace cellRefList.list.begin()); iter!=cellRefList.list.end(); ++iter) { - if (!iter->base->script.empty() && iter->mData.getCount()) + if (!iter->second->base->script.empty() && iter->second->mData.getCount()) { - if (const ESM::Script *script = store.scripts.find (iter->base->script)) + if (const ESM::Script *script = store.scripts.find (iter->second->base->script)) { iter->mData.setLocals (*script); - localScripts.add (iter->base->script, MWWorld::Ptr (&*iter, cell)); + localScripts.add (iter->base->script, MWWorld::Ptr (&iter->second, cell)); } } } @@ -48,10 +48,10 @@ namespace for (iterator iter (refList.list.begin()); iter!=refList.list.end(); ++iter) { - if(iter->mData.getCount() > 0 && iter->mData.getBaseNode()){ - if (iter->mData.getHandle()==handle) + if (iter->second.mData.getCount() > 0 && iter->second.mData.getBaseNode()){ + if (iter->second.mData.getHandle()==handle) { - return &*iter; + return &iter->second; } } } @@ -1115,10 +1115,10 @@ namespace MWWorld std::vector result; MWWorld::CellRefList& doors = cell->doors; - std::list< MWWorld::LiveCellRef >& refList = doors.list; - for (std::list< MWWorld::LiveCellRef >::iterator it = refList.begin(); it != refList.end(); ++it) + std::map >& refList = doors.list; + for (std::map >::iterator it = refList.begin(); it != refList.end(); ++it) { - MWWorld::LiveCellRef& ref = *it; + MWWorld::LiveCellRef& ref = it->second; if (ref.ref.mTeleport) { diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 1a1811a90..b7f27b08d 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -113,8 +113,6 @@ void Cell::load(ESMReader &esm) // Save position of the cell references and move on mContextList.push_back(esm.getContext()); - if (mContextList.size() > 1) - std::cout << "found two plugins" << std::endl; esm.skipRecord(); } @@ -202,10 +200,8 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) // In this case, do not spawn a new reference, but overwrite the old one. ref.mRefnum &= 0x00ffffff; // delete old plugin ID const ESM::ESMReader::MasterList &masters = esm.getMasters(); - // TODO: Test how Morrowind does it! Maybe the first entry in the list should be "1"... global = masters[local-1].index + 1; ref.mRefnum |= global << 24; // insert global plugin ID - std::cout << "Refnum_old = " << ref.mRefnum << " " << local << " " << global << std::endl; } else { @@ -256,7 +252,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref) esm.getHNOT(ref.mFltv, "FLTV"); esm.getHNT(ref.mPos, "DATA", 24); - + // Number of references in the cell? Maximum once in each cell, // but not always at the beginning, and not always right. In other // words, completely useless. diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 44b7e6569..14452fca9 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -523,7 +523,10 @@ namespace ESMS // Store exterior cells by grid position, try to merge with existing parent data. ESM::Cell *oldcell = const_cast(searchExt(cell->getGridX(), cell->getGridY())); if (oldcell) { - cell->mContextList.push_back(oldcell->mContextList.at(0)); + // The load order is important. Push the new source context on the *back* of the existing list, + // and then move the list to the new cell. + oldcell->mContextList.push_back(cell->mContextList.at(0)); + cell->mContextList = oldcell->mContextList; delete oldcell; } extCells[std::make_pair (cell->mData.mX, cell->mData.mY)] = cell;