diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index f99cffe04a..e9ac39f1d1 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -115,21 +115,11 @@ namespace MWClass if (ref->mRef.mTeleport) { - // teleport door - /// \todo remove this if clause once ActionTeleport can also support other actors - if (MWBase::Environment::get().getWorld()->getPlayerPtr()==actor) - { - boost::shared_ptr action(new MWWorld::ActionTeleport (ref->mRef.mDestCell, ref->mRef.mDoorDest)); + boost::shared_ptr action(new MWWorld::ActionTeleport (ref->mRef.mDestCell, ref->mRef.mDoorDest)); - action->setSound(openSound); + action->setSound(openSound); - return action; - } - else - { - // another NPC or a creature is using the door - return boost::shared_ptr (new MWWorld::FailedAction); - } + return action; } else { diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index 531ba55686..1f3c585216 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -1,8 +1,27 @@ #include "aiactivate.hpp" #include +#include "movement.hpp" + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwworld/class.hpp" +#include "../mwworld/action.hpp" + +#include "steering.hpp" + +namespace +{ + float sgn(float a) + { + if(a > 0) + return 1.0; + return -1.0; + } +} + MWMechanics::AiActivate::AiActivate(const std::string &objectId) -: mObjectId(objectId) + : mObjectId(objectId) { } MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const @@ -11,8 +30,81 @@ MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const } bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration) { - std::cout << "AiActivate completed.\n"; - return true; + 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()->mCell; + + MWWorld::Ptr player = world->getPlayerPtr(); + if(cell->mData.mX != player.getCell()->mCell->mData.mX) + { + int sideX = sgn(cell->mData.mX - player.getCell()->mCell->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()->mCell->mData.mY) + { + int sideY = sgn(cell->mData.mY - player.getCell()->mCell->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->getPtr(mObjectId,false); + 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; + + return false; } int MWMechanics::AiActivate::getTypeId() const diff --git a/apps/openmw/mwmechanics/aiactivate.hpp b/apps/openmw/mwmechanics/aiactivate.hpp index f922e238c2..7c94c25896 100644 --- a/apps/openmw/mwmechanics/aiactivate.hpp +++ b/apps/openmw/mwmechanics/aiactivate.hpp @@ -4,6 +4,8 @@ #include "aipackage.hpp" #include +#include "pathfinding.hpp" + namespace MWMechanics { @@ -18,6 +20,10 @@ namespace MWMechanics private: std::string mObjectId; + + PathFinder mPathFinder; + int mCellX; + int mCellY; }; } #endif // GAME_MWMECHANICS_AIACTIVATE_H diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 8a0b2ebd0f..03052f327b 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -21,8 +21,8 @@ namespace MWMechanics { AiTravel::AiTravel(float x, float y, float z) : mX(x),mY(y),mZ(z),mPathFinder() - , cellX(std::numeric_limits::max()) - , cellY(std::numeric_limits::max()) + , mCellX(std::numeric_limits::max()) + , mCellY(std::numeric_limits::max()) { } @@ -62,11 +62,11 @@ namespace MWMechanics } } - bool cellChange = cell->mData.mX != cellX || cell->mData.mY != cellY; + bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; if(!mPathFinder.isPathConstructed() || cellChange) { - cellX = cell->mData.mX; - cellY = cell->mData.mY; + mCellX = cell->mData.mX; + mCellY = cell->mData.mY; ESM::Pathgrid::Point dest; dest.mX = mX; diff --git a/apps/openmw/mwmechanics/aitravel.hpp b/apps/openmw/mwmechanics/aitravel.hpp index b479dfd431..72f3e02983 100644 --- a/apps/openmw/mwmechanics/aitravel.hpp +++ b/apps/openmw/mwmechanics/aitravel.hpp @@ -23,8 +23,8 @@ namespace MWMechanics float mY; float mZ; - int cellX; - int cellY; + int mCellX; + int mCellY; PathFinder mPathFinder; };