From 4302226a853811f1346ca96a78af0e649cdb4580 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Fri, 4 Jul 2014 22:00:46 +0200 Subject: Core/Spells: Fix Charge pathing Fallback to "straight path" pathing when raycast doesn't find a valid path. Fixes #7931 --- src/server/game/Spells/Spell.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0e0443cc675..1407a4975d9 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5046,12 +5046,19 @@ SpellCastResult Spell::CheckCast(bool strict) //target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); Position pos = target->GetFirstCollisionPosition(CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); + //first try with raycast, if it fails fall back to normal path 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(), false, true); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) - return SPELL_FAILED_NOPATH; + { + result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize(), false, false); + if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) + return SPELL_FAILED_OUT_OF_RANGE; + else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) + return SPELL_FAILED_NOPATH; + } } break; } -- cgit v1.2.3 From 124398feefc64fe77ab01f469fbde645edbeb80f Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 4 Jul 2014 22:22:28 +0100 Subject: Core/Spells: Improve charge path logic, get a point to the target and then reduce it by the necessary distance --- src/server/game/Movement/PathGenerator.cpp | 38 ++++++++++++++++++++++++++++++ src/server/game/Movement/PathGenerator.h | 2 ++ src/server/game/Spells/Spell.cpp | 14 ++++++----- 3 files changed, 48 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index d6912bac7c8..3140fc23296 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -882,3 +882,41 @@ float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) c { return (p1 - p2).squaredLength(); } + +void PathGenerator::ReducePathLenghtByDist(float dist) +{ + if (GetPathType() == PATHFIND_BLANK) + { + TC_LOG_ERROR("maps", "PathGenerator::ReducePathLenghtByDist called before path was built"); + return; + } + + if (_pathPoints.size() < 2) // path building failure + return; + + uint32 i = _pathPoints.size(); + G3D::Vector3 nextVec = _pathPoints[--i]; + while (i > 0) + { + G3D::Vector3 currVec = _pathPoints[--i]; + G3D::Vector3 diffVec = (nextVec - currVec); + float len = diffVec.length(); + if (len > dist) + { + float step = dist / len; + // same as nextVec + _pathPoints[i + 1] -= diffVec * step; + _pathPoints.resize(i + 2); + break; + } + else if (i == 0) // at second point + { + _pathPoints[1] = _pathPoints[0]; + _pathPoints.resize(2); + break; + } + + dist -= len; + nextVec = currVec; // we're going backwards + } +} diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index 6e0d72ec8da..a9a13c37251 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -72,6 +72,8 @@ class PathGenerator PathType GetPathType() const { return _type; } + void ReducePathLenghtByDist(float dist); // path must be already built + private: dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1407a4975d9..0d7dd8819af 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5043,22 +5043,24 @@ SpellCastResult Spell::CheckCast(bool strict) if (!target) return SPELL_FAILED_DONT_REPORT; - //target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - Position pos = target->GetFirstCollisionPosition(CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); + float objSize = target->GetObjectSize(); + float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict - //first try with raycast, if it fails fall back to normal path - 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(), false, true); + m_preGeneratedPath.SetPathLengthLimit(range); + // first try with raycast, if it fails fall back to normal path + bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, true); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) { - result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize(), false, false); + result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, false); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) return SPELL_FAILED_NOPATH; } + + m_preGeneratedPath.ReducePathLenghtByDist(objSize); // move back } break; } -- cgit v1.2.3