Prevent NPC from chosing farther pathgrid node

fix/skillcap
Andrei Kortunov 7 years ago
parent 9e6cba09a6
commit 75835c8326

@ -297,7 +297,7 @@ namespace MWBase
///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// doPhysics.
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0;
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, bool ignoreDoors=false) = 0;
///< cast a Ray and return true if there is an object in the ray path.
virtual bool toggleCollisionMode() = 0;

@ -231,6 +231,28 @@ namespace MWMechanics
{
mPath = pathgridGraph.aStarSearch(startNode, endNode.first);
// If nearest path node is in opposite direction from second, remove it from path.
// Especially useful for wandering actors, if the nearest node is blocked for some reason.
if (mPath.size() > 1)
{
ESM::Pathgrid::Point secondNode = *(++mPath.begin());
osg::Vec3f firstNodeVec3f = MakeOsgVec3(mPathgrid->mPoints[startNode]);
osg::Vec3f secondNodeVec3f = MakeOsgVec3(secondNode);
osg::Vec3f toSecondNodeVec3f = secondNodeVec3f - firstNodeVec3f;
osg::Vec3f toStartPointVec3f = startPointInLocalCoords - firstNodeVec3f;
if (toSecondNodeVec3f * toStartPointVec3f > 0)
{
ESM::Pathgrid::Point temp(secondNode);
converter.toWorld(temp);
// Add Z offset since path node can overlap with other objects.
// Also ignore doors in raytesting.
bool isPathClear = !MWBase::Environment::get().getWorld()->castRay(
startPoint.mX, startPoint.mY, startPoint.mZ+16, temp.mX, temp.mY, temp.mZ+16, true);
if (isPathClear)
mPath.pop_front();
}
}
// convert supplied path to world coordinates
for (std::list<ESM::Pathgrid::Point>::iterator iter(mPath.begin()); iter != mPath.end(); ++iter)
{

@ -1471,12 +1471,16 @@ namespace MWWorld
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
}
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2, bool ignoreDoors)
{
osg::Vec3f a(x1,y1,z1);
osg::Vec3f b(x2,y2,z2);
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), MWPhysics::CollisionType_World|MWPhysics::CollisionType_Door);
int mask = MWPhysics::CollisionType_World;
if (!ignoreDoors)
mask |= MWPhysics::CollisionType_Door;
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(a, b, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), mask);
return result.mHit;
}

@ -400,7 +400,7 @@ namespace MWWorld
///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// doPhysics.
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) override;
bool castRay (float x1, float y1, float z1, float x2, float y2, float z2, bool ignoreDoors=false) override;
///< cast a Ray and return true if there is an object in the ray path.
bool toggleCollisionMode() override;

Loading…
Cancel
Save