TrinityCore
PathGenerator Class Reference

#include <PathGenerator.h>

Public Member Functions

 PathGenerator (Unit const *owner)
 
 ~PathGenerator ()
 
bool CalculatePath (float destX, float destY, float destZ, bool forceDest=false, bool straightLine=false)
 
bool IsInvalidDestinationZ (Unit const *target) const
 
void SetUseStraightPath (bool useStraightPath)
 
void SetPathLengthLimit (float distance)
 
G3D::Vector3 const & GetStartPosition () const
 
G3D::Vector3 const & GetEndPosition () const
 
G3D::Vector3 const & GetActualEndPosition () const
 
Movement::PointsArray const & GetPath () const
 
PathType GetPathType () const
 
void ReducePathLenghtByDist (float dist)
 

Private Member Functions

void SetStartPosition (G3D::Vector3 const &point)
 
void SetEndPosition (G3D::Vector3 const &point)
 
void SetActualEndPosition (G3D::Vector3 const &point)
 
void NormalizePath ()
 
void Clear ()
 
bool InRange (G3D::Vector3 const &p1, G3D::Vector3 const &p2, float r, float h) const
 
float Dist3DSqr (G3D::Vector3 const &p1, G3D::Vector3 const &p2) const
 
bool InRangeYZX (float const *v1, float const *v2, float r, float h) const
 
dtPolyRef GetPathPolyByPosition (dtPolyRef const *polyPath, uint32 polyPathSize, float const *Point, float *Distance=nullptr) const
 
dtPolyRef GetPolyByLocation (float const *Point, float *Distance) const
 
bool HaveTile (G3D::Vector3 const &p) const
 
void BuildPolyPath (G3D::Vector3 const &startPos, G3D::Vector3 const &endPos)
 
void BuildPointPath (float const *startPoint, float const *endPoint)
 
void BuildShortcut ()
 
NavTerrainFlag GetNavTerrain (float x, float y, float z)
 
void CreateFilter ()
 
void UpdateFilter ()
 
uint32 FixupCorridor (dtPolyRef *path, uint32 npath, uint32 maxPath, dtPolyRef const *visited, uint32 nvisited)
 
bool GetSteerTarget (float const *startPos, float const *endPos, float minTargetDist, dtPolyRef const *path, uint32 pathSize, float *steerPos, unsigned char &steerPosFlag, dtPolyRef &steerPosRef)
 
dtStatus FindSmoothPath (float const *startPos, float const *endPos, dtPolyRef const *polyPath, uint32 polyPathSize, float *smoothPath, int *smoothPathSize, uint32 smoothPathMaxSize)
 

Private Attributes

dtPolyRef _pathPolyRefs [MAX_PATH_LENGTH]
 
uint32 _polyLength
 
Movement::PointsArray _pathPoints
 
PathType _type
 
bool _useStraightPath
 
bool _forceDestination
 
uint32 _pointPathLimit
 
bool _straightLine
 
G3D::Vector3 _startPosition
 
G3D::Vector3 _endPosition
 
G3D::Vector3 _actualEndPosition
 
Unit const *const _sourceUnit
 
dtNavMesh const * _navMesh
 
dtNavMeshQuery const * _navMeshQuery
 
dtQueryFilter _filter
 

Constructor & Destructor Documentation

◆ PathGenerator()

PathGenerator::PathGenerator ( Unit const *  owner)
explicit
31  :
34  _endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(nullptr),
35  _navMeshQuery(nullptr)
36 {
37  memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
38 
39  TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %s", _sourceUnit->GetGUID().ToString().c_str());
40 
43  {
45  _navMesh = mmap->GetNavMesh(mapId);
47  }
48 
49  CreateFilter();
50 }
uint32 _polyLength
Definition: PathGenerator.h:81
bool IsPathfindingEnabled(uint32 mapId)
Definition: DisableMgr.cpp:382
std::string ToString() const
Definition: ObjectGuid.cpp:238
dtNavMesh const * GetNavMesh(uint32 mapId)
Definition: MMapManager.cpp:390
bool _straightLine
Definition: PathGenerator.h:89
dtNavMesh const * _navMesh
Definition: PathGenerator.h:96
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
dtNavMeshQuery const * GetNavMeshQuery(uint32 mapId, uint32 instanceId)
Definition: MMapManager.cpp:399
float GetPositionY() const
Definition: Position.h:102
Map * GetMap() const
Definition: Object.h:535
ObjectGuid const & GetGUID() const
Definition: Object.h:154
Definition: PathGenerator.h:43
PhaseShift & GetPhaseShift()
Definition: Object.h:450
uint32_t uint32
Definition: Define.h:152
bool _forceDestination
Definition: PathGenerator.h:87
bool _useStraightPath
Definition: PathGenerator.h:86
float GetPositionX() const
Definition: Position.h:101
Definition: MMapManager.h:59
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
static uint32 GetTerrainMapId(PhaseShift const &phaseShift, Map const *map, float x, float y)
Definition: PhasingHandler.cpp:505
uint32 GetMapId() const
Definition: Position.h:252
uint32 GetInstanceId() const
Definition: Object.h:439
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
PathType _type
Definition: PathGenerator.h:84
void CreateFilter()
Definition: PathGenerator.cpp:605
static MMapManager * createOrGetMMapManager()
Definition: MMapFactory.cpp:27
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]
Definition: PathGenerator.h:80
#define MAX_POINT_PATH_LENGTH
Definition: PathGenerator.h:33
uint32 _pointPathLimit
Definition: PathGenerator.h:88
G3D::Vector3 _endPosition
Definition: PathGenerator.h:92
+ Here is the call graph for this function:

◆ ~PathGenerator()

PathGenerator::~PathGenerator ( )
53 {
54  TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %s", _sourceUnit->GetGUID().ToString().c_str());
55 }
std::string ToString() const
Definition: ObjectGuid.cpp:238
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
ObjectGuid const & GetGUID() const
Definition: Object.h:154
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
+ Here is the call graph for this function:

Member Function Documentation

◆ BuildPointPath()

