Core/MMAPs: Add support for raycast

Add an optional parameter "straightLine" to PathGenerator::CalculatePath() which will use raycast instead of path finding and will return only complete path from start to end position.
Implement this new type of path in SPELL_EFFECT_CHARGE , fixing strange behaviors when using Charge with mmaps enabled.
This commit is contained in:
jackpoz
2014-02-24 21:01:50 +01:00
parent a5d860c4fa
commit 272009ebee
3 changed files with 92 additions and 23 deletions

View File

@@ -29,7 +29,7 @@
////////////////// PathGenerator //////////////////
PathGenerator::PathGenerator(const Unit* owner) :
_polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false),
_forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH),
_forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), _straightLine(false),
_endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL),
_navMeshQuery(NULL)
{
@@ -53,7 +53,7 @@ PathGenerator::~PathGenerator()
TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow());
}
bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest)
bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest, bool straightLine)
{
float x, y, z;
_sourceUnit->GetPosition(x, y, z);
@@ -68,6 +68,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
SetStartPosition(start);
_forceDestination = forceDest;
_straightLine = straightLine;
TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow());
@@ -338,15 +339,45 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
// generate suffix
uint32 suffixPolyLength = 0;
dtStatus dtResult = _navMeshQuery->findPath(
suffixStartPoly, // start polygon
endPoly, // end polygon
suffixEndPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs + prefixPolyLength - 1, // [out] path
(int*)&suffixPolyLength,
MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path
dtStatus dtResult;
if (_straightLine)
{
float hit = 0;
float hitNormal[3];
memset(hitNormal, 0, sizeof(hitNormal));
dtResult = _navMeshQuery->raycast(
suffixStartPoly,
suffixEndPoint,
endPoint,
&_filter,
&hit,
hitNormal,
_pathPolyRefs + prefixPolyLength - 1,
(int*)&suffixPolyLength,
MAX_PATH_LENGTH - prefixPolyLength);
// raycast() sets hit to FLT_MAX if there is a ray between start and end
if (hit != FLT_MAX)
{
// the ray hit something, return no path instead of the incomplete one
_type = PATHFIND_NOPATH;
return;
}
}
else
{
dtResult = _navMeshQuery->findPath(
suffixStartPoly, // start polygon
endPoly, // end polygon
suffixEndPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs + prefixPolyLength - 1, // [out] path
(int*)&suffixPolyLength,
MAX_PATH_LENGTH - prefixPolyLength); // max number of polygons in output path
}
if (!suffixPolyLength || dtStatusFailed(dtResult))
{
@@ -372,15 +403,44 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
// free and invalidate old path data
Clear();
dtStatus dtResult = _navMeshQuery->findPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
dtStatus dtResult;
if (_straightLine)
{
float hit = 0;
float hitNormal[3];
memset(hitNormal, 0, sizeof(hitNormal));
dtResult = _navMeshQuery->raycast(
startPoly,
startPoint,
endPoint,
&_filter,
&hit,
hitNormal,
_pathPolyRefs,
(int*)&_polyLength,
MAX_PATH_LENGTH);
// raycast() sets hit to FLT_MAX if there is a ray between start and end
if (hit != FLT_MAX)
{
// the ray hit something, return no path instead of the incomplete one
_type = PATHFIND_NOPATH;
return;
}
}
else
{
dtResult = _navMeshQuery->findPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
}
if (!_polyLength || dtStatusFailed(dtResult))
{
@@ -407,7 +467,15 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin
float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
uint32 pointCount = 0;
dtStatus dtResult = DT_FAILURE;
if (_useStraightPath)
if (_straightLine)
{
// if the path is a straight line then start and end position are enough
dtResult = DT_SUCCESS;
pointCount = 2;
memcpy(&pathPoints[0], startPoint, sizeof(float)* 3);
memcpy(&pathPoints[3], endPoint, sizeof(float)* 3);
}
else if (_useStraightPath)
{
dtResult = _navMeshQuery->findStraightPath(
startPoint, // start position

View File

@@ -57,7 +57,7 @@ class PathGenerator
// Calculate the path from owner to given destination
// return: true if new path was calculated, false otherwise (no change needed)
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false, bool straightLine = false);
// option setters - use optional
void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }
@@ -83,6 +83,7 @@ class PathGenerator
bool _useStraightPath; // type of path will be generated
bool _forceDestination; // when set, we will always arrive at given point
uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH)
bool _straightLine; // use raycast if true for a straight line path
G3D::Vector3 _startPosition; // {x, y, z} of current location
G3D::Vector3 _endPosition; // {x, y, z} of the destination

View File

@@ -5000,7 +5000,7 @@ SpellCastResult Spell::CheckCast(bool strict)
target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster));
m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f);
bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize());
bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize(), false, true);
if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
return SPELL_FAILED_OUT_OF_RANGE;
else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH)