diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96be..c397b190f 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -200,6 +200,9 @@ namespace MWBase virtual MWWorld::Ptr searchPtrViaHandle (const std::string& handle) = 0; ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; + ///< Search is limited to the active cells. + /// \todo enable reference in the OGRE scene virtual void enable (const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 1482ee24e..9bfea41f3 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -11,6 +11,8 @@ namespace MWMechanics { + int CreatureStats::sActorId = 0; + CreatureStats::CreatureStats() : mLevel (0), mDead (false), mDied (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false), @@ -20,7 +22,7 @@ namespace MWMechanics mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), - mTradeTime(0,0), mGoldPool(0) + mTradeTime(0,0), mGoldPool(0), mActorId(-1) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -559,4 +561,22 @@ namespace MWMechanics { return mGoldPool; } + + int CreatureStats::getActorId() + { + if (mActorId==-1) + mActorId = sActorId++; + + return mActorId; + } + + bool CreatureStats::matchesActorId (int id) const + { + return mActorId!=-1 && id==mActorId; + } + + void CreatureStats::cleanup() + { + sActorId = 0; + } } diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 2301f9a67..7cec26fb8 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -24,6 +24,7 @@ namespace MWMechanics /// class CreatureStats { + static int sActorId; DrawState_ mDrawState; AttributeValue mAttributes[8]; DynamicStat mDynamic[3]; // health, magicka, fatigue @@ -58,6 +59,7 @@ namespace MWMechanics MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay int mGoldPool; // the pool of merchant gold not in inventory + int mActorId; protected: // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. @@ -236,6 +238,15 @@ namespace MWMechanics void setGoldPool(int pool); int getGoldPool() const; + + int getActorId(); + ///< Will generate an actor ID, if the actor does not have one yet. + + bool matchesActorId (int id) const; + ///< Check if \a id matches the actor ID of *this (if the actor does not have an ID + /// assigned this function will return false). + + static void cleanup(); }; } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 153da1f30..d261fe0c0 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -28,6 +28,7 @@ #include "../mwworld/inventorystore.hpp" #include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwscript/globalscripts.hpp" @@ -46,6 +47,8 @@ void MWState::StateManager::cleanup (bool force) mState = State_NoGame; mCharacterManager.clearCurrentCharacter(); mTimePlayed = 0; + + MWMechanics::CreatureStats::cleanup(); } } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 39f6538bb..67ab44b77 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -16,6 +16,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwmechanics/creaturestats.hpp" + #include "ptr.hpp" #include "esmstore.hpp" #include "class.hpp" @@ -41,6 +43,22 @@ namespace return MWWorld::Ptr(); } + template + MWWorld::Ptr searchViaActorId (MWWorld::CellRefList& actorList, int actorId, + MWWorld::CellStore *cell) + { + for (typename MWWorld::CellRefList::List::iterator iter (actorList.mList.begin()); + iter!=actorList.mList.end(); ++iter) + { + MWWorld::Ptr actor (&*iter, cell); + + if (MWWorld::Class::get (actor).getCreatureStats (actor).matchesActorId (actorId)) + return actor; + } + + return MWWorld::Ptr(); + } + template void writeReferenceCollection (ESM::ESMWriter& writer, const MWWorld::CellRefList& collection) @@ -323,6 +341,17 @@ namespace MWWorld return Ptr(); } + Ptr CellStore::searchViaActorId (int id) + { + if (Ptr ptr = ::searchViaActorId (mNpcs, id, this)) + return ptr; + + if (Ptr ptr = ::searchViaActorId (mCreatures, id, this)) + return ptr; + + return Ptr(); + } + float CellStore::getWaterLevel() const { return mWaterLevel; diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index cc3036647..91c536b43 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -91,6 +91,9 @@ namespace MWWorld Ptr searchViaHandle (const std::string& handle); ///< Will return an empty Ptr if cell is not loaded. + Ptr searchViaActorId (int id); + ///< Will return an empty Ptr if cell is not loaded. + float getWaterLevel() const; void setWaterLevel (float level); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 7af926dca..4b92a920b 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -507,4 +507,24 @@ namespace MWWorld } return false; } + + Ptr Scene::searchPtrViaHandle (const std::string& handle) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaHandle (handle)) + return ptr; + + return Ptr(); + } + + Ptr Scene::searchPtrViaActorId (int actorId) + { + for (CellStoreCollection::const_iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + if (Ptr ptr = (*iter)->searchViaActorId (actorId)) + return ptr; + + return Ptr(); + } } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 8d8765378..449644754 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -104,6 +104,10 @@ namespace MWWorld ///< Remove an object from the scene, but not from the world model. bool isCellActive(const CellStore &cell); + + Ptr searchPtrViaHandle (const std::string& handle); + + Ptr searchPtrViaActorId (int actorId); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 538cd17df..e07ee9df8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -546,17 +546,13 @@ namespace MWWorld { if (mPlayer->getPlayer().getRefData().getHandle()==handle) return mPlayer->getPlayer(); - for (Scene::CellStoreCollection::const_iterator iter (mWorldScene->getActiveCells().begin()); - iter!=mWorldScene->getActiveCells().end(); ++iter) - { - CellStore* cellstore = *iter; - Ptr ptr = cellstore->searchViaHandle (handle); - if (!ptr.isEmpty()) - return ptr; - } + return mWorldScene->searchPtrViaHandle (handle); + } - return MWWorld::Ptr(); + Ptr World::searchPtrViaActorId (int actorId) + { + return mWorldScene->searchPtrViaActorId (actorId); } void World::addContainerScripts(const Ptr& reference, CellStore * cell) @@ -1922,7 +1918,7 @@ namespace MWWorld out.push_back(searchPtrViaHandle(*it)); } } - + bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) { if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 645330683..2328e67a8 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -287,6 +287,9 @@ namespace MWWorld virtual Ptr searchPtrViaHandle (const std::string& handle); ///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found + virtual Ptr searchPtrViaActorId (int actorId); + ///< Search is limited to the active cells. + virtual void adjustPosition (const Ptr& ptr); ///< Adjust position after load to be on ground. Must be called after model load.