Rule for setting max navmesh nodes, default set higher than current to improve accuracy

This commit is contained in:
KimLS 2020-02-02 20:19:37 -08:00
parent c2300d514c
commit d65a97e556
3 changed files with 57 additions and 62 deletions

View File

@ -293,6 +293,7 @@ RULE_BOOL(Pathing, Find, true, "Enable pathing for FindPerson requests from the
RULE_BOOL(Pathing, Fear, true, "Enable pathing for fear") RULE_BOOL(Pathing, Fear, true, "Enable pathing for fear")
RULE_REAL(Pathing, NavmeshStepSize, 100.0f, "") RULE_REAL(Pathing, NavmeshStepSize, 100.0f, "")
RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "") RULE_REAL(Pathing, ShortMovementUpdateRange, 130.0f, "")
RULE_INT(Pathing, MaxNavmeshNodes, 4092)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Watermap) RULE_CATEGORY(Watermap)

View File

@ -1300,7 +1300,9 @@ void MobMovementManager::PushEvadeCombat(MobMovementEntry &mob_movement_entry)
*/ */
void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode) void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode)
{ {
auto sb = who->GetStuckBehavior(); LogDebug("Handle stuck behavior for {0} at ({1}, {2}, {3}) with movement_mode {4}", who->GetName(), x, y, z, mob_movement_mode);
auto sb = who->GetStuckBehavior();
MobStuckBehavior behavior = RunToTarget; MobStuckBehavior behavior = RunToTarget;
if (sb >= 0 && sb < MaxStuckBehavior) { if (sb >= 0 && sb < MaxStuckBehavior) {
@ -1308,7 +1310,7 @@ void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z
} }
auto eiter = _impl->Entries.find(who); auto eiter = _impl->Entries.find(who);
auto &ent = (*eiter); auto &ent = (*eiter);
switch (sb) { switch (sb) {
case RunToTarget: case RunToTarget:
@ -1323,8 +1325,7 @@ void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z
PushStopMoving(ent.second); PushStopMoving(ent.second);
break; break;
case EvadeCombat: case EvadeCombat:
//PushEvadeCombat(ent.second); PushEvadeCombat(ent.second);
PushStopMoving(ent.second);
break; break;
} }
} }

View File

