fix(anim): Phase L.1c bulk-copy ForwardCommand for MoveTo packets too
User-observed regression on commitff6d3d0: at login, monsters appear as "just a torso on the ground" until they start moving. Cause:f794832lifted the InterpretedState bulk-copy to apply to BOTH overlay and substate packets, but gated it on `!IsServerControlledMoveTo`. The original substate-only DoInterpretedMotion call I removed had previously updated InterpretedState for MoveTo packets too (fullMotion=RunForward seed from PlanMoveToStart routed through ApplyMotionToInterpretedState's RunForward case). My replacement only fired for non-MoveTo packets, silently regressing MoveTo creatures to a default ForwardCommand=Ready InterpretedState. Consequence: chasing creatures had ForwardCommand=Ready in their InterpretedState even though the cycle on the sequencer was RunForward. apply_current_movement (gate: RunForward||WalkForward) returned zero velocity — body never advanced via the steering branch's velocity integration. The body ONLY translated when an UpdatePosition hard-snap arrived (every ~200ms server tick), producing the "torso on the ground at spawn" pose before the first UP snap landed and "running on the spot" between snaps. Fix: drop the IsServerControlledMoveTo gate. Bulk-copy InterpretedState.ForwardCommand=fullMotion and ForwardSpeed=speedMod UNCONDITIONALLY for any packet that reaches OnLiveMotionUpdated. Matches retail's copy_movement_from (acclient_2013_pseudo_c.txt:293301-293311) which doesn't filter by movement type — for MoveTo, RunForward/speed*runRate; for substate, the wire's command/speed; for overlay, Attack/animSpeed (and get_state_velocity gates correctly to zero, the desired stop). Tests still 1420 green — the existing parser/driver tests cover the data; this is a code-path completeness fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ff6d3d0c94
commit
37de771778
1 changed files with 26 additions and 9 deletions
|
|
@ -2465,6 +2465,32 @@ public sealed class GameWindow : IDisposable
|
||||||
{
|
{
|
||||||
remoteMot.ServerMoveToActive = update.MotionState.IsServerControlledMoveTo;
|
remoteMot.ServerMoveToActive = update.MotionState.IsServerControlledMoveTo;
|
||||||
|
|
||||||
|
// Bulk-copy the wire's resolved ForwardCommand + speed
|
||||||
|
// into InterpretedState UNCONDITIONALLY (overlay,
|
||||||
|
// substate, AND MoveTo packets). Matches retail's
|
||||||
|
// copy_movement_from semantics
|
||||||
|
// (acclient_2013_pseudo_c.txt:293301-293311) which does
|
||||||
|
// not filter by MovementType.
|
||||||
|
//
|
||||||
|
// For MoveTo packets, fullMotion is the RunForward seed
|
||||||
|
// from PlanMoveToStart, so this populates
|
||||||
|
// ForwardCommand=RunForward + ForwardSpeed=speed*runRate
|
||||||
|
// — what the OLD substate-only DoInterpretedMotion call
|
||||||
|
// (commit f794832 removed) used to set. Without it,
|
||||||
|
// apply_current_movement reads the default
|
||||||
|
// ForwardCommand=Ready and produces zero velocity, so
|
||||||
|
// chasing creatures only translate via UpdatePosition
|
||||||
|
// hard-snaps and at spawn appear posed at default
|
||||||
|
// (visible as "torso on the ground" until the first UP
|
||||||
|
// snap hits).
|
||||||
|
//
|
||||||
|
// For overlay (Action) packets this sets ForwardCommand
|
||||||
|
// to the Attack/Twitch/etc command, and
|
||||||
|
// get_state_velocity returns 0 because the gate is
|
||||||
|
// RunForward||WalkForward — body stops moving forward.
|
||||||
|
remoteMot.Motion.InterpretedState.ForwardCommand = fullMotion;
|
||||||
|
remoteMot.Motion.InterpretedState.ForwardSpeed = speedMod <= 0f ? 1f : speedMod;
|
||||||
|
|
||||||
if (update.MotionState.IsServerControlledMoveTo
|
if (update.MotionState.IsServerControlledMoveTo
|
||||||
&& update.MotionState.MoveToPath is { } path)
|
&& update.MotionState.MoveToPath is { } path)
|
||||||
{
|
{
|
||||||
|
|
@ -2488,15 +2514,6 @@ public sealed class GameWindow : IDisposable
|
||||||
// Off MoveTo — clear stale destination so the per-tick
|
// Off MoveTo — clear stale destination so the per-tick
|
||||||
// driver doesn't keep steering.
|
// driver doesn't keep steering.
|
||||||
remoteMot.HasMoveToDestination = false;
|
remoteMot.HasMoveToDestination = false;
|
||||||
|
|
||||||
// Bulk-copy the wire's resolved ForwardCommand + speed
|
|
||||||
// into InterpretedState. For Action commands this
|
|
||||||
// makes apply_current_movement return zero velocity
|
|
||||||
// on the next tick (gate fails). For substate
|
|
||||||
// commands (Run/Walk/Ready), this is identical to
|
|
||||||
// what DoInterpretedMotion would have written.
|
|
||||||
remoteMot.Motion.InterpretedState.ForwardCommand = fullMotion;
|
|
||||||
remoteMot.Motion.InterpretedState.ForwardSpeed = speedMod <= 0f ? 1f : speedMod;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue