From 0975f60d594e8bfa906875bd2952d1493d784cd4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 14 Nov 2015 16:59:25 +0100 Subject: [PATCH 01/23] Stub out CellStore::get accessors in preparation of reference movement between cells --- apps/openmw/mwclass/activator.cpp | 3 +- apps/openmw/mwclass/apparatus.cpp | 3 +- apps/openmw/mwclass/armor.cpp | 3 +- apps/openmw/mwclass/book.cpp | 3 +- apps/openmw/mwclass/clothing.cpp | 3 +- apps/openmw/mwclass/container.cpp | 3 +- apps/openmw/mwclass/creature.cpp | 3 +- apps/openmw/mwclass/door.cpp | 3 +- apps/openmw/mwclass/ingredient.cpp | 3 +- apps/openmw/mwclass/light.cpp | 3 +- apps/openmw/mwclass/lockpick.cpp | 3 +- apps/openmw/mwclass/misc.cpp | 2 + apps/openmw/mwclass/npc.cpp | 3 +- apps/openmw/mwclass/potion.cpp | 3 +- apps/openmw/mwclass/probe.cpp | 3 +- apps/openmw/mwclass/repair.cpp | 3 +- apps/openmw/mwclass/static.cpp | 3 +- apps/openmw/mwclass/weapon.cpp | 3 +- apps/openmw/mwmechanics/obstacle.cpp | 2 + apps/openmw/mwworld/cellstore.hpp | 159 +-------------------------- apps/openmw/mwworld/localscripts.cpp | 2 + apps/openmw/mwworld/worldimp.cpp | 20 +++- 22 files changed, 60 insertions(+), 176 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 3a0f1b951..fdbff026f 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -130,6 +130,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index f93556ef9..06eea2c24 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -147,8 +147,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 324dd32ee..9ad28a537 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -381,8 +381,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 2c20435b2..cfa2508c4 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -186,8 +186,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index cea30d561..8bd3fd2e6 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -275,8 +275,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 6c44c97e2..b82dff706 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -292,8 +292,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 2cd11d113..7f43f8677 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -599,8 +599,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Creature::isBipedal(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 6fee79ddf..cb9f59e96 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -309,8 +309,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } void Door::ensureCustomData(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index c9e6e70f2..0b6724c6c 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -184,8 +184,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 34d93da67..0442fd2e0 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -216,8 +216,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 5cffdf13a..bd17a527b 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -165,8 +165,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 98b4faab9..16d926f5e 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -194,6 +194,7 @@ namespace MWClass { MWWorld::Ptr newPtr; + /* const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -223,6 +224,7 @@ namespace MWClass ptr.get(); newPtr = MWWorld::Ptr(&cell.get().insert(*ref), &cell); } + */ return newPtr; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 6633b3490..b5f2b52f3 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1129,8 +1129,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index cf6b0919b..0f449fa92 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -177,8 +177,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index ff717c506..80825466a 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -164,8 +164,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index e6baea2e0..993c39aa2 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -159,8 +159,9 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } boost::shared_ptr Repair::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 9755df28e..ae0b5d3dd 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -59,7 +59,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); + return MWWorld::Ptr(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index da4c7deb2..15c0039a4 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -417,7 +417,8 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(); + //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); } int Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index dae5f8496..a2cbae2a0 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -44,6 +44,7 @@ namespace MWMechanics return MWWorld::Ptr(); // check interior cells only // Check all the doors in this cell + /* MWWorld::CellRefList& doors = cell->get(); MWWorld::CellRefList::List& refList = doors.mList; MWWorld::CellRefList::List::iterator it = refList.begin(); @@ -66,6 +67,7 @@ namespace MWMechanics return MWWorld::Ptr(&ref, actor.getCell()); // found, stop searching } } + */ return MWWorld::Ptr(); // none found } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index f88bf0958..89b200262 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -73,6 +73,7 @@ namespace MWWorld MWWorld::TimeStamp mLastRespawn; + // List of refs owned by this cell CellRefList mActivators; CellRefList mPotions; CellRefList mAppas; @@ -179,6 +180,8 @@ namespace MWWorld forEachImp (functor, mNpcs); } + /// \todo add const version of forEach + bool isExterior() const; Ptr searchInContainer (const std::string& id); @@ -198,16 +201,6 @@ namespace MWWorld void respawn (); ///< Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded. - template - CellRefList& get() { - throw std::runtime_error ("Storage for type " + std::string(typeid(T).name())+ " does not exist in cells"); - } - - template - const CellRefList& getReadOnly() { - throw std::runtime_error ("Read Only CellRefList access not available for type " + std::string(typeid(T).name()) ); - } - bool isPointConnected(const int start, const int end) const; std::list aStarSearch(const int start, const int end) const; @@ -241,152 +234,6 @@ namespace MWWorld MWMechanics::PathgridGraph mPathgridGraph; }; - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mActivators; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mPotions; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mAppas; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mArmors; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mBooks; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mClothes; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mContainers; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mCreatures; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mDoors; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mIngreds; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mCreatureLists; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mItemLists; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mLights; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mLockpicks; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mMiscItems; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mNpcs; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mProbes; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mRepairs; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mStatics; - } - - template<> - inline CellRefList& CellStore::get() - { - mHasState = true; - return mWeapons; - } - - template<> - inline const CellRefList& CellStore::getReadOnly() - { - return mDoors; - } - bool operator== (const CellStore& left, const CellStore& right); bool operator!= (const CellStore& left, const CellStore& right); } diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index e30246f7c..aa5abc076 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -116,6 +116,7 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) void MWWorld::LocalScripts::addCell (CellStore *cell) { + /* listCellScripts (*this, cell->get(), cell); listCellScripts (*this, cell->get(), cell); listCellScripts (*this, cell->get(), cell); @@ -136,6 +137,7 @@ void MWWorld::LocalScripts::addCell (CellStore *cell) listCellScripts (*this, cell->get(), cell); listCellScripts (*this, cell->get(), cell); listCellScripts (*this, cell->get(), cell); + */ } void MWWorld::LocalScripts::clear() diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 22485ed92..950c38e76 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1693,6 +1693,7 @@ namespace MWWorld osg::Vec2f World::getNorthVector (CellStore* cell) { + /* MWWorld::CellRefList& statics = cell->get(); MWWorld::LiveCellRef* ref = statics.find("northmarker"); if (!ref) @@ -1702,10 +1703,13 @@ namespace MWWorld osg::Vec3f dir = orient * osg::Vec3f(0,1,0); osg::Vec2f d (dir.x(), dir.y()); return d; + */ + return osg::Vec2f(); } void World::getDoorMarkers (CellStore* cell, std::vector& out) { + /* MWWorld::CellRefList& doors = cell->get(); CellRefList::List& refList = doors.mList; for (CellRefList::List::iterator it = refList.begin(); it != refList.end(); ++it) @@ -1744,6 +1748,7 @@ namespace MWWorld out.push_back(newMarker); } } + */ } void World::setWaterHeight(const float height) @@ -2240,6 +2245,7 @@ namespace MWWorld void World::getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector& out) { + /* const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { @@ -2254,6 +2260,7 @@ namespace MWWorld out.push_back(ptr); } } + */ } struct ListObjectsFunctor @@ -2316,6 +2323,8 @@ namespace MWWorld bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) { + return false; + /* typedef MWWorld::CellRefList::List DoorList; typedef MWWorld::CellRefList::List StaticList; @@ -2368,6 +2377,7 @@ namespace MWWorld pos = statics.begin()->mRef.getPosition(); return true; } + */ return false; } @@ -2715,6 +2725,8 @@ namespace MWWorld bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result) { + return false; + /* if (cell->isExterior()) return false; @@ -2732,7 +2744,7 @@ namespace MWWorld MWWorld::CellStore *next = getInterior( *i ); if ( !next ) continue; - const MWWorld::CellRefList& doors = next->getReadOnly(); + const MWWorld::CellRefList& doors = next->getReadOnlyDoors(); const CellRefList::List& refList = doors.mList; // Check if any door in the cell leads to an exterior directly @@ -2761,10 +2773,12 @@ namespace MWWorld // No luck :( return false; + */ } MWWorld::Ptr World::getClosestMarker( const MWWorld::Ptr &ptr, const std::string &id ) { + /* if ( ptr.getCell()->isExterior() ) { return getClosestMarkerFromExteriorPosition(mPlayer->getLastKnownExteriorPosition(), id); } @@ -2792,7 +2806,7 @@ namespace MWWorld return closestMarker; } - const MWWorld::CellRefList& doors = next->getReadOnly(); + const MWWorld::CellRefList& doors = next->getReadOnlyDoors(); const CellRefList::List& doorList = doors.mList; // Check if any door in the cell leads to an exterior directly @@ -2816,7 +2830,7 @@ namespace MWWorld } } } - + */ return MWWorld::Ptr(); } From fc449233bebb6c6864ca284a6c8cd0d307d8a3c2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 14 Nov 2015 17:12:05 +0100 Subject: [PATCH 02/23] Restore support for inserting objects into a cell --- apps/openmw/mwclass/activator.cpp | 3 +- apps/openmw/mwclass/apparatus.cpp | 3 +- apps/openmw/mwclass/armor.cpp | 3 +- apps/openmw/mwclass/book.cpp | 3 +- apps/openmw/mwclass/clothing.cpp | 3 +- apps/openmw/mwclass/container.cpp | 3 +- apps/openmw/mwclass/creature.cpp | 3 +- apps/openmw/mwclass/door.cpp | 3 +- apps/openmw/mwclass/ingredient.cpp | 3 +- apps/openmw/mwclass/light.cpp | 3 +- apps/openmw/mwclass/lockpick.cpp | 3 +- apps/openmw/mwclass/misc.cpp | 7 +- apps/openmw/mwclass/npc.cpp | 3 +- apps/openmw/mwclass/potion.cpp | 3 +- apps/openmw/mwclass/probe.cpp | 3 +- apps/openmw/mwclass/repair.cpp | 3 +- apps/openmw/mwclass/static.cpp | 3 +- apps/openmw/mwclass/weapon.cpp | 3 +- apps/openmw/mwworld/cellstore.hpp | 125 +++++++++++++++++++++++++++++ 19 files changed, 145 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index fdbff026f..17757cb6b 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -130,7 +130,6 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 06eea2c24..07bf25086 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -147,9 +147,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 9ad28a537..631ddd912 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -381,9 +381,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index cfa2508c4..9ea9e659b 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -186,9 +186,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 8bd3fd2e6..7250e1837 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -275,9 +275,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index b82dff706..9e8c018cd 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -292,9 +292,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) const diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 7f43f8677..e5a98c889 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -599,9 +599,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Creature::isBipedal(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index cb9f59e96..d0448f7ec 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -309,9 +309,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } void Door::ensureCustomData(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 0b6724c6c..db2f2410b 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -184,9 +184,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 0442fd2e0..fe5149077 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -216,9 +216,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index bd17a527b..63f75a845 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -165,9 +165,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 16d926f5e..a14ab3330 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -194,7 +194,6 @@ namespace MWClass { MWWorld::Ptr newPtr; - /* const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); @@ -216,15 +215,15 @@ namespace MWClass MWWorld::ManualRef newRef(store, base); MWWorld::LiveCellRef *ref = newRef.getPtr().get(); - newPtr = MWWorld::Ptr(&cell.get().insert(*ref), &cell); + + newPtr = MWWorld::Ptr(cell.insert(ref), &cell); newPtr.getCellRef().setGoldValue(goldAmount); newPtr.getRefData().setCount(1); } else { MWWorld::LiveCellRef *ref = ptr.get(); - newPtr = MWWorld::Ptr(&cell.get().insert(*ref), &cell); + newPtr = MWWorld::Ptr(cell.insert(ref), &cell); } - */ return newPtr; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index b5f2b52f3..7ab95bffa 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1129,9 +1129,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 0f449fa92..20a849019 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -177,9 +177,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 80825466a..79f423b30 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -164,9 +164,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 993c39aa2..78ec2adcc 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -159,9 +159,8 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } boost::shared_ptr Repair::use (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index ae0b5d3dd..86019a5ad 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -59,8 +59,7 @@ namespace MWClass { MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 15c0039a4..5665bf1c4 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -417,8 +417,7 @@ namespace MWClass MWWorld::LiveCellRef *ref = ptr.get(); - return MWWorld::Ptr(); - //return MWWorld::Ptr(&cell.get().insert(*ref), &cell); + return MWWorld::Ptr(cell.insert(ref), &cell); } int Weapon::getEnchantmentPoints (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 89b200262..8bf4d0ae9 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -97,6 +97,9 @@ namespace MWWorld public: + template + LiveCellRefBase* insert(const LiveCellRef* ref); + CellStore (const ESM::Cell *cell_); const ESM::Cell *getCell() const; @@ -234,6 +237,128 @@ namespace MWWorld MWMechanics::PathgridGraph mPathgridGraph; }; + + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mActivators.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mPotions.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mAppas.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mArmors.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mBooks.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mClothes.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mContainers.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mCreatures.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mDoors.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mIngreds.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mCreatureLists.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mItemLists.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mLights.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mLockpicks.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mMiscItems.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mNpcs.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mProbes.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mRepairs.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mStatics.insert(*ref); + } + template<> + inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + { + mHasState = true; + return &mWeapons.insert(*ref); + } + bool operator== (const CellStore& left, const CellStore& right); bool operator!= (const CellStore& left, const CellStore& right); } From 7a983340bfd3502e500c6fe76e4b1005adc480cf Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 14 Nov 2015 17:25:00 +0100 Subject: [PATCH 03/23] Add comment --- apps/openmw/mwworld/cellstore.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 8bf4d0ae9..979316efc 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -97,6 +97,9 @@ namespace MWWorld public: + /// Make a copy of the given object and insert it into this cell. + /// @note If you get a linker error here, this means the given type can not be inserted into a cell. + /// The supported types are defined at the bottom of this file. template LiveCellRefBase* insert(const LiveCellRef* ref); From 64b4926127a7b7780213fa0feaac7b1c47a69487 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 14 Nov 2015 17:44:16 +0100 Subject: [PATCH 04/23] Add reference moving logic - untested --- apps/openmw/mwworld/cellstore.cpp | 48 ++++++++++++++++++++++++++++++- apps/openmw/mwworld/cellstore.hpp | 21 ++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 5832a6727..e3ee7d249 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -179,8 +179,54 @@ namespace MWWorld return (ref.mRef.mRefnum == pRefnum); } + void CellStore::moveFrom(const Ptr &object, CellStore *from) + { + MovedRefTracker::iterator found = mMovedToAnotherCell.find(object.getBase()); + if (found != mMovedToAnotherCell.end()) + { + // A cell we had previously moved an object to is returning it to us. + assert (found->second == from); + mMovedToAnotherCell.erase(found); + } + else + { + mMovedHere.insert(std::make_pair(object.getBase(), from)); + } + } + + void CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo) + { + MovedRefTracker::iterator found = mMovedHere.find(object.getBase()); + if (found != mMovedHere.end()) + { + // Special case - object didn't originate in this cell + // Move it back to its original cell first + CellStore* originalCell = found->second; + assert (originalCell != this); + originalCell->moveFrom(object, this); + + mMovedHere.erase(found); + + // Now that object is back to its rightful owner, we can move it + originalCell->moveTo(object, cellToMoveTo); + + updateMergedRefs(); + return; + } + + cellToMoveTo->moveFrom(object, this); + mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo)); + + updateMergedRefs(); + } + + void CellStore::updateMergedRefs() + { + + } + CellStore::CellStore (const ESM::Cell *cell) - : mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0) + : mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0) { mWaterLevel = cell->mWater; } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 979316efc..ef1192277 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -95,8 +95,29 @@ namespace MWWorld CellRefList mStatics; CellRefList mWeapons; + typedef std::map MovedRefTracker; + // References owned by a different cell that have been moved here. + // + MovedRefTracker mMovedHere; + // References owned by this cell that have been moved to another cell. + // + MovedRefTracker mMovedToAnotherCell; + + // Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from mMovedToAnotherCell + std::vector mMergedRefs; + + /// Moves object from the given cell to this cell. + void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from); + + /// Repopulate mMergedRefs. + void updateMergedRefs(); + public: + /// Moves object from this cell to the given cell. + /// @note automatically updates given cell by calling cellToMoveTo->moveFrom(...) + void moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo); + /// Make a copy of the given object and insert it into this cell. /// @note If you get a linker error here, this means the given type can not be inserted into a cell. /// The supported types are defined at the bottom of this file. From 3aa53f3cb4cacbe9f88fe71dec800b6177c84ed3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 4 Dec 2015 19:46:02 +0100 Subject: [PATCH 05/23] Object cell movement tracker works. Savegame handling is still missing and some game functionality is still stubbed out. --- apps/openmw/mwworld/cellstore.cpp | 178 ++++++++++++++++++------------ apps/openmw/mwworld/cellstore.hpp | 175 +++++++++++++++-------------- apps/openmw/mwworld/scene.cpp | 16 ++- apps/openmw/mwworld/worldimp.cpp | 11 +- 4 files changed, 214 insertions(+), 166 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index e3ee7d249..d56baf231 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -47,13 +47,16 @@ namespace template MWWorld::Ptr searchViaActorId (MWWorld::CellRefList& actorList, int actorId, - MWWorld::CellStore *cell) + MWWorld::CellStore *cell, const std::map& toIgnore) { for (typename MWWorld::CellRefList::List::iterator iter (actorList.mList.begin()); iter!=actorList.mList.end(); ++iter) { MWWorld::Ptr actor (&*iter, cell); + if (toIgnore.find(&*iter) != toIgnore.end()) + continue; + if (actor.getClass().getCreatureStats (actor).matchesActorId (actorId) && actor.getRefData().getCount() > 0) return actor; } @@ -181,6 +184,7 @@ namespace MWWorld void CellStore::moveFrom(const Ptr &object, CellStore *from) { + mHasState = true; MovedRefTracker::iterator found = mMovedToAnotherCell.find(object.getBase()); if (found != mMovedToAnotherCell.end()) { @@ -192,10 +196,27 @@ namespace MWWorld { mMovedHere.insert(std::make_pair(object.getBase(), from)); } + + if (mState == State_Loaded) + updateMergedRefs(); + else if (mState == State_Preloaded) + { + mIds.push_back(object.getCellRef().getRefId()); + std::sort(mIds.begin(), mIds.end()); + } } - void CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo) + MWWorld::Ptr CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo) { + if (cellToMoveTo == this) + throw std::runtime_error("object is already in this cell"); + + // We assume that *this is in State_Loaded since we could hardly have reference to a live object otherwise. + if (mState != State_Loaded) + throw std::runtime_error("can't move object from a non-loaded cell (how did you get this object anyway?)"); + + // TODO: ensure that the object actually exists in the cell + MovedRefTracker::iterator found = mMovedHere.find(object.getBase()); if (found != mMovedHere.end()) { @@ -208,21 +229,59 @@ namespace MWWorld mMovedHere.erase(found); // Now that object is back to its rightful owner, we can move it - originalCell->moveTo(object, cellToMoveTo); + if (cellToMoveTo != originalCell) + { + originalCell->moveTo(object, cellToMoveTo); + } updateMergedRefs(); - return; + return MWWorld::Ptr(object.getBase(), cellToMoveTo); } cellToMoveTo->moveFrom(object, this); mMovedToAnotherCell.insert(std::make_pair(object.getBase(), cellToMoveTo)); updateMergedRefs(); + return MWWorld::Ptr(object.getBase(), cellToMoveTo); } - void CellStore::updateMergedRefs() + struct MergeFunctor { + MergeFunctor(std::vector& mergeTo, const std::map& movedHere, + const std::map& movedToAnotherCell) + : mMergeTo(mergeTo) + , mMovedHere(movedHere) + , mMovedToAnotherCell(movedToAnotherCell) + { + } + bool operator() (const MWWorld::Ptr& ptr) + { + if (mMovedToAnotherCell.find(ptr.getBase()) != mMovedToAnotherCell.end()) + return true; + mMergeTo.push_back(ptr.getBase()); + return true; + } + + void merge() + { + for (std::map::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) + mMergeTo.push_back(it->first); + } + + private: + std::vector& mMergeTo; + + const std::map& mMovedHere; + const std::map& mMovedToAnotherCell; + }; + + void CellStore::updateMergedRefs() + { + mMergedRefs.clear(); + MergeFunctor functor(mMergedRefs, mMovedHere, mMovedToAnotherCell); + forEachInternal(functor); + functor.merge(); } CellStore::CellStore (const ESM::Cell *cell) @@ -258,85 +317,50 @@ namespace MWWorld return const_cast (this)->search (id).isEmpty(); } + struct SearchFunctor + { + MWWorld::Ptr mFound; + std::string mIdToFind; + bool operator()(const MWWorld::Ptr& ptr) + { + if (ptr.getCellRef().getRefId() == mIdToFind) + { + mFound = ptr; + return false; + } + return true; + } + }; + Ptr CellStore::search (const std::string& id) { bool oldState = mHasState; - mHasState = true; - - if (LiveCellRef *ref = mActivators.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mPotions.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mAppas.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mArmors.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mBooks.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mClothes.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mContainers.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mCreatures.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mDoors.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mIngreds.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mCreatureLists.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mItemLists.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mLights.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mLockpicks.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mMiscItems.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mNpcs.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mProbes.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mRepairs.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mStatics.find (id)) - return Ptr (ref, this); - - if (LiveCellRef *ref = mWeapons.find (id)) - return Ptr (ref, this); + SearchFunctor searchFunctor; + searchFunctor.mIdToFind = id; + forEach(searchFunctor); mHasState = oldState; - - return Ptr(); + return searchFunctor.mFound; } Ptr CellStore::searchViaActorId (int id) { - if (Ptr ptr = ::searchViaActorId (mNpcs, id, this)) + if (Ptr ptr = ::searchViaActorId (mNpcs, id, this, mMovedToAnotherCell)) return ptr; - if (Ptr ptr = ::searchViaActorId (mCreatures, id, this)) + if (Ptr ptr = ::searchViaActorId (mCreatures, id, this, mMovedToAnotherCell)) return ptr; + for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) + { + MWWorld::Ptr actor (it->first, this); + if (!actor.getClass().isActor()) + continue; + if (actor.getClass().getCreatureStats (actor).matchesActorId (id) && actor.getRefData().getCount() > 0) + return actor; + } + return Ptr(); } @@ -435,6 +459,8 @@ namespace MWWorld continue; } + // We don't need to check mMovedToAnotherCell because listRefs isn't used for loaded cells. + mIds.push_back (Misc::StringUtils::lowerCase (ref.mRefID)); } } @@ -447,6 +473,12 @@ namespace MWWorld mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID)); } + // List runtime moved references + for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) + { + mIds.push_back(Misc::StringUtils::lowerCase(it->first->mRef.getRefId())); + } + std::sort (mIds.begin(), mIds.end()); } @@ -489,6 +521,8 @@ namespace MWWorld loadRef (ref, false, store); } + + updateMergedRefs(); } bool CellStore::isExterior() const @@ -610,11 +644,15 @@ namespace MWWorld writeReferenceCollection (writer, mRepairs); writeReferenceCollection (writer, mStatics); writeReferenceCollection (writer, mWeapons); + + // TODO: write moved references } void CellStore::readReferences (ESM::ESMReader& reader, const std::map& contentFileMap) { + // TODO: read moved references + mHasState = true; while (reader.isNextSub ("OBJE")) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index ef1192277..2ef03e2c4 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -112,11 +112,64 @@ namespace MWWorld /// Repopulate mMergedRefs. void updateMergedRefs(); + template + LiveCellRefBase* insertBase(CellRefList& list, const LiveCellRef* ref) + { + mHasState = true; + LiveCellRefBase* ret = &list.insert(*ref); + updateMergedRefs(); + return ret; + } + + // helper function for forEachInternal + template + bool forEachImp (Functor& functor, List& list) + { + for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end(); + ++iter) + { + if (iter->mData.isDeletedByContentFile()) + continue; + if (!functor (MWWorld::Ptr(&*iter, this))) + return false; + } + return true; + } + + // listing only objects owned by this cell. Internal use only, you probably want to use forEach() so that moved objects are accounted for. + template + bool forEachInternal (Functor& functor) + { + return + forEachImp (functor, mActivators) && + forEachImp (functor, mPotions) && + forEachImp (functor, mAppas) && + forEachImp (functor, mArmors) && + forEachImp (functor, mBooks) && + forEachImp (functor, mClothes) && + forEachImp (functor, mContainers) && + forEachImp (functor, mDoors) && + forEachImp (functor, mIngreds) && + forEachImp (functor, mItemLists) && + forEachImp (functor, mLights) && + forEachImp (functor, mLockpicks) && + forEachImp (functor, mMiscItems) && + forEachImp (functor, mProbes) && + forEachImp (functor, mRepairs) && + forEachImp (functor, mStatics) && + forEachImp (functor, mWeapons) && + forEachImp (functor, mCreatures) && + forEachImp (functor, mNpcs) && + forEachImp (functor, mCreatureLists); + } + public: /// Moves object from this cell to the given cell. /// @note automatically updates given cell by calling cellToMoveTo->moveFrom(...) - void moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo); + /// @note throws exception if cellToMoveTo == this + /// @return updated MWWorld::Ptr with the new CellStore pointer set. + MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo); /// Make a copy of the given object and insert it into this cell. /// @note If you get a linker error here, this means the given type can not be inserted into a cell. @@ -136,6 +189,7 @@ namespace MWWorld bool hasId (const std::string& id) const; ///< May return true for deleted IDs when in preload state. Will return false, if cell is /// unloaded. + /// @note Will not account for moved references which may exist in Loaded state. Use search() instead if the cell is loaded. Ptr search (const std::string& id); ///< Will return an empty Ptr if cell is not loaded. Does not check references in @@ -166,45 +220,23 @@ namespace MWWorld /// false will abort the iteration. /// \attention This function also lists deleted (count 0) objects! /// \return Iteration completed? - /// - /// \note Creatures and NPCs are handled last. template bool forEach (Functor& functor) { - mHasState = true; - - return - forEachImp (functor, mActivators) && - forEachImp (functor, mPotions) && - forEachImp (functor, mAppas) && - forEachImp (functor, mArmors) && - forEachImp (functor, mBooks) && - forEachImp (functor, mClothes) && - forEachImp (functor, mContainers) && - forEachImp (functor, mDoors) && - forEachImp (functor, mIngreds) && - forEachImp (functor, mItemLists) && - forEachImp (functor, mLights) && - forEachImp (functor, mLockpicks) && - forEachImp (functor, mMiscItems) && - forEachImp (functor, mProbes) && - forEachImp (functor, mRepairs) && - forEachImp (functor, mStatics) && - forEachImp (functor, mWeapons) && - forEachImp (functor, mCreatures) && - forEachImp (functor, mNpcs) && - forEachImp (functor, mCreatureLists); - } + if (mState != State_Loaded) + return false; - template - bool forEachContainer (Functor& functor) - { mHasState = true; - return - forEachImp (functor, mContainers) && - forEachImp (functor, mCreatures) && - forEachImp (functor, mNpcs); + for (unsigned int i=0; imData.isDeletedByContentFile()) + continue; + + if (!functor(MWWorld::Ptr(mMergedRefs[i], this))) + return false; + } + return true; } /// \todo add const version of forEach @@ -234,20 +266,6 @@ namespace MWWorld private: - template - bool forEachImp (Functor& functor, List& list) - { - for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end(); - ++iter) - { - if (iter->mData.isDeletedByContentFile()) - continue; - if (!functor (MWWorld::Ptr(&*iter, this))) - return false; - } - return true; - } - /// Run through references and store IDs void listRefs(const MWWorld::ESMStore &store, std::vector &esm); @@ -261,126 +279,105 @@ namespace MWWorld MWMechanics::PathgridGraph mPathgridGraph; }; - template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mActivators.insert(*ref); + return insertBase(mActivators, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mPotions.insert(*ref); + return insertBase(mPotions, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mAppas.insert(*ref); + return insertBase(mAppas, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mArmors.insert(*ref); + return insertBase(mArmors, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mBooks.insert(*ref); + return insertBase(mBooks, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mClothes.insert(*ref); + return insertBase(mClothes, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mContainers.insert(*ref); + return insertBase(mContainers, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mCreatures.insert(*ref); + return insertBase(mCreatures, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mDoors.insert(*ref); + return insertBase(mDoors, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mIngreds.insert(*ref); + return insertBase(mIngreds, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mCreatureLists.insert(*ref); + return insertBase(mCreatureLists, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mItemLists.insert(*ref); + return insertBase(mItemLists, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mLights.insert(*ref); + return insertBase(mLights, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mLockpicks.insert(*ref); + return insertBase(mLockpicks, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mMiscItems.insert(*ref); + return insertBase(mMiscItems, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mNpcs.insert(*ref); + return insertBase(mNpcs, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mProbes.insert(*ref); + return insertBase(mProbes, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mRepairs.insert(*ref); + return insertBase(mRepairs, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mStatics.insert(*ref); + return insertBase(mStatics, ref); } template<> inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) { - mHasState = true; - return &mWeapons.insert(*ref); + return insertBase(mWeapons, ref); } bool operator== (const CellStore& left, const CellStore& right); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 45c94b6d9..896d5f8eb 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -116,7 +116,6 @@ namespace { addObject(ptr, mPhysics, mRendering); updateObjectRotation(ptr, mPhysics, mRendering, false); - ptr.getClass().adjustPosition (ptr, false); } catch (const std::exception& e) { @@ -129,6 +128,17 @@ namespace return true; } + + struct AdjustPositionFunctor + { + bool operator() (const MWWorld::Ptr& ptr) + { + if (!ptr.getRefData().isDeleted() && ptr.getRefData().isEnabled()) + ptr.getClass().adjustPosition (ptr, false); + return true; + } + }; + } @@ -553,6 +563,10 @@ namespace MWWorld { InsertFunctor functor (cell, rescale, *loadingListener, *mPhysics, mRendering); cell.forEach (functor); + + // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order + AdjustPositionFunctor adjustPosFunctor; + cell.forEach (adjustPosFunctor); } void Scene::addObjectToScene (const Ptr& ptr) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 950c38e76..bb2ca2aae 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -722,7 +722,7 @@ namespace MWWorld for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { FindContainerFunctor functor(ptr); - (*cellIt)->forEachContainer(functor); + //(*cellIt)->forEachContainer(functor); if (!functor.mResult.isEmpty()) return functor.mResult; @@ -1146,7 +1146,7 @@ namespace MWWorld bool newCellActive = mWorldScene->isCellActive(*newCell); if (!currCellActive && newCellActive) { - newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos); + newPtr = currCell->moveTo(ptr, newCell); mWorldScene->addObjectToScene(newPtr); std::string script = newPtr.getClass().getScript(newPtr); @@ -1162,14 +1162,14 @@ namespace MWWorld removeContainerScripts (ptr); haveToMove = false; - newPtr = ptr.getClass().copyToCell(ptr, *newCell); + newPtr = currCell->moveTo(ptr, newCell); newPtr.getRefData().setBaseNode(0); } else if (!currCellActive && !newCellActive) - newPtr = ptr.getClass().copyToCell(ptr, *newCell); + newPtr = currCell->moveTo(ptr, newCell); else // both cells active { - newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos); + newPtr = currCell->moveTo(ptr, newCell); mRendering->updatePtr(ptr, newPtr); ptr.getRefData().setBaseNode(NULL); @@ -1189,7 +1189,6 @@ namespace MWWorld addContainerScripts (newPtr, newCell); } } - ptr.getRefData().setCount(0); } } if (haveToMove && newPtr.getRefData().getBaseNode()) From 3dcefd17fc94bc970a8d8b6b3eb90245f78d781f Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 4 Dec 2015 20:03:14 +0100 Subject: [PATCH 06/23] Fix CellStore::count() --- apps/openmw/mwworld/cellstore.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index d56baf231..1a1802a05 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -379,27 +379,7 @@ namespace MWWorld int CellStore::count() const { - return - mActivators.mList.size() - + mPotions.mList.size() - + mAppas.mList.size() - + mArmors.mList.size() - + mBooks.mList.size() - + mClothes.mList.size() - + mContainers.mList.size() - + mDoors.mList.size() - + mIngreds.mList.size() - + mCreatureLists.mList.size() - + mItemLists.mList.size() - + mLights.mList.size() - + mLockpicks.mList.size() - + mMiscItems.mList.size() - + mProbes.mList.size() - + mRepairs.mList.size() - + mStatics.mList.size() - + mWeapons.mList.size() - + mCreatures.mList.size() - + mNpcs.mList.size(); + return mMergedRefs.size(); } void CellStore::load (const MWWorld::ESMStore &store, std::vector &esm) From 811df1e97ba2011b517c8fb16a60b7f920d174a2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 18:03:55 +0100 Subject: [PATCH 07/23] Pass the ESM reader list to CellStore constructor --- apps/openmw/mwworld/cells.cpp | 20 ++++++++++---------- apps/openmw/mwworld/cellstore.cpp | 28 +++++++++++++++++----------- apps/openmw/mwworld/cellstore.hpp | 18 ++++++++++++------ 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index b096301fd..127e43fc0 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -23,7 +23,7 @@ MWWorld::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) if (result==mInteriors.end()) { - result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell))).first; + result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell, mStore, mReader))).first; } return &result->second; @@ -36,7 +36,7 @@ MWWorld::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) if (result==mExteriors.end()) { result = mExteriors.insert (std::make_pair ( - std::make_pair (cell->getGridX(), cell->getGridY()), CellStore (cell))).first; + std::make_pair (cell->getGridX(), cell->getGridY()), CellStore (cell, mStore, mReader))).first; } @@ -70,7 +70,7 @@ MWWorld::Ptr MWWorld::Cells::getPtrAndCache (const std::string& name, CellStore& void MWWorld::Cells::writeCell (ESM::ESMWriter& writer, CellStore& cell) const { if (cell.getState()!=CellStore::State_Loaded) - cell.load (mStore, mReader); + cell.load (); ESM::CellState cellState; @@ -114,13 +114,13 @@ MWWorld::CellStore *MWWorld::Cells::getExterior (int x, int y) } result = mExteriors.insert (std::make_pair ( - std::make_pair (x, y), CellStore (cell))).first; + std::make_pair (x, y), CellStore (cell, mStore, mReader))).first; } if (result->second.getState()!=CellStore::State_Loaded) { // Multiple plugin support for landscape data is much easier than for references. The last plugin wins. - result->second.load (mStore, mReader); + result->second.load (); } return &result->second; @@ -135,12 +135,12 @@ MWWorld::CellStore *MWWorld::Cells::getInterior (const std::string& name) { const ESM::Cell *cell = mStore.get().find(lowerName); - result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell))).first; + result = mInteriors.insert (std::make_pair (lowerName, CellStore (cell, mStore, mReader))).first; } if (result->second.getState()!=CellStore::State_Loaded) { - result->second.load (mStore, mReader); + result->second.load (); } return &result->second; @@ -158,13 +158,13 @@ MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, CellStore& cell, bool searchInContainers) { if (cell.getState()==CellStore::State_Unloaded) - cell.preload (mStore, mReader); + cell.preload (); if (cell.getState()==CellStore::State_Preloaded) { if (cell.hasId (name)) { - cell.load (mStore, mReader); + cell.load (); } else return Ptr(); @@ -333,7 +333,7 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type, cellStore->readFog(reader); if (cellStore->getState()!=CellStore::State_Loaded) - cellStore->load (mStore, mReader); + cellStore->load (); cellStore->readReferences (reader, contentFileMap); diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 1a1802a05..c435b0478 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -284,8 +284,8 @@ namespace MWWorld functor.merge(); } - CellStore::CellStore (const ESM::Cell *cell) - : mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0) + CellStore::CellStore (const ESM::Cell *cell, const MWWorld::ESMStore& esmStore, std::vector& readerList) + : mStore(esmStore), mReader(readerList), mCell (cell), mState (State_Unloaded), mHasState (false), mLastRespawn(0,0) { mWaterLevel = cell->mWater; } @@ -382,14 +382,14 @@ namespace MWWorld return mMergedRefs.size(); } - void CellStore::load (const MWWorld::ESMStore &store, std::vector &esm) + void CellStore::load () { if (mState!=State_Loaded) { if (mState==State_Preloaded) mIds.clear(); - loadRefs (store, esm); + loadRefs (); mState = State_Loaded; @@ -399,18 +399,20 @@ namespace MWWorld } } - void CellStore::preload (const MWWorld::ESMStore &store, std::vector &esm) + void CellStore::preload () { if (mState==State_Unloaded) { - listRefs (store, esm); + listRefs (); mState = State_Preloaded; } } - void CellStore::listRefs(const MWWorld::ESMStore &store, std::vector &esm) + void CellStore::listRefs() { + std::vector& esm = mReader; + assert (mCell); if (mCell->mContextList.empty()) @@ -462,8 +464,10 @@ namespace MWWorld std::sort (mIds.begin(), mIds.end()); } - void CellStore::loadRefs(const MWWorld::ESMStore &store, std::vector &esm) + void CellStore::loadRefs() { + std::vector& esm = mReader; + assert (mCell); if (mCell->mContextList.empty()) @@ -490,7 +494,7 @@ namespace MWWorld continue; } - loadRef (ref, deleted, store); + loadRef (ref, deleted); } } @@ -499,7 +503,7 @@ namespace MWWorld { ESM::CellRef &ref = const_cast(*it); - loadRef (ref, false, store); + loadRef (ref, false); } updateMergedRefs(); @@ -530,10 +534,12 @@ namespace MWWorld return Ptr(); } - void CellStore::loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store) + void CellStore::loadRef (ESM::CellRef& ref, bool deleted) { Misc::StringUtils::toLower (ref.mRefID); + const MWWorld::ESMStore& store = mStore; + switch (store.find (ref.mRefID)) { case ESM::REC_ACTI: mActivators.load(ref, deleted, store); break; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 2ef03e2c4..80fcaf48a 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -60,6 +60,9 @@ namespace MWWorld private: + const MWWorld::ESMStore& mStore; + std::vector& mReader; + // Even though fog actually belongs to the player and not cells, // it makes sense to store it here since we need it once for each cell. // Note this is NULL until the cell is explored to save some memory @@ -177,7 +180,10 @@ namespace MWWorld template LiveCellRefBase* insert(const LiveCellRef* ref); - CellStore (const ESM::Cell *cell_); + /// @param readerList The readers to use for loading of the cell on-demand. + CellStore (const ESM::Cell *cell_, + const MWWorld::ESMStore& store, + std::vector& readerList); const ESM::Cell *getCell() const; @@ -210,10 +216,10 @@ namespace MWWorld int count() const; ///< Return total number of references, including deleted ones. - void load (const MWWorld::ESMStore &store, std::vector &esm); + void load (); ///< Load references from content file. - void preload (const MWWorld::ESMStore &store, std::vector &esm); + void preload (); ///< Build ID list from content file. /// Call functor (ref) for each reference. functor must return a bool. Returning @@ -267,11 +273,11 @@ namespace MWWorld private: /// Run through references and store IDs - void listRefs(const MWWorld::ESMStore &store, std::vector &esm); + void listRefs(); - void loadRefs(const MWWorld::ESMStore &store, std::vector &esm); + void loadRefs(); - void loadRef (ESM::CellRef& ref, bool deleted, const ESMStore& store); + void loadRef (ESM::CellRef& ref, bool deleted); ///< Make case-adjustments to \a ref and insert it into the respective container. /// /// Invalid \a ref objects are silently dropped. From 2301080c63dee1947ffe04bbb447077087da8dde Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 18:04:48 +0100 Subject: [PATCH 08/23] Load CellStore when an object is moved there --- apps/openmw/mwworld/cellstore.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index c435b0478..10315b126 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -184,6 +184,9 @@ namespace MWWorld void CellStore::moveFrom(const Ptr &object, CellStore *from) { + if (mState != State_Loaded) + load(); + mHasState = true; MovedRefTracker::iterator found = mMovedToAnotherCell.find(object.getBase()); if (found != mMovedToAnotherCell.end()) @@ -196,14 +199,7 @@ namespace MWWorld { mMovedHere.insert(std::make_pair(object.getBase(), from)); } - - if (mState == State_Loaded) - updateMergedRefs(); - else if (mState == State_Preloaded) - { - mIds.push_back(object.getCellRef().getRefId()); - std::sort(mIds.begin(), mIds.end()); - } + updateMergedRefs(); } MWWorld::Ptr CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo) From 5e99a3eda6400aa4be945acef3473152375e600c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 18:13:04 +0100 Subject: [PATCH 09/23] Rename CellStore Functor to Visitor --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwworld/cellstore.cpp | 20 +++---- apps/openmw/mwworld/cellstore.hpp | 58 +++++++++---------- .../{cellfunctors.hpp => cellvisitors.hpp} | 6 +- apps/openmw/mwworld/scene.cpp | 28 ++++----- apps/openmw/mwworld/worldimp.cpp | 35 ++++++----- 6 files changed, 74 insertions(+), 75 deletions(-) rename apps/openmw/mwworld/{cellfunctors.hpp => cellvisitors.hpp} (78%) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 03ce71f5c..0113fed02 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -62,7 +62,7 @@ add_openmw_dir (mwsound add_openmw_dir (mwworld refdata worldimp scene globals class action nullaction actionteleport - containerstore actiontalk actiontake manualref player cellfunctors failedaction + containerstore actiontalk actiontake manualref player cellvisitors failedaction cells localscripts customdata inventorystore ptr actionopen actionread actionequip timestamp actionalchemy cellstore actionapply actioneat store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 10315b126..507e3fd7f 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -241,9 +241,9 @@ namespace MWWorld return MWWorld::Ptr(object.getBase(), cellToMoveTo); } - struct MergeFunctor + struct MergeVisitor { - MergeFunctor(std::vector& mergeTo, const std::map& movedHere, + MergeVisitor(std::vector& mergeTo, const std::map& movedHere, const std::map& movedToAnotherCell) : mMergeTo(mergeTo) , mMovedHere(movedHere) @@ -275,9 +275,9 @@ namespace MWWorld void CellStore::updateMergedRefs() { mMergedRefs.clear(); - MergeFunctor functor(mMergedRefs, mMovedHere, mMovedToAnotherCell); - forEachInternal(functor); - functor.merge(); + MergeVisitor visitor(mMergedRefs, mMovedHere, mMovedToAnotherCell); + forEachInternal(visitor); + visitor.merge(); } CellStore::CellStore (const ESM::Cell *cell, const MWWorld::ESMStore& esmStore, std::vector& readerList) @@ -313,7 +313,7 @@ namespace MWWorld return const_cast (this)->search (id).isEmpty(); } - struct SearchFunctor + struct SearchVisitor { MWWorld::Ptr mFound; std::string mIdToFind; @@ -332,12 +332,12 @@ namespace MWWorld { bool oldState = mHasState; - SearchFunctor searchFunctor; - searchFunctor.mIdToFind = id; - forEach(searchFunctor); + SearchVisitor searchVisitor; + searchVisitor.mIdToFind = id; + forEach(searchVisitor); mHasState = oldState; - return searchFunctor.mFound; + return searchVisitor.mFound; } Ptr CellStore::searchViaActorId (int id) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 80fcaf48a..cedf2eeb0 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -125,45 +125,45 @@ namespace MWWorld } // helper function for forEachInternal - template - bool forEachImp (Functor& functor, List& list) + template + bool forEachImp (Visitor& visitor, List& list) { for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end(); ++iter) { if (iter->mData.isDeletedByContentFile()) continue; - if (!functor (MWWorld::Ptr(&*iter, this))) + if (!visitor (MWWorld::Ptr(&*iter, this))) return false; } return true; } // listing only objects owned by this cell. Internal use only, you probably want to use forEach() so that moved objects are accounted for. - template - bool forEachInternal (Functor& functor) + template + bool forEachInternal (Visitor& visitor) { return - forEachImp (functor, mActivators) && - forEachImp (functor, mPotions) && - forEachImp (functor, mAppas) && - forEachImp (functor, mArmors) && - forEachImp (functor, mBooks) && - forEachImp (functor, mClothes) && - forEachImp (functor, mContainers) && - forEachImp (functor, mDoors) && - forEachImp (functor, mIngreds) && - forEachImp (functor, mItemLists) && - forEachImp (functor, mLights) && - forEachImp (functor, mLockpicks) && - forEachImp (functor, mMiscItems) && - forEachImp (functor, mProbes) && - forEachImp (functor, mRepairs) && - forEachImp (functor, mStatics) && - forEachImp (functor, mWeapons) && - forEachImp (functor, mCreatures) && - forEachImp (functor, mNpcs) && - forEachImp (functor, mCreatureLists); + forEachImp (visitor, mActivators) && + forEachImp (visitor, mPotions) && + forEachImp (visitor, mAppas) && + forEachImp (visitor, mArmors) && + forEachImp (visitor, mBooks) && + forEachImp (visitor, mClothes) && + forEachImp (visitor, mContainers) && + forEachImp (visitor, mDoors) && + forEachImp (visitor, mIngreds) && + forEachImp (visitor, mItemLists) && + forEachImp (visitor, mLights) && + forEachImp (visitor, mLockpicks) && + forEachImp (visitor, mMiscItems) && + forEachImp (visitor, mProbes) && + forEachImp (visitor, mRepairs) && + forEachImp (visitor, mStatics) && + forEachImp (visitor, mWeapons) && + forEachImp (visitor, mCreatures) && + forEachImp (visitor, mNpcs) && + forEachImp (visitor, mCreatureLists); } public: @@ -222,12 +222,12 @@ namespace MWWorld void preload (); ///< Build ID list from content file. - /// Call functor (ref) for each reference. functor must return a bool. Returning + /// Call visitor (ref) for each reference. visitor must return a bool. Returning /// false will abort the iteration. /// \attention This function also lists deleted (count 0) objects! /// \return Iteration completed? - template - bool forEach (Functor& functor) + template + bool forEach (Visitor& visitor) { if (mState != State_Loaded) return false; @@ -239,7 +239,7 @@ namespace MWWorld if (mMergedRefs[i]->mData.isDeletedByContentFile()) continue; - if (!functor(MWWorld::Ptr(mMergedRefs[i], this))) + if (!visitor(MWWorld::Ptr(mMergedRefs[i], this))) return false; } return true; diff --git a/apps/openmw/mwworld/cellfunctors.hpp b/apps/openmw/mwworld/cellvisitors.hpp similarity index 78% rename from apps/openmw/mwworld/cellfunctors.hpp rename to apps/openmw/mwworld/cellvisitors.hpp index c7fdc793c..cfb07f749 100644 --- a/apps/openmw/mwworld/cellfunctors.hpp +++ b/apps/openmw/mwworld/cellvisitors.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWWORLD_CELLFUNCTORS_H -#define GAME_MWWORLD_CELLFUNCTORS_H +#ifndef GAME_MWWORLD_CELLVISITORS_H +#define GAME_MWWORLD_CELLVISITORS_H #include #include @@ -9,7 +9,7 @@ namespace MWWorld { - struct ListAndResetObjects + struct ListAndResetObjectsVisitor { std::vector mObjects; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 896d5f8eb..00cb8a810 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -22,7 +22,7 @@ #include "localscripts.hpp" #include "esmstore.hpp" #include "class.hpp" -#include "cellfunctors.hpp" +#include "cellvisitors.hpp" #include "cellstore.hpp" namespace @@ -78,7 +78,7 @@ namespace } } - struct InsertFunctor + struct InsertVisitor { MWWorld::CellStore& mCell; bool mRescale; @@ -86,13 +86,13 @@ namespace MWPhysics::PhysicsSystem& mPhysics; MWRender::RenderingManager& mRendering; - InsertFunctor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener, + InsertVisitor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener, MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering); bool operator() (const MWWorld::Ptr& ptr); }; - InsertFunctor::InsertFunctor (MWWorld::CellStore& cell, bool rescale, + InsertVisitor::InsertVisitor (MWWorld::CellStore& cell, bool rescale, Loading::Listener& loadingListener, MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering) : mCell (cell), mRescale (rescale), mLoadingListener (loadingListener), @@ -100,7 +100,7 @@ namespace mRendering (rendering) {} - bool InsertFunctor::operator() (const MWWorld::Ptr& ptr) + bool InsertVisitor::operator() (const MWWorld::Ptr& ptr) { if (mRescale) { @@ -129,7 +129,7 @@ namespace return true; } - struct AdjustPositionFunctor + struct AdjustPositionVisitor { bool operator() (const MWWorld::Ptr& ptr) { @@ -206,11 +206,11 @@ namespace MWWorld void Scene::unloadCell (CellStoreCollection::iterator iter) { std::cout << "Unloading cell\n"; - ListAndResetObjects functor; + ListAndResetObjectsVisitor visitor; - (*iter)->forEach(functor); - for (std::vector::const_iterator iter2 (functor.mObjects.begin()); - iter2!=functor.mObjects.end(); ++iter2) + (*iter)->forEach(visitor); + for (std::vector::const_iterator iter2 (visitor.mObjects.begin()); + iter2!=visitor.mObjects.end(); ++iter2) { mPhysics->remove(*iter2); } @@ -561,12 +561,12 @@ namespace MWWorld void Scene::insertCell (CellStore &cell, bool rescale, Loading::Listener* loadingListener) { - InsertFunctor functor (cell, rescale, *loadingListener, *mPhysics, mRendering); - cell.forEach (functor); + InsertVisitor insertVisitor (cell, rescale, *loadingListener, *mPhysics, mRendering); + cell.forEach (insertVisitor); // do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order - AdjustPositionFunctor adjustPosFunctor; - cell.forEach (adjustPosFunctor); + AdjustPositionVisitor adjustPosVisitor; + cell.forEach (adjustPosVisitor); } void Scene::addObjectToScene (const Ptr& ptr) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bb2ca2aae..3efce5c9e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -54,7 +54,6 @@ #include "player.hpp" #include "manualref.hpp" #include "cellstore.hpp" -#include "cellfunctors.hpp" #include "containerstore.hpp" #include "inventorystore.hpp" #include "actionteleport.hpp" @@ -690,12 +689,12 @@ namespace MWWorld return mWorldScene->searchPtrViaActorId (actorId); } - struct FindContainerFunctor + struct FindContainerVisitor { Ptr mContainedPtr; Ptr mResult; - FindContainerFunctor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {} + FindContainerVisitor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {} bool operator() (Ptr ptr) { @@ -721,11 +720,11 @@ namespace MWWorld const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { - FindContainerFunctor functor(ptr); - //(*cellIt)->forEachContainer(functor); + FindContainerVisitor visitor(ptr); + //(*cellIt)->forEachContainer(visitor); - if (!functor.mResult.isEmpty()) - return functor.mResult; + if (!visitor.mResult.isEmpty()) + return visitor.mResult; } return Ptr(); @@ -2262,7 +2261,7 @@ namespace MWWorld */ } - struct ListObjectsFunctor + struct ListObjectsVisitor { std::vector mObjects; @@ -2279,10 +2278,10 @@ namespace MWWorld const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { - ListObjectsFunctor functor; - (*cellIt)->forEach(functor); + ListObjectsVisitor visitor; + (*cellIt)->forEach(visitor); - for (std::vector::iterator it = functor.mObjects.begin(); it != functor.mObjects.end(); ++it) + for (std::vector::iterator it = visitor.mObjects.begin(); it != visitor.mObjects.end(); ++it) if (Misc::StringUtils::ciEqual(it->getCellRef().getOwner(), npc.getCellRef().getRefId())) out.push_back(*it); } @@ -2886,9 +2885,9 @@ namespace MWWorld mWeatherManager->update(duration, paused); } - struct AddDetectedReference + struct AddDetectedReferenceVisitor { - AddDetectedReference(std::vector& out, Ptr detector, World::DetectionType type, float squaredDist) + AddDetectedReferenceVisitor(std::vector& out, Ptr detector, World::DetectionType type, float squaredDist) : mOut(out), mDetector(detector), mSquaredDist(squaredDist), mType(type) { } @@ -2968,13 +2967,13 @@ namespace MWWorld dist = feetToGameUnits(dist); - AddDetectedReference functor (out, ptr, type, dist*dist); + AddDetectedReferenceVisitor visitor (out, ptr, type, dist*dist); const Scene::CellStoreCollection& active = mWorldScene->getActiveCells(); for (Scene::CellStoreCollection::const_iterator it = active.begin(); it != active.end(); ++it) { MWWorld::CellStore* cellStore = *it; - cellStore->forEach(functor); + cellStore->forEach(visitor); } } @@ -3230,7 +3229,7 @@ namespace MWWorld interpreterContext.executeActivation(object, actor); } - struct ResetActorsFunctor + struct ResetActorsVisitor { bool operator() (Ptr ptr) { @@ -3252,8 +3251,8 @@ namespace MWWorld iter!=mWorldScene->getActiveCells().end(); ++iter) { CellStore* cellstore = *iter; - ResetActorsFunctor functor; - cellstore->forEach(functor); + ResetActorsVisitor visitor; + cellstore->forEach(visitor); } } From 138957c49aaa892e199c58371c7b3961b252945c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 18:43:52 +0100 Subject: [PATCH 10/23] Special case objects with no refnum --- apps/openmw/mwworld/cellstore.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 507e3fd7f..edeb4f08d 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -213,6 +213,15 @@ namespace MWWorld // TODO: ensure that the object actually exists in the cell + // Objects with no refnum can't be handled correctly in the merging process that happens + // on a save/load, so do a simple copy & delete for these objects. + if (!object.getCellRef().getRefNum().hasContentFile()) + { + MWWorld::Ptr copied = object.getClass().copyToCell(object, *cellToMoveTo); + object.getRefData().setCount(0); + return copied; + } + MovedRefTracker::iterator found = mMovedHere.find(object.getBase()); if (found != mMovedHere.end()) { From 2219231230b31c2024300d11cbd48293794c678d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 18:46:49 +0100 Subject: [PATCH 11/23] Missing updateMergedRefs() --- apps/openmw/mwworld/cellstore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index edeb4f08d..47677064e 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -770,6 +770,7 @@ namespace MWWorld throw std::runtime_error ("unknown type in cell reference section"); } } + updateMergedRefs(); } bool operator== (const CellStore& left, const CellStore& right) From 671561ea37dc8e3c172030ca150cbe1527a448a7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 19:11:25 +0100 Subject: [PATCH 12/23] Write moved references to the save game file (not resolved on loading yet) --- apps/openmw/mwworld/cells.cpp | 1 - apps/openmw/mwworld/cellstore.cpp | 22 +++++++++++++++++++++- apps/openmw/mwworld/cellstore.hpp | 2 ++ components/esm/cellref.cpp | 6 +++--- components/esm/cellref.hpp | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 127e43fc0..b410e6488 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -119,7 +119,6 @@ MWWorld::CellStore *MWWorld::Cells::getExterior (int x, int y) if (result->second.getState()!=CellStore::State_Loaded) { - // Multiple plugin support for landscape data is much easier than for references. The last plugin wins. result->second.load (); } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 47677064e..578e5ed55 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -636,7 +636,15 @@ namespace MWWorld writeReferenceCollection (writer, mStatics); writeReferenceCollection (writer, mWeapons); - // TODO: write moved references + for (MovedRefTracker::const_iterator it = mMovedToAnotherCell.begin(); it != mMovedToAnotherCell.end(); ++it) + { + LiveCellRefBase* base = it->first; + ESM::RefNum refNum = base->mRef.getRefNum(); + ESM::CellId movedTo = it->second->getCell()->getCellId(); + + refNum.save(writer, true, "MVRF"); + movedTo.save(writer); + } } void CellStore::readReferences (ESM::ESMReader& reader, @@ -770,6 +778,18 @@ namespace MWWorld throw std::runtime_error ("unknown type in cell reference section"); } } + + while (reader.isNextSub("MVRF")) + { + reader.cacheSubName(); + ESM::RefNum refnum; + ESM::CellId movedTo; + refnum.load(reader, true, "MVRF"); + movedTo.load(reader); + + std::cout << "moved to " << movedTo.mWorldspace << " " << movedTo.mIndex.mX << " " << movedTo.mIndex.mY << std::endl; + } + updateMergedRefs(); } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index cedf2eeb0..892a5c06b 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -12,6 +12,8 @@ #include "livecellref.hpp" #include "cellreflist.hpp" +#include + #include #include #include diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 76a82fe23..7acaed86d 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -3,12 +3,12 @@ #include "esmreader.hpp" #include "esmwriter.hpp" -void ESM::RefNum::load (ESMReader& esm, bool wide) +void ESM::RefNum::load (ESMReader& esm, bool wide, const std::string& tag) { if (wide) - esm.getHNT (*this, "FRMR", 8); + esm.getHNT (*this, tag.c_str(), 8); else - esm.getHNT (mIndex, "FRMR"); + esm.getHNT (mIndex, tag.c_str()); } void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index c371a4f01..3c646cc61 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -16,7 +16,7 @@ namespace ESM unsigned int mIndex; int mContentFile; - void load (ESMReader& esm, bool wide = false); + void load (ESMReader& esm, bool wide = false, const std::string& tag = "FRMR"); void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const; From 176a3c16f4d595c28b3b5f0fab8192bfa0bcdf33 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 19:53:06 +0100 Subject: [PATCH 13/23] Resolve moved references loaded from a save game --- apps/openmw/mwworld/cells.cpp | 31 +++++++++++++++-- apps/openmw/mwworld/cellstore.cpp | 57 ++++++++++++++++++++++++++++--- apps/openmw/mwworld/cellstore.hpp | 13 +++++-- 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index b410e6488..109447959 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -1,5 +1,7 @@ #include "cells.hpp" +#include + #include #include #include @@ -303,6 +305,29 @@ void MWWorld::Cells::write (ESM::ESMWriter& writer, Loading::Listener& progress) } } +struct GetCellStoreCallback : public MWWorld::CellStore::GetCellStoreCallback +{ +public: + GetCellStoreCallback(MWWorld::Cells& cells) + : mCells(cells) + { + } + + MWWorld::Cells& mCells; + + virtual MWWorld::CellStore* getCellStore(const ESM::CellId& cellId) + { + try + { + return mCells.getCell(cellId); + } + catch (...) + { + return NULL; + } + } +}; + bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type, const std::map& contentFileMap) { @@ -320,9 +345,9 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type, catch (...) { // silently drop cells that don't exist anymore + std::cerr << "Dropping state for cell " << state.mId.mWorldspace << " (cell no longer exists)" << std::endl; reader.skipRecord(); return true; - /// \todo log } state.load (reader); @@ -334,7 +359,9 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type, if (cellStore->getState()!=CellStore::State_Loaded) cellStore->load (); - cellStore->readReferences (reader, contentFileMap); + GetCellStoreCallback callback(*this); + + cellStore->readReferences (reader, contentFileMap, &callback); return true; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 578e5ed55..cf9c4d830 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -613,6 +613,28 @@ namespace MWWorld mFogState->load(reader); } + struct SearchByRefNumVisitor + { + LiveCellRefBase* mFound; + ESM::RefNum mRefNumToFind; + + SearchByRefNumVisitor(const ESM::RefNum& toFind) + : mFound(NULL) + , mRefNumToFind(toFind) + { + } + + bool operator()(const MWWorld::Ptr& ptr) + { + if (ptr.getCellRef().getRefNum() == mRefNumToFind) + { + mFound = ptr.getBase(); + return false; + } + return true; + } + }; + void CellStore::writeReferences (ESM::ESMWriter& writer) const { writeReferenceCollection (writer, mActivators); @@ -647,11 +669,8 @@ namespace MWWorld } } - void CellStore::readReferences (ESM::ESMReader& reader, - const std::map& contentFileMap) + void CellStore::readReferences (ESM::ESMReader& reader, const std::map& contentFileMap, GetCellStoreCallback* callback) { - // TODO: read moved references - mHasState = true; while (reader.isNextSub ("OBJE")) @@ -787,7 +806,35 @@ namespace MWWorld refnum.load(reader, true, "MVRF"); movedTo.load(reader); - std::cout << "moved to " << movedTo.mWorldspace << " " << movedTo.mIndex.mX << " " << movedTo.mIndex.mY << std::endl; + // Search for the reference. It might no longer exist if its content file was removed. + SearchByRefNumVisitor visitor(refnum); + forEachInternal(visitor); + + if (!visitor.mFound) + { + std::cout << "Dropping moved ref tag for " << visitor.mFound->mRef.getRefId() << " (moved object no longer exists)" << std::endl; + continue; + } + + CellStore* otherCell = callback->getCellStore(movedTo); + + if (otherCell == NULL) + { + std::cerr << "Dropping moved ref tag for " << visitor.mFound->mRef.getRefId() + << " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location." << std::endl; + // Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates. + // Restore original coordinates: + visitor.mFound->mData.setPosition(visitor.mFound->mRef.getPosition()); + continue; + } + + if (otherCell == this) + { + std::cerr << "Found invalid moved ref, ignoring" << std::endl; + continue; + } + + moveTo(MWWorld::Ptr(visitor.mFound, this), otherCell); } updateMergedRefs(); diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 892a5c06b..542d4700e 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -12,8 +12,6 @@ #include "livecellref.hpp" #include "cellreflist.hpp" -#include - #include #include #include @@ -42,6 +40,7 @@ namespace ESM { struct CellState; struct FogState; + struct CellId; } namespace MWWorld @@ -263,7 +262,15 @@ namespace MWWorld void writeReferences (ESM::ESMWriter& writer) const; - void readReferences (ESM::ESMReader& reader, const std::map& contentFileMap); + struct GetCellStoreCallback + { + public: + ///@note must return NULL if the cell is not found + virtual CellStore* getCellStore(const ESM::CellId& cellId) = 0; + }; + + /// @param callback to use for retrieving of additional CellStore objects by ID (required for resolving moved references) + void readReferences (ESM::ESMReader& reader, const std::map& contentFileMap, GetCellStoreCallback* callback); void respawn (); ///< Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded. From 0af33b5abd71878d7c7e1b78e247375634fcf9ba Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 20:05:13 +0100 Subject: [PATCH 14/23] Throw exception if moveTo() is passed an object not part of *this --- apps/openmw/mwworld/cellstore.cpp | 56 +++++++++++++++++-------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index cf9c4d830..4f28fcfdf 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -144,6 +144,28 @@ namespace ref.load (state); collection.mList.push_back (ref); } + + struct SearchByRefNumVisitor + { + MWWorld::LiveCellRefBase* mFound; + ESM::RefNum mRefNumToFind; + + SearchByRefNumVisitor(const ESM::RefNum& toFind) + : mFound(NULL) + , mRefNumToFind(toFind) + { + } + + bool operator()(const MWWorld::Ptr& ptr) + { + if (ptr.getCellRef().getRefNum() == mRefNumToFind) + { + mFound = ptr.getBase(); + return false; + } + return true; + } + }; } namespace MWWorld @@ -205,13 +227,18 @@ namespace MWWorld MWWorld::Ptr CellStore::moveTo(const Ptr &object, CellStore *cellToMoveTo) { if (cellToMoveTo == this) - throw std::runtime_error("object is already in this cell"); + throw std::runtime_error("moveTo: object is already in this cell"); // We assume that *this is in State_Loaded since we could hardly have reference to a live object otherwise. if (mState != State_Loaded) - throw std::runtime_error("can't move object from a non-loaded cell (how did you get this object anyway?)"); + throw std::runtime_error("moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)"); + + // Ensure that the object actually exists in the cell + SearchByRefNumVisitor searchVisitor(object.getCellRef().getRefNum()); + forEach(searchVisitor); + if (!searchVisitor.mFound) + throw std::runtime_error("moveTo: object is not in this cell"); - // TODO: ensure that the object actually exists in the cell // Objects with no refnum can't be handled correctly in the merging process that happens // on a save/load, so do a simple copy & delete for these objects. @@ -613,28 +640,6 @@ namespace MWWorld mFogState->load(reader); } - struct SearchByRefNumVisitor - { - LiveCellRefBase* mFound; - ESM::RefNum mRefNumToFind; - - SearchByRefNumVisitor(const ESM::RefNum& toFind) - : mFound(NULL) - , mRefNumToFind(toFind) - { - } - - bool operator()(const MWWorld::Ptr& ptr) - { - if (ptr.getCellRef().getRefNum() == mRefNumToFind) - { - mFound = ptr.getBase(); - return false; - } - return true; - } - }; - void CellStore::writeReferences (ESM::ESMWriter& writer) const { writeReferenceCollection (writer, mActivators); @@ -830,6 +835,7 @@ namespace MWWorld if (otherCell == this) { + // Should never happen unless someone's tampering with files. std::cerr << "Found invalid moved ref, ignoring" << std::endl; continue; } From a517f4f9bad647489c654429285aef2770d08b9e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 20:19:07 +0100 Subject: [PATCH 15/23] Add CellStore::forEachType to help with porting over game logic to the new interfaces --- apps/openmw/mwworld/cellstore.hpp | 177 +++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 542d4700e..ae8ac8ae5 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -116,15 +116,6 @@ namespace MWWorld /// Repopulate mMergedRefs. void updateMergedRefs(); - template - LiveCellRefBase* insertBase(CellRefList& list, const LiveCellRef* ref) - { - mHasState = true; - LiveCellRefBase* ret = &list.insert(*ref); - updateMergedRefs(); - return ret; - } - // helper function for forEachInternal template bool forEachImp (Visitor& visitor, List& list) @@ -167,6 +158,11 @@ namespace MWWorld forEachImp (visitor, mCreatureLists); } + /// @note If you get a linker error here, this means the given type can not be stored in a cell. The supported types are + /// defined at the bottom of this file. + template + CellRefList& get(); + public: /// Moves object from this cell to the given cell. @@ -179,7 +175,14 @@ namespace MWWorld /// @note If you get a linker error here, this means the given type can not be inserted into a cell. /// The supported types are defined at the bottom of this file. template - LiveCellRefBase* insert(const LiveCellRef* ref); + LiveCellRefBase* insert(const LiveCellRef* ref) + { + mHasState = true; + CellRefList& list = get(); + LiveCellRefBase* ret = &list.insert(*ref); + updateMergedRefs(); + return ret; + } /// @param readerList The readers to use for loading of the cell on-demand. CellStore (const ESM::Cell *cell_, @@ -246,6 +249,41 @@ namespace MWWorld return true; } + /// Call visitor (ref) for each reference of given type. visitor must return a bool. Returning + /// false will abort the iteration. + /// \attention This function also lists deleted (count 0) objects! + /// \return Iteration completed? + template + bool forEachType(Visitor& visitor) + { + if (mState != State_Loaded) + return false; + + mHasState = true; + + CellRefList& list = get(); + + for (typename CellRefList::List::iterator it (list.mList.begin()); it!=list.mList.end(); ++it) + { + LiveCellRefBase* base = &*it; + if (mMovedToAnotherCell.find(base) != mMovedToAnotherCell.end()) + continue; + if (base->mData.isDeletedByContentFile()) + continue; + if (!visitor(MWWorld::Ptr(base, this))) + return false; + } + + for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) + { + LiveCellRefBase* base = it->first; + if (dynamic_cast*>(base)) + if (!visitor(MWWorld::Ptr(base, this))) + return false; + } + return true; + } + /// \todo add const version of forEach bool isExterior() const; @@ -295,104 +333,143 @@ namespace MWWorld }; template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mActivators, ref); + mHasState = true; + return mActivators; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mPotions, ref); + mHasState = true; + return mPotions; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mAppas, ref); + mHasState = true; + return mAppas; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mArmors, ref); + mHasState = true; + return mArmors; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mBooks, ref); + mHasState = true; + return mBooks; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mClothes, ref); + mHasState = true; + return mClothes; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mContainers, ref); + mHasState = true; + return mContainers; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mCreatures, ref); + mHasState = true; + return mCreatures; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mDoors, ref); + mHasState = true; + return mDoors; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mIngreds, ref); + mHasState = true; + return mIngreds; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mCreatureLists, ref); + mHasState = true; + return mCreatureLists; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mItemLists, ref); + mHasState = true; + return mItemLists; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mLights, ref); + mHasState = true; + return mLights; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mLockpicks, ref); + mHasState = true; + return mLockpicks; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mMiscItems, ref); + mHasState = true; + return mMiscItems; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mNpcs, ref); + mHasState = true; + return mNpcs; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mProbes, ref); + mHasState = true; + return mProbes; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mRepairs, ref); + mHasState = true; + return mRepairs; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mStatics, ref); + mHasState = true; + return mStatics; } + template<> - inline LiveCellRefBase* CellStore::insert(const LiveCellRef* ref) + inline CellRefList& CellStore::get() { - return insertBase(mWeapons, ref); + mHasState = true; + return mWeapons; } bool operator== (const CellStore& left, const CellStore& right); From 9ea475d00cd85f179e4eec10dd788a78e8435bd5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 20:30:52 +0100 Subject: [PATCH 16/23] Port LocalScripts::addCell to new CellStore interfaces --- apps/openmw/mwworld/localscripts.cpp | 89 +++++++++++++--------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index aa5abc076..030a41891 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -11,46 +11,54 @@ namespace { - template - void listCellScripts (MWWorld::LocalScripts& localScripts, - MWWorld::CellRefList& cellRefList, MWWorld::CellStore *cell) + + struct AddScriptsVisitor { - for (typename MWWorld::CellRefList::List::iterator iter ( - cellRefList.mList.begin()); - iter!=cellRefList.mList.end(); ++iter) + AddScriptsVisitor(MWWorld::LocalScripts& scripts) + : mScripts(scripts) { - if (!iter->mBase->mScript.empty() && !iter->mData.isDeleted()) - { - localScripts.add (iter->mBase->mScript, MWWorld::Ptr (&*iter, cell)); - } } - } + MWWorld::LocalScripts& mScripts; - // Adds scripts for items in containers (containers/npcs/creatures) - template - void listCellScriptsCont (MWWorld::LocalScripts& localScripts, - MWWorld::CellRefList& cellRefList, MWWorld::CellStore *cell) - { - for (typename MWWorld::CellRefList::List::iterator iter ( - cellRefList.mList.begin()); - iter!=cellRefList.mList.end(); ++iter) + bool operator()(const MWWorld::Ptr& ptr) { + if (ptr.getRefData().isDeleted()) + return true; + + std::string script = ptr.getClass().getScript(ptr); + + if (!script.empty()) + mScripts.add(script, ptr); + + return true; + } + }; - MWWorld::Ptr containerPtr (&*iter, cell); + struct AddContainerItemScriptsVisitor + { + AddContainerItemScriptsVisitor(MWWorld::LocalScripts& scripts) + : mScripts(scripts) + { + } + MWWorld::LocalScripts& mScripts; + bool operator()(const MWWorld::Ptr& containerPtr) + { MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr); - for(MWWorld::ContainerStoreIterator it3 = container.begin(); it3 != container.end(); ++it3) + for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it) { - std::string script = it3->getClass().getScript(*it3); + std::string script = it->getClass().getScript(*it); if(script != "") { - MWWorld::Ptr item = *it3; - item.mCell = cell; - localScripts.add (script, item); + MWWorld::Ptr item = *it; + item.mCell = containerPtr.getCell(); + mScripts.add (script, item); } } + return true; } - } + }; + } MWWorld::LocalScripts::LocalScripts (const MWWorld::ESMStore& store) : mStore (store) {} @@ -116,28 +124,13 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) void MWWorld::LocalScripts::addCell (CellStore *cell) { - /* - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScriptsCont (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScriptsCont (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScriptsCont (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - listCellScripts (*this, cell->get(), cell); - */ + AddScriptsVisitor addScriptsVisitor(*this); + cell->forEach(addScriptsVisitor); + + AddContainerItemScriptsVisitor addContainerItemScriptsVisitor(*this); + cell->forEachType(addContainerItemScriptsVisitor); + cell->forEachType(addContainerItemScriptsVisitor); + cell->forEachType(addContainerItemScriptsVisitor); } void MWWorld::LocalScripts::clear() From abcf91be5b0312a60dfbaa3b4c31f006d4b1fec3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 20:43:50 +0100 Subject: [PATCH 17/23] Port over more game logic to the visitor pattern --- apps/openmw/mwworld/worldimp.cpp | 84 ++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 3efce5c9e..cfb7b5c82 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1691,31 +1691,32 @@ namespace MWWorld osg::Vec2f World::getNorthVector (CellStore* cell) { - /* - MWWorld::CellRefList& statics = cell->get(); - MWWorld::LiveCellRef* ref = statics.find("northmarker"); - if (!ref) + MWWorld::Ptr northmarker = cell->search("northmarker"); + + if (northmarker.isEmpty()) return osg::Vec2f(0, 1); - osg::Quat orient (-ref->mData.getPosition().rot[2], osg::Vec3f(0,0,1)); + osg::Quat orient (-northmarker.getRefData().getPosition().rot[2], osg::Vec3f(0,0,1)); osg::Vec3f dir = orient * osg::Vec3f(0,1,0); osg::Vec2f d (dir.x(), dir.y()); return d; - */ - return osg::Vec2f(); } - void World::getDoorMarkers (CellStore* cell, std::vector& out) + struct GetDoorMarkerVisitor { - /* - MWWorld::CellRefList& doors = cell->get(); - CellRefList::List& refList = doors.mList; - for (CellRefList::List::iterator it = refList.begin(); it != refList.end(); ++it) + GetDoorMarkerVisitor(std::vector& out) + : mOut(out) { - MWWorld::LiveCellRef& ref = *it; + } - if (!ref.mData.isEnabled()) - continue; + std::vector& mOut; + + bool operator()(const MWWorld::Ptr& ptr) + { + MWWorld::LiveCellRef& ref = *static_cast* >(ptr.getBase()); + + if (!ref.mData.isEnabled() || ref.mData.isDeleted()) + return true; if (ref.mRef.getTeleport()) { @@ -1731,7 +1732,7 @@ namespace MWWorld else { cellid.mPaged = true; - positionToIndex( + MWBase::Environment::get().getWorld()->positionToIndex( ref.mRef.getDoorDest().pos[0], ref.mRef.getDoorDest().pos[1], cellid.mIndex.mX, @@ -1743,10 +1744,16 @@ namespace MWWorld newMarker.x = pos.pos[0]; newMarker.y = pos.pos[1]; - out.push_back(newMarker); + mOut.push_back(newMarker); } + return true; } - */ + }; + + void World::getDoorMarkers (CellStore* cell, std::vector& out) + { + GetDoorMarkerVisitor visitor(out); + cell->forEachType(visitor); } void World::setWaterHeight(const float height) @@ -2241,24 +2248,37 @@ namespace MWWorld return osg::Vec3f(0,1,0); } - void World::getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector& out) + struct GetContainersOwnedByVisitor + { + GetContainersOwnedByVisitor(const MWWorld::Ptr& owner, std::vector& out) + : mOwner(owner) + , mOut(out) + { + } + + MWWorld::Ptr mOwner; + std::vector& mOut; + + bool operator()(const MWWorld::Ptr& ptr) + { + if (ptr.getRefData().isDeleted()) + return true; + + if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), mOwner.getCellRef().getRefId())) + mOut.push_back(ptr); + + return true; + } + }; + + void World::getContainersOwnedBy (const MWWorld::Ptr& owner, std::vector& out) { - /* const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { - MWWorld::CellRefList& containers = (*cellIt)->get(); - CellRefList::List& refList = containers.mList; - for (CellRefList::List::iterator container = refList.begin(); container != refList.end(); ++container) - { - MWWorld::Ptr ptr (&*container, *cellIt); - if (ptr.getRefData().isDeleted()) - continue; - if (Misc::StringUtils::ciEqual(ptr.getCellRef().getOwner(), npc.getCellRef().getRefId())) - out.push_back(ptr); - } + GetContainersOwnedByVisitor visitor (owner, out); + (*cellIt)->forEachType(visitor); } - */ } struct ListObjectsVisitor @@ -2776,11 +2796,11 @@ namespace MWWorld MWWorld::Ptr World::getClosestMarker( const MWWorld::Ptr &ptr, const std::string &id ) { - /* if ( ptr.getCell()->isExterior() ) { return getClosestMarkerFromExteriorPosition(mPlayer->getLastKnownExteriorPosition(), id); } + /* // Search for a 'nearest' marker, counting each cell between the starting // cell and the exterior as a distance of 1. If an exterior is found, jump // to the nearest exterior marker, without further interior searching. From 51b892195b329b2e7a1ce5604f904bf53fa24c0a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 21:58:25 +0100 Subject: [PATCH 18/23] Restore getReadOnlyDoors() --- apps/openmw/mwworld/cellstore.hpp | 12 ++++++++++++ apps/openmw/mwworld/worldimp.cpp | 19 ++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index ae8ac8ae5..b08349293 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -286,6 +286,18 @@ namespace MWWorld /// \todo add const version of forEach + + // NOTE: does not account for moved references + // Should be phased out when we have const version of forEach + inline const CellRefList& getReadOnlyDoors() const + { + return mDoors; + } + inline const CellRefList& getReadOnlyStatics() const + { + return mStatics; + } + bool isExterior() const; Ptr searchInContainer (const std::string& id); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index cfb7b5c82..c64d90811 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2341,8 +2341,6 @@ namespace MWWorld bool World::findInteriorPosition(const std::string &name, ESM::Position &pos) { - return false; - /* typedef MWWorld::CellRefList::List DoorList; typedef MWWorld::CellRefList::List StaticList; @@ -2354,7 +2352,8 @@ namespace MWWorld if (0 == cellStore) { return false; } - const DoorList &doors = cellStore->get().mList; + + const DoorList &doors = cellStore->getReadOnlyDoors().mList; for (DoorList::const_iterator it = doors.begin(); it != doors.end(); ++it) { if (!it->mRef.getTeleport()) { continue; @@ -2376,7 +2375,7 @@ namespace MWWorld if (0 != source) { // Find door leading to our current teleport door // and use it destination to position inside cell. - const DoorList &doors = source->get().mList; + const DoorList &doors = source->getReadOnlyDoors().mList; for (DoorList::const_iterator jt = doors.begin(); jt != doors.end(); ++jt) { if (it->mRef.getTeleport() && Misc::StringUtils::ciEqual(name, jt->mRef.getDestCell())) @@ -2390,12 +2389,11 @@ namespace MWWorld } } // Fall back to the first static location. - const StaticList &statics = cellStore->get().mList; + const StaticList &statics = cellStore->getReadOnlyStatics().mList; if ( statics.begin() != statics.end() ) { pos = statics.begin()->mRef.getPosition(); return true; } - */ return false; } @@ -2743,8 +2741,6 @@ namespace MWWorld bool World::findInteriorPositionInWorldSpace(MWWorld::CellStore* cell, osg::Vec3f& result) { - return false; - /* if (cell->isExterior()) return false; @@ -2791,7 +2787,6 @@ namespace MWWorld // No luck :( return false; - */ } MWWorld::Ptr World::getClosestMarker( const MWWorld::Ptr &ptr, const std::string &id ) @@ -2800,7 +2795,6 @@ namespace MWWorld return getClosestMarkerFromExteriorPosition(mPlayer->getLastKnownExteriorPosition(), id); } - /* // Search for a 'nearest' marker, counting each cell between the starting // cell and the exterior as a distance of 1. If an exterior is found, jump // to the nearest exterior marker, without further interior searching. @@ -2848,7 +2842,6 @@ namespace MWWorld } } } - */ return MWWorld::Ptr(); } @@ -2916,7 +2909,7 @@ namespace MWWorld Ptr mDetector; float mSquaredDist; World::DetectionType mType; - bool operator() (MWWorld::Ptr ptr) + bool operator() (const MWWorld::Ptr& ptr) { if ((ptr.getRefData().getPosition().asVec3() - mDetector.getRefData().getPosition().asVec3()).length2() >= mSquaredDist) return true; @@ -2947,7 +2940,7 @@ namespace MWWorld return true; } - bool needToAdd (MWWorld::Ptr ptr, MWWorld::Ptr detector) + bool needToAdd (const MWWorld::Ptr& ptr, const MWWorld::Ptr& detector) { if (mType == World::Detect_Creature) { From 4b0ecaa0a0afdc35b33d8b789130443be580433a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 22:10:01 +0100 Subject: [PATCH 19/23] Fix physics bug --- apps/openmw/mwworld/cellstore.cpp | 1 + apps/openmw/mwworld/worldimp.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 4f28fcfdf..68ea2de00 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -246,6 +246,7 @@ namespace MWWorld { MWWorld::Ptr copied = object.getClass().copyToCell(object, *cellToMoveTo); object.getRefData().setCount(0); + object.getRefData().setBaseNode(NULL); return copied; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c64d90811..930fddd3e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1171,7 +1171,6 @@ namespace MWWorld newPtr = currCell->moveTo(ptr, newCell); mRendering->updatePtr(ptr, newPtr); - ptr.getRefData().setBaseNode(NULL); MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr); mPhysics->updatePtr(ptr, newPtr); From 45a609bc54682f5afa0a897a1f073f84caf64fac Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 6 Dec 2015 22:37:04 +0100 Subject: [PATCH 20/23] Improve PositionCell warning message --- apps/openmw/mwscript/transformationextensions.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 592168687..61fafc40f 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -300,14 +300,16 @@ namespace MWScript } catch(std::exception&) { + // cell not found, move to exterior instead (vanilla PositionCell compatibility) const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID); int cx,cy; MWBase::Environment::get().getWorld()->positionToIndex(x,y,cx,cy); store = MWBase::Environment::get().getWorld()->getExterior(cx,cy); if(!cell) { - runtime.getContext().report ("unknown cell (" + cellID + ")"); - std::cerr << "unknown cell (" << cellID << ")\n"; + std::string error = "PositionCell: unknown interior cell (" + cellID + "), moving to exterior instead"; + runtime.getContext().report (error); + std::cerr << error << std::endl; } } if(store) From f9dd549bffaf16bd4ffb6c6504625e0479196c27 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 7 Dec 2015 03:47:40 +0100 Subject: [PATCH 21/23] Restore FindContainerVisitor --- apps/openmw/mwworld/worldimp.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 930fddd3e..36b3be01d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -721,7 +721,11 @@ namespace MWWorld for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) { FindContainerVisitor visitor(ptr); - //(*cellIt)->forEachContainer(visitor); + (*cellIt)->forEachType(visitor); + if (visitor.mResult.isEmpty()) + (*cellIt)->forEachType(visitor); + if (visitor.mResult.isEmpty()) + (*cellIt)->forEachType(visitor); if (!visitor.mResult.isEmpty()) return visitor.mResult; From 1875aa4a18704ee6aeb9feb84aedb64baa74165c Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 7 Dec 2015 03:51:03 +0100 Subject: [PATCH 22/23] Restore getNearbyDoor --- apps/openmw/mwmechanics/obstacle.cpp | 13 ++++++------- apps/openmw/mwworld/refdata.cpp | 2 +- apps/openmw/mwworld/refdata.hpp | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index a2cbae2a0..5815d8cbe 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -44,10 +44,9 @@ namespace MWMechanics return MWWorld::Ptr(); // check interior cells only // Check all the doors in this cell - /* - MWWorld::CellRefList& doors = cell->get(); - MWWorld::CellRefList::List& refList = doors.mList; - MWWorld::CellRefList::List::iterator it = refList.begin(); + const MWWorld::CellRefList& doors = cell->getReadOnlyDoors(); + const MWWorld::CellRefList::List& refList = doors.mList; + MWWorld::CellRefList::List::const_iterator it = refList.begin(); osg::Vec3f pos(actor.getRefData().getPosition().asVec3()); /// TODO: How to check whether the actor is facing a door? Below code is for @@ -60,14 +59,14 @@ namespace MWMechanics /// opposite of the code in World::activateDoor() ::confused:: for (; it != refList.end(); ++it) { - MWWorld::LiveCellRef& ref = *it; + const MWWorld::LiveCellRef& ref = *it; if((pos - ref.mData.getPosition().asVec3()).length2() < minSqr && ref.mData.getPosition().rot[2] == ref.mRef.getPosition().rot[2]) { - return MWWorld::Ptr(&ref, actor.getCell()); // found, stop searching + // FIXME cast + return MWWorld::Ptr(&const_cast &>(ref), actor.getCell()); // found, stop searching } } - */ return MWWorld::Ptr(); // none found } diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 8acba43df..997b3fc94 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -182,7 +182,7 @@ namespace MWWorld mPosition = pos; } - const ESM::Position& RefData::getPosition() + const ESM::Position& RefData::getPosition() const { return mPosition; } diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 6713334d7..19c31a14b 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -103,7 +103,7 @@ namespace MWWorld void disable(); void setPosition (const ESM::Position& pos); - const ESM::Position& getPosition(); + const ESM::Position& getPosition() const; void setCustomData (CustomData *data); ///< Set custom data (potentially replacing old custom data). The ownership of \a data is From 621347b20fb7a8d778b3219dd3cd23a2232cf1a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 7 Dec 2015 03:55:26 +0100 Subject: [PATCH 23/23] Remove moved ref handling from listRefs() Not needed since we now load cells when a reference is moved there. --- apps/openmw/mwworld/cellstore.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 68ea2de00..b5db42b00 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -474,8 +474,6 @@ namespace MWWorld continue; } - // We don't need to check mMovedToAnotherCell because listRefs isn't used for loaded cells. - mIds.push_back (Misc::StringUtils::lowerCase (ref.mRefID)); } } @@ -488,12 +486,6 @@ namespace MWWorld mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID)); } - // List runtime moved references - for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it) - { - mIds.push_back(Misc::StringUtils::lowerCase(it->first->mRef.getRefId())); - } - std::sort (mIds.begin(), mIds.end()); }