mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-11 07:38:36 +00:00
Pathing is essentially fully functional now, still could use improvements here and there
This commit is contained in:
+102
-32
@@ -1,13 +1,34 @@
|
||||
#include "pathfind.h"
|
||||
#include "random.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
|
||||
const uint32_t nav_mesh_file_version = 1;
|
||||
const float max_dest_drift = 10.0f;
|
||||
const float at_waypoint_eps = 1.0f;
|
||||
EQEmu::Random path_rng;
|
||||
|
||||
float vec_dist(const glm::vec3 &a, const glm::vec3 &b) {
|
||||
float dist_x = a.x - b.x;
|
||||
float dist_y = a.y - b.y;
|
||||
float dist_z = a.z - b.z;
|
||||
return sqrt((dist_x * dist_x) + (dist_y * dist_y) + (dist_z * dist_z));
|
||||
}
|
||||
|
||||
PathfindingManager::PathfindingManager()
|
||||
{
|
||||
m_nav_mesh = nullptr;
|
||||
m_nav_query = nullptr;
|
||||
m_filter.setIncludeFlags(NavigationPolyFlagAll);
|
||||
m_filter.setAreaCost(NavigationAreaFlagNormal, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagWater, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagLava, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagPvP, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagSlime, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagIce, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagVWater, 2.5f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagGeneralArea, 1.0f);
|
||||
m_filter.setAreaCost(NavigationAreaFlagPortal, 1.0f);
|
||||
}
|
||||
|
||||
PathfindingManager::~PathfindingManager()
|
||||
@@ -17,6 +38,8 @@ PathfindingManager::~PathfindingManager()
|
||||
|
||||
void PathfindingManager::Load(const std::string &zone_name)
|
||||
{
|
||||
Clear();
|
||||
|
||||
std::string filename = MAP_DIR + std::string("/") + zone_name + ".nav";
|
||||
FILE *f = fopen(filename.c_str(), "rb");
|
||||
if (f) {
|
||||
@@ -109,6 +132,11 @@ void PathfindingManager::Clear()
|
||||
dtFreeNavMesh(m_nav_mesh);
|
||||
m_nav_mesh = nullptr;
|
||||
}
|
||||
|
||||
if (m_nav_query) {
|
||||
dtFreeNavMeshQuery(m_nav_query);
|
||||
m_nav_query = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const glm::vec3 &dest_loc)
|
||||
@@ -117,8 +145,10 @@ PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const g
|
||||
glm::vec3 dest_location(dest_loc.x, dest_loc.z, dest_loc.y);
|
||||
|
||||
PathfindingRoute ret;
|
||||
ret.m_dest = dest_location;
|
||||
|
||||
ret.m_dest = dest_loc;
|
||||
ret.m_current_node = 0;
|
||||
ret.m_active = true;
|
||||
|
||||
if (!m_nav_mesh) {
|
||||
PathfindingNode src;
|
||||
@@ -134,30 +164,19 @@ PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const g
|
||||
return ret;
|
||||
}
|
||||
|
||||
glm::vec3 ext(5.0f, 5.0f, 5.0f);
|
||||
dtQueryFilter filter;
|
||||
filter.setIncludeFlags(NavigationPolyFlagAll);
|
||||
filter.setAreaCost(NavigationAreaFlagNormal, 1.0f);
|
||||
filter.setAreaCost(NavigationAreaFlagWater, 2.5f);
|
||||
filter.setAreaCost(NavigationAreaFlagLava, 2.5f);
|
||||
filter.setAreaCost(NavigationAreaFlagPvP, 1.0f);
|
||||
filter.setAreaCost(NavigationAreaFlagSlime, 1.0f);
|
||||
filter.setAreaCost(NavigationAreaFlagIce, 1.0f);
|
||||
filter.setAreaCost(NavigationAreaFlagVWater, 2.5f);
|
||||
filter.setAreaCost(NavigationAreaFlagGeneralArea, 1.0f);
|
||||
filter.setAreaCost(NavigationAreaFlagPortal, 1.0f);
|
||||
if (!m_nav_query) {
|
||||
m_nav_query = dtAllocNavMeshQuery();
|
||||
m_nav_query->init(m_nav_mesh, 4092);
|
||||
}
|
||||
|
||||
dtNavMeshQuery *query = dtAllocNavMeshQuery();
|
||||
query->init(m_nav_mesh, 4092);
|
||||
dtPolyRef start_ref;
|
||||
dtPolyRef end_ref;
|
||||
glm::vec3 ext(10.0f, 10.0f, 10.0f);
|
||||
|
||||
query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0);
|
||||
query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0);
|
||||
m_nav_query->findNearestPoly(¤t_location[0], &ext[0], &m_filter, &start_ref, 0);
|
||||
m_nav_query->findNearestPoly(&dest_location[0], &ext[0], &m_filter, &end_ref, 0);
|
||||
|
||||
if (!start_ref || !end_ref) {
|
||||
dtFreeNavMeshQuery(query);
|
||||
|
||||
PathfindingNode src;
|
||||
src.flag = NavigationPolyFlagNormal;
|
||||
src.position = current_location;
|
||||
@@ -173,23 +192,21 @@ PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const g
|
||||
|
||||
int npoly = 0;
|
||||
dtPolyRef path[256] = { 0 };
|
||||
query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, 256);
|
||||
m_nav_query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &m_filter, path, &npoly, 256);
|
||||
|
||||
if (npoly) {
|
||||
glm::vec3 epos = dest_location;
|
||||
if (path[npoly - 1] != end_ref)
|
||||
query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
|
||||
m_nav_query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
|
||||
|
||||
float straight_path[256 * 3];
|
||||
unsigned char straight_path_flags[256];
|
||||
int n_straight_polys;
|
||||
dtPolyRef straight_path_polys[256];
|
||||
query->findStraightPath(¤t_location[0], &epos[0], path, npoly,
|
||||
m_nav_query->findStraightPath(¤t_location[0], &epos[0], path, npoly,
|
||||
straight_path, straight_path_flags,
|
||||
straight_path_polys, &n_straight_polys, 256, DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||
|
||||
dtFreeNavMeshQuery(query);
|
||||
|
||||
if (n_straight_polys) {
|
||||
ret.m_nodes.reserve(n_straight_polys);
|
||||
for (int i = 0; i < n_straight_polys; ++i)
|
||||
@@ -222,17 +239,52 @@ PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const g
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PathfindingManager::GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos)
|
||||
{
|
||||
if(!m_nav_mesh)
|
||||
return false;
|
||||
|
||||
if (!m_nav_query) {
|
||||
m_nav_query = dtAllocNavMeshQuery();
|
||||
m_nav_query->init(m_nav_mesh, 4092);
|
||||
}
|
||||
|
||||
glm::vec3 ext(10.0f, 10.0f, 10.0f);
|
||||
dtPolyRef start_ref;
|
||||
m_nav_query->findNearestPoly(&start[0], &ext[0], &m_filter, &start_ref, 0);
|
||||
if (!start_ref) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dtPolyRef random_ref;
|
||||
glm::vec3 pt;
|
||||
|
||||
dtStatus status = m_nav_query->findRandomPointAroundCircle(start_ref, &start[0], radius,
|
||||
&m_filter, []() -> float { return (float)path_rng.Real(0.0, 1.0); }, &random_ref, &pt[0]);
|
||||
|
||||
if (dtStatusSucceed(status))
|
||||
{
|
||||
pos.x = pt.x;
|
||||
pos.z = pt.y;
|
||||
pos.y = pt.z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PathfindingRoute::PathfindingRoute()
|
||||
{
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
PathfindingRoute::~PathfindingRoute()
|
||||
{
|
||||
}
|
||||
|
||||
bool PathfindingRoute::Valid(const glm::vec3 &dest)
|
||||
bool PathfindingRoute::DestinationValid(const glm::vec3 &dest)
|
||||
{
|
||||
auto dist = (dest - m_dest).length();
|
||||
auto dist = vec_dist(dest, m_dest);
|
||||
if (dist <= max_dest_drift) {
|
||||
return true;
|
||||
}
|
||||
@@ -240,11 +292,29 @@ bool PathfindingRoute::Valid(const glm::vec3 &dest)
|
||||
return false;
|
||||
}
|
||||
|
||||
void PathfindingRoute::CalcCurrentNode()
|
||||
void PathfindingRoute::CalcCurrentNode(const glm::vec3 ¤t_pos, bool &wp_changed)
|
||||
{
|
||||
//if we're at last node then we dont need to do anything.
|
||||
wp_changed = false;
|
||||
if (m_active) {
|
||||
//if we're at last node then we dont need to do anything.
|
||||
if (m_nodes.size() - 1 == m_current_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
//else need to see if we're at current_node
|
||||
//if so then we advance to the next node and return it
|
||||
//else just return the current node
|
||||
auto ¤t = GetCurrentNode();
|
||||
auto dist = vec_dist(current.position, current_pos);
|
||||
if (dist < at_waypoint_eps) {
|
||||
m_current_node++;
|
||||
wp_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short PathfindingRoute::GetPreviousNodeFlag()
|
||||
{
|
||||
if(m_current_node == 0)
|
||||
return 0;
|
||||
|
||||
return m_nodes[m_current_node - 1].flag;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user