feat(physics): movement blockers the server's movers can't walk through

Enemies are moved along navmesh paths without collision, so a wall only stops
them if their path stops at it. dpWorld now keeps a list of such walls, each
with the collision filter it blocks with, and cuts a path where it first walks
into one (a little short of the wall; a mover inside one can walk out).

Which objects block comes from data (dpMovementBlockers::BlockingFilter):
- navmesh carvers (navmesh_carver in the level config, which the client reads
  with add_to_navmesh and carver_only) block every mover;
- solid objects whose collision group touches enemies and not players (group 18,
  e.g. "FV - Enemy Blocking Volume", "PR - Pet Blocker") block what that group
  touches.

dpShapeBox gains SegmentEntry, a segment test against the rotated box.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 17:37:37 -05:00
parent 69ee6b0bc6
commit 425b913848
10 changed files with 305 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include "dpShapeBase.h"
#include <optional>
#include <vector>
#include "NiPoint3.h"
#include "NiQuaternion.h"
@@ -39,6 +40,13 @@ public:
*/
float SquaredDistanceTo(const NiPoint3& point) const;
/**
* Where the segment from a to b first goes into the box, as a fraction of the way from a to b (0 to 1), tested
* against the box's real (rotated) shape. Empty when the segment misses the box, or starts inside it (so
* something already in the box can always leave it).
*/
std::optional<float> SegmentEntry(const NiPoint3& a, const NiPoint3& b) const;
void InitVertices();
void SetPosition(const NiPoint3& position);