From 846517c655b45151fcd3ef7ac6416db54c5c77a7 Mon Sep 17 00:00:00 2001 From: SylvaniaCore deploy Date: Sun, 26 Jul 2026 17:22:16 +0000 Subject: [PATCH] Transcription ArgusCore : anti-clip des clotures (d21a91eb) PathGenerator::ValidatePathAgainstCollision() appelee en fin de BuildPointPath : valide chaque segment du chemin MMAP contre la collision vmap (isInLineOfSight, ModelIgnoreFlags::Nothing). Le MMAP ne modelise pas les objets fins (clotures, barrieres) -> un chemin nav-mesh valide peut les traverser. Si un segment est bloque, on tronque le chemin (PATHFIND_INCOMPLETE) pour que l unite s arrete devant l obstacle. Adapte a nos APIs : _sourceUnit, isInLineOfSight 8-params, log printf, halfHeight fixe. Skippe les chemins non-MMAP (vol/nage/raccourcis). ARBITRAGE reversible : plus realiste mais risque de sur-troncature (PNJ qui s arretent devant une porte/rampe M2 vue comme obstacle). A surveiller : PNJ bloques en mouvement. Co-Authored-By: Claude Fable 5 --- src/server/game/Movement/PathGenerator.cpp | 38 ++++++++++++++++++++++ src/server/game/Movement/PathGenerator.h | 7 ++++ 2 files changed, 45 insertions(+) diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 8db07c7..12d7494 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -590,6 +590,8 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } + ValidatePathAgainstCollision(); + TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength); } @@ -599,6 +601,42 @@ void PathGenerator::NormalizePath() _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); } +void PathGenerator::ValidatePathAgainstCollision() +{ + // Raccourcis en ligne droite voulus (vol, nage, repli). Seuls les chemins sol MMAP sont valides. + if (_type & PATHFIND_NOT_USING_PATH) + return; + if (_pathPoints.size() < 2) + return; + // rayon leve a hauteur de torse pour accrocher une cloture et non le sol + float const halfHeight = 1.0f; + for (uint32 i = 0; i + 1 < _pathPoints.size(); ++i) + { + G3D::Vector3 const& from = _pathPoints[i]; + G3D::Vector3 const& to = _pathPoints[i + 1]; + if (_sourceUnit->GetMap()->isInLineOfSight(_sourceUnit->GetPhaseShift(), + from.x, from.y, from.z + halfHeight, to.x, to.y, to.z + halfHeight, + VMAP::ModelIgnoreFlags::Nothing)) + continue; + // segment bloque par une geometrie absente du navmesh (cloture) : on tronque + if (i == 0) + { + Clear(); + _pathPoints.resize(2); + _pathPoints[0] = GetStartPosition(); + _pathPoints[1] = GetStartPosition(); + _type = PATHFIND_NOPATH; + } + else + { + _pathPoints.resize(i + 1); + SetActualEndPosition(_pathPoints.back()); + _type = PathType(_type | PATHFIND_INCOMPLETE); + } + return; + } +} + void PathGenerator::BuildShortcut() { TC_LOG_DEBUG("maps", "++ BuildShortcut :: making shortcut\n"); diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index 1e69f08..ed873e2 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -106,6 +106,13 @@ class TC_GAME_API PathGenerator void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; } void NormalizePath(); + // Apres la generation du chemin MMAP, valide chaque segment contre la collision vmap + // statique. Le MMAP ne modelise pas les objets fins (clotures, petites barrieres) : un + // chemin nav-mesh valide peut donc traverser une cloture. Si un segment est bloque, on + // tronque le chemin la et on marque PATHFIND_INCOMPLETE pour que l unite s arrete devant + // l obstacle au lieu de le traverser (ArgusCore d21a91eb). + void ValidatePathAgainstCollision(); + void Clear() { _polyLength = 0;