From 71fe0ed94370a13d6e1eaefeeccf3e6136638753 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Thu, 21 Jan 2021 15:38:03 +0100 Subject: [PATCH] Core/PathFinding: calculate pathing with 0.5f steps and convert them to blizzlike splines later in the process to get more precise results --- src/server/game/Movement/PathGenerator.cpp | 31 +++++++++++++--------- src/server/game/Movement/PathGenerator.h | 17 +++++++----- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 3484f8283f8..94683e143ed 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -591,14 +591,25 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin return; } - _pathPoints.resize(pointCount); + // We are only going to use the path points that are 4yrds apart from each other as well as the first and final point to get a blizzlike result + uint32 splinePointCount = 1 + (pointCount / SMOOTH_PATH_MULTIPLIER) + (pointCount % SMOOTH_PATH_MULTIPLIER ? 1 : 0); + _pathPoints.resize(splinePointCount); + + uint32 splineIndex = 0; for (uint32 i = 0; i < pointCount; ++i) - _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + { + // We only want every 8th waypoint as well as the first and final point of pathPoints + if (i == 0 || !((i + 1) % SMOOTH_PATH_MULTIPLIER) || i == (pointCount - 1)) + { + _pathPoints[splineIndex] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + ++splineIndex; + } + } NormalizePath(); - // first point is always our current location - we need the next one - SetActualEndPosition(_pathPoints[pointCount-1]); + // Set the actual end position to be our final path point which is at the end of the _pathPoints vector + SetActualEndPosition(_pathPoints[_pathPoints.size()-1]); // force the given destination, if needed if (_forceDestination && @@ -845,8 +856,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); nsmoothPath++; - // Move towards target a small advancement at a time until target reached or - // when ran out of memory to store the path. + // Move towards target a small advancement at a time until target reached or when ran out of memory to store the path. while (npolys && nsmoothPath < maxSmoothPathSize) { // Find location to steer towards. @@ -865,10 +875,10 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo dtVsub(delta, steerPos, iterPos); float len = dtMathSqrtf(dtVdot(delta, delta)); // If the steer target is end of path or off-mesh link, do not move past the location. - if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) + if ((endOfPath || offMeshConnection) && len < RECAST_PATH_STEP_SIZE) len = 1.0f; else - len = SMOOTH_PATH_STEP_SIZE / len; + len = RECAST_PATH_STEP_SIZE / len; float moveTgt[VERTEX_SIZE]; dtVmad(moveTgt, iterPos, delta, len); @@ -1031,10 +1041,7 @@ bool PathGenerator::IsInvalidDestinationZ(Unit const* target) const void PathGenerator::SetPathLengthLimit(float length) { - if (!(uint32(length) % uint32(SMOOTH_PATH_STEP_SIZE))) - _pointPathLimit = std::min(length / SMOOTH_PATH_STEP_SIZE, MAX_POINT_PATH_LENGTH); - else - _pointPathLimit = std::min((length + SMOOTH_PATH_STEP_SIZE) / SMOOTH_PATH_STEP_SIZE, MAX_POINT_PATH_LENGTH); + _pointPathLimit = uint32(ceilf(length / RECAST_PATH_STEP_SIZE)); } void PathGenerator::AddFarFromPolyFlags(bool startFarFromPoly, bool endFarFromPoly) diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index 826a25205a6..c5c36f8cdbe 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -27,17 +27,20 @@ class Unit; class WorldObject; -// 74*4.0f=296y number_of_points*interval = max_path_len +// 592*0.5f=296y number_of_points*interval = max_path_len // this is way more than actual evade range // I think we can safely cut those down even more -#define MAX_PATH_LENGTH 74 -#define MAX_POINT_PATH_LENGTH 74 +constexpr uint32 const MAX_PATH_LENGTH = 592; +constexpr uint32 const MAX_POINT_PATH_LENGTH = 592; -#define SMOOTH_PATH_STEP_SIZE 4.0f -#define SMOOTH_PATH_SLOP 0.3f +// Retail spline points are 4yrds apart from each other so we use a multiplier of 4 / RECAST_PATH_STEP_SIZE to skip unneeded generated points +constexpr uint8 const SMOOTH_PATH_MULTIPLIER = 8; -#define VERTEX_SIZE 3 -#define INVALID_POLYREF 0 +constexpr float const RECAST_PATH_STEP_SIZE = 0.5f; +constexpr float const SMOOTH_PATH_SLOP = 0.3f; + +constexpr uint8 const VERTEX_SIZE = 3; +constexpr uint8 const INVALID_POLYREF = 0; enum PathType {