mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-29 21:32:52 +01:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user