1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-03 23:45:33 +00:00

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
This commit is contained in:
Thomas 2014-05-13 03:58:32 -04:00
parent 2c74ea381e
commit cbfa282f8d
14 changed files with 149 additions and 128 deletions

View file

@ -67,7 +67,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects 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 aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
disease pickpocket levelledlist combat steering obstacle disease pickpocket levelledlist combat steering obstacle
) )

View file

@ -390,10 +390,14 @@ namespace MWBase
virtual void setupPlayer() = 0; virtual void setupPlayer() = 0;
virtual void renderPlayer() = 0; virtual void renderPlayer() = 0;
/// if activated, should this door be opened or closed?
virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door) = 0; 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; 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 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 virtual bool getActorStandingOn (const MWWorld::Ptr& object) = 0; ///< @return true if any actor is standing on \a object

View file

@ -20,82 +20,26 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const
} }
bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld(); ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
ESM::Position pos = actor.getRefData().getPosition(); const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mObjectId, false); //The target to follow
Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Cell *cell = actor.getCell()->getCell();
MWWorld::Ptr player = world->getPlayerPtr(); if(target == MWWorld::Ptr())
if(cell->mData.mX != player.getCell()->getCell()->mData.mX) return true; //Target doesn't exist
{
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); //Set the target desition from the actor
if(target == MWWorld::Ptr()) return true; ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;
ESM::Position targetPos = target.getRefData().getPosition(); 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;
bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false);
if(!mPathFinder.isPathConstructed() || cellChange) MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player
{
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; return true;
} }
else {
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) pathTo(actor, dest, duration); //Go to the destination
{ actor.getClass().getMovementSettings(actor).mPosition[1] = 1;
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;
return false; return false;
} }

View file

@ -9,6 +9,7 @@
namespace MWMechanics 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 class AiActivate : public AiPackage
{ {
public: public:
@ -21,8 +22,6 @@ namespace MWMechanics
private: private:
std::string mObjectId; std::string mObjectId;
PathFinder mPathFinder;
int mCellX; int mCellX;
int mCellY; int mCellY;
}; };

View file

@ -12,23 +12,17 @@
#include "steering.hpp" #include "steering.hpp"
MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) 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) 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) 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) bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration)

View file

@ -1,5 +1,5 @@
#ifndef GAME_MWMECHANICS_AIFALLOW_H #ifndef GAME_MWMECHANICS_AIFOLLOW_H
#define GAME_MWMECHANICS_AIFALLOW_H #define GAME_MWMECHANICS_AIFOLLOW_H
#include "aipackage.hpp" #include "aipackage.hpp"
#include <string> #include <string>

View file

@ -8,6 +8,7 @@
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "creaturestats.hpp" #include "creaturestats.hpp"
#include "movement.hpp" #include "movement.hpp"
#include "../mwworld/action.hpp"
#include <OgreMath.h> #include <OgreMath.h>
@ -15,13 +16,18 @@
MWMechanics::AiPackage::~AiPackage() {} 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) bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration)
{ {
//Update various Timers //Update various Timers
mTimer = mTimer + duration; //Update timer mTimer += duration; //Update timer
mStuckTimer = mStuckTimer + duration; //Update stuck timer mStuckTimer += duration; //Update stuck timer
mTotalTime = mTotalTime + duration; //Update total time following mTotalTime += duration; //Update total time following
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor 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 /// 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 /// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason
mPathFinder.buildPath(start, dest, actor.getCell(), true); //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<ESM::Door>* 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; mStuckTimer = 0;
mStuckPos = pos; 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])));
}
} }

View file

@ -4,6 +4,8 @@
#include "pathfinding.hpp" #include "pathfinding.hpp"
#include "../../../components/esm/defs.hpp" #include "../../../components/esm/defs.hpp"
#include "obstacle.hpp"
namespace MWWorld namespace MWWorld
{ {
class Ptr; class Ptr;
@ -24,9 +26,13 @@ namespace MWMechanics
TypeIdFollow = 3, TypeIdFollow = 3,
TypeIdActivate = 4, TypeIdActivate = 4,
TypeIdCombat = 5, TypeIdCombat = 5,
TypeIdPursue = 6 TypeIdPursue = 6,
TypeIdAvoidDoor = 7
}; };
///Default constructor
AiPackage();
///Default Deconstructor ///Default Deconstructor
virtual ~AiPackage(); virtual ~AiPackage();
@ -50,11 +56,15 @@ namespace MWMechanics
bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration);
PathFinder mPathFinder; PathFinder mPathFinder;
ObstacleCheck mObstacleCheck;
float mDoorCheckDuration;
float mTimer; float mTimer;
float mStuckTimer; float mStuckTimer;
float mTotalTime; float mTotalTime;
MWWorld::LiveCellRef<ESM::Door>* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door
ESM::Position mStuckPos; ESM::Position mStuckPos;
}; };
} }

View file

@ -31,16 +31,15 @@ bool MWMechanics::AiPursue::execute (const MWWorld::Ptr& actor, float duration)
//Set the target desition from the actor //Set the target desition from the actor
ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos; 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 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; actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false); MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(mObjectId,false);
MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player MWWorld::Class::get(target).activate(target,actor).get()->execute(actor); //Arrest player
return true; return true;
} }
else else {
actor.getClass().getMovementSettings(actor).mPosition[1] = 1; pathTo(actor, dest, duration); //Go to the destination
}
actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run

View file

