From 73a967174267891896e03d9ddc3c369bc3e81961 Mon Sep 17 00:00:00 2001 From: Torben Carrington Date: Wed, 29 May 2013 20:05:17 -0700 Subject: [PATCH] Pathfinding Overhaul - Changed the name of checkIfNextPointReached to a more intuitive name considering what it does (checkPathCompleted) and fixed a minor bug in it, modified buildPath() to take one final parameter, a bool which dictates whether or not to always use pathfinding (like AIWander should be doing) or to allow for "shortcuts", modified all ai packages to work with these two changes. --- apps/openmw/mwmechanics/aiescort.cpp | 4 ++-- apps/openmw/mwmechanics/aitravel.cpp | 4 ++-- apps/openmw/mwmechanics/aiwander.cpp | 4 ++-- apps/openmw/mwmechanics/pathfinding.cpp | 24 ++++++++++++++++-------- apps/openmw/mwmechanics/pathfinding.hpp | 4 ++-- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index b873844a24..755994622f 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -129,10 +129,10 @@ bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor) start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start,dest,pathgrid,xCell,yCell); + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, 1); } - if(mPathFinder.checkIfNextPointReached(pos.pos[0],pos.pos[1],pos.pos[2])) + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) { MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; return true; diff --git a/apps/openmw/mwmechanics/aitravel.cpp b/apps/openmw/mwmechanics/aitravel.cpp index 99df68a916..4307ed2849 100644 --- a/apps/openmw/mwmechanics/aitravel.cpp +++ b/apps/openmw/mwmechanics/aitravel.cpp @@ -78,10 +78,10 @@ bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor) start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start,dest,pathgrid,xCell,yCell); + mPathFinder.buildPath(start, dest, pathgrid, xCell, yCell, 1); } - if(mPathFinder.checkIfNextPointReached(pos.pos[0],pos.pos[1],pos.pos[2])) + if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) { MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0; return true; diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 310cc3274c..b7d391a9f3 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -235,7 +235,7 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor) start.mY = pos.pos[1]; start.mZ = pos.pos[2]; - mPathFinder.buildPath(start,dest,mPathgrid,mXCell,mYCell); + mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, 0); mWalking = true; } } @@ -254,7 +254,7 @@ bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor) actorPos[1] = actorPos[1] - mYCell; float distance = actorPos.squaredDistance(destNodePos); - if(distance < 1200 || mPathFinder.checkIfNextPointReached(pos.pos[0],pos.pos[1],pos.pos[2])) + if(distance < 1200 || mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) { stopWalking(actor); mMoveNow = false; diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 3c15b050e9..78be90804c 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -148,11 +148,16 @@ namespace MWMechanics } void PathFinder::buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint, - const ESM::Pathgrid* pathGrid, float xCell, float yCell) + const ESM::Pathgrid* pathGrid, float xCell, float yCell, bool allowShortcuts) { + if(allowShortcuts) + { + if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, endPoint.mX, endPoint.mY, + endPoint.mZ)) + allowShortcuts = false; + } //first check if there is an obstacle - if(MWBase::Environment::get().getWorld()->castRay(startPoint.mX, startPoint.mY, startPoint.mZ, - endPoint.mX, endPoint.mY, endPoint.mZ) ) + if(!allowShortcuts) { int startNode = getClosestPoint(pathGrid, startPoint.mX - xCell, startPoint.mY - yCell,startPoint.mZ); int endNode = getClosestPoint(pathGrid, endPoint.mX - xCell, endPoint.mY - yCell, endPoint.mZ); @@ -175,14 +180,14 @@ namespace MWMechanics return 0; ESM::Pathgrid::Point nextPoint = *mPath.begin(); - float dX = nextPoint.mX - x; - float dY = nextPoint.mY - y; - float h = sqrt(dX * dX + dY * dY); + float directionX = nextPoint.mX - x; + float directionY = nextPoint.mY - y; + float directionResult = sqrt(directionX * directionX + directionY * directionY); - return Ogre::Radian(acos(dY / h) * sgn(asin(dX / h))).valueDegrees(); + return Ogre::Radian(acos(directionY / directionResult) * sgn(asin(directionX / directionResult))).valueDegrees(); } - bool PathFinder::checkIfNextPointReached(float x, float y, float z) + bool PathFinder::checkPathCompleted(float x, float y, float z) { if(mPath.empty()) return true; @@ -192,7 +197,10 @@ namespace MWMechanics { mPath.pop_front(); if(mPath.empty()) + { + mIsPathConstructed = false; return true; + } } return false; diff --git a/apps/openmw/mwmechanics/pathfinding.hpp b/apps/openmw/mwmechanics/pathfinding.hpp index fcd609c8e4..1727c650f3 100644 --- a/apps/openmw/mwmechanics/pathfinding.hpp +++ b/apps/openmw/mwmechanics/pathfinding.hpp @@ -13,9 +13,9 @@ namespace MWMechanics void clearPath(); void buildPath(ESM::Pathgrid::Point startPoint, ESM::Pathgrid::Point endPoint, - const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0); + const ESM::Pathgrid* pathGrid, float xCell = 0, float yCell = 0, bool allowShortcuts = 1); - bool checkIfNextPointReached(float x, float y, float z); + bool checkPathCompleted(float x, float y, float z); ///< \Returns true if the last point of the path has been reached. float getZAngleToNext(float x, float y);