diff options
author | Ovah <dreadkiller@gmx.de> | 2020-05-01 13:43:24 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-01-01 23:30:48 +0100 |
commit | 26e7da1622b217f66d28771836014ca9023efd16 (patch) | |
tree | 6b0787286ac4f2127febb8dafc49f407c3fd0655 | |
parent | 99aef26563c689bdf4f334bfc27b442c6730eabc (diff) |
Core/Objects: further improvements for MovePositionToFirstCollision (#24523)
* Core/Objects: further improvements for MovePositionToFirstCollision
* the PathGenerator will now normalize incomplete destinations as well
* normalize destination positions before launching detour raycasts to get better direction data
* exclude unwanted pathfinding results from further use to avoid unintended behaivior
* Core/PathFinding: Split PATHFIND_FARFROMPOLY into PATHFIND_FARFROMPOLY_START and PATHFIND_FARFROMPOLY_END for start and end position
Handle PATHFIND_FARFROMPOLY_END as valid in MovePositionToFirstCollision
Co-authored-by: jackpoz <giacomopoz@gmail.com>
(cherry picked from commit 6485422c6127262855b3c90183388e29dc251de5)
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.cpp | 40 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.h | 18 |
3 files changed, 66 insertions, 17 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 484631d902d..6ae346f26de 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -3212,16 +3212,37 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float // Use a detour raycast to get our first collision point PathGenerator path(this); path.CalculatePath(destx, desty, destz, false, true); + + // We have a invalid path result. Skip further processing. + if (path.GetPathType() & ~(PATHFIND_NORMAL | PATHFIND_SHORTCUT | PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END)) + return; + G3D::Vector3 result = path.GetPath().back(); destx = result.x; desty = result.y; destz = result.z; - UpdateAllowedPositionZ(destx, desty, destz); + // Object is using a shortcut. Check static LOS + float halfHeight = GetCollisionHeight() * 0.5f; + if (path.GetPathType() & PATHFIND_SHORTCUT) + { + bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(PhasingHandler::GetTerrainMapId(GetPhaseShift(), GetMap(), pos.m_positionX, pos.m_positionY), + pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight, + destx, desty, destz + halfHeight, + destx, desty, destz, -0.5f); + + destz -= halfHeight; + // Collided with static LOS object, move back to collision point + if (col) + { + destx -= CONTACT_DISTANCE * std::cos(angle); + desty -= CONTACT_DISTANCE * std::sin(angle); + dist = std::sqrt((pos.m_positionX - destx) * (pos.m_positionX - destx) + (pos.m_positionY - desty) * (pos.m_positionY - desty)); + } + } // check dynamic collision - float halfHeight = GetCollisionHeight() * 0.5f; bool col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight, destx, desty, destz + halfHeight, diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 37c1fef5378..593a347f424 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -200,8 +200,9 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con } // we may need a better number here - bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); - if (farFromPoly) + bool startFarFromPoly = distToStartPoly > 7.0f; + bool endFarFromPoly = distToEndPoly > 7.0f; + if (startFarFromPoly || endFarFromPoly) { TC_LOG_DEBUG("maps.mmaps", "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f", distToStartPoly, distToEndPoly); @@ -231,7 +232,13 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con if (buildShotrcut) { BuildShortcut(); - _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH | PATHFIND_FARFROMPOLY); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + + if (startFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_START); + if (endFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_END); + return; } else @@ -244,7 +251,12 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); } - _type = PathType(PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY); + _type = PathType(PATHFIND_INCOMPLETE); + + if (startFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_START); + if (endFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_END); } } @@ -258,7 +270,17 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con _pathPolyRefs[0] = startPoly; _polyLength = 1; - _type = farFromPoly ? PathType(PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY) : PATHFIND_NORMAL; + if (startFarFromPoly || endFarFromPoly) + { + _type = PathType(PATHFIND_INCOMPLETE); + + if (startFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_START); + if (endFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_END); + } + else + _type = PATHFIND_NORMAL; BuildPointPath(startPoint, endPoint); return; @@ -383,6 +405,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con dtVlerp(hitPos, startPoint, endPoint, hit); _pathPoints[1] = G3D::Vector3(hitPos[2], hitPos[0], hitPos[1]); + NormalizePath(); _type = PATHFIND_INCOMPLETE; return; } @@ -454,6 +477,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con dtVlerp(hitPos, startPoint, endPoint, hit); _pathPoints[1] = G3D::Vector3(hitPos[2], hitPos[0], hitPos[1]); + NormalizePath(); _type = PATHFIND_INCOMPLETE; return; } @@ -489,8 +513,10 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con else _type = PATHFIND_INCOMPLETE; - if (farFromPoly) - _type = PathType(_type | PATHFIND_FARFROMPOLY); + if (startFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_START); + if (endFarFromPoly) + _type = PathType(_type | PATHFIND_FARFROMPOLY_END); // generate the point-path out of our up-to-date poly-path BuildPointPath(startPoint, endPoint); diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index c2d850a421d..769e396c3a1 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -40,14 +40,16 @@ class WorldObject; enum PathType { - PATHFIND_BLANK = 0x00, // path not built yet - PATHFIND_NORMAL = 0x01, // normal path - PATHFIND_SHORTCUT = 0x02, // travel through obstacles, terrain, air, etc (old behavior) - PATHFIND_INCOMPLETE = 0x04, // we have partial path to follow - getting closer to target - PATHFIND_NOPATH = 0x08, // no valid path at all or error in generating one - PATHFIND_NOT_USING_PATH = 0x10, // used when we are either flying/swiming or on map w/o mmaps - PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length - PATHFIND_FARFROMPOLY = 0x40, // start of end positions are far from the mmap poligon + PATHFIND_BLANK = 0x00, // path not built yet + PATHFIND_NORMAL = 0x01, // normal path + PATHFIND_SHORTCUT = 0x02, // travel through obstacles, terrain, air, etc (old behavior) + PATHFIND_INCOMPLETE = 0x04, // we have partial path to follow - getting closer to target + PATHFIND_NOPATH = 0x08, // no valid path at all or error in generating one + PATHFIND_NOT_USING_PATH = 0x10, // used when we are either flying/swiming or on map w/o mmaps + PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length + PATHFIND_FARFROMPOLY_START = 0x40, // start position is far from the mmap poligon + PATHFIND_FARFROMPOLY_END = 0x80, // end positions is far from the mmap poligon + PATHFIND_FARFROMPOLY = PATHFIND_FARFROMPOLY_START | PATHFIND_FARFROMPOLY_END, // start or end positions are far from the mmap poligon }; class TC_GAME_API PathGenerator |