From cbfa282f8d04932eaf01f20fa108c9094da1b1c3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 13 May 2014 03:58:32 -0400 Subject: [PATCH] Changed implementations of aifollow/pursue/activate slightly, added ability for NPCs to go through unlocked doors (They even try locked ones), and step back from opening doors (Although it still needs some work) Notes - When the door hits them while it's about to finish closing they will try to walk through the door. - Considerably more works is needed in making the NPC work out troublesome areas where they get stuck --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 8 ++- apps/openmw/mwmechanics/aiactivate.cpp | 98 ++++++-------------------- apps/openmw/mwmechanics/aiactivate.hpp | 5 +- apps/openmw/mwmechanics/aifollow.cpp | 12 +--- apps/openmw/mwmechanics/aifollow.hpp | 4 +- apps/openmw/mwmechanics/aipackage.cpp | 61 ++++++++++++---- apps/openmw/mwmechanics/aipackage.hpp | 14 +++- apps/openmw/mwmechanics/aipursue.cpp | 7 +- apps/openmw/mwmechanics/aipursue.hpp | 4 +- apps/openmw/mwmechanics/obstacle.cpp | 22 ++++-- apps/openmw/mwmechanics/obstacle.hpp | 14 +++- apps/openmw/mwworld/worldimp.cpp | 19 ++++- apps/openmw/mwworld/worldimp.hpp | 7 +- 14 files changed, 149 insertions(+), 128 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7a5283125..aee5cbeac 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -67,7 +67,7 @@ add_openmw_dir (mwclass add_openmw_dir (mwmechanics mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects - drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow + drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle ) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 44c8c96be..2dfa34ba3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -390,10 +390,14 @@ namespace MWBase virtual void setupPlayer() = 0; virtual void renderPlayer() = 0; + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door) = 0; - ///< activate (open or close) an non-teleport door + + /// Is door currently opening/closing? + virtual bool getIsMovingDoor(const MWWorld::Ptr& door) = 0; virtual bool getPlayerStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index eeedc0d7a..1463dff7e 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -19,83 +19,27 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const return new AiActivate(*this); } bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) -{ - MWBase::World *world = MWBase::Environment::get().getWorld(); - ESM::Position pos = actor.getRefData().getPosition(); - Movement &movement = actor.getClass().getMovementSettings(actor); - const ESM::Cell *cell = actor.getCell()->getCell(); - - MWWorld::Ptr player = world->getPlayerPtr(); - if(cell->mData.mX != player.getCell()->getCell()->mData.mX) - { - int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > - sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - if(cell->mData.mY != player.getCell()->getCell()->mData.mY) - { - int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); - //check if actor is near the border of an inactive cell. If so, stop walking. - if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > - sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) - { - movement.mPosition[1] = 0; - return false; - } - } - - MWWorld::Ptr target = world->searchPtr(mObjectId,false); - if(target == MWWorld::Ptr()) return true; - - ESM::Position targetPos = target.getRefData().getPosition(); - - bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; - if(!mPathFinder.isPathConstructed() || cellChange) - { - mCellX = cell->mData.mX; - mCellY = cell->mData.mY; - - ESM::Pathgrid::Point dest; - dest.mX = targetPos.pos[0]; - dest.mY = targetPos.pos[1]; - dest.mZ = targetPos.pos[2]; - - ESM::Pathgrid::Point start; - start.mX = pos.pos[0]; - start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - mPathFinder.buildPath(start, dest, actor.getCell(), true); - } - - if((pos.pos[0]-targetPos.pos[0])*(pos.pos[0]-targetPos.pos[0])+ - (pos.pos[1]-targetPos.pos[1])*(pos.pos[1]-targetPos.pos[1])+ - (pos.pos[2]-targetPos.pos[2])*(pos.pos[2]-targetPos.pos[2]) < 200*200) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) - { - movement.mPosition[1] = 0; - MWWorld::Ptr target = world->getPtr(mObjectId,false); - MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); - return true; - } - - float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); - zTurn(actor, Ogre::Degree(zAngle)); - MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1; - movement.mPosition[1] = 1; - +{ + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow + + if(target == MWWorld::Ptr()) + return true; //Target doesn't exist + + //Set the target desition from the actor + ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; + + if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 200 || mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) { //Stop when you get close + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); + MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player + return true; + } + else { + pathTo(actor, dest, duration); //Go to the destination + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + } + return false; } diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index b6ce9f85d..f68438872 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -8,7 +8,8 @@ namespace MWMechanics { - /// \brief Causes actor to walk to activatable object and activate it + /// \brief Causes actor to walk to activatable object and activate it + /** Will actiavte when close to object or path grid complete **/ class AiActivate : public AiPackage { public: @@ -21,8 +22,6 @@ namespace MWMechanics private: std::string mObjectId; - - PathFinder mPathFinder; int mCellX; int mCellY; }; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 98ac5ee14..8d9e01939 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -12,23 +12,17 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +: mAlwaysFollow(false), mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } MWMechanics::AiFollow::AiFollow(const std::string &actorId) -: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") +: mAlwaysFollow(true), mDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId(""), AiPackage() { - mTimer = 0; - mStuckTimer = 0; } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index 531082357..43681c163 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -1,5 +1,5 @@ -#ifndef GAME_MWMECHANICS_AIFALLOW_H -#define GAME_MWMECHANICS_AIFALLOW_H +#ifndef GAME_MWMECHANICS_AIFOLLOW_H +#define GAME_MWMECHANICS_AIFOLLOW_H #include "aipackage.hpp" #include diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index afe99e2c0..90f0505a4 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -8,6 +8,7 @@ #include "../mwworld/cellstore.hpp" #include "creaturestats.hpp" #include "movement.hpp" +#include "../mwworld/action.hpp" #include @@ -15,13 +16,18 @@ MWMechanics::AiPackage::~AiPackage() {} +MWMechanics::AiPackage::AiPackage() : mLastDoorChecked(NULL), mTimer(0), mStuckTimer(0) { + +} + bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration) { //Update various Timers - mTimer = mTimer + duration; //Update timer - mStuckTimer = mStuckTimer + duration; //Update stuck timer - mTotalTime = mTotalTime + duration; //Update total time following + mTimer += duration; //Update timer + mStuckTimer += duration; //Update stuck timer + mTotalTime += duration; //Update total time following + ESM::Position pos = actor.getRefData().getPosition(); //position of the actor @@ -78,18 +84,45 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po //************************ /// Checks if you aren't moving; attempts to unstick you //************************ - if(mStuckTimer>0.5) //Checks every half of a second + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished? + return true; + else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something { - if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) //NPC hasn't moved much is half a second, he's stuck - mPathFinder.buildPath(start, dest, actor.getCell(), true); - - mStuckTimer = 0; - mStuckPos = pos; +/// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason + //if(mObstacleCheck.check(actor, duration)) { + if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //Actually stuck + // first check if we're walking into a door + MWWorld::LiveCellRef* door = getNearbyDoor(actor); + if(door != NULL) // NOTE: checks interior cells only + { + if(door->mRef.mTrap.empty() && mLastDoorChecked != door) { //Open the door if untrapped + door->mClass->activate(MWBase::Environment::get().getWorld()->getPtr(door->mRef.mRefID,false), actor).get()->execute(actor); + mLastDoorChecked = door; + } + } + else // probably walking into another NPC + { + // TODO: diagonal should have same animation as walk forward + // but doesn't seem to do that? + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f; + // change the angle a bit, too + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1]))); + } + /*else if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10) { //NPC hasn't moved much is half a second, he's stuck + actor.getClass().getMovementSettings(actor).mPosition[1] = 0; + actor.getClass().getMovementSettings(actor).mPosition[0] = 1; + }*/ + } + else { + mStuckTimer = 0; + mStuckPos = pos; + mLastDoorChecked = NULL; //Resets it, in case he gets stuck behind the door again + } + } + else { + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; } - //Checks if the path isn't over, turn tomards the direction that you're going - if(!mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) - { - zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); - } + zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); } diff --git a/apps/openmw/mwmechanics/aipackage.hpp b/apps/openmw/mwmechanics/aipackage.hpp index e36b51f69..37de32d8d 100644 --- a/apps/openmw/mwmechanics/aipackage.hpp +++ b/apps/openmw/mwmechanics/aipackage.hpp @@ -4,6 +4,8 @@ #include "pathfinding.hpp" #include "../../../components/esm/defs.hpp" +#include "obstacle.hpp" + namespace MWWorld { class Ptr; @@ -24,9 +26,13 @@ namespace MWMechanics TypeIdFollow = 3, TypeIdActivate = 4, TypeIdCombat = 5, - TypeIdPursue = 6 + TypeIdPursue = 6, + TypeIdAvoidDoor = 7 }; + ///Default constructor + AiPackage(); + ///Default Deconstructor virtual ~AiPackage(); @@ -50,10 +56,14 @@ namespace MWMechanics bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); PathFinder mPathFinder; + ObstacleCheck mObstacleCheck; + float mDoorCheckDuration; float mTimer; float mStuckTimer; - float mTotalTime; + float mTotalTime; + + MWWorld::LiveCellRef* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door ESM::Position mStuckPos; }; diff --git a/apps/openmw/mwmechanics/aipursue.cpp b/apps/openmw/mwmechanics/aipursue.cpp index 4e0bc7104..6e91ccb71 100644 --- a/apps/openmw/mwmechanics/aipursue.cpp +++ b/apps/openmw/mwmechanics/aipursue.cpp @@ -31,16 +31,15 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration) //Set the target desition from the actor ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; - pathTo(actor, dest, duration); //Go to the destination - if(distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]) < 100) { //Stop when you get close actor.getClass().getMovementSettings(actor).mPosition[1] = 0; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player return true; } - else - actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + else { + pathTo(actor, dest, duration); //Go to the destination + } actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run diff --git a/apps/openmw/mwmechanics/aipursue.hpp b/apps/openmw/mwmechanics/aipursue.hpp index 7d1ea5bb9..2eb533d62 100644 --- a/apps/openmw/mwmechanics/aipursue.hpp +++ b/apps/openmw/mwmechanics/aipursue.hpp @@ -9,7 +9,9 @@ namespace MWMechanics { /// \brief Makes the actor very closely follow the actor - /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. **/ + /** Used for arresting players. Causes the actor to run to the pursued actor and activate them, to arrest them. + Note that while very similar to AiActivate, it will ONLY activate when evry close to target (Not also when the + path is completed). **/ class AiPursue : public AiPackage { public: diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 181560935..7cd85685b 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -19,11 +19,19 @@ namespace MWMechanics // Limitation: there can be false detections, and does not test whether the // actor is facing the door. bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) + { + if(getNearbyDoor(actor, minSqr, closed)!=NULL) + return true; + else + return false; + } + + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) { MWWorld::CellStore *cell = actor.getCell(); if(cell->getCell()->isExterior()) - return false; // check interior cells only + return NULL; // check interior cells only // Check all the doors in this cell MWWorld::CellRefList& doors = cell->get(); @@ -31,14 +39,14 @@ namespace MWMechanics MWWorld::CellRefList::List::iterator it = refList.begin(); Ogre::Vector3 pos(actor.getRefData().getPosition().pos); - // TODO: How to check whether the actor is facing a door? Below code is for - // the player, perhaps it can be adapted. + /// TODO: How to check whether the actor is facing a door? Below code is for + /// the player, perhaps it can be adapted. //MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject(); //if(!ptr.isEmpty()) //std::cout << "faced door " << ptr.getClass().getName(ptr) << std::endl; - // TODO: The in-game observation of rot[2] value seems to be the - // opposite of the code in World::activateDoor() ::confused:: + /// TODO: The in-game observation of rot[2] value seems to be the + /// opposite of the code in World::activateDoor() ::confused:: for (; it != refList.end(); ++it) { MWWorld::LiveCellRef& ref = *it; @@ -46,10 +54,10 @@ namespace MWMechanics if((closed && ref.mData.getLocalRotation().rot[2] == 0) || (!closed && ref.mData.getLocalRotation().rot[2] >= 1)) { - return true; // found, stop searching + return &ref; // found, stop searching } } - return false; // none found + return NULL; // none found } ObstacleCheck::ObstacleCheck(): diff --git a/apps/openmw/mwmechanics/obstacle.hpp b/apps/openmw/mwmechanics/obstacle.hpp index 12030b2be..e737ef9cf 100644 --- a/apps/openmw/mwmechanics/obstacle.hpp +++ b/apps/openmw/mwmechanics/obstacle.hpp @@ -1,6 +1,10 @@ #ifndef OPENMW_MECHANICS_OBSTACLE_H #define OPENMW_MECHANICS_OBSTACLE_H +//#include "../mwbase/world.hpp" +//#include "../mwworld/class.hpp" +#include "../mwworld/cellstore.hpp" + namespace MWWorld { class Ptr; @@ -8,14 +12,20 @@ namespace MWWorld namespace MWMechanics { - // NOTE: determined empirically based on in-game behaviour + /// NOTE: determined empirically based on in-game behaviour static const float MIN_DIST_TO_DOOR_SQUARED = 128*128; - // tests actor's proximity to a closed door by default + /// tests actor's proximity to a closed door by default bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr = MIN_DIST_TO_DOOR_SQUARED, bool closed = true); + /// Returns door pointer within range. No guarentee is given as too which one + /** \return Pointer to the door, or NULL if none exists **/ + MWWorld::LiveCellRef* getNearbyDoor(const MWWorld::Ptr& actor, + float minSqr = MIN_DIST_TO_DOOR_SQUARED, + bool closed = true); + class ObstacleCheck { public: diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index ba36d4a86..5d1657a34 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -30,6 +30,7 @@ #include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/levelledlist.hpp" #include "../mwmechanics/combat.hpp" +#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors #include "../mwrender/sky.hpp" #include "../mwrender/animation.hpp" @@ -1210,7 +1211,11 @@ namespace MWWorld MWWorld::Ptr ptr = getPtrViaHandle(*cit); if (MWWorld::Class::get(ptr).isActor()) { - // we collided with an actor, we need to undo the rotation + // Collided with actor, ask actor to try to avoid door + MWMechanics::AiSequence& seq = MWWorld::Class::get(ptr).getCreatureStats(ptr).getAiSequence(); + if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) //Only add it once + seq.stack(MWMechanics::AiAvoidDoor(it->first),ptr); + // we need to undo the rotation localRotateObject(it->first, 0, 0, oldRot); break; } @@ -1853,6 +1858,16 @@ namespace MWWorld return door.getRefData().getLocalRotation().rot[2] == 0; } + bool World::getIsMovingDoor(const Ptr& door) + { + //This more expensive comparison is needed for some reason + // TODO (tluppi#1#): Figure out why comparing Ptr isn't working + for(std::map::iterator it = mDoorStates.begin(); it != mDoorStates.end(); it++) + if(it->first.getCellRef().mRefID == door.getCellRef().mRefID) + return true; + return false; + } + bool World::getPlayerStandingOn (const MWWorld::Ptr& object) { MWWorld::Ptr player = mPlayer->getPlayer(); @@ -1919,7 +1934,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..d111d0008 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -493,10 +493,13 @@ namespace MWWorld virtual void setupPlayer(); virtual void renderPlayer(); + /// if activated, should this door be opened or closed? virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); - ///< if activated, should this door be opened or closed? + + /// activate (open or close) an non-teleport door virtual void activateDoor(const MWWorld::Ptr& door); - ///< activate (open or close) an non-teleport door + + virtual bool getIsMovingDoor(const MWWorld::Ptr& door); virtual bool getPlayerStandingOn (const MWWorld::Ptr& object); ///< @return true if the player is standing on \a object virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object