Guest User

Untitled

a guest
Oct 24th, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 51.46 KB | None | 0 0
  1. diff --git a/src/game/PathFinder.cpp b/src/game/PathFinder.cpp
  2. index 6e65cc2..2952fd4 100644
  3. --- a/src/game/PathFinder.cpp
  4. +++ b/src/game/PathFinder.cpp
  5. @@ -22,25 +22,38 @@
  6. #include "../recastnavigation/Detour/Include/DetourCommon.h"
  7.  
  8. ////////////////// PathInfo //////////////////
  9. -PathInfo::PathInfo(const WorldObject* from, const float x, const float y, const float z) :
  10. - m_navMesh(NULL), m_navMeshQuery(NULL), m_polyLength(0), m_pathPolyRefs(NULL),
  11. - m_pointPathPointer(0), m_sourceObject(from), m_type(PATHFIND_BLANK)
  12. +PathInfo::PathInfo(const WorldObject* from, const float destX, const float destY, const float destZ) :
  13. + m_pathPolyRefs(NULL), m_polyLength(0), m_pointPathPointer(0), m_type(PATHFIND_BLANK),
  14. + m_sourceObject(from), m_navMesh(NULL), m_navMeshQuery(NULL)
  15. {
  16. - setEndPosition(PathNode(x, y, z));
  17. + PathNode endPoint(destX, destY, destZ);
  18. + setEndPosition(endPoint);
  19. +
  20. + float x,y,z;
  21. + m_sourceObject->GetPosition(x, y, z);
  22. + PathNode startPoint(x, y, z);
  23. + setStartPosition(startPoint);
  24. +
  25. + PATH_DEBUG("++ PathInfo::PathInfo for %u \n", m_sourceObject->GetGUID());
  26.  
  27. if(m_navMesh = m_sourceObject->GetMap()->GetNavMesh())
  28. {
  29. m_navMeshQuery = dtAllocNavMeshQuery();
  30. m_navMeshQuery->init(m_navMesh, MESH_MAX_NODES);
  31.  
  32. - BuildFreshPath();
  33. + BuildPolyPath(startPoint, endPoint);
  34. }
  35. else
  36. - shortcut();
  37. + {
  38. + BuildShortcut();
  39. + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
  40. + }
  41. }
  42.  
  43. PathInfo::~PathInfo()
  44. {
  45. + PATH_DEBUG("++ PathInfo::~PathInfo() for %u \n", m_sourceObject->GetGUID());
  46. +
  47. if (m_pathPolyRefs)
  48. delete [] m_pathPolyRefs;
  49.  
  50. @@ -48,87 +61,184 @@ PathInfo::~PathInfo()
  51. dtFreeNavMeshQuery(m_navMeshQuery);
  52. }
  53.  
  54. -dtPolyRef PathInfo::getPathPolyByPosition(float x, float y, float z)
  55. +void PathInfo::Update(const float destX, const float destY, const float destZ)
  56. {
  57. - if(!m_navMesh || !m_pathPolyRefs)
  58. - return INVALID_POLYREF;
  59. + PathNode newDest(destX, destY, destZ);
  60. + PathNode oldDest = getEndPosition();
  61. + setEndPosition(newDest);
  62.  
  63. - float point[VERTEX_SIZE] = {y, z, x};
  64. - for(uint32 i = 0; i < m_polyLength; ++i)
  65. - {
  66. - const dtMeshTile* tile;
  67. - const dtPoly* poly;
  68. - if(!m_navMesh->getTileAndPolyByRef(m_pathPolyRefs[i], &tile, &poly))
  69. - return INVALID_POLYREF; // m_pathPolyRefs[i] is invalid
  70. + float x, y, z;
  71. + m_sourceObject->GetPosition(x, y, z);
  72. + PathNode newStart(x, y, z);
  73. + PathNode oldStart = getStartPosition();
  74. + setStartPosition(newStart);
  75.  
  76. - if(!tile)
  77. - continue; // tile isn't loaded, no information about target polygon
  78. + PATH_DEBUG("++ PathInfo::Update() for %u \n", m_sourceObject->GetGUID());
  79.  
  80. - if(dtPointInPolygon(point, tile->verts, poly->vertCount))
  81. - return m_pathPolyRefs[i]; // point is inside this polygon
  82. + // make sure navMesh works - we can run on map w/o mmap
  83. + if(!m_navMesh)
  84. + {
  85. + BuildShortcut();
  86. + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
  87. + return;
  88. }
  89.  
  90. - return INVALID_POLYREF; // point is not inside the path
  91. + float dist = 2*m_sourceObject->GetObjectBoundingRadius();
  92. + bool oldDestInRange = inRange(oldDest, newDest, dist, dist);
  93. +
  94. + // this can happen only if caller did a bad job calculating the need for path update
  95. + if(oldDestInRange && inRange(newStart, oldStart, dist, dist))
  96. + return;
  97. +
  98. + // check if destination moved - if not we can optimize something here
  99. + // we are following old, precalculated path?
  100. + if(oldDestInRange && m_pathPoints.size() > 2 && m_pointPathPointer + 1 < m_pathPoints.size())
  101. + {
  102. + // our target is not moving - we just coming closer
  103. + // increment pointPathPointer to the next point in the path
  104. + m_pointPathPointer++;
  105. +
  106. + // we are moving on precalculated path - enjoy the ride
  107. + PATH_DEBUG("++ PathInfo::Update:: precalculated path\n");
  108. + setNextPosition(m_pathPoints[m_pointPathPointer]);
  109. + }
  110. + else
  111. + {
  112. + // target moved, so we need to update the poly path
  113. + m_pointPathPointer = 0;
  114. + BuildPolyPath(newStart, newDest);
  115. + }
  116. }
  117.  
  118. -void PathInfo::BuildFreshPath()
  119. +dtPolyRef PathInfo::getPathPolyByPosition(PathNode p, float &distance)
  120. {
  121. - clear();
  122. + distance = -1.0f; // set to invalid value
  123.  
  124. - float x, y, z;
  125. - // set start and a default next position
  126. - m_sourceObject->GetPosition(x, y, z);
  127. - setStartPosition(PathNode(x, y, z));
  128. -
  129. - // get start and end positions
  130. - float startPos[VERTEX_SIZE] = {y, z, x};
  131. - getEndPosition(x, y, z);
  132. - float endPos[VERTEX_SIZE] = {y, z, x};
  133. + if(!m_navMesh || !m_pathPolyRefs || !m_polyLength)
  134. + return INVALID_POLYREF;
  135.  
  136. - // find start and end poly
  137. - float extents[VERTEX_SIZE] = {2.0f, 4.0f, 2.0f}; // defines bounds of box for search area
  138. - dtQueryFilter filter = dtQueryFilter(); // use general filter so we know if we are near navmesh
  139. + float point[VERTEX_SIZE] = {p.y, p.z, p.x};
  140. + dtPolyRef nearestPoly = INVALID_POLYREF;
  141. + float minDist = FLT_MAX;
  142.  
  143. - dtPolyRef startPoly = m_navMeshQuery->findNearestPoly(startPos, extents, &filter, NULL);
  144. - dtPolyRef endPoly = m_navMeshQuery->findNearestPoly(endPos, extents, &filter, NULL);
  145. + for(uint32 i = 0; i < m_polyLength; ++i)
  146. + {
  147. + float closestPoint[VERTEX_SIZE];
  148. + if (!m_navMeshQuery->closestPointOnPoly(m_pathPolyRefs[i], point, closestPoint))
  149. + continue;
  150. +
  151. + float d = dtVdistSqr(point, closestPoint);
  152. + if (d < minDist)
  153. + {
  154. + minDist = d;
  155. + nearestPoly = m_pathPolyRefs[i];
  156. + }
  157. +
  158. + if(minDist < 4.0f) // shortcut out - close enough for us
  159. + break;
  160. + }
  161.  
  162. - BuildPath(startPoly, startPos, endPoly, endPos);
  163. + distance = dtSqrt(minDist);
  164. + return (distance < 6.0f) ? nearestPoly : INVALID_POLYREF;
  165. }
  166.  
  167. -void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly, float* endPos)
  168. +void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos)
  169. {
  170. + // *** getting start/end poly logic ***
  171. +
  172. + float distToStartPoly, distToEndPoly;
  173. +
  174. + // first we check the current path
  175. + // if the current path doesn't contain the current poly,
  176. + // we need to use the expensive navMesh.findNearestPoly
  177. + dtPolyRef startPoly = getPathPolyByPosition(startPos, distToStartPoly);
  178. + dtPolyRef endPoly = getPathPolyByPosition(endPos, distToEndPoly);
  179. +
  180. + float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
  181. + float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
  182. +
  183. + // we don't have it in our old path
  184. + // try to get it by findNearestPoly()
  185. + // use huge vertical range here
  186. + if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
  187. + {
  188. + float extents[VERTEX_SIZE] = {3.f, 500.f, 3.f}; // bounds of poly search area
  189. + dtQueryFilter filter = dtQueryFilter(); // filter for poly search
  190. + float closestPoint[VERTEX_SIZE];
  191. +
  192. + if(startPoly == INVALID_POLYREF)
  193. + {
  194. + startPoly = m_navMeshQuery->findNearestPoly(startPoint, extents, &filter, closestPoint);
  195. + distToStartPoly = dtVdist(closestPoint, startPoint);
  196. + }
  197. +
  198. + if(endPoly == INVALID_POLYREF)
  199. + {
  200. + endPoly = m_navMeshQuery->findNearestPoly(endPoint, extents, &filter, closestPoint);
  201. + distToEndPoly = dtVdist(closestPoint, endPoint);
  202. + }
  203. + }
  204. +
  205. + // we have a hole in our mesh
  206. + // make shortcut path and mark it as NOPATH ( with flying exception )
  207. + // its up to caller how he will use this info
  208. if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
  209. {
  210. - // source or dest not near navmesh polygons:
  211. - // flying, falling, swimming, or navmesh has a hole
  212. - // ignore obstacles/terrain is better than giving up
  213. - //printf("++ PathInfo::BuildPath :: (startPoly == 0 || endPoly == 0) %u\n", m_sourceObject->GetGUID());
  214. - shortcut();
  215. + PATH_DEBUG("++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n");
  216. + BuildShortcut();
  217. + m_type = canFly() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH;
  218. +
  219. + return;
  220. + }
  221.  
  222. + // we may need a better number here
  223. + bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f);
  224. + if(farFromPoly)
  225. + {
  226. // TODO: swimming case
  227. - // in both cases paths will be generated here
  228. + PATH_DEBUG("++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly);
  229. if(canFly())
  230. - m_type = PATHFIND_NORMAL;
  231. + {
  232. + BuildShortcut();
  233. + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
  234. + PATH_DEBUG("++ BuildPolyPath :: flying case (type %u)\n", m_type);
  235. + return;
  236. + }
  237. + else
  238. + {
  239. + float closestPoint[VERTEX_SIZE];
  240. + // we may want to use closestPointOnPolyBoundary instead
  241. + if(m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))
  242. + {
  243. + dtVcopy(endPoint, closestPoint);
  244. + setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1]));
  245. + }
  246.  
  247. - return;
  248. + m_type = PATHFIND_INCOMPLETE;
  249. + }
  250. }
  251.  
  252. + // *** poly path generating logic ***
  253. +
  254. // start and end are on same polygon
  255. - // just need to move in straight line - nothing more to do here
  256. + // just need to move in straight line
  257. if(startPoly == endPoly)
  258. {
  259. - //printf("++ PathInfo::BuildPath :: (startPoly == endPoly) %u\n",m_sourceObject->GetGUID());
  260. - shortcut();
  261. + PATH_DEBUG("++ BuildPolyPath :: (startPoly == endPoly)\n");
  262. +
  263. + BuildShortcut();
  264.  
  265. m_pathPolyRefs = new dtPolyRef[1];
  266. m_pathPolyRefs[0] = startPoly;
  267. m_polyLength = 1;
  268.  
  269. - m_type = PATHFIND_NORMAL;
  270. + m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL;
  271. + PATH_DEBUG("++ BuildPolyPath :: path type %d\n", m_type);
  272. return;
  273. }
  274.  
  275. // look for startPoly/endPoly in current path
  276. + // TODO: we can merge it with getPathPolyByPosition() loop
  277. bool startPolyFound = false;
  278. bool endPolyFound = false;
  279. uint32 pathStartIndex, pathEndIndex;
  280. @@ -152,7 +262,7 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  281.  
  282. if(startPolyFound && endPolyFound)
  283. {
  284. - //printf("++ PathInfo::BuildPath :: (startPolyFound && endPolyFound) %u\n",m_sourceObject->GetGUID());
  285. + PATH_DEBUG("++ BuildPolyPath :: (startPolyFound && endPolyFound)\n");
  286.  
  287. // we moved along the path and the target did not move out of our old poly-path
  288. // our path is a simple subpath case, we have all the data we need
  289. @@ -168,7 +278,7 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  290. }
  291. else if(startPolyFound && !endPolyFound)
  292. {
  293. - //printf("++ PathInfo::BuildPath :: (startPolyFound && !endPolyFound) %u\n",m_sourceObject->GetGUID());
  294. + PATH_DEBUG("++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n");
  295.  
  296. // we are moving on the old path but target moved out
  297. // so we have atleast part of poly-path ready
  298. @@ -189,30 +299,28 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  299. dtPolyRef suffixStartPoly = prefixPathPolys[prefixPolyLength-1];
  300.  
  301. // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
  302. - const dtMeshTile* tile;
  303. - const dtPoly* poly;
  304. - if(!m_navMesh->getTileAndPolyByRef(suffixStartPoly, &tile, &poly))
  305. + float suffixEndPoint[VERTEX_SIZE];
  306. + if(!m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))
  307. {
  308. // suffixStartPoly is invalid somehow, or the navmesh is broken => error state
  309. sLog.outError("%u's Path Build failed: invalid polyRef in path", m_sourceObject->GetGUID());
  310.  
  311. - // we need to get usable start/end polyRefs and recalculate path from scratch
  312. - BuildFreshPath();
  313. + BuildShortcut();
  314. + m_type = PATHFIND_NOPATH;
  315. return;
  316. }
  317.  
  318. + // generate suffix
  319. dtQueryFilter filter = createFilter();
  320. dtPolyRef suffixPathPolys[MAX_PATH_LENGTH];
  321.  
  322. - // generate suffix
  323. uint32 suffixPolyLength = m_navMeshQuery->findPath(
  324. - suffixStartPoly, // start polygon
  325. + suffixStartPoly, // start polygon
  326. endPoly, // end polygon
  327. - // we might need to get better point here
  328. - &tile->verts[poly->verts[0]], // start position
  329. - endPos, // end position
  330. + suffixEndPoint, // start position
  331. + endPoint, // end position
  332. &filter, // polygon search filter
  333. - suffixPathPolys, // [out] path
  334. + suffixPathPolys, // [out] path
  335. MAX_PATH_LENGTH); // max number of polygons in output path
  336.  
  337. if(suffixPolyLength == 0)
  338. @@ -223,6 +331,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  339. sLog.outError("%u's Path Build failed: 0 length path", m_sourceObject->GetGUID());
  340. }
  341.  
  342. + PATH_DEBUG("++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength);
  343. +
  344. // new path = prefix + suffix - overlap
  345. m_polyLength = prefixPolyLength + suffixPolyLength - 1;
  346. delete [] m_pathPolyRefs;
  347. @@ -237,13 +347,13 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  348. }
  349. else
  350. {
  351. - //printf("++ PathInfo::BuildPath :: (!startPolyFound && !endPolyFound) %u\n",m_sourceObject->GetGUID());
  352. + PATH_DEBUG("++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n");
  353.  
  354. // either we have no path at all -> first run
  355. // or something went really wrong -> we aren't moving along the path to the target
  356. // just generate new path
  357.  
  358. - // free and invalidate old path data (particularly m_pointPathPointer)
  359. + // free and invalidate old path data
  360. clear();
  361.  
  362. dtQueryFilter filter = createFilter(); // use special filter so we use proper terrain types
  363. @@ -252,8 +362,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  364. m_polyLength = m_navMeshQuery->findPath(
  365. startPoly, // start polygon
  366. endPoly, // end polygon
  367. - startPos, // start position
  368. - endPos, // end position
  369. + startPoint, // start position
  370. + endPoint, // end position
  371. &filter, // polygon search filter
  372. pathPolys, // [out] path
  373. MAX_PATH_LENGTH); // max number of polygons in output path
  374. @@ -262,7 +372,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  375. {
  376. // only happens if we passed bad data to findPath(), or navmesh is messed up
  377. sLog.outError("%u's Path Build failed: 0 length path", m_sourceObject->GetGUID());
  378. - shortcut();
  379. + BuildShortcut();
  380. + m_type = PATHFIND_NOPATH;
  381. return;
  382. }
  383.  
  384. @@ -270,140 +381,60 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
  385. memcpy(m_pathPolyRefs, pathPolys, m_polyLength*sizeof(dtPolyRef));
  386. }
  387.  
  388. - if(m_pathPolyRefs[m_polyLength - 1] == endPoly)
  389. + // by now we know what type of path we can get
  390. + if(m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE))
  391. m_type = PATHFIND_NORMAL;
  392. - else if (m_polyLength < MAX_PATH_LENGTH)
  393. - m_type = PATHFIND_NOPATH;
  394. else
  395. m_type = PATHFIND_INCOMPLETE;
  396.  
  397. // generate the point-path out of our up-to-date poly-path
  398. - updateNextPosition();
  399. + BuildPointPath(startPoint, endPoint);
  400. }
  401.  
  402. -void PathInfo::Update(const float destX, const float destY, const float destZ)
  403. +void PathInfo::BuildPointPath(float *startPoint, float *endPoint, bool buildSmoothPath)
  404. {
  405. - // make sure navMesh works - we can run on map w/o mmap
  406. - if(!m_navMesh)
  407. + // get the actual reachable point on last poly in path
  408. + float closestPoint[VERTEX_SIZE];
  409. + if((m_type & PATHFIND_INCOMPLETE)
  410. + && m_navMeshQuery->closestPointOnPoly(m_pathPolyRefs[m_polyLength-1], endPoint, closestPoint))
  411. {
  412. - setEndPosition(PathNode(destX, destY, destZ));
  413. - shortcut();
  414. - return;
  415. + dtVcopy(endPoint, closestPoint);
  416. + setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1]));
  417. }
  418.  
  419. - if(!m_pathPolyRefs && m_pathPoints.empty())
  420. + float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
  421. + uint32 pointCount = 0;
  422. + if(!buildSmoothPath)
  423. {
  424. - // path was not built before, most likely because we are on shortcut path
  425. - // start from scratch, then return
  426. - setEndPosition(PathNode(destX, destY, destZ));
  427. - BuildFreshPath();
  428. - return;
  429. + pointCount = m_navMeshQuery->findStraightPath(
  430. + startPoint, // start position
  431. + endPoint, // end position
  432. + m_pathPolyRefs, // current path
  433. + m_polyLength, // lenth of current path
  434. + pathPoints, // [out] path corner points
  435. + NULL, // [out] flags
  436. + NULL, // [out] shortened path
  437. + MAX_POINT_PATH_LENGTH); // maximum number of points/polygons to use
  438. }
  439. -
  440. - float x, y, z;
  441. -
  442. - m_sourceObject->GetPosition(x, y, z);
  443. - setStartPosition(PathNode(x, y, z));
  444. -
  445. - // check if destination moved - if not we can optimize something here
  446. - // we are following old, precalculated path?
  447. - float dist = m_sourceObject->GetObjectBoundingRadius();
  448. -
  449. - PathNode oldDest = getEndPosition();
  450. - PathNode newDest = PathNode(destX, destY, destZ);
  451. -
  452. - if(inRange(oldDest, newDest, dist, 2*dist) &&
  453. - m_pathPoints.size() > 2 &&
  454. - m_pointPathPointer + 1 < m_pathPoints.size())
  455. - // our target is not moving - we just coming closer
  456. - // increment pointPathPointer to the next point in the path
  457. - m_pointPathPointer++;
  458. else
  459. - // target moved, so we need to update the poly path
  460. - m_pointPathPointer = 0;
  461. -
  462. - // update destination
  463. - setEndPosition(newDest);
  464. -
  465. - if(!m_pointPathPointer)
  466. {
  467. - float startPos[VERTEX_SIZE] = {y, z, x};
  468. - float endPos[VERTEX_SIZE] = {destY, destZ, destX};
  469. -
  470. - // find start and end poly
  471. - // first we check the current path
  472. - // if the current path doesn't contain the current poly,
  473. - // we need to use the expensive navMesh.findNearestPoly
  474. -
  475. - dtPolyRef startPoly = getPathPolyByPosition(x, y, z);
  476. - dtPolyRef endPoly = getPathPolyByPosition(destX, destY, destZ);
  477. - if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
  478. - {
  479. - // start or end is off the path or invalid, need to find the polygon
  480. - float extents[VERTEX_SIZE] = {2.f, 4.f, 2.f}; // bounds of poly search area
  481. - dtQueryFilter filter = dtQueryFilter(); // filter for poly search
  482. -
  483. - if(startPoly == INVALID_POLYREF)
  484. - startPoly = m_navMeshQuery->findNearestPoly(startPos, extents, &filter, NULL);
  485. -
  486. - if(endPoly == INVALID_POLYREF)
  487. - endPoly = m_navMeshQuery->findNearestPoly(endPos, extents, &filter, NULL);
  488. - }
  489. -
  490. - BuildPath(startPoly, startPos, endPoly, endPos);
  491. + pointCount = findSmoothPath(
  492. + startPoint, // start position
  493. + endPoint, // end position
  494. + m_pathPolyRefs, // current path
  495. + m_polyLength, // length of current path
  496. + pathPoints, // [out] path corner points
  497. + MAX_POINT_PATH_LENGTH); // maximum number of points
  498. }
  499. - else
  500. - {
  501. - // we are moving on prefixed path - enjoy the ride
  502. - // we already have all the data we need
  503. - updateNextPosition();
  504. - }
  505. -}
  506. -
  507. -void PathInfo::updateNextPosition()
  508. -{
  509. - // we are moving on precalculated path - enjoy the ride
  510. - if(m_pointPathPointer)
  511. - {
  512. - //printf("++ PathInfo::updateNextPosition :: precalculated path %u\n",m_sourceObject->GetGUID());
  513. - setNextPosition(m_pathPoints[m_pointPathPointer]);
  514. - return;
  515. - }
  516. -
  517. - float x, y, z;
  518. -
  519. - getStartPosition(x, y, z);
  520. - float startPos[VERTEX_SIZE] = {y, z, x};
  521. - getEndPosition(x, y, z);
  522. - float endPos[VERTEX_SIZE] = {y, z, x};
  523. -
  524. -#ifndef _USE_SMOOTH_PATH
  525. - float pathPoints[MAX_PATH_LENGTH*VERTEX_SIZE];
  526. - uint32 pointCount = m_navMeshQuery->findStraightPath(
  527. - startPos, // start position
  528. - endPos, // end position
  529. - m_pathPolyRefs, // current path
  530. - m_polyLength, // lenth of current path
  531. - pathPoints, // [out] path corner points
  532. - NULL, // [out] flags
  533. - NULL, // [out] shortened path PATHFIND TODO: see if this is usable (IE, doesn't leave gaps in path)
  534. - MAX_PATH_LENGTH); // maximum number of points/polygons to use
  535. -#else
  536. - float pathPoints[MAX_SMOOTH_PATH_LENGTH*VERTEX_SIZE];
  537. - uint32 pointCount = findSmoothPath(
  538. - startPos, // start position
  539. - endPos, // end position
  540. - m_pathPolyRefs, // current path
  541. - m_polyLength, // length of current path
  542. - pathPoints, // [out] path corner points
  543. - MAX_SMOOTH_PATH_LENGTH); // maximum number of points
  544. -#endif
  545.  
  546. if(pointCount < 2)
  547. {
  548. // only happens if pass bad data to findStraightPath or navmesh is broken
  549. - sLog.outError("%u's UpdateNextPosition failed: %u length path", m_sourceObject->GetGUID(), pointCount);
  550. - shortcut();
  551. + // single point paths can be generated here
  552. + // TODO : check the exact cases
  553. + PATH_DEBUG("++ PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount);
  554. + BuildShortcut();
  555. + m_type = PATHFIND_NOPATH;
  556. return;
  557. }
  558.  
  559. @@ -414,25 +445,22 @@ void PathInfo::updateNextPosition()
  560. // first point is always our current location - we need the next one
  561. setNextPosition(m_pathPoints[1]);
  562. m_pointPathPointer = 1;
  563. +
  564. + PATH_DEBUG("++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength);
  565. }
  566.  
  567. -void PathInfo::shortcut()
  568. +void PathInfo::BuildShortcut()
  569. {
  570. clear();
  571.  
  572. // make two point path, our curr pos is the start, and dest is the end
  573. m_pathPoints.resize(2);
  574.  
  575. - float x, y, z;
  576. -
  577. // set start and a default next position
  578. - m_sourceObject->GetPosition(x, y, z);
  579. - m_pathPoints.set(0, PathNode(x, y, z));
  580. + m_pathPoints.set(0, getStartPosition());
  581. + m_pathPoints.set(1, getActualEndPosition());
  582.  
  583. - getEndPosition(x, y, z);
  584. - m_pathPoints.set(1, PathNode(x, y, z));
  585. -
  586. - setNextPosition(m_pathPoints[1]);
  587. + setNextPosition(getActualEndPosition());
  588. m_pointPathPointer = 1;
  589.  
  590. m_type = PATHFIND_SHORTCUT;
  591. @@ -455,10 +483,9 @@ dtQueryFilter PathInfo::createFilter()
  592. if(creature->canSwim())
  593. filter.includeFlags |= NAV_WATER; // swim
  594.  
  595. - // TODO: check for NAV_MAGMA
  596. - //if(creature->IsImmunedToDamage(SPELL_SCHOOL_MASK_FIRE)) // immune to fire damage - valid?
  597. -
  598. - // TODO: check for NAV_SLIME
  599. + // creatures don't take environmental damage
  600. + if(creature->canSwim())
  601. + filter.includeFlags |= NAV_MAGMA | NAV_SLIME;
  602.  
  603. // allow creatures to cheat and use different movement types if they are moved
  604. // forcefully into terrain they can't normally move in
  605. @@ -505,16 +532,6 @@ NavTerrain PathInfo::getNavTerrain(float x, float y, float z)
  606. }
  607. }
  608.  
  609. -bool PathInfo::noPath()
  610. -{
  611. - return m_type == PATHFIND_NOPATH;
  612. -}
  613. -
  614. -bool PathInfo::incompletePath()
  615. -{
  616. - return m_type == PATHFIND_INCOMPLETE;
  617. -}
  618. -
  619. uint32 PathInfo::fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath,
  620. const dtPolyRef* visited, const uint32 nvisited)
  621. {
  622. @@ -609,7 +626,7 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
  623. const dtPolyRef* path, const uint32 pathSize,
  624. float* smoothPath, const uint32 maxSmoothPathSize)
  625. {
  626. - uint32 m_nsmoothPath = 0;
  627. + uint32 nsmoothPath = 0;
  628.  
  629. dtPolyRef polys[MAX_PATH_LENGTH];
  630. memcpy(polys, path, sizeof(dtPolyRef)*pathSize);
  631. @@ -619,12 +636,12 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
  632. m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos);
  633. m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos);
  634.  
  635. - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
  636. - m_nsmoothPath++;
  637. + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
  638. + nsmoothPath++;
  639.  
  640. // Move towards target a small advancement at a time until target reached or
  641. // when ran out of memory to store the path.
  642. - while (npolys && m_nsmoothPath < maxSmoothPathSize)
  643. + while (npolys && nsmoothPath < maxSmoothPathSize)
  644. {
  645. // Find location to steer towards.
  646. float steerPos[VERTEX_SIZE];
  647. @@ -668,10 +685,10 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
  648. {
  649. // Reached end of path.
  650. dtVcopy(iterPos, targetPos);
  651. - if (m_nsmoothPath < maxSmoothPathSize)
  652. + if (nsmoothPath < maxSmoothPathSize)
  653. {
  654. - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
  655. - m_nsmoothPath++;
  656. + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
  657. + nsmoothPath++;
  658. }
  659. break;
  660. }
  661. @@ -698,15 +715,15 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
  662. // Handle the connection.
  663. if (m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
  664. {
  665. - if (m_nsmoothPath < maxSmoothPathSize)
  666. + if (nsmoothPath < maxSmoothPathSize)
  667. {
  668. - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], startPos);
  669. - m_nsmoothPath++;
  670. + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
  671. + nsmoothPath++;
  672. // Hack to make the dotted path not visible during off-mesh connection.
  673. - if (m_nsmoothPath & 1)
  674. + if (nsmoothPath & 1)
  675. {
  676. - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], startPos);
  677. - m_nsmoothPath++;
  678. + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
  679. + nsmoothPath++;
  680. }
  681. }
  682. // Move position at the other side of the off-mesh link.
  683. @@ -718,12 +735,12 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
  684. }
  685.  
  686. // Store results.
  687. - if (m_nsmoothPath < maxSmoothPathSize)
  688. + if (nsmoothPath < maxSmoothPathSize)
  689. {
  690. - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
  691. - m_nsmoothPath++;
  692. + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
  693. + nsmoothPath++;
  694. }
  695. }
  696.  
  697. - return m_nsmoothPath;
  698. + return nsmoothPath;
  699. }
  700. diff --git a/src/game/PathFinder.h b/src/game/PathFinder.h
  701. index 2762b3b..b4be199 100644
  702. --- a/src/game/PathFinder.h
  703. +++ b/src/game/PathFinder.h
  704. @@ -25,16 +25,27 @@
  705.  
  706. class WorldObject;
  707.  
  708. -#define MESH_MAX_NODES 2048
  709. -#define MAX_PATH_LENGTH 256
  710. -#define VERTEX_SIZE 3
  711. +#define PRINT_DEBUG_INFO 0
  712. +#define PATH_DEBUG(...) \
  713. + do { \
  714. + if (PRINT_DEBUG_INFO) \
  715. + printf(__VA_ARGS__); \
  716. + } while(0)
  717. +
  718. +
  719. +// 128*6.0f=768y number_of_points*interval = max_path_len
  720. +// this is way more than actual evade range
  721. +// I think we can safely cut those down even more
  722. +#define MESH_MAX_NODES 1024
  723. +#define MAX_PATH_LENGTH 128
  724. +#define MAX_POINT_PATH_LENGTH 128
  725.  
  726. -#define _USE_SMOOTH_PATH
  727. -#define MAX_SMOOTH_PATH_LENGTH 2048
  728. #define SMOOTH_PATH_STEP_SIZE 6.0f
  729. -#define SMOOTH_PATH_SLOP 0.2f
  730. +#define SMOOTH_PATH_SLOP 0.4f
  731.  
  732. -#define INVALID_POLYREF 0
  733. +#define VERTEX_SIZE 3
  734. +
  735. +#define INVALID_POLYREF 0
  736.  
  737. // see contrib/mmap/src/TileBuilder.h
  738. enum NavTerrain
  739. @@ -51,39 +62,35 @@ enum NavTerrain
  740.  
  741. enum PathType
  742. {
  743. - PATHFIND_BLANK = 0x0000, // path not built yet
  744. - PATHFIND_NORMAL = 0x0001, // normal path
  745. - PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior)
  746. - PATHFIND_INCOMPLETE = 0x0004, // path is too long, more will be calculated later
  747. - PATHFIND_NOPATH = 0x0008 // could not find a path
  748. + PATHFIND_BLANK = 0x0000, // path not built yet
  749. + PATHFIND_NORMAL = 0x0001, // normal path
  750. + PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior)
  751. + PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target
  752. + PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one
  753. + PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps
  754. };
  755.  
  756. class PathInfo
  757. {
  758. public:
  759. - PathInfo(const WorldObject* from, const float x, const float y, const float z);
  760. + PathInfo(const WorldObject* from, const float destX, const float destY, const float destZ);
  761. ~PathInfo();
  762.  
  763. + void Update(const float destX, const float destY, const float destZ);
  764. +
  765. inline void getStartPosition(float &x, float &y, float &z) { x = m_startPosition.x; y = m_startPosition.y; z = m_startPosition.z; }
  766. inline void getNextPosition(float &x, float &y, float &z) { x = m_nextPosition.x; y = m_nextPosition.y; z = m_nextPosition.z; }
  767. inline void getEndPosition(float &x, float &y, float &z) { x = m_endPosition.x; y = m_endPosition.y; z = m_endPosition.z; }
  768. + inline void getActualEndPosition(float &x, float &y, float &z) { x = m_actualEndPosition.x; y = m_actualEndPosition.y; z = m_actualEndPosition.z; }
  769.  
  770. inline PathNode getStartPosition() { return m_startPosition; }
  771. inline PathNode getNextPosition() { return m_nextPosition; }
  772. inline PathNode getEndPosition() { return m_endPosition; }
  773. + inline PathNode getActualEndPosition() { return m_actualEndPosition; }
  774.  
  775. inline uint32 getPathPointer() { return m_pointPathPointer == 0 ? 1 : m_pointPathPointer; }
  776. inline PointPath& getFullPath() { return m_pathPoints; }
  777. -
  778. - void Update(const float x, const float y, const float z);
  779. - bool noPath();
  780. - bool incompletePath();
  781. -
  782. - // only for debug
  783. - dtNavMesh *getMesh(){ return m_navMesh;}
  784. - dtNavMeshQuery *getMeshQuery(){ return m_navMeshQuery;}
  785. - dtPolyRef *getPathPolyRef(){ return m_pathPolyRefs;}
  786. - uint32 getPolyLength(){ return m_polyLength; }
  787. + inline PathType getPathType() {return m_type;}
  788.  
  789. private:
  790.  
  791. @@ -93,19 +100,21 @@ class PathInfo
  792. PointPath m_pathPoints; // our actual (x,y,z) path to the target
  793. uint32 m_pointPathPointer; // points to current triple in m_pathPoints - used when dest do not change
  794. // the triple is the one that is currently being moved toward
  795. + PathType m_type; // tells what kind of path this is
  796.  
  797. PathNode m_startPosition; // {x, y, z} of current location
  798. PathNode m_nextPosition; // {x, y, z} of next location on the path
  799. PathNode m_endPosition; // {x, y, z} of the destination
  800. + PathNode m_actualEndPosition; // {x, y, z} of the closest possible point to given destination
  801.  
  802. - const WorldObject * m_sourceObject; // the object that is moving (safe pointer because PathInfo is only accessed from the mover?)
  803. + const WorldObject *m_sourceObject; // the object that is moving (safe pointer because PathInfo is only accessed from the mover?)
  804. dtNavMesh * m_navMesh; // the nav mesh
  805. dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path
  806. - PathType m_type; // tells what kind of path this is
  807.  
  808. inline void setNextPosition(PathNode point) { m_nextPosition = point; }
  809. inline void setStartPosition(PathNode point) { m_startPosition = point; }
  810. - inline void setEndPosition(PathNode point) { m_endPosition = point; }
  811. + inline void setEndPosition(PathNode point) { m_actualEndPosition = point; m_endPosition = point; }
  812. + inline void setActualEndPosition(PathNode point) { m_actualEndPosition = point; }
  813.  
  814. inline void clear()
  815. {
  816. @@ -118,20 +127,18 @@ class PathInfo
  817. m_pointPathPointer = 0;
  818. }
  819.  
  820. - dtPolyRef getPathPolyByPosition(float x, float y, float z);
  821. -
  822. - void BuildFreshPath();
  823. - void BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly, float* endPos);
  824. - // NODE: startPos, endPos is in Y,Z,X format!
  825. -
  826. - void updateNextPosition();
  827. - void shortcut();
  828. + dtPolyRef getPathPolyByPosition(PathNode p, float &distance);
  829.  
  830. - dtQueryFilter createFilter();
  831. + void BuildPolyPath(PathNode startPos, PathNode endPos);
  832. + void BuildPointPath(float *startPoint, float *endPoint, bool buildSmoothPath = true);
  833. + void BuildShortcut();
  834.  
  835. + // owner calls
  836. bool canFly();
  837. bool canSwim();
  838. +
  839. NavTerrain getNavTerrain(float x, float y, float z);
  840. + dtQueryFilter createFilter();
  841.  
  842. // smooth path functions
  843. uint32 fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath,
  844. diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp
  845. index 4fc9a3d..c3c589a 100644
  846. --- a/src/game/TargetedMovementGenerator.cpp
  847. +++ b/src/game/TargetedMovementGenerator.cpp
  848. @@ -22,12 +22,8 @@
  849. #include "Creature.h"
  850. #include "DestinationHolderImp.h"
  851. #include "World.h"
  852. -//#include "ace/High_Res_Timer.h"
  853. -
  854. -#define SMALL_ALPHA 0.05f
  855. -
  856. -#include <cmath>
  857.  
  858. +//#include "ace/High_Res_Timer.h"
  859. //class ACE_High_Res_Timer;
  860.  
  861. //-----------------------------------------------//
  862. @@ -91,12 +87,19 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner, bool upd
  863. //timer.elapsed_microseconds(elapsed);
  864. //sLog.outDebug("Path found in %llu microseconds", elapsed);
  865.  
  866. + // we need to evade - evade code must be called from outside movement master
  867. + if(i_path->getPathType() & PATHFIND_NOPATH)
  868. + {
  869. + owner.evadeWhenCan();
  870. + return;
  871. + }
  872. +
  873. PointPath pointPath = i_path->getFullPath();
  874.  
  875. // get current dest node's index
  876. uint32 startIndex = i_path->getPathPointer();
  877.  
  878. - if (i_destinationHolder.HasArrived())
  879. + if (i_destinationHolder.HasArrived() && m_pathPointsSent)
  880. --m_pathPointsSent;
  881.  
  882. Traveller<T> traveller(owner);
  883. @@ -111,7 +114,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner, bool upd
  884. if (m_pathPointsSent < 2 || startIndex == 1 || i_recalculateTravel || owner.IsStopped())
  885. {
  886. // send 10 nodes, or send all nodes if there are less than 10 left
  887. - m_pathPointsSent = std::min(uint32(10), uint32(pointPath.size() - startIndex));
  888. + m_pathPointsSent = std::min<uint32>(10, pointPath.size() - startIndex);
  889. uint32 endIndex = m_pathPointsSent + startIndex;
  890.  
  891. // dist to next node + world-unit length of the path
  892. @@ -201,19 +204,38 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
  893. if (owner.GetObjectBoundingRadius())
  894. i_destinationHolder.ResetUpdate(100);
  895.  
  896. + //More distance let have better performance, less distance let have more sensitive reaction at target move.
  897. float dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
  898.  
  899. - //More distance let have better performance, less distance let have more sensitive reaction at target move.
  900. + float x,y,z;
  901. + i_target->GetPosition(x, y, z);
  902. + PathNode target_point(x, y, z);
  903. + PathNode next_point(x, y, z);
  904.  
  905. bool targetMoved = false, needNewDest = false;
  906. - PathNode next_point(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ());
  907. -
  908. if(i_path)
  909. {
  910. PathNode end_point = i_path->getEndPosition();
  911. next_point = i_path->getNextPosition();
  912.  
  913. - needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, end_point, dist, 2*dist);
  914. + // check if we cannot hit the target while we are at the end of the path
  915. + // if so, evade after EVADE_TIME
  916. + if(i_destinationHolder.HasArrived()
  917. + && inRange(next_point, i_path->getActualEndPosition(), dist, dist)
  918. + && ((i_path->getPathType() & PATHFIND_INCOMPLETE)
  919. + || !inRange(end_point, target_point, 2*dist, dist + CREATURE_Z_ATTACK_RANGE))
  920. + )
  921. + {
  922. + if (i_evade_timer < time_diff)
  923. + {
  924. + owner.evadeWhenCan();
  925. + return true;
  926. + }
  927. + else i_evade_timer -= time_diff;
  928. + }
  929. + else i_evade_timer = EVADE_TIME;
  930. +
  931. + needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, i_path->getActualEndPosition(), dist, 2*dist);
  932.  
  933. // GetClosePoint() will always return a point on the ground, so we need to
  934. // handle the difference in elevation when the creature is flying
  935. @@ -228,13 +250,10 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
  936. // (re)calculate path
  937. _setTargetLocation(owner, targetMoved || needNewDest);
  938.  
  939. - if(i_path)
  940. - {
  941. - next_point = i_path->getNextPosition();
  942. + next_point = i_path->getNextPosition();
  943.  
  944. - // Set new Angle For Map::
  945. - owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
  946. - }
  947. + // Set new Angle For Map::
  948. + owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
  949. }
  950. // Update the Angle of the target only for Map::, no need to send packet for player
  951. else if (!i_angle && !owner.HasInArc(0.01f, next_point.x, next_point.y))
  952. diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h
  953. index c55b5f2..e062cae 100644
  954. --- a/src/game/TargetedMovementGenerator.h
  955. +++ b/src/game/TargetedMovementGenerator.h
  956. @@ -25,6 +25,8 @@
  957. #include "FollowerReference.h"
  958. #include "PathFinder.h"
  959.  
  960. +#define EVADE_TIME 2000 // in ms
  961. +
  962. class MANGOS_DLL_SPEC TargetedMovementGeneratorBase
  963. {
  964. public:
  965. @@ -40,11 +42,14 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
  966. {
  967. protected:
  968. TargetedMovementGeneratorMedium()
  969. - : TargetedMovementGeneratorBase(), i_offset(0), i_angle(0), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
  970. + : TargetedMovementGeneratorBase(), i_offset(0), i_angle(0), i_recalculateTravel(false),
  971. + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
  972. TargetedMovementGeneratorMedium(Unit &target)
  973. - : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
  974. + : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false),
  975. + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
  976. TargetedMovementGeneratorMedium(Unit &target, float offset, float angle)
  977. - : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
  978. + : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false),
  979. + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
  980. ~TargetedMovementGeneratorMedium() { delete i_path; }
  981.  
  982. public:
  983. @@ -72,6 +77,8 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
  984.  
  985. PathInfo* i_path;
  986. uint32 m_pathPointsSent;
  987. +
  988. + uint32 i_evade_timer;
  989. };
  990.  
  991. template<class T>
  992. diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
  993. index 15564df..5d40f9e 100644
  994. --- a/src/game/Unit.cpp
  995. +++ b/src/game/Unit.cpp
  996. @@ -267,6 +267,8 @@ Unit::Unit()
  997. // remove aurastates allowing special moves
  998. for(int i=0; i < MAX_REACTIVE; ++i)
  999. m_reactiveTimer[i] = 0;
  1000. +
  1001. + m_evadeWhenCan = false;
  1002. }
  1003.  
  1004. Unit::~Unit()
  1005. @@ -350,6 +352,12 @@ void Unit::Update( uint32 p_time )
  1006. ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
  1007. ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
  1008.  
  1009. + if (m_evadeWhenCan && GetTypeId() == TYPEID_UNIT)
  1010. + {
  1011. + ((Creature*)this)->AI()->EnterEvadeMode();
  1012. + m_evadeWhenCan = false;
  1013. + }
  1014. +
  1015. i_motionMaster.UpdateMotion(p_time);
  1016. }
  1017.  
  1018. diff --git a/src/game/Unit.h b/src/game/Unit.h
  1019. index 5821bfc..0b88077 100644
  1020. --- a/src/game/Unit.h
  1021. +++ b/src/game/Unit.h
  1022. @@ -1917,6 +1917,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  1023. // Movement info
  1024. MovementInfo m_movementInfo;
  1025.  
  1026. + // evade code will be called next update
  1027. + void evadeWhenCan() { m_evadeWhenCan = true; }
  1028. protected:
  1029. explicit Unit ();
  1030.  
  1031. @@ -1967,6 +1969,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
  1032. uint32 m_lastManaUseTimer;
  1033.  
  1034. private:
  1035. + bool m_evadeWhenCan;
  1036. +
  1037. void CleanupDeletedAuras();
  1038.  
  1039. // player or player's pet
  1040. diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp
  1041. index d5a036e..29ec04c 100644
  1042. --- a/src/game/WaypointMovementGenerator.cpp
  1043. +++ b/src/game/WaypointMovementGenerator.cpp
  1044. @@ -307,11 +307,11 @@ void WaypointMovementGenerator<Creature>::MoveToNextNode(CreatureTraveller &trav
  1045. i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z, false);
  1046.  
  1047. PathInfo sub_path(owner, node.x, node.y, node.z);
  1048. - PointPath myPath = sub_path.getFullPath();
  1049. + PointPath pointPath = sub_path.getFullPath();
  1050.  
  1051. float speed = traveller.Speed()*0.001f; // in ms
  1052. - uint32 traveltime = uint32(myPath.GetTotalLength()/speed);
  1053. - owner->SendMonsterMoveByPath(myPath, 1, myPath.size(), owner->GetSplineFlags(), traveltime);
  1054. + uint32 traveltime = uint32(pointPath.GetTotalLength()/speed);
  1055. + owner->SendMonsterMoveByPath(pointPath, 1, pointPath.size(), owner->GetSplineFlags(), traveltime);
  1056.  
  1057. i_nextMoveTime.Reset(traveltime);
  1058. }
  1059. diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp
  1060. index b0d94ae..7aa4af7 100644
  1061. --- a/src/game/debugcmds.cpp
  1062. +++ b/src/game/debugcmds.cpp
  1063. @@ -248,15 +248,17 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1064. PathInfo path = PathInfo(target, x, y, z);
  1065. PointPath pointPath = path.getFullPath();
  1066. PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName());
  1067. - PSendSysMessage("length %i", pointPath.size());
  1068. + PSendSysMessage("length %i type %u", pointPath.size(), path.getPathType());
  1069.  
  1070. PathNode start = path.getStartPosition();
  1071. PathNode next = path.getNextPosition();
  1072. PathNode end = path.getEndPosition();
  1073. + PathNode actualEnd = path.getActualEndPosition();
  1074.  
  1075. - PSendSysMessage("start (%f,%f,%f)", start.x, start.y, start.z);
  1076. - PSendSysMessage("next (%f,%f,%f)", next.x, next.y, next.z);
  1077. - PSendSysMessage("end (%f,%f,%f)", end.x, end.y, end.z);
  1078. + PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z);
  1079. + PSendSysMessage("next (%.3f, %.3f, %.3f)", next.x, next.y, next.z);
  1080. + PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z);
  1081. + PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z);
  1082.  
  1083. // this entry visible only to GM's with "gm on"
  1084. static const uint32 WAYPOINT_NPC_ENTRY = 1;
  1085. @@ -268,7 +270,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1086. else if(w && strcmp(w, "verts") == 0)
  1087. {
  1088. PSendSysMessage("mmap verts:");
  1089. -
  1090. +
  1091. // units
  1092. Player* player = m_session->GetPlayer();
  1093. Unit* target = getSelectedUnit();
  1094. @@ -285,50 +287,55 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1095. player->GetPosition(x, y, z);
  1096. float end[VERTEX_SIZE] = {y, z, x};
  1097.  
  1098. - PathInfo path = PathInfo(target, x, y, z);
  1099. -
  1100. - if(path.getPolyLength() == 0)
  1101. - {
  1102. - PSendSysMessage("Path is 0 length");
  1103. - return true;
  1104. - }
  1105. + dtNavMesh* navmesh = player->GetMap()->GetNavMesh();
  1106. + dtNavMeshQuery* query = dtAllocNavMeshQuery();
  1107. + query->init(navmesh, MESH_MAX_NODES);
  1108.  
  1109. float extents[VERTEX_SIZE] = {2.f, 4.f, 2.f};
  1110. dtQueryFilter filter = dtQueryFilter();
  1111. - dtPolyRef startPoly = path.getMeshQuery()->findNearestPoly(start, extents, &filter, 0);
  1112. - dtPolyRef endPoly = path.getMeshQuery()->findNearestPoly(end, extents, &filter, 0);
  1113. + dtPolyRef startPoly = query->findNearestPoly(start, extents, &filter, NULL);
  1114. + dtPolyRef endPoly = query->findNearestPoly(end, extents, &filter, NULL);
  1115.  
  1116. // vertices stuff
  1117. + float vertices[DT_VERTS_PER_POLYGON*VERTEX_SIZE];
  1118. const dtMeshTile* tile;
  1119. const dtPoly* poly;
  1120. - path.getMesh()->getTileAndPolyByRef(startPoly, &tile, &poly);
  1121. - float vertices[DT_VERTS_PER_POLYGON*VERTEX_SIZE];
  1122. + uint32 nv = 0;
  1123.  
  1124. // startpoly vertices
  1125. - int nv = 0;
  1126. - for (uint32 i = 0; i < poly->vertCount; ++i)
  1127. + if(!navmesh->getTileAndPolyByRef(startPoly, &tile, &poly))
  1128. + PSendSysMessage("No start poly found.");
  1129. + else
  1130. {
  1131. - dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
  1132. - nv++;
  1133. - }
  1134. + for (uint32 i = 0; i < poly->vertCount; ++i)
  1135. + {
  1136. + dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
  1137. + nv++;
  1138. + }
  1139.  
  1140. - PSendSysMessage("Poly vertices for %i:", startPoly);
  1141. - for(uint32 i = 0; i < poly->vertCount; ++i)
  1142. - PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
  1143. + PSendSysMessage("Poly vertices for %i:", startPoly);
  1144. + for(uint32 i = 0; i < poly->vertCount; ++i)
  1145. + PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
  1146. + }
  1147.  
  1148. // endpoly vertices
  1149. - path.getMesh()->getTileAndPolyByRef(endPoly, &tile, &poly);
  1150. - nv = 0;
  1151. - for (uint32 i = 0; i < poly->vertCount; ++i)
  1152. + if(!navmesh->getTileAndPolyByRef(endPoly, &tile, &poly))
  1153. + PSendSysMessage("No end poly found.");
  1154. + else
  1155. {
  1156. - dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
  1157. - nv++;
  1158. - }
  1159. + nv = 0;
  1160. + for (uint32 i = 0; i < poly->vertCount; ++i)
  1161. + {
  1162. + dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
  1163. + nv++;
  1164. + }
  1165.  
  1166. - PSendSysMessage("Poly vertices for %i:", endPoly);
  1167. - for(uint32 i = 0; i < poly->vertCount; ++i)
  1168. - PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
  1169. + PSendSysMessage("Poly vertices for %i:", endPoly);
  1170. + for(uint32 i = 0; i < poly->vertCount; ++i)
  1171. + PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
  1172. + }
  1173.  
  1174. + dtFreeNavMeshQuery(query);
  1175. return true;
  1176. }
  1177. else if(w && strcmp(w, "tileloc") == 0)
  1178. @@ -362,8 +369,8 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1179.  
  1180. // navmesh poly -> navmesh tile location
  1181. dtPolyRef polyRef = query->findNearestPoly(location, extents, &(dtQueryFilter()), NULL);
  1182. -
  1183. - if(!polyRef)
  1184. +
  1185. + if(polyRef == INVALID_POLYREF)
  1186. PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)");
  1187. else
  1188. {
  1189. @@ -399,6 +406,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1190. delete [] data;
  1191. }
  1192.  
  1193. + dtFreeNavMeshQuery(query);
  1194. return true;
  1195. }
  1196. else if(w && strcmp(w, "polytest") == 0)
  1197. @@ -413,7 +421,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1198. float x, y, z;
  1199. player->GetPosition(x, y, z);
  1200. float location[VERTEX_SIZE] = {y, z, x};
  1201. - float extents[VERTEX_SIZE] = {2.f,4.f,2.f};
  1202. + float extents[VERTEX_SIZE] = {1.f,2.f,1.f};
  1203. dtQueryFilter filter = dtQueryFilter();
  1204. filter.includeFlags = 0xFFFF;
  1205.  
  1206. @@ -424,6 +432,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1207. PSendSysMessage("(%.2f,%.2f,%.2f)", y, z, x);
  1208. PSendSysMessage("%u", nearestPoly);
  1209.  
  1210. + dtFreeNavMeshQuery(query);
  1211. return true;
  1212. }
  1213. else if(w && strcmp(w, "loadedtiles") == 0)
  1214. @@ -443,6 +452,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1215. PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y);
  1216. }
  1217.  
  1218. + dtFreeNavMeshQuery(query);
  1219. return true;
  1220. }
  1221. else if(w && strcmp(w, "stats") == 0)
  1222. @@ -491,7 +501,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
  1223. PSendSysMessage(" polytest print the current polygon's ref");
  1224. PSendSysMessage(" loadedtiles print tile info for loaded tiles");
  1225. PSendSysMessage(" stats print stats about the current navmesh");
  1226. -
  1227. +
  1228. return true;
  1229. }
Add Comment
Please, Sign In to add comment