forked from mirror/openmw-tes3mp
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:
parent
2c74ea381e
commit
cbfa282f8d
14 changed files with 149 additions and 128 deletions
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <string>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "movement.hpp"
|
||||
#include "../mwworld/action.hpp"
|
||||
|
||||
#include <OgreMath.h>
|
||||
|
||||
|
@ -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<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;
|
||||
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])));
|
||||
}
|
||||
|
|
|
@ -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<ESM::Door>* mLastDoorChecked; //Used to ensure we don't try to CONSTANTLY open a door
|
||||
|
||||
ESM::Position mStuckPos;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<ESM::Door>* 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<ESM::Door>& doors = cell->get<ESM::Door>();
|
||||
|
@ -31,14 +39,14 @@ namespace MWMechanics
|
|||
MWWorld::CellRefList<ESM::Door>::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<ESM::Door>& 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():
|
||||
|
|
|
@ -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<ESM::Door>* getNearbyDoor(const MWWorld::Ptr& actor,
|
||||
float minSqr = MIN_DIST_TO_DOOR_SQUARED,
|
||||
bool closed = true);
|
||||
|
||||
class ObstacleCheck
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -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<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)
|
||||
{
|
||||
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())
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue