fix(anim): preserve Falling cycle while remote is airborne + reset on land
Two issues from the K-fix16 jump-now-renders launch: 1. Mid-air movement broke the jump animation. When a remote turned or ran while airborne, ACE broadcast UpdateMotion with the new motion state. OnLiveMotionUpdated's SetCycle call swapped Falling -> RunForward / TurnRight / etc., breaking the visible jump pose. The arc still played out (physics integrated body position correctly) but the legs ran instead of folded. Fix: skip the SetCycle in OnLiveMotionUpdated when rm.Airborne is true. The InterpretedState DoMotion calls below it still fire, so the body's velocity matches the new motion command and the body keeps moving correctly -- only the visible cycle stays Falling. 2. Stuck in Falling pose after landing. K-fix15 cleared rm.Airborne + restored ground state on landing, but never told the sequencer to swap cycles. The remote stayed in the Falling pose forever (legs folded) until the server happened to send a fresh UpdateMotion (e.g. when the player walked again). Idle landing left them frozen. Fix: post-land, read InterpretedState.ForwardCommand and call SetCycle with that command + the recorded ForwardSpeed. Default to Ready / 1.0 when the state is blank. The next UpdateMotion from the server will refine if needed (e.g. mid-strafe land), but the legs come out of Falling immediately. Drive-by: stripped K-fix16's unconditional [VU.recv] log now that the parser is verified working. Tests stay 1222 green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0ebf0cad09
commit
ff504e9ec1
1 changed files with 45 additions and 1 deletions
|
|
@ -2180,7 +2180,22 @@ public sealed class GameWindow : IDisposable
|
|||
animSpeed = MathF.Abs(update.MotionState.TurnSpeed ?? 1f);
|
||||
}
|
||||
}
|
||||
ae.Sequencer.SetCycle(fullStyle, animCycle, animSpeed);
|
||||
// K-fix17 (2026-04-26): preserve the Falling cycle while
|
||||
// the remote is airborne. ACE broadcasts UpdateMotion
|
||||
// mid-arc when the player turns / runs — the previous
|
||||
// SetCycle here swapped Falling → RunForward, breaking
|
||||
// the visible jump animation. The arc still played out
|
||||
// physics-wise (body went up/down), but the legs ran
|
||||
// instead of folded. Skip the cycle swap when airborne;
|
||||
// the InterpretedState updates below still fire so the
|
||||
// body's velocity matches the new motion command, AND
|
||||
// the post-resolve landing path restores the cycle to
|
||||
// whatever the interpreted state says when the body
|
||||
// lands.
|
||||
bool remoteIsAirborne = _remoteDeadReckon.TryGetValue(update.Guid, out var rmCheck)
|
||||
&& rmCheck.Airborne;
|
||||
if (!remoteIsAirborne)
|
||||
ae.Sequencer.SetCycle(fullStyle, animCycle, animSpeed);
|
||||
|
||||
// Retail runs the full MotionInterp state machine on every
|
||||
// remote. Route each wire command (forward, sidestep, turn)
|
||||
|
|
@ -4755,6 +4770,35 @@ public sealed class GameWindow : IDisposable
|
|||
rm.Body.Velocity = new System.Numerics.Vector3(
|
||||
rm.Body.Velocity.X, rm.Body.Velocity.Y, 0f);
|
||||
rm.Motion.HitGround();
|
||||
|
||||
// K-fix17 (2026-04-26): reset the sequencer cycle
|
||||
// from Falling back to whatever the interpreted
|
||||
// motion state says they should be doing now.
|
||||
// Without this, the remote stays in the Falling
|
||||
// pose forever (legs folded) until the next
|
||||
// server-sent UpdateMotion arrives. Use the
|
||||
// sequencer's current style (preserved across
|
||||
// jump) and pick the cycle from
|
||||
// InterpretedState.ForwardCommand: Ready
|
||||
// (idle), WalkForward, RunForward, WalkBackward.
|
||||
// SideStep / Turn aren't strict locomotion
|
||||
// priorities — the next UM the server sends will
|
||||
// refine the cycle if the player is mid-strafe
|
||||
// when they land; this just gets the legs out
|
||||
// of Falling immediately.
|
||||
if (ae.Sequencer is not null)
|
||||
{
|
||||
uint style = ae.Sequencer.CurrentStyle != 0
|
||||
? ae.Sequencer.CurrentStyle
|
||||
: 0x8000003Du;
|
||||
uint landingCmd = rm.Motion.InterpretedState.ForwardCommand;
|
||||
if (landingCmd == 0)
|
||||
landingCmd = AcDream.Core.Physics.MotionCommand.Ready;
|
||||
float landingSpeed = rm.Motion.InterpretedState.ForwardSpeed;
|
||||
if (landingSpeed <= 0f) landingSpeed = 1f;
|
||||
ae.Sequencer.SetCycle(style, landingCmd, landingSpeed);
|
||||
}
|
||||
|
||||
if (Environment.GetEnvironmentVariable("ACDREAM_DUMP_MOTION") == "1")
|
||||
Console.WriteLine($"VU.land guid=0x{serverGuid:X8} Z={rm.Body.Position.Z:F2}");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue