Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/src/game/PathFinder.cpp b/src/game/PathFinder.cpp
- index 6e65cc2..2952fd4 100644
- --- a/src/game/PathFinder.cpp
- +++ b/src/game/PathFinder.cpp
- @@ -22,25 +22,38 @@
- #include "../recastnavigation/Detour/Include/DetourCommon.h"
- ////////////////// PathInfo //////////////////
- -PathInfo::PathInfo(const WorldObject* from, const float x, const float y, const float z) :
- - m_navMesh(NULL), m_navMeshQuery(NULL), m_polyLength(0), m_pathPolyRefs(NULL),
- - m_pointPathPointer(0), m_sourceObject(from), m_type(PATHFIND_BLANK)
- +PathInfo::PathInfo(const WorldObject* from, const float destX, const float destY, const float destZ) :
- + m_pathPolyRefs(NULL), m_polyLength(0), m_pointPathPointer(0), m_type(PATHFIND_BLANK),
- + m_sourceObject(from), m_navMesh(NULL), m_navMeshQuery(NULL)
- {
- - setEndPosition(PathNode(x, y, z));
- + PathNode endPoint(destX, destY, destZ);
- + setEndPosition(endPoint);
- +
- + float x,y,z;
- + m_sourceObject->GetPosition(x, y, z);
- + PathNode startPoint(x, y, z);
- + setStartPosition(startPoint);
- +
- + PATH_DEBUG("++ PathInfo::PathInfo for %u \n", m_sourceObject->GetGUID());
- if(m_navMesh = m_sourceObject->GetMap()->GetNavMesh())
- {
- m_navMeshQuery = dtAllocNavMeshQuery();
- m_navMeshQuery->init(m_navMesh, MESH_MAX_NODES);
- - BuildFreshPath();
- + BuildPolyPath(startPoint, endPoint);
- }
- else
- - shortcut();
- + {
- + BuildShortcut();
- + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- + }
- }
- PathInfo::~PathInfo()
- {
- + PATH_DEBUG("++ PathInfo::~PathInfo() for %u \n", m_sourceObject->GetGUID());
- +
- if (m_pathPolyRefs)
- delete [] m_pathPolyRefs;
- @@ -48,87 +61,184 @@ PathInfo::~PathInfo()
- dtFreeNavMeshQuery(m_navMeshQuery);
- }
- -dtPolyRef PathInfo::getPathPolyByPosition(float x, float y, float z)
- +void PathInfo::Update(const float destX, const float destY, const float destZ)
- {
- - if(!m_navMesh || !m_pathPolyRefs)
- - return INVALID_POLYREF;
- + PathNode newDest(destX, destY, destZ);
- + PathNode oldDest = getEndPosition();
- + setEndPosition(newDest);
- - float point[VERTEX_SIZE] = {y, z, x};
- - for(uint32 i = 0; i < m_polyLength; ++i)
- - {
- - const dtMeshTile* tile;
- - const dtPoly* poly;
- - if(!m_navMesh->getTileAndPolyByRef(m_pathPolyRefs[i], &tile, &poly))
- - return INVALID_POLYREF; // m_pathPolyRefs[i] is invalid
- + float x, y, z;
- + m_sourceObject->GetPosition(x, y, z);
- + PathNode newStart(x, y, z);
- + PathNode oldStart = getStartPosition();
- + setStartPosition(newStart);
- - if(!tile)
- - continue; // tile isn't loaded, no information about target polygon
- + PATH_DEBUG("++ PathInfo::Update() for %u \n", m_sourceObject->GetGUID());
- - if(dtPointInPolygon(point, tile->verts, poly->vertCount))
- - return m_pathPolyRefs[i]; // point is inside this polygon
- + // make sure navMesh works - we can run on map w/o mmap
- + if(!m_navMesh)
- + {
- + BuildShortcut();
- + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- + return;
- }
- - return INVALID_POLYREF; // point is not inside the path
- + float dist = 2*m_sourceObject->GetObjectBoundingRadius();
- + bool oldDestInRange = inRange(oldDest, newDest, dist, dist);
- +
- + // this can happen only if caller did a bad job calculating the need for path update
- + if(oldDestInRange && inRange(newStart, oldStart, dist, dist))
- + return;
- +
- + // check if destination moved - if not we can optimize something here
- + // we are following old, precalculated path?
- + if(oldDestInRange && m_pathPoints.size() > 2 && m_pointPathPointer + 1 < m_pathPoints.size())
- + {
- + // our target is not moving - we just coming closer
- + // increment pointPathPointer to the next point in the path
- + m_pointPathPointer++;
- +
- + // we are moving on precalculated path - enjoy the ride
- + PATH_DEBUG("++ PathInfo::Update:: precalculated path\n");
- + setNextPosition(m_pathPoints[m_pointPathPointer]);
- + }
- + else
- + {
- + // target moved, so we need to update the poly path
- + m_pointPathPointer = 0;
- + BuildPolyPath(newStart, newDest);
- + }
- }
- -void PathInfo::BuildFreshPath()
- +dtPolyRef PathInfo::getPathPolyByPosition(PathNode p, float &distance)
- {
- - clear();
- + distance = -1.0f; // set to invalid value
- - float x, y, z;
- - // set start and a default next position
- - m_sourceObject->GetPosition(x, y, z);
- - setStartPosition(PathNode(x, y, z));
- -
- - // get start and end positions
- - float startPos[VERTEX_SIZE] = {y, z, x};
- - getEndPosition(x, y, z);
- - float endPos[VERTEX_SIZE] = {y, z, x};
- + if(!m_navMesh || !m_pathPolyRefs || !m_polyLength)
- + return INVALID_POLYREF;
- - // find start and end poly
- - float extents[VERTEX_SIZE] = {2.0f, 4.0f, 2.0f}; // defines bounds of box for search area
- - dtQueryFilter filter = dtQueryFilter(); // use general filter so we know if we are near navmesh
- + float point[VERTEX_SIZE] = {p.y, p.z, p.x};
- + dtPolyRef nearestPoly = INVALID_POLYREF;
- + float minDist = FLT_MAX;
- - dtPolyRef startPoly = m_navMeshQuery->findNearestPoly(startPos, extents, &filter, NULL);
- - dtPolyRef endPoly = m_navMeshQuery->findNearestPoly(endPos, extents, &filter, NULL);
- + for(uint32 i = 0; i < m_polyLength; ++i)
- + {
- + float closestPoint[VERTEX_SIZE];
- + if (!m_navMeshQuery->closestPointOnPoly(m_pathPolyRefs[i], point, closestPoint))
- + continue;
- +
- + float d = dtVdistSqr(point, closestPoint);
- + if (d < minDist)
- + {
- + minDist = d;
- + nearestPoly = m_pathPolyRefs[i];
- + }
- +
- + if(minDist < 4.0f) // shortcut out - close enough for us
- + break;
- + }
- - BuildPath(startPoly, startPos, endPoly, endPos);
- + distance = dtSqrt(minDist);
- + return (distance < 6.0f) ? nearestPoly : INVALID_POLYREF;
- }
- -void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly, float* endPos)
- +void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos)
- {
- + // *** getting start/end poly logic ***
- +
- + float distToStartPoly, distToEndPoly;
- +
- + // first we check the current path
- + // if the current path doesn't contain the current poly,
- + // we need to use the expensive navMesh.findNearestPoly
- + dtPolyRef startPoly = getPathPolyByPosition(startPos, distToStartPoly);
- + dtPolyRef endPoly = getPathPolyByPosition(endPos, distToEndPoly);
- +
- + float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
- + float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
- +
- + // we don't have it in our old path
- + // try to get it by findNearestPoly()
- + // use huge vertical range here
- + if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
- + {
- + float extents[VERTEX_SIZE] = {3.f, 500.f, 3.f}; // bounds of poly search area
- + dtQueryFilter filter = dtQueryFilter(); // filter for poly search
- + float closestPoint[VERTEX_SIZE];
- +
- + if(startPoly == INVALID_POLYREF)
- + {
- + startPoly = m_navMeshQuery->findNearestPoly(startPoint, extents, &filter, closestPoint);
- + distToStartPoly = dtVdist(closestPoint, startPoint);
- + }
- +
- + if(endPoly == INVALID_POLYREF)
- + {
- + endPoly = m_navMeshQuery->findNearestPoly(endPoint, extents, &filter, closestPoint);
- + distToEndPoly = dtVdist(closestPoint, endPoint);
- + }
- + }
- +
- + // we have a hole in our mesh
- + // make shortcut path and mark it as NOPATH ( with flying exception )
- + // its up to caller how he will use this info
- if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
- {
- - // source or dest not near navmesh polygons:
- - // flying, falling, swimming, or navmesh has a hole
- - // ignore obstacles/terrain is better than giving up
- - //printf("++ PathInfo::BuildPath :: (startPoly == 0 || endPoly == 0) %u\n", m_sourceObject->GetGUID());
- - shortcut();
- + PATH_DEBUG("++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n");
- + BuildShortcut();
- + m_type = canFly() ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH;
- +
- + return;
- + }
- + // we may need a better number here
- + bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f);
- + if(farFromPoly)
- + {
- // TODO: swimming case
- - // in both cases paths will be generated here
- + PATH_DEBUG("++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly);
- if(canFly())
- - m_type = PATHFIND_NORMAL;
- + {
- + BuildShortcut();
- + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
- + PATH_DEBUG("++ BuildPolyPath :: flying case (type %u)\n", m_type);
- + return;
- + }
- + else
- + {
- + float closestPoint[VERTEX_SIZE];
- + // we may want to use closestPointOnPolyBoundary instead
- + if(m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))
- + {
- + dtVcopy(endPoint, closestPoint);
- + setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1]));
- + }
- - return;
- + m_type = PATHFIND_INCOMPLETE;
- + }
- }
- + // *** poly path generating logic ***
- +
- // start and end are on same polygon
- - // just need to move in straight line - nothing more to do here
- + // just need to move in straight line
- if(startPoly == endPoly)
- {
- - //printf("++ PathInfo::BuildPath :: (startPoly == endPoly) %u\n",m_sourceObject->GetGUID());
- - shortcut();
- + PATH_DEBUG("++ BuildPolyPath :: (startPoly == endPoly)\n");
- +
- + BuildShortcut();
- m_pathPolyRefs = new dtPolyRef[1];
- m_pathPolyRefs[0] = startPoly;
- m_polyLength = 1;
- - m_type = PATHFIND_NORMAL;
- + m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL;
- + PATH_DEBUG("++ BuildPolyPath :: path type %d\n", m_type);
- return;
- }
- // look for startPoly/endPoly in current path
- + // TODO: we can merge it with getPathPolyByPosition() loop
- bool startPolyFound = false;
- bool endPolyFound = false;
- uint32 pathStartIndex, pathEndIndex;
- @@ -152,7 +262,7 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- if(startPolyFound && endPolyFound)
- {
- - //printf("++ PathInfo::BuildPath :: (startPolyFound && endPolyFound) %u\n",m_sourceObject->GetGUID());
- + PATH_DEBUG("++ BuildPolyPath :: (startPolyFound && endPolyFound)\n");
- // we moved along the path and the target did not move out of our old poly-path
- // our path is a simple subpath case, we have all the data we need
- @@ -168,7 +278,7 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- }
- else if(startPolyFound && !endPolyFound)
- {
- - //printf("++ PathInfo::BuildPath :: (startPolyFound && !endPolyFound) %u\n",m_sourceObject->GetGUID());
- + PATH_DEBUG("++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n");
- // we are moving on the old path but target moved out
- // so we have atleast part of poly-path ready
- @@ -189,30 +299,28 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- dtPolyRef suffixStartPoly = prefixPathPolys[prefixPolyLength-1];
- // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
- - const dtMeshTile* tile;
- - const dtPoly* poly;
- - if(!m_navMesh->getTileAndPolyByRef(suffixStartPoly, &tile, &poly))
- + float suffixEndPoint[VERTEX_SIZE];
- + if(!m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))
- {
- // suffixStartPoly is invalid somehow, or the navmesh is broken => error state
- sLog.outError("%u's Path Build failed: invalid polyRef in path", m_sourceObject->GetGUID());
- - // we need to get usable start/end polyRefs and recalculate path from scratch
- - BuildFreshPath();
- + BuildShortcut();
- + m_type = PATHFIND_NOPATH;
- return;
- }
- + // generate suffix
- dtQueryFilter filter = createFilter();
- dtPolyRef suffixPathPolys[MAX_PATH_LENGTH];
- - // generate suffix
- uint32 suffixPolyLength = m_navMeshQuery->findPath(
- - suffixStartPoly, // start polygon
- + suffixStartPoly, // start polygon
- endPoly, // end polygon
- - // we might need to get better point here
- - &tile->verts[poly->verts[0]], // start position
- - endPos, // end position
- + suffixEndPoint, // start position
- + endPoint, // end position
- &filter, // polygon search filter
- - suffixPathPolys, // [out] path
- + suffixPathPolys, // [out] path
- MAX_PATH_LENGTH); // max number of polygons in output path
- if(suffixPolyLength == 0)
- @@ -223,6 +331,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- sLog.outError("%u's Path Build failed: 0 length path", m_sourceObject->GetGUID());
- }
- + PATH_DEBUG("++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength);
- +
- // new path = prefix + suffix - overlap
- m_polyLength = prefixPolyLength + suffixPolyLength - 1;
- delete [] m_pathPolyRefs;
- @@ -237,13 +347,13 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- }
- else
- {
- - //printf("++ PathInfo::BuildPath :: (!startPolyFound && !endPolyFound) %u\n",m_sourceObject->GetGUID());
- + PATH_DEBUG("++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n");
- // either we have no path at all -> first run
- // or something went really wrong -> we aren't moving along the path to the target
- // just generate new path
- - // free and invalidate old path data (particularly m_pointPathPointer)
- + // free and invalidate old path data
- clear();
- dtQueryFilter filter = createFilter(); // use special filter so we use proper terrain types
- @@ -252,8 +362,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- m_polyLength = m_navMeshQuery->findPath(
- startPoly, // start polygon
- endPoly, // end polygon
- - startPos, // start position
- - endPos, // end position
- + startPoint, // start position
- + endPoint, // end position
- &filter, // polygon search filter
- pathPolys, // [out] path
- MAX_PATH_LENGTH); // max number of polygons in output path
- @@ -262,7 +372,8 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- {
- // only happens if we passed bad data to findPath(), or navmesh is messed up
- sLog.outError("%u's Path Build failed: 0 length path", m_sourceObject->GetGUID());
- - shortcut();
- + BuildShortcut();
- + m_type = PATHFIND_NOPATH;
- return;
- }
- @@ -270,140 +381,60 @@ void PathInfo::BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly
- memcpy(m_pathPolyRefs, pathPolys, m_polyLength*sizeof(dtPolyRef));
- }
- - if(m_pathPolyRefs[m_polyLength - 1] == endPoly)
- + // by now we know what type of path we can get
- + if(m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE))
- m_type = PATHFIND_NORMAL;
- - else if (m_polyLength < MAX_PATH_LENGTH)
- - m_type = PATHFIND_NOPATH;
- else
- m_type = PATHFIND_INCOMPLETE;
- // generate the point-path out of our up-to-date poly-path
- - updateNextPosition();
- + BuildPointPath(startPoint, endPoint);
- }
- -void PathInfo::Update(const float destX, const float destY, const float destZ)
- +void PathInfo::BuildPointPath(float *startPoint, float *endPoint, bool buildSmoothPath)
- {
- - // make sure navMesh works - we can run on map w/o mmap
- - if(!m_navMesh)
- + // get the actual reachable point on last poly in path
- + float closestPoint[VERTEX_SIZE];
- + if((m_type & PATHFIND_INCOMPLETE)
- + && m_navMeshQuery->closestPointOnPoly(m_pathPolyRefs[m_polyLength-1], endPoint, closestPoint))
- {
- - setEndPosition(PathNode(destX, destY, destZ));
- - shortcut();
- - return;
- + dtVcopy(endPoint, closestPoint);
- + setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1]));
- }
- - if(!m_pathPolyRefs && m_pathPoints.empty())
- + float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
- + uint32 pointCount = 0;
- + if(!buildSmoothPath)
- {
- - // path was not built before, most likely because we are on shortcut path
- - // start from scratch, then return
- - setEndPosition(PathNode(destX, destY, destZ));
- - BuildFreshPath();
- - return;
- + pointCount = m_navMeshQuery->findStraightPath(
- + startPoint, // start position
- + endPoint, // end position
- + m_pathPolyRefs, // current path
- + m_polyLength, // lenth of current path
- + pathPoints, // [out] path corner points
- + NULL, // [out] flags
- + NULL, // [out] shortened path
- + MAX_POINT_PATH_LENGTH); // maximum number of points/polygons to use
- }
- -
- - float x, y, z;
- -
- - m_sourceObject->GetPosition(x, y, z);
- - setStartPosition(PathNode(x, y, z));
- -
- - // check if destination moved - if not we can optimize something here
- - // we are following old, precalculated path?
- - float dist = m_sourceObject->GetObjectBoundingRadius();
- -
- - PathNode oldDest = getEndPosition();
- - PathNode newDest = PathNode(destX, destY, destZ);
- -
- - if(inRange(oldDest, newDest, dist, 2*dist) &&
- - m_pathPoints.size() > 2 &&
- - m_pointPathPointer + 1 < m_pathPoints.size())
- - // our target is not moving - we just coming closer
- - // increment pointPathPointer to the next point in the path
- - m_pointPathPointer++;
- else
- - // target moved, so we need to update the poly path
- - m_pointPathPointer = 0;
- -
- - // update destination
- - setEndPosition(newDest);
- -
- - if(!m_pointPathPointer)
- {
- - float startPos[VERTEX_SIZE] = {y, z, x};
- - float endPos[VERTEX_SIZE] = {destY, destZ, destX};
- -
- - // find start and end poly
- - // first we check the current path
- - // if the current path doesn't contain the current poly,
- - // we need to use the expensive navMesh.findNearestPoly
- -
- - dtPolyRef startPoly = getPathPolyByPosition(x, y, z);
- - dtPolyRef endPoly = getPathPolyByPosition(destX, destY, destZ);
- - if(startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
- - {
- - // start or end is off the path or invalid, need to find the polygon
- - float extents[VERTEX_SIZE] = {2.f, 4.f, 2.f}; // bounds of poly search area
- - dtQueryFilter filter = dtQueryFilter(); // filter for poly search
- -
- - if(startPoly == INVALID_POLYREF)
- - startPoly = m_navMeshQuery->findNearestPoly(startPos, extents, &filter, NULL);
- -
- - if(endPoly == INVALID_POLYREF)
- - endPoly = m_navMeshQuery->findNearestPoly(endPos, extents, &filter, NULL);
- - }
- -
- - BuildPath(startPoly, startPos, endPoly, endPos);
- + pointCount = findSmoothPath(
- + startPoint, // start position
- + endPoint, // end position
- + m_pathPolyRefs, // current path
- + m_polyLength, // length of current path
- + pathPoints, // [out] path corner points
- + MAX_POINT_PATH_LENGTH); // maximum number of points
- }
- - else
- - {
- - // we are moving on prefixed path - enjoy the ride
- - // we already have all the data we need
- - updateNextPosition();
- - }
- -}
- -
- -void PathInfo::updateNextPosition()
- -{
- - // we are moving on precalculated path - enjoy the ride
- - if(m_pointPathPointer)
- - {
- - //printf("++ PathInfo::updateNextPosition :: precalculated path %u\n",m_sourceObject->GetGUID());
- - setNextPosition(m_pathPoints[m_pointPathPointer]);
- - return;
- - }
- -
- - float x, y, z;
- -
- - getStartPosition(x, y, z);
- - float startPos[VERTEX_SIZE] = {y, z, x};
- - getEndPosition(x, y, z);
- - float endPos[VERTEX_SIZE] = {y, z, x};
- -
- -#ifndef _USE_SMOOTH_PATH
- - float pathPoints[MAX_PATH_LENGTH*VERTEX_SIZE];
- - uint32 pointCount = m_navMeshQuery->findStraightPath(
- - startPos, // start position
- - endPos, // end position
- - m_pathPolyRefs, // current path
- - m_polyLength, // lenth of current path
- - pathPoints, // [out] path corner points
- - NULL, // [out] flags
- - NULL, // [out] shortened path PATHFIND TODO: see if this is usable (IE, doesn't leave gaps in path)
- - MAX_PATH_LENGTH); // maximum number of points/polygons to use
- -#else
- - float pathPoints[MAX_SMOOTH_PATH_LENGTH*VERTEX_SIZE];
- - uint32 pointCount = findSmoothPath(
- - startPos, // start position
- - endPos, // end position
- - m_pathPolyRefs, // current path
- - m_polyLength, // length of current path
- - pathPoints, // [out] path corner points
- - MAX_SMOOTH_PATH_LENGTH); // maximum number of points
- -#endif
- if(pointCount < 2)
- {
- // only happens if pass bad data to findStraightPath or navmesh is broken
- - sLog.outError("%u's UpdateNextPosition failed: %u length path", m_sourceObject->GetGUID(), pointCount);
- - shortcut();
- + // single point paths can be generated here
- + // TODO : check the exact cases
- + PATH_DEBUG("++ PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount);
- + BuildShortcut();
- + m_type = PATHFIND_NOPATH;
- return;
- }
- @@ -414,25 +445,22 @@ void PathInfo::updateNextPosition()
- // first point is always our current location - we need the next one
- setNextPosition(m_pathPoints[1]);
- m_pointPathPointer = 1;
- +
- + PATH_DEBUG("++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength);
- }
- -void PathInfo::shortcut()
- +void PathInfo::BuildShortcut()
- {
- clear();
- // make two point path, our curr pos is the start, and dest is the end
- m_pathPoints.resize(2);
- - float x, y, z;
- -
- // set start and a default next position
- - m_sourceObject->GetPosition(x, y, z);
- - m_pathPoints.set(0, PathNode(x, y, z));
- + m_pathPoints.set(0, getStartPosition());
- + m_pathPoints.set(1, getActualEndPosition());
- - getEndPosition(x, y, z);
- - m_pathPoints.set(1, PathNode(x, y, z));
- -
- - setNextPosition(m_pathPoints[1]);
- + setNextPosition(getActualEndPosition());
- m_pointPathPointer = 1;
- m_type = PATHFIND_SHORTCUT;
- @@ -455,10 +483,9 @@ dtQueryFilter PathInfo::createFilter()
- if(creature->canSwim())
- filter.includeFlags |= NAV_WATER; // swim
- - // TODO: check for NAV_MAGMA
- - //if(creature->IsImmunedToDamage(SPELL_SCHOOL_MASK_FIRE)) // immune to fire damage - valid?
- -
- - // TODO: check for NAV_SLIME
- + // creatures don't take environmental damage
- + if(creature->canSwim())
- + filter.includeFlags |= NAV_MAGMA | NAV_SLIME;
- // allow creatures to cheat and use different movement types if they are moved
- // forcefully into terrain they can't normally move in
- @@ -505,16 +532,6 @@ NavTerrain PathInfo::getNavTerrain(float x, float y, float z)
- }
- }
- -bool PathInfo::noPath()
- -{
- - return m_type == PATHFIND_NOPATH;
- -}
- -
- -bool PathInfo::incompletePath()
- -{
- - return m_type == PATHFIND_INCOMPLETE;
- -}
- -
- uint32 PathInfo::fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath,
- const dtPolyRef* visited, const uint32 nvisited)
- {
- @@ -609,7 +626,7 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
- const dtPolyRef* path, const uint32 pathSize,
- float* smoothPath, const uint32 maxSmoothPathSize)
- {
- - uint32 m_nsmoothPath = 0;
- + uint32 nsmoothPath = 0;
- dtPolyRef polys[MAX_PATH_LENGTH];
- memcpy(polys, path, sizeof(dtPolyRef)*pathSize);
- @@ -619,12 +636,12 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
- m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos);
- m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos);
- - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
- - m_nsmoothPath++;
- + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- + nsmoothPath++;
- // Move towards target a small advancement at a time until target reached or
- // when ran out of memory to store the path.
- - while (npolys && m_nsmoothPath < maxSmoothPathSize)
- + while (npolys && nsmoothPath < maxSmoothPathSize)
- {
- // Find location to steer towards.
- float steerPos[VERTEX_SIZE];
- @@ -668,10 +685,10 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
- {
- // Reached end of path.
- dtVcopy(iterPos, targetPos);
- - if (m_nsmoothPath < maxSmoothPathSize)
- + if (nsmoothPath < maxSmoothPathSize)
- {
- - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
- - m_nsmoothPath++;
- + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- + nsmoothPath++;
- }
- break;
- }
- @@ -698,15 +715,15 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
- // Handle the connection.
- if (m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
- {
- - if (m_nsmoothPath < maxSmoothPathSize)
- + if (nsmoothPath < maxSmoothPathSize)
- {
- - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], startPos);
- - m_nsmoothPath++;
- + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
- + nsmoothPath++;
- // Hack to make the dotted path not visible during off-mesh connection.
- - if (m_nsmoothPath & 1)
- + if (nsmoothPath & 1)
- {
- - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], startPos);
- - m_nsmoothPath++;
- + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
- + nsmoothPath++;
- }
- }
- // Move position at the other side of the off-mesh link.
- @@ -718,12 +735,12 @@ uint32 PathInfo::findSmoothPath(const float* startPos, const float* endPos,
- }
- // Store results.
- - if (m_nsmoothPath < maxSmoothPathSize)
- + if (nsmoothPath < maxSmoothPathSize)
- {
- - dtVcopy(&smoothPath[m_nsmoothPath*VERTEX_SIZE], iterPos);
- - m_nsmoothPath++;
- + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- + nsmoothPath++;
- }
- }
- - return m_nsmoothPath;
- + return nsmoothPath;
- }
- diff --git a/src/game/PathFinder.h b/src/game/PathFinder.h
- index 2762b3b..b4be199 100644
- --- a/src/game/PathFinder.h
- +++ b/src/game/PathFinder.h
- @@ -25,16 +25,27 @@
- class WorldObject;
- -#define MESH_MAX_NODES 2048
- -#define MAX_PATH_LENGTH 256
- -#define VERTEX_SIZE 3
- +#define PRINT_DEBUG_INFO 0
- +#define PATH_DEBUG(...) \
- + do { \
- + if (PRINT_DEBUG_INFO) \
- + printf(__VA_ARGS__); \
- + } while(0)
- +
- +
- +// 128*6.0f=768y number_of_points*interval = max_path_len
- +// this is way more than actual evade range
- +// I think we can safely cut those down even more
- +#define MESH_MAX_NODES 1024
- +#define MAX_PATH_LENGTH 128
- +#define MAX_POINT_PATH_LENGTH 128
- -#define _USE_SMOOTH_PATH
- -#define MAX_SMOOTH_PATH_LENGTH 2048
- #define SMOOTH_PATH_STEP_SIZE 6.0f
- -#define SMOOTH_PATH_SLOP 0.2f
- +#define SMOOTH_PATH_SLOP 0.4f
- -#define INVALID_POLYREF 0
- +#define VERTEX_SIZE 3
- +
- +#define INVALID_POLYREF 0
- // see contrib/mmap/src/TileBuilder.h
- enum NavTerrain
- @@ -51,39 +62,35 @@ enum NavTerrain
- enum PathType
- {
- - PATHFIND_BLANK = 0x0000, // path not built yet
- - PATHFIND_NORMAL = 0x0001, // normal path
- - PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior)
- - PATHFIND_INCOMPLETE = 0x0004, // path is too long, more will be calculated later
- - PATHFIND_NOPATH = 0x0008 // could not find a path
- + PATHFIND_BLANK = 0x0000, // path not built yet
- + PATHFIND_NORMAL = 0x0001, // normal path
- + PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior)
- + PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target
- + PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one
- + PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps
- };
- class PathInfo
- {
- public:
- - PathInfo(const WorldObject* from, const float x, const float y, const float z);
- + PathInfo(const WorldObject* from, const float destX, const float destY, const float destZ);
- ~PathInfo();
- + void Update(const float destX, const float destY, const float destZ);
- +
- inline void getStartPosition(float &x, float &y, float &z) { x = m_startPosition.x; y = m_startPosition.y; z = m_startPosition.z; }
- inline void getNextPosition(float &x, float &y, float &z) { x = m_nextPosition.x; y = m_nextPosition.y; z = m_nextPosition.z; }
- inline void getEndPosition(float &x, float &y, float &z) { x = m_endPosition.x; y = m_endPosition.y; z = m_endPosition.z; }
- + inline void getActualEndPosition(float &x, float &y, float &z) { x = m_actualEndPosition.x; y = m_actualEndPosition.y; z = m_actualEndPosition.z; }
- inline PathNode getStartPosition() { return m_startPosition; }
- inline PathNode getNextPosition() { return m_nextPosition; }
- inline PathNode getEndPosition() { return m_endPosition; }
- + inline PathNode getActualEndPosition() { return m_actualEndPosition; }
- inline uint32 getPathPointer() { return m_pointPathPointer == 0 ? 1 : m_pointPathPointer; }
- inline PointPath& getFullPath() { return m_pathPoints; }
- -
- - void Update(const float x, const float y, const float z);
- - bool noPath();
- - bool incompletePath();
- -
- - // only for debug
- - dtNavMesh *getMesh(){ return m_navMesh;}
- - dtNavMeshQuery *getMeshQuery(){ return m_navMeshQuery;}
- - dtPolyRef *getPathPolyRef(){ return m_pathPolyRefs;}
- - uint32 getPolyLength(){ return m_polyLength; }
- + inline PathType getPathType() {return m_type;}
- private:
- @@ -93,19 +100,21 @@ class PathInfo
- PointPath m_pathPoints; // our actual (x,y,z) path to the target
- uint32 m_pointPathPointer; // points to current triple in m_pathPoints - used when dest do not change
- // the triple is the one that is currently being moved toward
- + PathType m_type; // tells what kind of path this is
- PathNode m_startPosition; // {x, y, z} of current location
- PathNode m_nextPosition; // {x, y, z} of next location on the path
- PathNode m_endPosition; // {x, y, z} of the destination
- + PathNode m_actualEndPosition; // {x, y, z} of the closest possible point to given destination
- - const WorldObject * m_sourceObject; // the object that is moving (safe pointer because PathInfo is only accessed from the mover?)
- + const WorldObject *m_sourceObject; // the object that is moving (safe pointer because PathInfo is only accessed from the mover?)
- dtNavMesh * m_navMesh; // the nav mesh
- dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path
- - PathType m_type; // tells what kind of path this is
- inline void setNextPosition(PathNode point) { m_nextPosition = point; }
- inline void setStartPosition(PathNode point) { m_startPosition = point; }
- - inline void setEndPosition(PathNode point) { m_endPosition = point; }
- + inline void setEndPosition(PathNode point) { m_actualEndPosition = point; m_endPosition = point; }
- + inline void setActualEndPosition(PathNode point) { m_actualEndPosition = point; }
- inline void clear()
- {
- @@ -118,20 +127,18 @@ class PathInfo
- m_pointPathPointer = 0;
- }
- - dtPolyRef getPathPolyByPosition(float x, float y, float z);
- -
- - void BuildFreshPath();
- - void BuildPath(dtPolyRef startPoly, float* startPos, dtPolyRef endPoly, float* endPos);
- - // NODE: startPos, endPos is in Y,Z,X format!
- -
- - void updateNextPosition();
- - void shortcut();
- + dtPolyRef getPathPolyByPosition(PathNode p, float &distance);
- - dtQueryFilter createFilter();
- + void BuildPolyPath(PathNode startPos, PathNode endPos);
- + void BuildPointPath(float *startPoint, float *endPoint, bool buildSmoothPath = true);
- + void BuildShortcut();
- + // owner calls
- bool canFly();
- bool canSwim();
- +
- NavTerrain getNavTerrain(float x, float y, float z);
- + dtQueryFilter createFilter();
- // smooth path functions
- uint32 fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath,
- diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp
- index 4fc9a3d..c3c589a 100644
- --- a/src/game/TargetedMovementGenerator.cpp
- +++ b/src/game/TargetedMovementGenerator.cpp
- @@ -22,12 +22,8 @@
- #include "Creature.h"
- #include "DestinationHolderImp.h"
- #include "World.h"
- -//#include "ace/High_Res_Timer.h"
- -
- -#define SMALL_ALPHA 0.05f
- -
- -#include <cmath>
- +//#include "ace/High_Res_Timer.h"
- //class ACE_High_Res_Timer;
- //-----------------------------------------------//
- @@ -91,12 +87,19 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner, bool upd
- //timer.elapsed_microseconds(elapsed);
- //sLog.outDebug("Path found in %llu microseconds", elapsed);
- + // we need to evade - evade code must be called from outside movement master
- + if(i_path->getPathType() & PATHFIND_NOPATH)
- + {
- + owner.evadeWhenCan();
- + return;
- + }
- +
- PointPath pointPath = i_path->getFullPath();
- // get current dest node's index
- uint32 startIndex = i_path->getPathPointer();
- - if (i_destinationHolder.HasArrived())
- + if (i_destinationHolder.HasArrived() && m_pathPointsSent)
- --m_pathPointsSent;
- Traveller<T> traveller(owner);
- @@ -111,7 +114,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner, bool upd
- if (m_pathPointsSent < 2 || startIndex == 1 || i_recalculateTravel || owner.IsStopped())
- {
- // send 10 nodes, or send all nodes if there are less than 10 left
- - m_pathPointsSent = std::min(uint32(10), uint32(pointPath.size() - startIndex));
- + m_pathPointsSent = std::min<uint32>(10, pointPath.size() - startIndex);
- uint32 endIndex = m_pathPointsSent + startIndex;
- // dist to next node + world-unit length of the path
- @@ -201,19 +204,38 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
- if (owner.GetObjectBoundingRadius())
- i_destinationHolder.ResetUpdate(100);
- + //More distance let have better performance, less distance let have more sensitive reaction at target move.
- float dist = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + sWorld.getConfig(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE);
- - //More distance let have better performance, less distance let have more sensitive reaction at target move.
- + float x,y,z;
- + i_target->GetPosition(x, y, z);
- + PathNode target_point(x, y, z);
- + PathNode next_point(x, y, z);
- bool targetMoved = false, needNewDest = false;
- - PathNode next_point(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ());
- -
- if(i_path)
- {
- PathNode end_point = i_path->getEndPosition();
- next_point = i_path->getNextPosition();
- - needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, end_point, dist, 2*dist);
- + // check if we cannot hit the target while we are at the end of the path
- + // if so, evade after EVADE_TIME
- + if(i_destinationHolder.HasArrived()
- + && inRange(next_point, i_path->getActualEndPosition(), dist, dist)
- + && ((i_path->getPathType() & PATHFIND_INCOMPLETE)
- + || !inRange(end_point, target_point, 2*dist, dist + CREATURE_Z_ATTACK_RANGE))
- + )
- + {
- + if (i_evade_timer < time_diff)
- + {
- + owner.evadeWhenCan();
- + return true;
- + }
- + else i_evade_timer -= time_diff;
- + }
- + else i_evade_timer = EVADE_TIME;
- +
- + needNewDest = i_destinationHolder.HasArrived() && !inRange(next_point, i_path->getActualEndPosition(), dist, 2*dist);
- // GetClosePoint() will always return a point on the ground, so we need to
- // handle the difference in elevation when the creature is flying
- @@ -228,13 +250,10 @@ bool TargetedMovementGeneratorMedium<T,D>::Update(T &owner, const uint32 & time_
- // (re)calculate path
- _setTargetLocation(owner, targetMoved || needNewDest);
- - if(i_path)
- - {
- - next_point = i_path->getNextPosition();
- + next_point = i_path->getNextPosition();
- - // Set new Angle For Map::
- - owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
- - }
- + // Set new Angle For Map::
- + owner.SetOrientation(owner.GetAngle(next_point.x, next_point.y));
- }
- // Update the Angle of the target only for Map::, no need to send packet for player
- else if (!i_angle && !owner.HasInArc(0.01f, next_point.x, next_point.y))
- diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h
- index c55b5f2..e062cae 100644
- --- a/src/game/TargetedMovementGenerator.h
- +++ b/src/game/TargetedMovementGenerator.h
- @@ -25,6 +25,8 @@
- #include "FollowerReference.h"
- #include "PathFinder.h"
- +#define EVADE_TIME 2000 // in ms
- +
- class MANGOS_DLL_SPEC TargetedMovementGeneratorBase
- {
- public:
- @@ -40,11 +42,14 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
- {
- protected:
- TargetedMovementGeneratorMedium()
- - : TargetedMovementGeneratorBase(), i_offset(0), i_angle(0), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
- + : TargetedMovementGeneratorBase(), i_offset(0), i_angle(0), i_recalculateTravel(false),
- + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
- TargetedMovementGeneratorMedium(Unit &target)
- - : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
- + : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0), i_recalculateTravel(false),
- + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
- TargetedMovementGeneratorMedium(Unit &target, float offset, float angle)
- - : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_path(NULL), m_pathPointsSent(0) {}
- + : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false),
- + i_path(NULL), m_pathPointsSent(0), i_evade_timer(EVADE_TIME) {}
- ~TargetedMovementGeneratorMedium() { delete i_path; }
- public:
- @@ -72,6 +77,8 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium
- PathInfo* i_path;
- uint32 m_pathPointsSent;
- +
- + uint32 i_evade_timer;
- };
- template<class T>
- diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
- index 15564df..5d40f9e 100644
- --- a/src/game/Unit.cpp
- +++ b/src/game/Unit.cpp
- @@ -267,6 +267,8 @@ Unit::Unit()
- // remove aurastates allowing special moves
- for(int i=0; i < MAX_REACTIVE; ++i)
- m_reactiveTimer[i] = 0;
- +
- + m_evadeWhenCan = false;
- }
- Unit::~Unit()
- @@ -350,6 +352,12 @@ void Unit::Update( uint32 p_time )
- ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
- ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
- + if (m_evadeWhenCan && GetTypeId() == TYPEID_UNIT)
- + {
- + ((Creature*)this)->AI()->EnterEvadeMode();
- + m_evadeWhenCan = false;
- + }
- +
- i_motionMaster.UpdateMotion(p_time);
- }
- diff --git a/src/game/Unit.h b/src/game/Unit.h
- index 5821bfc..0b88077 100644
- --- a/src/game/Unit.h
- +++ b/src/game/Unit.h
- @@ -1917,6 +1917,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- // Movement info
- MovementInfo m_movementInfo;
- + // evade code will be called next update
- + void evadeWhenCan() { m_evadeWhenCan = true; }
- protected:
- explicit Unit ();
- @@ -1967,6 +1969,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
- uint32 m_lastManaUseTimer;
- private:
- + bool m_evadeWhenCan;
- +
- void CleanupDeletedAuras();
- // player or player's pet
- diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp
- index d5a036e..29ec04c 100644
- --- a/src/game/WaypointMovementGenerator.cpp
- +++ b/src/game/WaypointMovementGenerator.cpp
- @@ -307,11 +307,11 @@ void WaypointMovementGenerator<Creature>::MoveToNextNode(CreatureTraveller &trav
- i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z, false);
- PathInfo sub_path(owner, node.x, node.y, node.z);
- - PointPath myPath = sub_path.getFullPath();
- + PointPath pointPath = sub_path.getFullPath();
- float speed = traveller.Speed()*0.001f; // in ms
- - uint32 traveltime = uint32(myPath.GetTotalLength()/speed);
- - owner->SendMonsterMoveByPath(myPath, 1, myPath.size(), owner->GetSplineFlags(), traveltime);
- + uint32 traveltime = uint32(pointPath.GetTotalLength()/speed);
- + owner->SendMonsterMoveByPath(pointPath, 1, pointPath.size(), owner->GetSplineFlags(), traveltime);
- i_nextMoveTime.Reset(traveltime);
- }
- diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp
- index b0d94ae..7aa4af7 100644
- --- a/src/game/debugcmds.cpp
- +++ b/src/game/debugcmds.cpp
- @@ -248,15 +248,17 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- PathInfo path = PathInfo(target, x, y, z);
- PointPath pointPath = path.getFullPath();
- PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName());
- - PSendSysMessage("length %i", pointPath.size());
- + PSendSysMessage("length %i type %u", pointPath.size(), path.getPathType());
- PathNode start = path.getStartPosition();
- PathNode next = path.getNextPosition();
- PathNode end = path.getEndPosition();
- + PathNode actualEnd = path.getActualEndPosition();
- - PSendSysMessage("start (%f,%f,%f)", start.x, start.y, start.z);
- - PSendSysMessage("next (%f,%f,%f)", next.x, next.y, next.z);
- - PSendSysMessage("end (%f,%f,%f)", end.x, end.y, end.z);
- + PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z);
- + PSendSysMessage("next (%.3f, %.3f, %.3f)", next.x, next.y, next.z);
- + PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z);
- + PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z);
- // this entry visible only to GM's with "gm on"
- static const uint32 WAYPOINT_NPC_ENTRY = 1;
- @@ -268,7 +270,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- else if(w && strcmp(w, "verts") == 0)
- {
- PSendSysMessage("mmap verts:");
- -
- +
- // units
- Player* player = m_session->GetPlayer();
- Unit* target = getSelectedUnit();
- @@ -285,50 +287,55 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- player->GetPosition(x, y, z);
- float end[VERTEX_SIZE] = {y, z, x};
- - PathInfo path = PathInfo(target, x, y, z);
- -
- - if(path.getPolyLength() == 0)
- - {
- - PSendSysMessage("Path is 0 length");
- - return true;
- - }
- + dtNavMesh* navmesh = player->GetMap()->GetNavMesh();
- + dtNavMeshQuery* query = dtAllocNavMeshQuery();
- + query->init(navmesh, MESH_MAX_NODES);
- float extents[VERTEX_SIZE] = {2.f, 4.f, 2.f};
- dtQueryFilter filter = dtQueryFilter();
- - dtPolyRef startPoly = path.getMeshQuery()->findNearestPoly(start, extents, &filter, 0);
- - dtPolyRef endPoly = path.getMeshQuery()->findNearestPoly(end, extents, &filter, 0);
- + dtPolyRef startPoly = query->findNearestPoly(start, extents, &filter, NULL);
- + dtPolyRef endPoly = query->findNearestPoly(end, extents, &filter, NULL);
- // vertices stuff
- + float vertices[DT_VERTS_PER_POLYGON*VERTEX_SIZE];
- const dtMeshTile* tile;
- const dtPoly* poly;
- - path.getMesh()->getTileAndPolyByRef(startPoly, &tile, &poly);
- - float vertices[DT_VERTS_PER_POLYGON*VERTEX_SIZE];
- + uint32 nv = 0;
- // startpoly vertices
- - int nv = 0;
- - for (uint32 i = 0; i < poly->vertCount; ++i)
- + if(!navmesh->getTileAndPolyByRef(startPoly, &tile, &poly))
- + PSendSysMessage("No start poly found.");
- + else
- {
- - dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
- - nv++;
- - }
- + for (uint32 i = 0; i < poly->vertCount; ++i)
- + {
- + dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
- + nv++;
- + }
- - PSendSysMessage("Poly vertices for %i:", startPoly);
- - for(uint32 i = 0; i < poly->vertCount; ++i)
- - PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
- + PSendSysMessage("Poly vertices for %i:", startPoly);
- + for(uint32 i = 0; i < poly->vertCount; ++i)
- + PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
- + }
- // endpoly vertices
- - path.getMesh()->getTileAndPolyByRef(endPoly, &tile, &poly);
- - nv = 0;
- - for (uint32 i = 0; i < poly->vertCount; ++i)
- + if(!navmesh->getTileAndPolyByRef(endPoly, &tile, &poly))
- + PSendSysMessage("No end poly found.");
- + else
- {
- - dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
- - nv++;
- - }
- + nv = 0;
- + for (uint32 i = 0; i < poly->vertCount; ++i)
- + {
- + dtVcopy(&vertices[nv*VERTEX_SIZE], &tile->verts[poly->verts[i]*VERTEX_SIZE]);
- + nv++;
- + }
- - PSendSysMessage("Poly vertices for %i:", endPoly);
- - for(uint32 i = 0; i < poly->vertCount; ++i)
- - PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
- + PSendSysMessage("Poly vertices for %i:", endPoly);
- + for(uint32 i = 0; i < poly->vertCount; ++i)
- + PSendSysMessage("(%.2f,%.2f,%.2f)", vertices[i*VERTEX_SIZE], vertices[i*VERTEX_SIZE+1], vertices[i*VERTEX_SIZE+2]);
- + }
- + dtFreeNavMeshQuery(query);
- return true;
- }
- else if(w && strcmp(w, "tileloc") == 0)
- @@ -362,8 +369,8 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- // navmesh poly -> navmesh tile location
- dtPolyRef polyRef = query->findNearestPoly(location, extents, &(dtQueryFilter()), NULL);
- -
- - if(!polyRef)
- +
- + if(polyRef == INVALID_POLYREF)
- PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)");
- else
- {
- @@ -399,6 +406,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- delete [] data;
- }
- + dtFreeNavMeshQuery(query);
- return true;
- }
- else if(w && strcmp(w, "polytest") == 0)
- @@ -413,7 +421,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- float x, y, z;
- player->GetPosition(x, y, z);
- float location[VERTEX_SIZE] = {y, z, x};
- - float extents[VERTEX_SIZE] = {2.f,4.f,2.f};
- + float extents[VERTEX_SIZE] = {1.f,2.f,1.f};
- dtQueryFilter filter = dtQueryFilter();
- filter.includeFlags = 0xFFFF;
- @@ -424,6 +432,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- PSendSysMessage("(%.2f,%.2f,%.2f)", y, z, x);
- PSendSysMessage("%u", nearestPoly);
- + dtFreeNavMeshQuery(query);
- return true;
- }
- else if(w && strcmp(w, "loadedtiles") == 0)
- @@ -443,6 +452,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y);
- }
- + dtFreeNavMeshQuery(query);
- return true;
- }
- else if(w && strcmp(w, "stats") == 0)
- @@ -491,7 +501,7 @@ bool ChatHandler::HandleDebugMoveMapCommand(char* args)
- PSendSysMessage(" polytest print the current polygon's ref");
- PSendSysMessage(" loadedtiles print tile info for loaded tiles");
- PSendSysMessage(" stats print stats about the current navmesh");
- -
- +
- return true;
- }
Add Comment
Please, Sign In to add comment