acdream/docs/research/2026-07-04-171-pickup-prompt.md
Erik d413ac2a29 docs(#171): file the group-melee interpenetration issue + R5-V3 handoff/pickup
User report during the #170 gate: pack-melee monsters partly inside each
other with slightly stale facings vs retail on the same ACE. Investigation
(report-only) pinned two code-grounded causes, both already-tracked R5-V3
scope, fix APPROVED by the user:

1. TS-39 — sticky melee is a no-op: ACE arms melee chases with Sticky
   (Monster_Navigation.cs:416); retail's arrival hands off to
   PositionManager::StickTo -> StickyManager::adjust_offset (0x00555430,
   per-tick 0.3m edge gap + facing tracking); acdream's StickTo/Unstick
   seams are unbound so attackers freeze at stale arrival poses.
2. Arrival radii are zero: getOwnRadius () => 0f (the R5-V3 pin) and
   RouteServerMoveTo never sets MovementStruct.Radius/Height — retail/ACE
   arrive edge-to-edge with setup-derived radii (ACE PhysicsObj.MoveToObject
   reads the TARGET's PartArray radius/height).

Ruled out: the between-snap collision sweep (remotes run full
ResolveWithTransition; CollisionExemption keeps creatures collidable).
Caveat recorded: ACE has no server-side monster avoidance — acceptance is
retail PARITY, not zero overlap.

ISSUES #171 filed; handoff docs/research/2026-07-04-171-sticky-melee-handoff.md
+ pickup docs/research/2026-07-04-171-pickup-prompt.md; memory index updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 22:38:58 +02:00

3.2 KiB

Pickup prompt — #171 sticky melee / R5-V3 (paste into a fresh session)

Read docs/research/2026-07-04-171-sticky-melee-handoff.md first — it is the SSOT for this task (root causes, retail anchors, approved scope, gotchas). Then implement R5-V3.

Context: #170 (chase slide) is CLOSED — gate passed at 4cad626f; do not reopen that machinery. During its gate the user observed #171: in a pack melee, monsters sit partly inside each other with slightly stale facings vs retail on the same ACE. Investigated + fix approved by the user 2026-07-04.

The two causes (both R5-V3 scope, already register-tracked):

  1. Sticky melee is a no-op (TS-39): ACE arms melee chases with Sticky; retail's arrival hands off to PositionManager::StickToStickyManager::adjust_offset (0x00555430, per-tick 0.3 m gap + facing tracking). Our MoveToManager.StickTo/Unstick seams are unbound — attackers freeze at stale arrival poses.
  2. Arrival radii are zero: getOwnRadius: () => 0f (the R5-V3 pin in EnsureRemoteMotionBindings) + RouteServerMoveTo never sets MovementStruct.Radius/Height — retail/ACE arrive edge-to-edge with setup-derived radii (ACE PhysicsObj.MoveToObject reads the TARGET's PartArray radius/height).

Do, in order:

  1. Grep the named decomp for StickyManager:: + PositionManager:: bodies (adjust_offset 0x00555430; per-tick anchors already pinned: PositionManager::adjust_offset @0x00512d0e inside UpdatePositionInternal, PositionManager::UseTime @0x005159b3 in UpdateObjectInternal). Pseudocode, then port verbatim; cross-check references/ACE/Source/ACE.Server/Physics/Managers/{StickyManager,PositionManager}.cs. Groundwork already in tree: MoveToMath.CylinderDistanceNoZ / GlobalToLocalVec / NormalizeCheckSmall; ConstraintManager (R5-V1) is the port-style reference. Do NOT arm ConstraintManager (#167 separate).
  2. Bind StickTo/UnStick in EnsureRemoteMotionBindings AND the player wiring; wire PositionManager into the tick at the retail-matching points.
  3. Thread real cylsphere radii (own from the entity's Setup; target resolved at RouteServerMoveTo's MoveToObject branch). Sweep remote + player.
  4. Same-commit register bookkeeping: retire TS-39, update the radius pin.
  5. Extend RemoteChaseEndToEndHarnessTests with a sticky scenario (arrive → target strafes → follower tracks gap + facing; UnStick on next PerformMovement). Harness bodies MUST mirror the live RemoteMotion construction (InWorld=true, RemoteWeenie — see RemoteChaseDrainBisectTests).
  6. dotnet build + full dotnet test green → commit → launch for the user's visual gate: pack melee side-by-side vs retail, strafe around the pack; attackers should reshuffle + keep facing like retail. Acceptance is retail PARITY — some overlap is ACE-server-side and shows on retail too.

Gotchas: revert-prone remote-motion area — verbatim port, no redesign; per-entity probes must print the guid (memory feedback_probe_identity_attribution); PowerShell Tee logs are UTF-16 (tr -d '\000' before grep); the user manages client lifecycle (graceful close); both clients hit the same local ACE (127.0.0.1:9000).