diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 6a1ab68d86..19c3fa2f3a 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -49,8 +49,6 @@ namespace MWMechanics //MWWorld::Class::get(actor).getCreatureStats(actor).setAttackingOrSpell(true); } ESM::Position pos = actor.getRefData().getPosition(); - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); float xCell = 0; float yCell = 0; @@ -74,20 +72,19 @@ namespace MWMechanics mTimer2 = mTimer2 + duration; if(!mPathFinder.isPathConstructed()) - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); else { if(mTimer2 > 0.25) { mTimer2 = 0; - mPathFinder2.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder2.buildPath(start, dest, actor.getCell(), true); ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); if(mPathFinder2.getPathSize() < mPathFinder.getPathSize() || (dest.mX - lastPt.mX)*(dest.mX - lastPt.mX)+(dest.mY - lastPt.mY)*(dest.mY - lastPt.mY)+(dest.mZ - lastPt.mZ)*(dest.mZ - lastPt.mZ) > 200*200) mPathFinder = mPathFinder2; } } - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 35f9f19932..0d44dd6fce 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -85,8 +85,6 @@ namespace MWMechanics MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); ESM::Position pos = actor.getRefData().getPosition(); bool cellChange = actor.getCell()->mCell->mData.mX != cellX || actor.getCell()->mCell->mData.mY != cellY; - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX) { @@ -136,7 +134,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 399504ff1d..a711ebe7cd 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -81,10 +81,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) ESM::Pathgrid::Point start; start.mX = pos.pos[0]; start.mY = pos.pos[1]; - start.mZ = pos.pos[2]; - - const ESM::Pathgrid *pathgrid = - MWBase::Environment::get().getWorld()->getStore().get().search(*actor.getCell()->mCell); + start.mZ = pos.pos[2]; float xCell = 0; float yCell = 0; @@ -94,7 +91,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) xCell = actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE; yCell = actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE; } - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } mStuckTimer = 0; mStuckPos = pos; diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 73b38dd130..24a61310b0 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -61,7 +61,6 @@ namespace MWMechanics } } - const ESM::Pathgrid *pathgrid = world->getStore().get().search(*cell); bool cellChange = cell->mData.mX != cellX || cell->mData.mY != cellY; if(!mPathFinder.isPathConstructed() || cellChange) { @@ -86,7 +85,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, true); + mPathFinder.buildPath(start, dest, actor.getCell(), true); } if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2])) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7df88c076b..353121a3ec 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -213,7 +213,7 @@ namespace MWMechanics start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, false); + mPathFinder.buildPath(start, dest, actor.getCell(), false); if(mPathFinder.isPathConstructed()) { diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index c8bc9b49cf..86019fe549 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -6,7 +6,6 @@ #include "OgreMath.h" #include -#include namespace { @@ -136,8 +135,8 @@ namespace namespace MWMechanics { PathFinder::PathFinder() + :mIsPathConstructed(false),mIsGraphConstructed(false) { - mIsPathConstructed = false; } void PathFinder::clearPath() @@ -147,10 +146,19 @@ namespace MWMechanics mIsPathConstructed = false; } + void PathFinder::buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell, float yCell) + { + mGraph = buildGraph(pathGrid, xCell, yCell); + mIsGraphConstructed = true; + } + void PathFinder::buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, - const ESM::Pathgrid *pathGrid, float xCell, float yCell, bool allowShortcuts) + const MWWorld::CellStore* cell, bool allowShortcuts) { mPath.clear(); + if(mCell != cell) mIsGraphConstructed = false; + mCell = cell; + if(allowShortcuts) { if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, @@ -160,13 +168,24 @@ namespace MWMechanics if(!allowShortcuts) { + const ESM::Pathgrid *pathGrid = + MWBase::Environment::get().getWorld()->getStore().get().search(*mCell->mCell); + float xCell = 0; + float yCell = 0; + + if (mCell->isExterior()) + { + xCell = mCell->mCell->mData.mX * ESM::Land::REAL_SIZE; + yCell = mCell->mCell->mData.mY * ESM::Land::REAL_SIZE; + } int startNode = getClosestPoint(pathGrid, startPoint.mX - xCell, startPoint.mY - yCell,startPoint.mZ); int endNode = getClosestPoint(pathGrid, endPoint.mX - xCell, endPoint.mY - yCell, endPoint.mZ); if(startNode != -1 && endNode != -1) { - PathGridGraph graph = buildGraph(pathGrid, xCell, yCell); - mPath = findPath(startNode, endNode, graph); + if(!mIsGraphConstructed) buildPathgridGraph(pathGrid, xCell, yCell); + + mPath = findPath(startNode, endNode, mGraph); if(!mPath.empty()) { diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index f9c2c5cc77..6870314910 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -3,6 +3,12 @@ #include #include +#include + +namespace MWWorld +{ + class CellStore; +} namespace MWMechanics { @@ -12,9 +18,11 @@ namespace MWMechanics PathFinder(); void clearPath(); + + void buildPathgridGraph(const ESM::Pathgrid* pathGrid,float xCell = 0, float yCell = 0); + void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, - const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0, - bool allowShortcuts = true); + const MWWorld::CellStore* cell, bool allowShortcuts = true); bool checkPathCompleted(float x, float y, float z); ///< \Returns true if the last point of the path has been reached. @@ -45,6 +53,13 @@ namespace MWMechanics private: std::list mPath; bool mIsPathConstructed; + + typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, + boost::property, boost::property > + PathGridGraph; + PathGridGraph mGraph; + bool mIsGraphConstructed; + const MWWorld::CellStore* mCell; }; }