@ -9,7 +9,9 @@
namespace MWMechanics namespace MWMechanics
{ {
/// \brief Makes the actor very closely follow the actor /// \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 class AiPursue : public AiPackage
{ {
public: public:

View file

@ -19,11 +19,19 @@ namespace MWMechanics
// Limitation: there can be false detections, and does not test whether the // Limitation: there can be false detections, and does not test whether the
// actor is facing the door. // actor is facing the door.
bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed) bool proximityToDoor(const MWWorld::Ptr& actor, float minSqr, bool closed)
{
if(getNearbyDoor(actor, minSqr, closed)!=NULL)
return true;
else
return false;
}
MWWorld::LiveCellRef<ESM::Door>* getNearbyDoor(const MWWorld::Ptr& actor, float minSqr, bool closed)
{ {
MWWorld::CellStore *cell = actor.getCell(); MWWorld::CellStore *cell = actor.getCell();
if(cell->getCell()->isExterior()) if(cell->getCell()->isExterior())
return false; // check interior cells only return NULL; // check interior cells only
// Check all the doors in this cell // Check all the doors in this cell
MWWorld::CellRefList<ESM::Door>& doors = cell->get<ESM::Door>(); MWWorld::CellRefList<ESM::Door>& doors = cell->get<ESM::Door>();
@ -31,14 +39,14 @@ namespace MWMechanics
MWWorld::CellRefList<ESM::Door>::List::iterator it = refList.begin(); MWWorld::CellRefList<ESM::Door>::List::iterator it = refList.begin();
Ogre::Vector3 pos(actor.getRefData().getPosition().pos); Ogre::Vector3 pos(actor.getRefData().getPosition().pos);
// TODO: How to check whether the actor is facing a door? Below code is for /// TODO: How to check whether the actor is facing a door? Below code is for
// the player, perhaps it can be adapted. /// the player, perhaps it can be adapted.
//MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject(); //MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject();
//if(!ptr.isEmpty()) //if(!ptr.isEmpty())
//std::cout << "faced door " << ptr.getClass().getName(ptr) << std::endl; //std::cout << "faced door " << ptr.getClass().getName(ptr) << std::endl;
// TODO: The in-game observation of rot[2] value seems to be the /// TODO: The in-game observation of rot[2] value seems to be the
// opposite of the code in World::activateDoor() ::confused:: /// opposite of the code in World::activateDoor() ::confused::
for (; it != refList.end(); ++it) for (; it != refList.end(); ++it)
{ {
MWWorld::LiveCellRef<ESM::Door>& ref = *it; MWWorld::LiveCellRef<ESM::Door>& ref = *it;
@ -46,10 +54,10 @@ namespace MWMechanics
if((closed && ref.mData.getLocalRotation().rot[2] == 0) || if((closed && ref.mData.getLocalRotation().rot[2] == 0) ||
(!closed && ref.mData.getLocalRotation().rot[2] >= 1)) (!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(): ObstacleCheck::ObstacleCheck():

View file

@ -1,6 +1,10 @@
#ifndef OPENMW_MECHANICS_OBSTACLE_H #ifndef OPENMW_MECHANICS_OBSTACLE_H
#define OPENMW_MECHANICS_OBSTACLE_H #define OPENMW_MECHANICS_OBSTACLE_H
//#include "../mwbase/world.hpp"
//#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
namespace MWWorld namespace MWWorld
{ {
class Ptr; class Ptr;
@ -8,14 +12,20 @@ namespace MWWorld
namespace MWMechanics 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; 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, bool proximityToDoor(const MWWorld::Ptr& actor,
float minSqr = MIN_DIST_TO_DOOR_SQUARED, float minSqr = MIN_DIST_TO_DOOR_SQUARED,
bool closed = true); 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<ESM::Door>* getNearbyDoor(const MWWorld::Ptr& actor,
float minSqr = MIN_DIST_TO_DOOR_SQUARED,
bool closed = true);
class ObstacleCheck class ObstacleCheck
{ {
public: public:

View file

@ -30,6 +30,7 @@
#include "../mwmechanics/spellcasting.hpp" #include "../mwmechanics/spellcasting.hpp"
#include "../mwmechanics/levelledlist.hpp" #include "../mwmechanics/levelledlist.hpp"
#include "../mwmechanics/combat.hpp" #include "../mwmechanics/combat.hpp"
#include "../mwmechanics/aiavoiddoor.hpp" //Used to tell actors to avoid doors
#include "../mwrender/sky.hpp" #include "../mwrender/sky.hpp"
#include "../mwrender/animation.hpp" #include "../mwrender/animation.hpp"
@ -1210,7 +1211,11 @@ namespace MWWorld
MWWorld::Ptr ptr = getPtrViaHandle(*cit); MWWorld::Ptr ptr = getPtrViaHandle(*cit);
if (MWWorld::Class::get(ptr).isActor()) 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); localRotateObject(it->first, 0, 0, oldRot);
break; break;
} }
@ -1853,6 +1858,16 @@ namespace MWWorld
return door.getRefData().getLocalRotation().rot[2] == 0; 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<MWWorld::Ptr, int>::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) bool World::getPlayerStandingOn (const MWWorld::Ptr& object)
{ {
MWWorld::Ptr player = mPlayer->getPlayer(); MWWorld::Ptr player = mPlayer->getPlayer();

View file

@ -493,10 +493,13 @@ namespace MWWorld
virtual void setupPlayer(); virtual void setupPlayer();
virtual void renderPlayer(); virtual void renderPlayer();
/// if activated, should this door be opened or closed?
virtual bool getOpenOrCloseDoor(const MWWorld::Ptr& door); 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); 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 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 virtual bool getActorStandingOn (const MWWorld::Ptr& object); ///< @return true if any actor is standing on \a object