fix(motion): landing fallback + TurnLeft omega sign + vel diagnostic (L.3.2)

Three Option-A patches addressing visual issues from the L.3.1+L.3.2
remote-entity motion path (gated by ACDREAM_INTERP_MANAGER=1):

1. Landing fallback. ACE doesn't always send IsGrounded=true on the
   landing frame, so airborne remotes kept falling under gravity and
   visually "disappeared into the ground" until the next non-stop UP
   forced a re-snap. Track the most recent server-broadcast Z on every
   UP (including mid-arc airborne ones) and, in TickAnimations, snap
   the body back up + clear airborne when its predicted Z drops more
   than 0.5 m below that floor.

2. TurnLeft omega sign. The synthesize-omega fallback in
   AnimationSequencer (used when MotionData ships without HasOmega)
   had case 0x0E using zomega = +(pi/2) * adjustedSpeed, but
   adjust_motion above already remapped 0x0E to 0x0D with
   adjustedSpeed = -speedMod. The double-negate produced -Z (clockwise
   = right) for both turn directions, matching the reported "turning
   left animates as turning right". Use the same -(pi/2) * adjustedSpeed
   formula as case 0x0D so the negation lands the result on +Z (CCW).

3. Velocity diagnostic. New env var ACDREAM_REMOTE_VEL_DIAG=1 prints
   one line per moving remote per ~2 seconds comparing the sequencer's
   CurrentVelocity to the server's effective broadcast pace
   ((LastServerPos - PrevServerPos) / dt). Lets us measure the
   speed-overshoot ratio that produces the residual 1-Hz blippiness
   before tuning a fix.

Refs Phase L.3.1+L.3.2 spec at
docs/superpowers/specs/2026-05-02-l3-remote-entity-motion-design.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-03 10:48:10 +02:00
parent c1bfd64834
commit 0997f96078
2 changed files with 114 additions and 4 deletions

View file

@ -567,10 +567,15 @@ public sealed class AnimationSequencer
case 0x0D: // TurnRight — clockwise from above = -Z in right-handed.
zomega = -(MathF.PI / 2f) * adjustedSpeed;
break;
case 0x0E: // TurnLeft — counter-clockwise = +Z. adjust_motion
// may have remapped 0x0E → 0x0D with negated speed;
// in that case the negation preserves correct sign.
zomega = (MathF.PI / 2f) * adjustedSpeed;
case 0x0E: // TurnLeft — counter-clockwise = +Z.
// adjust_motion above ALREADY remapped 0x0E → 0x0D
// with adjustedSpeed = -speedMod, so the same
// formula as 0x0D applied to the negated speed
// produces the correct +Z (CCW) result. Using a
// different sign here would double-negate and
// animate a left turn as a right turn — that was
// the bug observed before this fix (commit follows).
zomega = -(MathF.PI / 2f) * adjustedSpeed;
break;
}
if (zomega != 0f)