@ -12,8 +12,6 @@
extern Zone *zone; extern Zone *zone;
const int MaxNavmeshNodes = 1024;
struct PathfinderNavmesh::Implementation struct PathfinderNavmesh::Implementation
{ {
dtNavMesh *nav_mesh; dtNavMesh *nav_mesh;
@ -36,19 +34,19 @@ PathfinderNavmesh::~PathfinderNavmesh()
IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags) IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags)
{ {
partial = false; partial = false;
if (!m_impl->nav_mesh) { if (!m_impl->nav_mesh) {
return IPath(); return IPath();
} }
if (!m_impl->query) { if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery(); m_impl->query = dtAllocNavMeshQuery();
} }
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes); m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes));
glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 current_location(start.x, start.z, start.y);
glm::vec3 dest_location(end.x, end.z, end.y); glm::vec3 dest_location(end.x, end.z, end.y);
dtQueryFilter filter; dtQueryFilter filter;
filter.setIncludeFlags(flags); filter.setIncludeFlags(flags);
filter.setAreaCost(0, 1.0f); //Normal filter.setAreaCost(0, 1.0f); //Normal
@ -61,48 +59,48 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
filter.setAreaCost(8, 1.0f); //General Area filter.setAreaCost(8, 1.0f); //General Area
filter.setAreaCost(9, 0.1f); //Portal filter.setAreaCost(9, 0.1f); //Portal
filter.setAreaCost(10, 0.1f); //Prefer filter.setAreaCost(10, 0.1f); //Prefer
dtPolyRef start_ref; dtPolyRef start_ref;
dtPolyRef end_ref; dtPolyRef end_ref;
glm::vec3 ext(5.0f, 100.0f, 5.0f); glm::vec3 ext(5.0f, 100.0f, 5.0f);
m_impl->query->findNearestPoly(&current_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&current_location[0], &ext[0], &filter, &start_ref, 0);
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) {
return IPath(); return IPath();
} }
int npoly = 0; int npoly = 0;
dtPolyRef path[1024] = { 0 }; dtPolyRef path[1024] = { 0 };
auto status = m_impl->query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &filter, path, &npoly, 1024); auto status = m_impl->query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &filter, path, &npoly, 1024);
if (npoly) { if (npoly) {
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; partial = true;
auto dist = DistanceSquared(epos, current_location); auto dist = DistanceSquared(epos, current_location);
if (dist < 10000.0f) { if (dist < 10000.0f) {
stuck = true; stuck = true;
} }
} }
float straight_path[2048 * 3]; float straight_path[2048 * 3];
unsigned char straight_path_flags[2048]; unsigned char straight_path_flags[2048];
int n_straight_polys; int n_straight_polys;
dtPolyRef straight_path_polys[2048]; dtPolyRef straight_path_polys[2048];
status = m_impl->query->findStraightPath(&current_location[0], &epos[0], path, npoly, status = m_impl->query->findStraightPath(&current_location[0], &epos[0], path, npoly,
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 (dtStatusFailed(status)) { if (dtStatusFailed(status)) {
return IPath(); return IPath();
} }
if (n_straight_polys) { if (n_straight_polys) {
IPath Route; IPath Route;
for (int i = 0; i < n_straight_polys; ++i) for (int i = 0; i < n_straight_polys; ++i)
@ -111,9 +109,9 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
node.x = straight_path[i * 3]; node.x = straight_path[i * 3];
node.z = straight_path[i * 3 + 1]; node.z = straight_path[i * 3 + 1];
node.y = straight_path[i * 3 + 2]; node.y = straight_path[i * 3 + 2];
Route.push_back(node); Route.push_back(node);
unsigned short flag = 0; unsigned short flag = 0;
if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) {
if (flag & 512) { if (flag & 512) {
@ -121,11 +119,11 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
} }
} }
} }
return Route; return Route;
} }
} }
IPath Route; IPath Route;
Route.push_back(end); Route.push_back(end);
return Route; return Route;
@ -134,19 +132,19 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts) IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts)
{ {
partial = false; partial = false;
if (!m_impl->nav_mesh) { if (!m_impl->nav_mesh) {
return IPath(); return IPath();
} }
if (!m_impl->query) { if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery(); m_impl->query = dtAllocNavMeshQuery();
} }
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes); m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes));
glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 current_location(start.x, start.z, start.y);
glm::vec3 dest_location(end.x, end.z, end.y); glm::vec3 dest_location(end.x, end.z, end.y);
dtQueryFilter filter; dtQueryFilter filter;
filter.setIncludeFlags(opts.flags); filter.setIncludeFlags(opts.flags);
filter.setAreaCost(0, opts.flag_cost[0]); //Normal filter.setAreaCost(0, opts.flag_cost[0]); //Normal
@ -159,83 +157,78 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm
filter.setAreaCost(8, opts.flag_cost[7]); //General Area filter.setAreaCost(8, opts.flag_cost[7]); //General Area
filter.setAreaCost(9, opts.flag_cost[8]); //Portal filter.setAreaCost(9, opts.flag_cost[8]); //Portal
filter.setAreaCost(10, opts.flag_cost[9]); //Prefer filter.setAreaCost(10, opts.flag_cost[9]); //Prefer
static const int max_polys = 256; static const int max_polys = 256;
dtPolyRef start_ref; dtPolyRef start_ref;
dtPolyRef end_ref; dtPolyRef end_ref;
glm::vec3 ext(10.0f, 200.0f, 10.0f); glm::vec3 ext(10.0f, 200.0f, 10.0f);
m_impl->query->findNearestPoly(&current_location[0], &ext[0], &filter, &start_ref, 0); m_impl->query->findNearestPoly(&current_location[0], &ext[0], &filter, &start_ref, 0);
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) {
return IPath(); return IPath();
} }
int npoly = 0; int npoly = 0;
dtPolyRef path[max_polys] = { 0 }; dtPolyRef path[max_polys] = { 0 };
m_impl->query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &filter, path, &npoly, max_polys); auto status = m_impl->query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &filter, path, &npoly, max_polys);
if (npoly) { if (npoly) {
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; partial = true;
auto dist = DistanceSquared(epos, current_location);
if (dist < 10000.0f) {
stuck = true;
}
} }
int n_straight_polys; int n_straight_polys;
glm::vec3 straight_path[max_polys]; glm::vec3 straight_path[max_polys];
unsigned char straight_path_flags[max_polys]; unsigned char straight_path_flags[max_polys];
dtPolyRef straight_path_polys[max_polys]; dtPolyRef straight_path_polys[max_polys];
auto status = m_impl->query->findStraightPath(&current_location[0], &epos[0], path, npoly, auto status = m_impl->query->findStraightPath(&current_location[0], &epos[0], path, npoly,
(float*)&straight_path[0], straight_path_flags, (float*)&straight_path[0], straight_path_flags,
straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS); straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS);
if (dtStatusFailed(status)) { if (dtStatusFailed(status)) {
return IPath(); return IPath();
} }
if (n_straight_polys) { if (n_straight_polys) {
if (opts.smooth_path) { if (opts.smooth_path) {
IPath Route; IPath Route;
//Add the first point //Add the first point
{ {
auto &flag = straight_path_flags[0]; auto &flag = straight_path_flags[0];
if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) {
auto &p = straight_path[0]; auto &p = straight_path[0];
Route.push_back(glm::vec3(p.x, p.z, p.y)); Route.push_back(glm::vec3(p.x, p.z, p.y));
} }
else { else {
auto &p = straight_path[0]; auto &p = straight_path[0];
float h = 0.0f; float h = 0.0f;
if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, p, &h))) { if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, p, &h))) {
p.y = h + opts.offset; p.y = h + opts.offset;
} }
Route.push_back(glm::vec3(p.x, p.z, p.y)); Route.push_back(glm::vec3(p.x, p.z, p.y));
} }
} }
for (int i = 0; i < n_straight_polys - 1; ++i) for (int i = 0; i < n_straight_polys - 1; ++i)
{ {
auto &flag = straight_path_flags[i]; auto &flag = straight_path_flags[i];
if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) { if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) {
auto &poly = straight_path_polys[i]; auto &poly = straight_path_polys[i];
auto &p2 = straight_path[i + 1]; auto &p2 = straight_path[i + 1];
glm::vec3 node(p2.x, p2.z, p2.y); glm::vec3 node(p2.x, p2.z, p2.y);
Route.push_back(node); Route.push_back(node);
unsigned short pflag = 0; unsigned short pflag = 0;
if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &pflag))) { if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &pflag))) {
if (pflag & 512) { if (pflag & 512) {
@ -250,12 +243,12 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm
auto dir = glm::normalize(p2 - p1); auto dir = glm::normalize(p2 - p1);
float total = 0.0f; float total = 0.0f;
glm::vec3 previous_pt = p1; glm::vec3 previous_pt = p1;
while (total < dist) { while (total < dist) {
glm::vec3 current_pt; glm::vec3 current_pt;
float dist_to_move = opts.step_size; float dist_to_move = opts.step_size;
float ff = opts.step_size / 2.0f; float ff = opts.step_size / 2.0f;
if (total + dist_to_move + ff >= dist) { if (total + dist_to_move + ff >= dist) {
current_pt = p2; current_pt = p2;
total = dist; total = dist;
@ -264,18 +257,18 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm
total += dist_to_move; total += dist_to_move;
current_pt = p1 + dir * total; current_pt = p1 + dir * total;
} }
float h = 0.0f; float h = 0.0f;
if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, current_pt, &h))) { if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, current_pt, &h))) {
current_pt.y = h + opts.offset; current_pt.y = h + opts.offset;
} }
Route.push_back(glm::vec3(current_pt.x, current_pt.z, current_pt.y)); Route.push_back(glm::vec3(current_pt.x, current_pt.z, current_pt.y));
previous_pt = current_pt; previous_pt = current_pt;
} }
} }
} }
return Route; return Route;
} }
else { else {
@ -285,7 +278,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm
auto &current = straight_path[i]; auto &current = straight_path[i];
glm::vec3 node(current.x, current.z, current.y); glm::vec3 node(current.x, current.z, current.y);
Route.push_back(node); Route.push_back(node);
unsigned short flag = 0; unsigned short flag = 0;
if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) { if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) {
if (flag & 512) { if (flag & 512) {
@ -293,7 +286,7 @@ IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm
} }
} }
} }
return Route; return Route;
} }
} }
@ -313,7 +306,7 @@ glm::vec3 PathfinderNavmesh::GetRandomLocation(const glm::vec3 &start)
if (!m_impl->query) { if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery(); m_impl->query = dtAllocNavMeshQuery();
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes); m_impl->query->init(m_impl->nav_mesh, RuleI(Pathing, MaxNavmeshNodes));
} }
dtQueryFilter filter; dtQueryFilter filter;