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 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); 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()) if (pathlist.empty() || error || partial)
{
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
//the client seems to have issues with packets larger than this
if (pathlist.size() > 36)
{ {
EQApplicationPacket outapp(OP_FindPersonReply, 0); EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp); QueuePacket(&outapp);

View File

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

View File

@ -29,7 +29,7 @@ public:
IPathfinder() { } IPathfinder() { }
virtual ~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 glm::vec3 GetRandomLocation() = 0;
virtual void DebugCommand(Client *c, const Seperator *sep) = 0; virtual void DebugCommand(Client *c, const Seperator *sep) = 0;

View File

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

View File

@ -9,7 +9,7 @@ public:
PathfinderNavmesh(const std::string &path); PathfinderNavmesh(const std::string &path);
virtual ~PathfinderNavmesh(); 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 glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep); virtual void DebugCommand(Client *c, const Seperator *sep);

View File

@ -1,7 +1,9 @@
#include "pathfinder_null.h" #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; IPath ret;
ret.push_back(start); ret.push_back(start);
ret.push_back(end); ret.push_back(end);

View File

@ -8,7 +8,7 @@ public:
PathfinderNull() { } PathfinderNull() { }
virtual ~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 glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep) { } 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; 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)); 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) { if (result_start_n.size() == 0) {
error = true;
return IPath(); return IPath();
} }
std::vector<RTreeValue> result_end_n; 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)); 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) { if (result_end_n.size() == 0) {
error = true;
return IPath(); return IPath();
} }
@ -179,6 +183,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g
return Route; return Route;
} }
error = true;
IPath Route; IPath Route;
Route.push_front(start); Route.push_front(start);
Route.push_back(glm::vec3(nearest_start.first.get<0>(), nearest_start.first.get<1>(), nearest_start.first.get<2>())); 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) 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; std::vector<FindPerson_Point> points;
FindPerson_Point p; FindPerson_Point p;

View File

@ -11,7 +11,7 @@ public:
PathfinderWaypoint(const std::string &path); PathfinderWaypoint(const std::string &path);
virtual ~PathfinderWaypoint(); 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 glm::vec3 GetRandomLocation();
virtual void DebugCommand(Client *c, const Seperator *sep); 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()) { 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()); AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To; PathingDestination = To;
WaypointChanged = true; WaypointChanged = true;
NodeReached = false; NodeReached = false;
if (Route.empty()) { if (partial && Route.size() <= 2) {
return From; //We are stuck
Route.clear();
Teleport(To);
return To;
}
else if (error || Route.empty()) {
return To;
} }
else { else {
return (*Route.begin()).pos; 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; bool SameDestination = DistanceSquared(To, PathingDestination) < 100.0f;
if (!SameDestination) { if (!SameDestination) {
//We had a route but our target position moved too much //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()); AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To; PathingDestination = To;
WaypointChanged = true; WaypointChanged = true;
NodeReached = false; NodeReached = false;
if (Route.empty()) { if (partial && Route.size() <= 2) {
return From; Route.clear();
Teleport(To);
return To;
} else if (error || Route.empty()) {
return To;
} }
else { else {
return (*Route.begin()).pos; 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(); Route.pop_front();
if (Route.empty()) { 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()); AdjustRoute(Route, flymode, GetModelOffset());
PathingDestination = To; PathingDestination = To;
WaypointChanged = true; WaypointChanged = true;
if (Route.empty()) { if (partial && Route.size() <= 2) {
return From; //We are stuck
Route.clear();
Teleport(To);
return To;
}
else if (error || Route.empty()) {
return To;
} }
else { else {
return (*Route.begin()).pos; 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 (*Route.begin()).pos;
} }
} }
return To;
} }
void CullPoints(std::vector<FindPerson_Point> &points) { void CullPoints(std::vector<FindPerson_Point> &points) {