Commit graph

2 commits

Author SHA1 Message Date
Erik
5bd2b8bc8b fix(#171): R5-V3 — bind sticky melee (StickyManager live) + real arrival radii
Group-melee interpenetration + facing drift: the R5-V1-ported
StickyManager/PositionManager were Core-only — the StickTo/Unstick seams
were unbound and every arrival radius was 0, so ACE's Sticky|UseSpheres
melee chases closed ~one body-radius too deep and froze at stale arrival
poses until the next wire re-arm. Retires TS-39.

Wiring (anchors re-verified against the named decomp this session):
- EntityPhysicsHost owns a PositionManager; HandleUpdateTarget fans
  MoveToManager then PositionManager (CPhysicsObj::HandleUpdateTarget
  0x00512bc0 order).
- Seams bound remote + player: MoveToManager.StickTo (BeginNextNode
  sticky arrival @0x00529d3a), Unstick (PerformMovement head), and
  MotionInterpreter.UnstickFromObject (UM funnel head, 0x0050eaea).
- AdjustOffset at the retail UpdatePositionInternal slot (@0x00512d0e):
  NPC branch composes pre-sweep (steer is swept by ResolveWithTransition);
  remote-player branch chains the combiner offset through the shared
  delta frame (the interp stage) so sticky OVERWRITES when armed
  (0x00555430 assigns m_fOrigin, not accumulates); player inside the
  30 Hz physics quantum before UpdatePhysicsInternal.
- UseTime (the 1 s lease watchdog) at the UpdateObjectInternal tail
  (@0x005159b3): unconditional per remote; player gated on the physics
  tick (retail's MinQuantum gate skips UseTime too).
- Real setup cylsphere radii (CPartArray::GetRadius/GetHeight
  0x005180a0/0x005180b0 = setup radius/height x ObjScale from the spawn
  record): own via EnsureRemoteMotionBindings + player wiring; target via
  RouteServerMoveTo AND the speculative use-walk install (retail resolves
  the target PartArray at EVERY MoveToObject site — ACE PhysicsObj.cs:951).
- Teardown parity: exit_world (0x00514e60) UnStick + ClearTarget before
  the ExitWorld notify; player teleport fires teleport_hook's tail
  (UnStick in SetPosition + EntityPhysicsHost.NotifyTeleported =
  ClearTarget + NotifyVoyeurOfEvent(Teleported) @0x00514f1b) so mobs
  stuck to the player drop their sticks on a recall.
- SERVERVEL arbitration also yields to a stuck entity (same starvation
  class as the #170 fix — sticky owns the between-snap translation).
- StickyManager.UseTime aligned to retail's strict > deadline
  (0x00555626; ACE >): two V1 tests had pinned the >= edge — corrected.

Register: TS-39 deleted; TS-41 narrowed (stickyArmed gate); TS-43 added
(remote teleport_hook gap — self-corrects within the 1 s lease); AP-23
narrowed (real radii at the speculative site; only the use-radius
buckets remain invented).

Conformance: 2 new full-stack sticky scenarios in
RemoteChaseEndToEndHarnessTests (arrive -> stick -> strafing-target
gap+facing track -> lease expiry; unstick-on-rearm -> re-stick).
Full suite 4038 green.

Pre-commit adversarial diff review (3 lenses + per-finding refuters)
confirmed and fixed 4 findings: ObjScale-dead radius read, player
UseTime order inversion, missing teleport voyeur notify, speculative-
site radius asymmetry.

Awaiting the user visual gate: pack melee side-by-side vs retail
(attackers reshuffle + keep facing; some overlap is ACE-server-side).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 23:46:17 +02:00
Erik
3d89446d98 feat(physics): R5-V1 — port PositionManager/Sticky/Constraint + TargetManager (Core, unwired)
The retail movement-manager family the R4 MoveToManager port left as
do-not-invent seams (decomp §9f/§9g). Faithful C# ports of retail's
PositionManager facade + StickyManager + ConstraintManager + the
TargetManager voyeur system, with full conformance tests. NO wiring yet
— purely additive, no behavior change. Wiring (retiring TS-39 sticky +
AP-79 target adapter) is R5-V2/V3.

New Core classes (src/AcDream.Core/Physics/Motion/):
- StickyManager (0x00555400): follow-a-target steering. adjust_offset's
  dense x87 mush decoded via ACE (StickyRadius 0.3, StickyTime 1.0,
  follow speed ×5 / fallback 15) — speed-clamped signed-distance steer +
  bounded turn-to-face; 1 s watchdog; Ok→initialized / non-Ok→teardown.
- ConstraintManager (0x00556090): the server-position rubber-band leash.
  90% IsFullyConstrained jump gate + grounded linear brake taper.
  Structural only — acdream never ARMS it (retail arms from
  SmartBox::HandleReceivedPosition, which acdream lacks, with two x87
  constants BN elided). IsFullyConstrained stays false = TS-35 behavior;
  leash-arming + the unknown constants are a deferred issue.
- PositionManager facade (0x00555160): lazy Sticky/Constraint + fan-out.
- TargetManager (0x0051a370) + TargettedVoyeurInfo: the peer-to-peer
  voyeur subscription system (0.5 s throttle, 10 s staleness,
  send-on-drift-past-radius, dead-reckon GetInterpolatedPosition). A
  faithful superset of the AP-79 adapter — SetTarget subscribes ON the
  target; the target's HandleTargetting pushes updates back.
- IPhysicsObjHost: the CPhysicsObj back-pointer seam (position/velocity/
  radius/contact/GetObjectA + target-tracking fan-out) the App wires per
  entity in V2/V3. MotionDeltaFrame: mutable retail-Frame delta accumulator.

Supporting:
- TargetInfo extended to the full retail 10-field struct (additive
  defaults keep the R4 4-arg call sites compiling).
- MoveToMath: signed CylinderDistanceNoZ, NormalizeCheckSmall,
  GlobalToLocalVec.
- Rename: the misnamed AcDream.Core.Physics.PositionManager (a remote
  anim+interp per-frame combiner, NOT the retail facade) → RemoteMotion
  Combiner, freeing the name and removing the ambiguity that breaks every
  file importing both Physics + Physics.Motion (GameWindow will in V2/V3).

Tests: 42 new conformance cases (Sticky/Constraint/Position facade +
TargetManager incl. the full cross-entity voyeur round-trip). Full suite
4006 green (+2 skipped), no regressions.

Decomp + ACE cross-ref + port plan: docs/research/2026-07-03-r5-managers/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 19:34:49 +02:00