diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 6a49f2f5e..91c77702e 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -240,16 +240,20 @@ namespace MWMechanics //target is at far distance: build path to target OR follow target (if previously actor had reached it once) mFollowTarget = false; - buildNewPath(actor); + buildNewPath(actor); //not guaranteed, check before use //delete visited path node mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]); - //try shortcut - if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget)) - mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees(); - else - mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + //if buildNewPath() failed leave mTargetAngle unchanged + if(!mPathFinder.getPath().empty()) + { + //try shortcut + if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget)) + mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees(); + else + mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]); + } mRotate = true; mMovement.mPosition[1] = 1; @@ -300,9 +304,13 @@ namespace MWMechanics dest.mZ = mTarget.getRefData().getPosition().pos[2]; Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ); - ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); - Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ); - float dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length()); + float dist = -1; //hack to indicate first time, to construct a new path + if(!mPathFinder.getPath().empty()) + { + ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); + Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ); + dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length()); + } float targetPosThreshold; bool isOutside = actor.getCell()->mCell->isExterior(); @@ -311,7 +319,7 @@ namespace MWMechanics else targetPosThreshold = 100; - if(dist > targetPosThreshold) + if((dist < 0) || (dist > targetPosThreshold)) { //construct new path only if target has moved away more than on ESM::Position pos = actor.getRefData().getPosition(); @@ -332,8 +340,11 @@ namespace MWMechanics //maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path, //not the actual path length. Here we should know if the new path is actually more effective. //if(pathFinder2.getPathSize() < mPathFinder.getPathSize()) - newPathFinder.syncStart(mPathFinder.getPath()); - mPathFinder = newPathFinder; + if(!mPathFinder.getPath().empty()) + { + newPathFinder.syncStart(mPathFinder.getPath()); + mPathFinder = newPathFinder; + } } } } diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 4407363a6..5996eb079 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -391,6 +391,8 @@ namespace MWMechanics void PathFinder::syncStart(const std::list &path) { + if (path.size() < 2) + return; //nothing to pop std::list::const_iterator oldStart = path.begin(); std::list::iterator iter = ++mPath.begin();