diff options
author | Anton Popovichenko <walkline.ua@gmail.com> | 2025-07-11 16:44:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-11 11:44:44 -0300 |
commit | 628f6255c49e1ef2123b0f5fb33c3de0a968432e (patch) | |
tree | 82eb01f64e332f4792c2bfdd3bf20f0b6d103a21 | |
parent | 1c3cbd3d9e1d07369be77a049cb95f22c2caf03d (diff) |
fix(Core/FleeingMovementGenerator): Prevent fear movement from causing characters to fall through the ground (#22451)
3 files changed, 24 insertions, 2 deletions
diff --git a/deps/recastnavigation/Detour/Include/DetourStatus.h b/deps/recastnavigation/Detour/Include/DetourStatus.h index 8e1bb44b9d..96dcb5b004 100644 --- a/deps/recastnavigation/Detour/Include/DetourStatus.h +++ b/deps/recastnavigation/Detour/Include/DetourStatus.h @@ -36,6 +36,7 @@ static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search. static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess. static const unsigned int DT_ALREADY_OCCUPIED = 1 << 7; // A tile has already been assigned to the given x,y coordinate +static const unsigned int DT_SLOPE_TOO_STEEP = 1 << 8; // Surface slope too steep to be walkable. // Returns true of status is success. diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 2547e4ddf3..a4d9867abf 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -137,9 +137,12 @@ void FleeingMovementGenerator<T>::SetTargetLocation(T* owner) _path->Clear(); } + if (owner->IsPlayer()) + _path->SetSlopeCheck(true); + _path->SetPathLengthLimit(30.0f); bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); - if (!result || (_path->GetPathType() & PathType(PATHFIND_NOPATH | PATHFIND_SHORTCUT | PATHFIND_FARFROMPOLY))) + if (!result || (_path->GetPathType() & PathType(PATHFIND_NOPATH | PATHFIND_SHORTCUT | PATHFIND_FARFROMPOLY | PATHFIND_NOT_USING_PATH))) { _timer.Reset(100); return; diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp index 015d3973c7..33bd7ec22a 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp @@ -564,6 +564,22 @@ void PathGenerator::BuildPointPath(const float* startPoint, const float* endPoin } else if (pointCount < 2 || dtStatusFailed(dtResult)) { + // If its too steep, just return incomplete path. + if (pointCount > 0 && dtResult & DT_SLOPE_TOO_STEEP) + { + _pathPoints.resize(pointCount); + for (uint32 i = 0; i < pointCount; ++i) + _pathPoints[i] = G3D::Vector3(pathPoints[i * VERTEX_SIZE + 2], pathPoints[i * VERTEX_SIZE], pathPoints[i * VERTEX_SIZE + 1]); + + NormalizePath(); + + // first point is always our current location - we need the next one + SetActualEndPosition(_pathPoints[pointCount - 1]); + + _type = PathType(_type | PATHFIND_INCOMPLETE); + return; + } + // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here /// @todo check the exact cases @@ -884,7 +900,9 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo if (canCheckSlope && !IsSwimmableSegment(iterPos, steerPos) && !IsWalkableClimb(iterPos, steerPos)) { - return DT_FAILURE; + nsmoothPath--; + *smoothPathSize = nsmoothPath; + return DT_FAILURE | DT_SLOPE_TOO_STEEP; } // Handle end of path and off-mesh links when close enough. |