void PathGenerator::BuildPointPath ( float const *  startPoint,
float const *  endPoint 
)
private
Todo:
check the exact cases
477 {
478  float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
479  uint32 pointCount = 0;
480  dtStatus dtResult = DT_FAILURE;
481  if (_straightLine)
482  {
483  dtResult = DT_SUCCESS;
484  pointCount = 1;
485  memcpy(&pathPoints[VERTEX_SIZE * 0], startPoint, sizeof(float)* 3); // first point
486 
487  // path has to be split into polygons with dist SMOOTH_PATH_STEP_SIZE between them
488  G3D::Vector3 startVec = G3D::Vector3(startPoint[0], startPoint[1], startPoint[2]);
489  G3D::Vector3 endVec = G3D::Vector3(endPoint[0], endPoint[1], endPoint[2]);
490  G3D::Vector3 diffVec = (endVec - startVec);
491  G3D::Vector3 prevVec = startVec;
492  float len = diffVec.length();
493  diffVec *= SMOOTH_PATH_STEP_SIZE / len;
494  while (len > SMOOTH_PATH_STEP_SIZE)
495  {
496  len -= SMOOTH_PATH_STEP_SIZE;
497  prevVec += diffVec;
498  pathPoints[VERTEX_SIZE * pointCount + 0] = prevVec.x;
499  pathPoints[VERTEX_SIZE * pointCount + 1] = prevVec.y;
500  pathPoints[VERTEX_SIZE * pointCount + 2] = prevVec.z;
501  ++pointCount;
502  }
503 
504  memcpy(&pathPoints[VERTEX_SIZE * pointCount], endPoint, sizeof(float)* 3); // last point
505  ++pointCount;
506  }
507  else if (_useStraightPath)
508  {
509  dtResult = _navMeshQuery->findStraightPath(
510  startPoint, // start position
511  endPoint, // end position
512  _pathPolyRefs, // current path
513  _polyLength, // lenth of current path
514  pathPoints, // [out] path corner points
515  nullptr, // [out] flags
516  nullptr, // [out] shortened path
517  (int*)&pointCount,
518  _pointPathLimit); // maximum number of points/polygons to use
519  }
520  else
521  {
522  dtResult = FindSmoothPath(
523  startPoint, // start position
524  endPoint, // end position
525  _pathPolyRefs, // current path
526  _polyLength, // length of current path
527  pathPoints, // [out] path corner points
528  (int*)&pointCount,
529  _pointPathLimit); // maximum number of points
530  }
531 
532  if (pointCount < 2 || dtStatusFailed(dtResult))
533  {
534  // only happens if pass bad data to findStraightPath or navmesh is broken
535  // single point paths can be generated here
537  TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount);
538  BuildShortcut();
540  return;
541  }
542  else if (pointCount == _pointPathLimit)
543  {
544  TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit);
545  BuildShortcut();
547  return;
548  }
549 
550  _pathPoints.resize(pointCount);
551  for (uint32 i = 0; i < pointCount; ++i)
552  _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]);
553 
554  NormalizePath();
555 
556  // first point is always our current location - we need the next one
557  SetActualEndPosition(_pathPoints[pointCount-1]);
558 
559  // force the given destination, if needed
560  if (_forceDestination &&
561  (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f)))
562  {
563  // we may want to keep partial subpath
565  {
567  _pathPoints[_pathPoints.size()-1] = GetEndPosition();
568  }
569  else
570  {
572  BuildShortcut();
573  }
574 
575  _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
576  }
577 
578  TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength);
579 }
uint32 _polyLength
Definition: PathGenerator.h:81
PathType
Definition: PathGenerator.h:41
Definition: PathGenerator.h:47
Definition: PathGenerator.h:44
void SetActualEndPosition(G3D::Vector3 const &point)
Definition: PathGenerator.h:103
bool _straightLine
Definition: PathGenerator.h:89
dtStatus FindSmoothPath(float const *startPos, float const *endPos, dtPolyRef const *polyPath, uint32 polyPathSize, float *smoothPath, int *smoothPathSize, uint32 smoothPathMaxSize)
Definition: PathGenerator.cpp:766
G3D::Vector3 const & GetStartPosition() const
Definition: PathGenerator.h:68
void NormalizePath()
Definition: PathGenerator.cpp:581
G3D::Vector3 const & GetActualEndPosition() const
Definition: PathGenerator.h:70
G3D::Vector3 const & GetEndPosition() const
Definition: PathGenerator.h:69
uint32_t uint32
Definition: Define.h:152
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
bool _forceDestination
Definition: PathGenerator.h:87
bool _useStraightPath
Definition: PathGenerator.h:86
Definition: PathGenerator.h:49
Definition: PathGenerator.h:48
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
float Dist3DSqr(G3D::Vector3 const &p1, G3D::Vector3 const &p2) const
Definition: PathGenerator.cpp:902
PathType _type
Definition: PathGenerator.h:84
void BuildShortcut()
Definition: PathGenerator.cpp:587
#define VERTEX_SIZE
Definition: PathGenerator.h:38
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]
Definition: PathGenerator.h:80
#define SMOOTH_PATH_STEP_SIZE
Definition: PathGenerator.h:35
#define MAX_POINT_PATH_LENGTH
Definition: PathGenerator.h:33
bool InRange(G3D::Vector3 const &p1, G3D::Vector3 const &p2, float r, float h) const
Definition: PathGenerator.cpp:896
uint32 _pointPathLimit
Definition: PathGenerator.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildPolyPath()

void PathGenerator::BuildPolyPath ( G3D::Vector3 const &  startPos,
G3D::Vector3 const &  endPos 
)
private
Todo:
we can merge it with getPathPolyByPosition() loop
Todo:
play with the values here
162 {
163  // *** getting start/end poly logic ***
164 
165  float distToStartPoly, distToEndPoly;
166  float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
167  float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
168 
169  dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly);
170  dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly);
171 
172  // we have a hole in our mesh
173  // make shortcut path and mark it as NOPATH ( with flying and swimming exception )
174  // its up to caller how he will use this info
175  if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
176  {
177  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n");
178  BuildShortcut();
179  bool path = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanFly();
180 
181  bool waterPath = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanSwim();
182  if (waterPath)
183  {
184  // Check both start and end points, if they're both in water, then we can *safely* let the creature move
185  for (uint32 i = 0; i < _pathPoints.size(); ++i)
186  {
188  // One of the points is not in the water, cancel movement.
189  if (status == LIQUID_MAP_NO_WATER)
190  {
191  waterPath = false;
192  break;
193  }
194  }
195  }
196 
198  return;
199  }
200 
201  // we may need a better number here
202  bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f);
203  if (farFromPoly)
204  {
205  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly);
206 
207  bool buildShotrcut = false;
209  {
210  Creature* owner = (Creature*)_sourceUnit;
211 
212  G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos;
213  if (_sourceUnit->GetMap()->IsUnderWater(_sourceUnit->GetPhaseShift(), p.x, p.y, p.z))
214  {
215  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: underWater case\n");
216  if (owner->CanSwim())
217  buildShotrcut = true;
218  }
219  else
220  {
221  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: flying case\n");
222  if (owner->CanFly())
223  buildShotrcut = true;
224  }
225  }
226 
227  if (buildShotrcut)
228  {
229  BuildShortcut();
231  return;
232  }
233  else
234  {
235  float closestPoint[VERTEX_SIZE];
236  // we may want to use closestPointOnPolyBoundary instead
237  if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint, nullptr)))
238  {
239  dtVcopy(endPoint, closestPoint);
240  SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1]));
241  }
242 
244  }
245  }
246 
247  // *** poly path generating logic ***
248 
249  // start and end are on same polygon
250  // just need to move in straight line
251  if (startPoly == endPoly)
252  {
253  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == endPoly)\n");
254 
255  BuildShortcut();
256 
257  _pathPolyRefs[0] = startPoly;
258  _polyLength = 1;
259 
260  _type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL;
261  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: path type %d\n", _type);
262  return;
263  }
264 
265  // look for startPoly/endPoly in current path
267  bool startPolyFound = false;
268  bool endPolyFound = false;
269  uint32 pathStartIndex = 0;
270  uint32 pathEndIndex = 0;
271 
272  if (_polyLength)
273  {
274  for (; pathStartIndex < _polyLength; ++pathStartIndex)
275  {
276  // here to catch few bugs
277  if (_pathPolyRefs[pathStartIndex] == INVALID_POLYREF)
278  {
279  TC_LOG_ERROR("maps", "Invalid poly ref in BuildPolyPath. _polyLength: %u, pathStartIndex: %u,"
280  " startPos: %s, endPos: %s, mapid: %u",
281  _polyLength, pathStartIndex, startPos.toString().c_str(), endPos.toString().c_str(),
282  _sourceUnit->GetMapId());
283 
284  break;
285  }
286 
287  if (_pathPolyRefs[pathStartIndex] == startPoly)
288  {
289  startPolyFound = true;
290  break;
291  }
292  }
293 
294  for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex)
295  if (_pathPolyRefs[pathEndIndex] == endPoly)
296  {
297  endPolyFound = true;
298  break;
299  }
300  }
301 
302  if (startPolyFound && endPolyFound)
303  {
304  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n");
305 
306  // we moved along the path and the target did not move out of our old poly-path
307  // our path is a simple subpath case, we have all the data we need
308  // just "cut" it out
309 
310  _polyLength = pathEndIndex - pathStartIndex + 1;
311  memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef));
312  }
313  else if (startPolyFound && !endPolyFound)
314  {
315  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n");
316 
317  // we are moving on the old path but target moved out
318  // so we have atleast part of poly-path ready
319 
320  _polyLength -= pathStartIndex;
321 
322  // try to adjust the suffix of the path instead of recalculating entire length
323  // at given interval the target cannot get too far from its last location
324  // thus we have less poly to cover
325  // sub-path of optimal path is optimal
326 
327  // take ~80% of the original length
329  uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f);
330  memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef));
331 
332  dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
333 
334  // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
335  float suffixEndPoint[VERTEX_SIZE];
336  if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, nullptr)))
337  {
338  // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that
339  // try to recover by using prev polyref
340  --prefixPolyLength;
341  suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
342  if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, nullptr)))
343  {
344  // suffixStartPoly is still invalid, error state
345  BuildShortcut();
347  return;
348  }
349  }
350 
351  // generate suffix
352  uint32 suffixPolyLength = 0;
353 
354  dtStatus dtResult;
355  if (_straightLine)
356  {
357  float hit = 0;
358  float hitNormal[3];
359  memset(hitNormal, 0, sizeof(hitNormal));
360 
361  dtResult = _navMeshQuery->raycast(
362  suffixStartPoly,
363  suffixEndPoint,
364  endPoint,
365  &_filter,
366  &hit,
367  hitNormal,
368  _pathPolyRefs + prefixPolyLength - 1,
369  (int*)&suffixPolyLength,
370  MAX_PATH_LENGTH - prefixPolyLength);
371 
372  // raycast() sets hit to FLT_MAX if there is a ray between start and end
373  if (hit != FLT_MAX)
374  {
375  // the ray hit something, return no path instead of the incomplete one
377  return;
378  }
379  }
380  else
381  {
382  dtResult = _navMeshQuery->findPath(
383  suffixStartPoly, // start polygon
384  endPoly, // end polygon
385  suffixEndPoint, // start position
386  endPoint, // end position
387  &_filter, // polygon search filter
388  _pathPolyRefs + prefixPolyLength - 1, // [out] path
389  (int*)&suffixPolyLength,
390  MAX_PATH_LENGTH - prefixPolyLength); // max number of polygons in output path
391  }
392 
393  if (!suffixPolyLength || dtStatusFailed(dtResult))
394  {
395  // this is probably an error state, but we'll leave it
396  // and hopefully recover on the next Update
397  // we still need to copy our preffix
398  TC_LOG_ERROR("maps", "%s's Path Build failed: 0 length path", _sourceUnit->GetGUID().ToString().c_str());
399  }
400 
401  TC_LOG_DEBUG("maps", "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength);
402 
403  // new path = prefix + suffix - overlap
404  _polyLength = prefixPolyLength + suffixPolyLength - 1;
405  }
406  else
407  {
408  TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n");
409 
410  // either we have no path at all -> first run
411  // or something went really wrong -> we aren't moving along the path to the target
412  // just generate new path
413 
414  // free and invalidate old path data
415  Clear();
416 
417  dtStatus dtResult;
418  if (_straightLine)
419  {
420  float hit = 0;
421  float hitNormal[3];
422  memset(hitNormal, 0, sizeof(hitNormal));
423 
424  dtResult = _navMeshQuery->raycast(
425  startPoly,
426  startPoint,
427  endPoint,
428  &_filter,
429  &hit,
430  hitNormal,
432  (int*)&_polyLength,
434 
435  // raycast() sets hit to FLT_MAX if there is a ray between start and end
436  if (hit != FLT_MAX)
437  {
438  // the ray hit something, return no path instead of the incomplete one
440  return;
441  }
442  }
443  else
444  {
445  dtResult = _navMeshQuery->findPath(
446  startPoly, // start polygon
447  endPoly, // end polygon
448  startPoint, // start position
449  endPoint, // end position
450  &_filter, // polygon search filter
451  _pathPolyRefs, // [out] path
452  (int*)&_polyLength,
453  MAX_PATH_LENGTH); // max number of polygons in output path
454  }
455 
456  if (!_polyLength || dtStatusFailed(dtResult))
457  {
458  // only happens if we passed bad data to findPath(), or navmesh is messed up
459  TC_LOG_ERROR("maps", "%s's Path Build failed: 0 length path", _sourceUnit->GetGUID().ToString().c_str());
460  BuildShortcut();
462  return;
463  }
464  }
465 
466  // by now we know what type of path we can get
467  if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE))
469  else
471 
472  // generate the point-path out of our up-to-date poly-path
473  BuildPointPath(startPoint, endPoint);
474 }
uint32 _polyLength
Definition: PathGenerator.h:81
PathType
Definition: PathGenerator.h:41
Definition: PathGenerator.h:47
Definition: PathGenerator.h:44
TypeID GetTypeId() const
Definition: Object.h:167
void SetActualEndPosition(G3D::Vector3 const &point)
Definition: PathGenerator.h:103
std::string ToString() const
Definition: ObjectGuid.cpp:238
bool _straightLine
Definition: PathGenerator.h:89
ZLiquidStatus
Definition: Map.h:85
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:186
Definition: ObjectGuid.h:39
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
Definition: Creature.h:61
bool IsUnderWater(PhaseShift const &phaseShift, float x, float y, float z)
Definition: Map.cpp:2929
Definition: Map.h:87
Map * GetMap() const
Definition: Object.h:535
ObjectGuid const & GetGUID() const
Definition: Object.h:154
#define INVALID_POLYREF
Definition: PathGenerator.h:39
ZLiquidStatus GetLiquidStatus(PhaseShift const &phaseShift, float x, float y, float z, map_liquidHeaderTypeFlags ReqLiquidType, LiquidData *data=nullptr, float collisionHeight=2.03128f)
Definition: Map.cpp:2692
PhaseShift & GetPhaseShift()
Definition: Object.h:450
uint32_t uint32
Definition: Define.h:152
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
dtQueryFilter _filter
Definition: PathGenerator.h:99
float GetCollisionHeight() const override
Definition: Unit.cpp:13219
Definition: PathGenerator.h:46
bool CanFly() const override
Definition: Creature.h:102
Definition: PathGenerator.h:48
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
uint32 GetMapId() const
Definition: Position.h:252
Creature * ToCreature()
Definition: Object.h:196
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
PathType _type
Definition: PathGenerator.h:84
dtPolyRef GetPolyByLocation(float const *Point, float *Distance) const
Definition: PathGenerator.cpp:127
void BuildShortcut()
Definition: PathGenerator.cpp:587
#define VERTEX_SIZE
Definition: PathGenerator.h:38
#define MAX_PATH_LENGTH
Definition: PathGenerator.h:32
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]
Definition: PathGenerator.h:80
void Clear()
Definition: PathGenerator.h:106
void BuildPointPath(float const *startPoint, float const *endPoint)
Definition: PathGenerator.cpp:476
bool CanSwim() const override
Definition: Creature.h:101
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildShortcut()

void PathGenerator::BuildShortcut ( )
private
588 {
589  TC_LOG_DEBUG("maps", "++ BuildShortcut :: making shortcut\n");
590 
591  Clear();
592 
593  // make two point path, our curr pos is the start, and dest is the end
594  _pathPoints.resize(2);
595 
596  // set start and a default next position
599 
600  NormalizePath();
601 
603 }
Definition: PathGenerator.h:45
G3D::Vector3 const & GetStartPosition() const
Definition: PathGenerator.h:68
void NormalizePath()
Definition: PathGenerator.cpp:581
G3D::Vector3 const & GetActualEndPosition() const
Definition: PathGenerator.h:70
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
PathType _type
Definition: PathGenerator.h:84
void Clear()
Definition: PathGenerator.h:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CalculatePath()

bool PathGenerator::CalculatePath ( float  destX,
float  destY,
float  destZ,
bool  forceDest = false,
bool  straightLine = false 
)
58 {
59  float x, y, z;
60  _sourceUnit->GetPosition(x, y, z);
61 
62  if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z))
63  return false;
64 
65  TC_METRIC_EVENT("mmap_events", "CalculatePath", "");
66 
67  G3D::Vector3 dest(destX, destY, destZ);
68  SetEndPosition(dest);
69 
70  G3D::Vector3 start(x, y, z);
71  SetStartPosition(start);
72 
73  _forceDestination = forceDest;
74  _straightLine = straightLine;
75 
76  TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %s", _sourceUnit->GetGUID().ToString().c_str());
77 
78  // make sure navMesh works - we can run on map w/o mmap
79  // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
81  !HaveTile(start) || !HaveTile(dest))
82  {
83  BuildShortcut();
85  return true;
86  }
87 
88  UpdateFilter();
89 
90  BuildPolyPath(start, dest);
91  return true;
92 }
PathType
Definition: PathGenerator.h:41
Definition: PathGenerator.h:44
bool HaveTile(G3D::Vector3 const &p) const
Definition: PathGenerator.cpp:668
std::string ToString() const
Definition: ObjectGuid.cpp:238
bool _straightLine
Definition: PathGenerator.h:89
Definition: Unit.h:263
dtNavMesh const * _navMesh
Definition: PathGenerator.h:96
void SetEndPosition(G3D::Vector3 const &point)
Definition: PathGenerator.h:102
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
void UpdateFilter()
Definition: PathGenerator.cpp:632
ObjectGuid const & GetGUID() const
Definition: Object.h:154
bool IsValidMapCoord(float c)
Definition: GridDefines.h:220
bool HasUnitState(const uint32 f) const
Definition: Unit.h:830
void BuildPolyPath(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos)
Definition: PathGenerator.cpp:161
bool _forceDestination
Definition: PathGenerator.h:87
Definition: PathGenerator.h:48
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:177
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
PathType _type
Definition: PathGenerator.h:84
void BuildShortcut()
Definition: PathGenerator.cpp:587
void SetStartPosition(G3D::Vector3 const &point)
Definition: PathGenerator.h:101
void GetPosition(float &x, float &y) const
Definition: Position.h:106
#define TC_METRIC_EVENT(category, title, description)
Definition: Metric.h:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Clear()

void PathGenerator::Clear ( )
inlineprivate
107  {
108  _polyLength = 0;
109  _pathPoints.clear();
110  }
uint32 _polyLength
Definition: PathGenerator.h:81
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
+ Here is the caller graph for this function:

◆ CreateFilter()

void PathGenerator::CreateFilter ( )
private
606 {
607  uint16 includeFlags = 0;
608  uint16 excludeFlags = 0;
609 
611  {
612  Creature* creature = (Creature*)_sourceUnit;
613  if (creature->CanWalk())
614  includeFlags |= NAV_GROUND; // walk
615 
616  // creatures don't take environmental damage
617  if (creature->CanSwim())
618  includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME); // swim
619  }
620  else // assume Player
621  {
622  // perfect support not possible, just stay 'safe'
623  includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA_SLIME);
624  }
625 
626  _filter.setIncludeFlags(includeFlags);
627  _filter.setExcludeFlags(excludeFlags);
628 
629  UpdateFilter();
630 }
TypeID GetTypeId() const
Definition: Object.h:167
Definition: MMapDefines.h:62
Definition: ObjectGuid.h:39
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
Definition: Creature.h:61
void UpdateFilter()
Definition: PathGenerator.cpp:632
Definition: MMapDefines.h:64
uint16_t uint16
Definition: Define.h:153
dtQueryFilter _filter
Definition: PathGenerator.h:99
bool CanWalk() const
Definition: Creature.h:100
Definition: MMapDefines.h:63
bool CanSwim() const override
Definition: Creature.h:101
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Dist3DSqr()

float PathGenerator::Dist3DSqr ( G3D::Vector3 const &  p1,
G3D::Vector3 const &  p2 
) const
private
903 {
904  return (p1 - p2).squaredLength();
905 }
+ Here is the caller graph for this function:

◆ FindSmoothPath()

dtStatus PathGenerator::FindSmoothPath ( float const *  startPos,
float const *  endPos,
dtPolyRef const *  polyPath,
uint32  polyPathSize,
float *  smoothPath,
int *  smoothPathSize,
uint32  smoothPathMaxSize 
)
private
769 {
770  *smoothPathSize = 0;
771  uint32 nsmoothPath = 0;
772 
773  dtPolyRef polys[MAX_PATH_LENGTH];
774  memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize);
775  uint32 npolys = polyPathSize;
776 
777  float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE];
778  if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)))
779  return DT_FAILURE;
780 
781  if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)))
782  return DT_FAILURE;
783 
784  dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
785  nsmoothPath++;
786 
787  // Move towards target a small advancement at a time until target reached or
788  // when ran out of memory to store the path.
789  while (npolys && nsmoothPath < maxSmoothPathSize)
790  {
791  // Find location to steer towards.
792  float steerPos[VERTEX_SIZE];
793  unsigned char steerPosFlag;
794  dtPolyRef steerPosRef = INVALID_POLYREF;
795 
796  if (!GetSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef))
797  break;
798 
799  bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END) != 0;
800  bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0;
801 
802  // Find movement delta.
803  float delta[VERTEX_SIZE];
804  dtVsub(delta, steerPos, iterPos);
805  float len = dtMathSqrtf(dtVdot(delta, delta));
806  // If the steer target is end of path or off-mesh link, do not move past the location.
807  if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE)
808  len = 1.0f;
809  else
810  len = SMOOTH_PATH_STEP_SIZE / len;
811 
812  float moveTgt[VERTEX_SIZE];
813  dtVmad(moveTgt, iterPos, delta, len);
814 
815  // Move
816  float result[VERTEX_SIZE];
817  const static uint32 MAX_VISIT_POLY = 16;
818  dtPolyRef visited[MAX_VISIT_POLY];
819 
820  uint32 nvisited = 0;
821  _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY);
822  npolys = FixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited);
823 
824  _navMeshQuery->getPolyHeight(polys[0], result, &result[1]);
825  result[1] += 0.5f;
826  dtVcopy(iterPos, result);
827 
828  // Handle end of path and off-mesh links when close enough.
829  if (endOfPath && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
830  {
831  // Reached end of path.
832  dtVcopy(iterPos, targetPos);
833  if (nsmoothPath < maxSmoothPathSize)
834  {
835  dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
836  nsmoothPath++;
837  }
838  break;
839  }
840  else if (offMeshConnection && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
841  {
842  // Advance the path up to and over the off-mesh connection.
843  dtPolyRef prevRef = INVALID_POLYREF;
844  dtPolyRef polyRef = polys[0];
845  uint32 npos = 0;
846  while (npos < npolys && polyRef != steerPosRef)
847  {
848  prevRef = polyRef;
849  polyRef = polys[npos];
850  npos++;
851  }
852 
853  for (uint32 i = npos; i < npolys; ++i)
854  polys[i-npos] = polys[i];
855 
856  npolys -= npos;
857 
858  // Handle the connection.
859  float connectionStartPos[VERTEX_SIZE], connectionEndPos[VERTEX_SIZE];
860  if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, connectionStartPos, connectionEndPos)))
861  {
862  if (nsmoothPath < maxSmoothPathSize)
863  {
864  dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], connectionStartPos);
865  nsmoothPath++;
866  }
867  // Move position at the other side of the off-mesh link.
868  dtVcopy(iterPos, connectionEndPos);
869  _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
870  iterPos[1] += 0.5f;
871  }
872  }
873 
874  // Store results.
875  if (nsmoothPath < maxSmoothPathSize)
876  {
877  dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
878  nsmoothPath++;
879  }
880  }
881 
882  *smoothPathSize = nsmoothPath;
883 
884  // this is most likely a loop
885  return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE;
886 }
dtNavMesh const * _navMesh
Definition: PathGenerator.h:96
#define INVALID_POLYREF
Definition: PathGenerator.h:39
uint32_t uint32
Definition: Define.h:152
dtQueryFilter _filter
Definition: PathGenerator.h:99
#define SMOOTH_PATH_SLOP
Definition: PathGenerator.h:36
uint32 FixupCorridor(dtPolyRef *path, uint32 npath, uint32 maxPath, dtPolyRef const *visited, uint32 nvisited)
Definition: PathGenerator.cpp:684
bool GetSteerTarget(float const *startPos, float const *endPos, float minTargetDist, dtPolyRef const *path, uint32 pathSize, float *steerPos, unsigned char &steerPosFlag, dtPolyRef &steerPosRef)
Definition: PathGenerator.cpp:729
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
#define VERTEX_SIZE
Definition: PathGenerator.h:38
#define MAX_PATH_LENGTH
Definition: PathGenerator.h:32
#define SMOOTH_PATH_STEP_SIZE
Definition: PathGenerator.h:35
#define MAX_POINT_PATH_LENGTH
Definition: PathGenerator.h:33
bool InRangeYZX(float const *v1, float const *v2, float r, float h) const
Definition: PathGenerator.cpp:888
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ FixupCorridor()

uint32 PathGenerator::FixupCorridor ( dtPolyRef *  path,
uint32  npath,
uint32  maxPath,
dtPolyRef const *  visited,
uint32  nvisited 
)
private
685 {
686  int32 furthestPath = -1;
687  int32 furthestVisited = -1;
688 
689  // Find furthest common polygon.
690  for (int32 i = npath-1; i >= 0; --i)
691  {
692  bool found = false;
693  for (int32 j = nvisited-1; j >= 0; --j)
694  {
695  if (path[i] == visited[j])
696  {
697  furthestPath = i;
698  furthestVisited = j;
699  found = true;
700  }
701  }
702  if (found)
703  break;
704  }
705 
706  // If no intersection found just return current path.
707  if (furthestPath == -1 || furthestVisited == -1)
708  return npath;
709 
710  // Concatenate paths.
711 
712  // Adjust beginning of the buffer to include the visited.
713  uint32 req = nvisited - furthestVisited;
714  uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath;
715  uint32 size = npath > orig ? npath - orig : 0;
716  if (req + size > maxPath)
717  size = maxPath-req;
718 
719  if (size)
720  memmove(path + req, path + orig, size * sizeof(dtPolyRef));
721 
722  // Store visited
723  for (uint32 i = 0; i < req; ++i)
724  path[i] = visited[(nvisited - 1) - i];
725 
726  return req+size;
727 }
constexpr auto size(const C &c)
Definition: advstd.h:89
int32_t int32
Definition: Define.h:148
uint32_t uint32
Definition: Define.h:152
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetActualEndPosition()

G3D::Vector3 const& PathGenerator::GetActualEndPosition ( ) const
inline
70 { return _actualEndPosition; }
G3D::Vector3 _actualEndPosition
Definition: PathGenerator.h:93
+ Here is the caller graph for this function:

◆ GetEndPosition()

G3D::Vector3 const& PathGenerator::GetEndPosition ( ) const
inline
69 { return _endPosition; }
G3D::Vector3 _endPosition
Definition: PathGenerator.h:92
+ Here is the caller graph for this function:

◆ GetNavTerrain()

NavTerrainFlag PathGenerator::GetNavTerrain ( float  x,
float  y,
float  z 
)
private
648 {
651  if (liquidStatus == LIQUID_MAP_NO_WATER)
652  return NAV_GROUND;
653 
654  data.type_flags &= map_liquidHeaderTypeFlags::DarkWater;
655  switch (data.type_flags)
656  {
659  return NAV_WATER;
662  return NAV_MAGMA_SLIME;
663  default:
664  return NAV_GROUND;
665  }
666 }
Definition: MMapDefines.h:62
constexpr auto data(C &c)
Definition: advstd.h:96
Definition: Map.h:97
ZLiquidStatus
Definition: Map.h:85
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
Definition: Map.h:87
Map * GetMap() const
Definition: Object.h:535
Definition: MMapDefines.h:64
ZLiquidStatus GetLiquidStatus(PhaseShift const &phaseShift, float x, float y, float z, map_liquidHeaderTypeFlags ReqLiquidType, LiquidData *data=nullptr, float collisionHeight=2.03128f)
Definition: Map.cpp:2692
PhaseShift & GetPhaseShift()
Definition: Object.h:450
float GetCollisionHeight() const override
Definition: Unit.cpp:13219
Definition: MMapDefines.h:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetPath()

Movement::PointsArray const& PathGenerator::GetPath ( ) const
inline
72 { return _pathPoints; }
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
+ Here is the caller graph for this function:

◆ GetPathPolyByPosition()

dtPolyRef PathGenerator::GetPathPolyByPosition ( dtPolyRef const *  polyPath,
uint32  polyPathSize,
float const *  Point,
float *  Distance = nullptr 
) const
private
95 {
96  if (!polyPath || !polyPathSize)
97  return INVALID_POLYREF;
98 
99  dtPolyRef nearestPoly = INVALID_POLYREF;
100  float minDist2d = FLT_MAX;
101  float minDist3d = 0.0f;
102 
103  for (uint32 i = 0; i < polyPathSize; ++i)
104  {
105  float closestPoint[VERTEX_SIZE];
106  if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint, nullptr)))
107  continue;
108 
109  float d = dtVdist2DSqr(point, closestPoint);
110  if (d < minDist2d)
111  {
112  minDist2d = d;
113  nearestPoly = polyPath[i];
114  minDist3d = dtVdistSqr(point, closestPoint);
115  }
116 
117  if (minDist2d < 1.0f) // shortcut out - close enough for us
118  break;
119  }
120 
121  if (distance)
122  *distance = dtMathSqrtf(minDist3d);
123 
124  return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF;
125 }
#define INVALID_POLYREF
Definition: PathGenerator.h:39
uint32_t uint32
Definition: Define.h:152
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
#define VERTEX_SIZE
Definition: PathGenerator.h:38
+ Here is the caller graph for this function:

◆ GetPathType()

PathType PathGenerator::GetPathType ( ) const
inline
74 { return _type; }
PathType _type
Definition: PathGenerator.h:84
+ Here is the caller graph for this function:

◆ GetPolyByLocation()

dtPolyRef PathGenerator::GetPolyByLocation ( float const *  Point,
float *  Distance 
) const
private
128 {
129  // first we check the current path
130  // if the current path doesn't contain the current poly,
131  // we need to use the expensive navMesh.findNearestPoly
132  dtPolyRef polyRef = GetPathPolyByPosition(_pathPolyRefs, _polyLength, point, distance);
133  if (polyRef != INVALID_POLYREF)
134  return polyRef;
135 
136  // we don't have it in our old path
137  // try to get it by findNearestPoly()
138  // first try with low search box
139  float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area
140  float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f};
141  if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
142  {
143  *distance = dtVdist(closestPoint, point);
144  return polyRef;
145  }
146 
147  // still nothing ..
148  // try with bigger search box
149  // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly)
150  extents[1] = 50.0f;
151 
152  if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
153  {
154  *distance = dtVdist(closestPoint, point);
155  return polyRef;
156  }
157 
158  return INVALID_POLYREF;
159 }
uint32 _polyLength
Definition: PathGenerator.h:81
dtPolyRef GetPathPolyByPosition(dtPolyRef const *polyPath, uint32 polyPathSize, float const *Point, float *Distance=nullptr) const
Definition: PathGenerator.cpp:94
#define INVALID_POLYREF
Definition: PathGenerator.h:39
dtQueryFilter _filter
Definition: PathGenerator.h:99
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
#define VERTEX_SIZE
Definition: PathGenerator.h:38
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]
Definition: PathGenerator.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetStartPosition()

G3D::Vector3 const& PathGenerator::GetStartPosition ( ) const
inline
68 { return _startPosition; }
G3D::Vector3 _startPosition
Definition: PathGenerator.h:91
+ Here is the caller graph for this function:

◆ GetSteerTarget()

bool PathGenerator::GetSteerTarget ( float const *  startPos,
float const *  endPos,
float  minTargetDist,
dtPolyRef const *  path,
uint32  pathSize,
float *  steerPos,
unsigned char &  steerPosFlag,
dtPolyRef &  steerPosRef 
)
private
732 {
733  // Find steer target.
734  static const uint32 MAX_STEER_POINTS = 3;
735  float steerPath[MAX_STEER_POINTS*VERTEX_SIZE];
736  unsigned char steerPathFlags[MAX_STEER_POINTS];
737  dtPolyRef steerPathPolys[MAX_STEER_POINTS];
738  uint32 nsteerPath = 0;
739  dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
740  steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
741  if (!nsteerPath || dtStatusFailed(dtResult))
742  return false;
743 
744  // Find vertex far enough to steer to.
745  uint32 ns = 0;
746  while (ns < nsteerPath)
747  {
748  // Stop at Off-Mesh link or when point is further than slop away.
749  if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
750  !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
751  break;
752  ns++;
753  }
754  // Failed to find good point to steer to.
755  if (ns >= nsteerPath)
756  return false;
757 
758  dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]);
759  steerPos[1] = startPos[1]; // keep Z value
760  steerPosFlag = steerPathFlags[ns];
761  steerPosRef = steerPathPolys[ns];
762 
763  return true;
764 }
size_t const pathSize
Definition: zone_dun_morogh_area_coldridge_valley.cpp:253
uint32_t uint32
Definition: Define.h:152
dtNavMeshQuery const * _navMeshQuery
Definition: PathGenerator.h:97
#define VERTEX_SIZE
Definition: PathGenerator.h:38
bool InRangeYZX(float const *v1, float const *v2, float r, float h) const
Definition: PathGenerator.cpp:888
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HaveTile()

bool PathGenerator::HaveTile ( G3D::Vector3 const &  p) const
private

Workaround For some reason, often the tx and ty variables wont get a valid value Use this check to prevent getting negative tile coords and crashing on getTileAt

669 {
670  int tx = -1, ty = -1;
671  float point[VERTEX_SIZE] = {p.y, p.z, p.x};
672 
673  _navMesh->calcTileLoc(point, &tx, &ty);
674 
678  if (tx < 0 || ty < 0)
679  return false;
680 
681  return (_navMesh->getTileAt(tx, ty, 0) != nullptr);
682 }
dtNavMesh const * _navMesh
Definition: PathGenerator.h:96
#define VERTEX_SIZE
Definition: PathGenerator.h:38
+ Here is the caller graph for this function:

◆ InRange()

bool PathGenerator::InRange ( G3D::Vector3 const &  p1,
G3D::Vector3 const &  p2,
float  r,
float  h 
) const
private
897 {
898  G3D::Vector3 d = p1 - p2;
899  return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h;
900 }
+ Here is the caller graph for this function:

◆ InRangeYZX()

bool PathGenerator::InRangeYZX ( float const *  v1,
float const *  v2,
float  r,
float  h 
) const
private
889 {
890  const float dx = v2[0] - v1[0];
891  const float dy = v2[1] - v1[1]; // elevation
892  const float dz = v2[2] - v1[2];
893  return (dx * dx + dz * dz) < r * r && fabsf(dy) < h;
894 }
+ Here is the caller graph for this function:

