Pathing stuck detection, and logic to go with it

This commit is contained in:
KimLS 2017-08-30 19:55:35 -07:00
parent 0ba9b3fedc
commit c52ff4249a
10 changed files with 81 additions and 41 deletions

View File

@ -5737,17 +5737,11 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION);
auto pathlist = zone->pathing->FindRoute(Start, End);
bool partial = false;
bool error = false;
auto pathlist = zone->pathing->FindRoute(Start, End, partial, error);
if (pathlist.empty())
{
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
//the client seems to have issues with packets larger than this
if (pathlist.size() > 36)
if (pathlist.empty() || error || partial)
{
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);

View File

@ -445,7 +445,7 @@ Mob::Mob(const char* in_name,
AssistAggro = false;
npc_assist_cap = 0;
PathRecalcTimer.reset(new Timer(2000));
PathRecalcTimer.reset(new Timer(1500));
PathingLoopCount = 0;
}

View File

@ -29,7 +29,7 @@ public:
IPathfinder() { }
virtual ~IPathfinder() { }
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end) = 0;
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error) = 0;
virtual glm::vec3 GetRandomLocation() = 0;
virtual void DebugCommand(Client *c, const Seperator *sep) = 0;

View File

@ -12,6 +12,8 @@
extern Zone *zone;
const int MaxNavmeshNodes = 4092;
struct PathfinderNavmesh::Implementation
{
dtNavMesh *nav_mesh;
@ -31,9 +33,13 @@ PathfinderNavmesh::~PathfinderNavmesh()
Clear();
}
IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end)
IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error)
{
partial = false;
error = false;
if (!m_impl->nav_mesh) {
error = true;
IPath Route;
Route.push_back(end);
return Route;
@ -41,7 +47,7 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery();
m_impl->query->init(m_impl->nav_mesh, 32768);
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
}
glm::vec3 current_location(start.x, start.z, start.y);
@ -68,6 +74,7 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0);
if (!start_ref || !end_ref) {
error = true;
IPath Route;
Route.push_back(end);
return Route;
@ -81,6 +88,7 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
glm::vec3 epos = dest_location;
if (path[npoly - 1] != end_ref) {
m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
partial = true;
}
float straight_path[2048 * 3];
@ -93,7 +101,8 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
straight_path, straight_path_flags,
straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS);
if (status & DT_OUT_OF_NODES) {
if (dtStatusFailed(status)) {
error = true;
IPath Route;
Route.push_back(end);
return Route;
@ -135,7 +144,7 @@ glm::vec3 PathfinderNavmesh::GetRandomLocation()
if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery();
m_impl->query->init(m_impl->nav_mesh, 32768);
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
}
dtQueryFilter filter;
@ -282,9 +291,12 @@ void PathfinderNavmesh::Load(const std::string &path)
void PathfinderNavmesh::ShowPath(Client * c, const glm::vec3 &start, const glm::vec3 &end)
{
auto path = FindRoute(start, end);
bool partial = false;
bool error = false;
auto path = FindRoute(start, end, partial, error);
std::vector<FindPerson_Point> points;
if (!partial && !error) {
FindPerson_Point p;
for (auto &node : path)
{
@ -296,6 +308,7 @@ void PathfinderNavmesh::ShowPath(Client * c, const glm::vec3 & start, const glm:
points.push_back(p);
}
}
}
c->SendPathPacket(points);
}

View File

@ -9,7 +9,7 @@ public:
PathfinderNavmesh(const std::string &path);
virtual ~PathfinderNavmesh();
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end);
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error);
virtual glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep);

View File

@ -1,7 +1,9 @@
#include "pathfinder_null.h"
IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end)
IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error)
{
error = false;
partial = false;
IPath ret;
ret.push_back(start);
ret.push_back(end);

View File

@ -8,7 +8,7 @@ public:
PathfinderNull() { }
virtual ~PathfinderNull() { }
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end);
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error);
virtual glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep) { }
};

View File

@ -114,17 +114,21 @@ PathfinderWaypoint::~PathfinderWaypoint()
{
}
IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const glm::vec3 &end)
IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error)
{
partial = false;
error = false;
std::vector<RTreeValue> result_start_n;
m_impl->Tree.query(boost::geometry::index::nearest(Point(start.x, start.y, start.z), 1), std::back_inserter(result_start_n));
if (result_start_n.size() == 0) {
error = true;
return IPath();
}
std::vector<RTreeValue> result_end_n;
m_impl->Tree.query(boost::geometry::index::nearest(Point(end.x, end.y, end.z), 1), std::back_inserter(result_end_n));
if (result_end_n.size() == 0) {
error = true;
return IPath();
}
@ -179,6 +183,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g
return Route;
}
error = true;
IPath Route;
Route.push_front(start);
Route.push_back(glm::vec3(nearest_start.first.get<0>(), nearest_start.first.get<1>(), nearest_start.first.get<2>()));
@ -395,7 +400,9 @@ void PathfinderWaypoint::ShowNodes()
void PathfinderWaypoint::ShowPath(Client *c, const glm::vec3 &start, const glm::vec3 &end)
{
auto path = FindRoute(start, end);
bool partial = false;
bool error = false;
auto path = FindRoute(start, end, partial, error);
std::vector<FindPerson_Point> points;
FindPerson_Point p;

View File

@ -11,7 +11,7 @@ public:
PathfinderWaypoint(const std::string &path);
virtual ~PathfinderWaypoint();
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end);
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &error);
virtual glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep);

View File

@ -39,14 +39,22 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
}
if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
bool partial = false;
bool error = false;
Route = zone->pathing->FindRoute(From, To, partial, error);
AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To;
WaypointChanged = true;
NodeReached = false;
if (Route.empty()) {
return From;
if (partial && Route.size() <= 2) {
//We are stuck
Route.clear();
Teleport(To);
return To;
}
else if (error || Route.empty()) {
return To;
}
else {
return (*Route.begin()).pos;
@ -57,15 +65,21 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
bool SameDestination = DistanceSquared(To, PathingDestination) < 100.0f;
if (!SameDestination) {
//We had a route but our target position moved too much
Route = zone->pathing->FindRoute(From, To);
bool partial = false;
bool error = false;
Route = zone->pathing->FindRoute(From, To, partial, error);
AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To;
WaypointChanged = true;
NodeReached = false;
if (Route.empty()) {
return From;
if (partial && Route.size() <= 2) {
Route.clear();
Teleport(To);
return To;
} else if (error || Route.empty()) {
return To;
}
else {
return (*Route.begin()).pos;
@ -118,13 +132,21 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
Route.pop_front();
if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
bool partial = false;
bool error = false;
Route = zone->pathing->FindRoute(From, To, partial, error);
AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To;
WaypointChanged = true;
if (Route.empty()) {
return From;
if (partial && Route.size() <= 2) {
//We are stuck
Route.clear();
Teleport(To);
return To;
}
else if (error || Route.empty()) {
return To;
}
else {
return (*Route.begin()).pos;
@ -161,6 +183,8 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
return (*Route.begin()).pos;
}
}
return To;
}
void CullPoints(std::vector<FindPerson_Point> &points) {