◆ IsInvalidDestinationZ()

bool PathGenerator::IsInvalidDestinationZ ( Unit const *  target) const
947 {
948  return (target->GetPositionZ() - GetActualEndPosition().z) > 5.0f;
949 }
G3D::Vector3 const & GetActualEndPosition() const
Definition: PathGenerator.h:70
+ Here is the call graph for this function:

◆ NormalizePath()

void PathGenerator::NormalizePath ( )
private
582 {
583  for (uint32 i = 0; i < _pathPoints.size(); ++i)
585 }
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
void UpdateAllowedPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1314
uint32_t uint32
Definition: Define.h:152
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ReducePathLenghtByDist()

void PathGenerator::ReducePathLenghtByDist ( float  dist)
908 {
909  if (GetPathType() == PATHFIND_BLANK)
910  {
911  TC_LOG_ERROR("maps", "PathGenerator::ReducePathLenghtByDist called before path was built");
912  return;
913  }
914 
915  if (_pathPoints.size() < 2) // path building failure
916  return;
917 
918  uint32 i = _pathPoints.size();
919  G3D::Vector3 nextVec = _pathPoints[--i];
920  while (i > 0)
921  {
922  G3D::Vector3 currVec = _pathPoints[--i];
923  G3D::Vector3 diffVec = (nextVec - currVec);
924  float len = diffVec.length();
925  if (len > dist)
926  {
927  float step = dist / len;
928  // same as nextVec
929  _pathPoints[i + 1] -= diffVec * step;
931  _pathPoints.resize(i + 2);
932  break;
933  }
934  else if (i == 0) // at second point
935  {
936  _pathPoints[1] = _pathPoints[0];
937  _pathPoints.resize(2);
938  break;
939  }
940 
941  dist -= len;
942  nextVec = currVec; // we're going backwards
943  }
944 }
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:186
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
PathType GetPathType() const
Definition: PathGenerator.h:74
void UpdateAllowedPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1314
Definition: PathGenerator.h:43
uint32_t uint32
Definition: Define.h:152
Movement::PointsArray _pathPoints
Definition: PathGenerator.h:83
+ Here is the call graph for this function:

◆ SetActualEndPosition()

void PathGenerator::SetActualEndPosition ( G3D::Vector3 const &  point)
inlineprivate
103 { _actualEndPosition = point; }
G3D::Vector3 _actualEndPosition
Definition: PathGenerator.h:93
+ Here is the caller graph for this function:

◆ SetEndPosition()

void PathGenerator::SetEndPosition ( G3D::Vector3 const &  point)
inlineprivate
102 { _actualEndPosition = point; _endPosition = point; }
G3D::Vector3 _actualEndPosition
Definition: PathGenerator.h:93
G3D::Vector3 _endPosition
Definition: PathGenerator.h:92
+ Here is the caller graph for this function:

◆ SetPathLengthLimit()

void PathGenerator::SetPathLengthLimit ( float  distance)
inline
65 { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }
uint32_t uint32
Definition: Define.h:152
#define SMOOTH_PATH_STEP_SIZE
Definition: PathGenerator.h:35
#define MAX_POINT_PATH_LENGTH
Definition: PathGenerator.h:33
uint32 _pointPathLimit
Definition: PathGenerator.h:88
+ Here is the caller graph for this function:

◆ SetStartPosition()

void PathGenerator::SetStartPosition ( G3D::Vector3 const &  point)
inlineprivate
101 { _startPosition = point; }
G3D::Vector3 _startPosition
Definition: PathGenerator.h:91
+ Here is the caller graph for this function:

◆ SetUseStraightPath()

void PathGenerator::SetUseStraightPath ( bool  useStraightPath)
inline
64 { _useStraightPath = useStraightPath; }
bool _useStraightPath
Definition: PathGenerator.h:86
+ Here is the caller graph for this function:

◆ UpdateFilter()

void PathGenerator::UpdateFilter ( )
private
633 {
634  // allow creatures to cheat and use different movement types if they are moved
635  // forcefully into terrain they can't normally move in
637  {
638  uint16 includedFlags = _filter.getIncludeFlags();
639  includedFlags |= GetNavTerrain(_sourceUnit->GetPositionX(),
642 
643  _filter.setIncludeFlags(includedFlags);
644  }
645 }
virtual bool IsInWater() const
Definition: Unit.cpp:3022
virtual bool IsUnderWater() const
Definition: Unit.cpp:3027
Unit const *const _sourceUnit
Definition: PathGenerator.h:95
float GetPositionY() const
Definition: Position.h:102
uint16_t uint16
Definition: Define.h:153
dtQueryFilter _filter
Definition: PathGenerator.h:99
float GetPositionZ() const
Definition: Position.h:103
NavTerrainFlag GetNavTerrain(float x, float y, float z)
Definition: PathGenerator.cpp:647
float GetPositionX() const
Definition: Position.h:101
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ _actualEndPosition

G3D::Vector3 PathGenerator::_actualEndPosition
private

◆ _endPosition

G3D::Vector3 PathGenerator::_endPosition
private

◆ _filter

dtQueryFilter PathGenerator::_filter
private

◆ _forceDestination

bool PathGenerator::_forceDestination
private

◆ _navMesh

dtNavMesh const* PathGenerator::_navMesh
private

◆ _navMeshQuery

dtNavMeshQuery const* PathGenerator::_navMeshQuery
private

◆ _pathPoints

Movement::PointsArray PathGenerator::_pathPoints
private

◆ _pathPolyRefs

dtPolyRef PathGenerator::_pathPolyRefs[MAX_PATH_LENGTH]
private

◆ _pointPathLimit

uint32 PathGenerator::_pointPathLimit
private

◆ _polyLength

uint32 PathGenerator::_polyLength
private

◆ _sourceUnit

Unit const* const PathGenerator::_sourceUnit
private

◆ _startPosition

G3D::Vector3 PathGenerator::_startPosition
private

◆ _straightLine

bool PathGenerator::_straightLine
private

◆ _type

PathType PathGenerator::_type
private

◆ _useStraightPath

bool PathGenerator::_useStraightPath
private

The documentation for this class was generated from the following files: