diff --git a/.gitignore b/.gitignore index acdabd2c..a4efa6a5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,3 @@ __pycache__/ # Per-session scratch (Claude commit message drafts, ad-hoc temp files) tmp/ - -# Git worktrees for isolated feature work -.worktrees/ diff --git a/src/AcDream.App/Input/PlayerMovementController.cs b/src/AcDream.App/Input/PlayerMovementController.cs index 13bcde7c..e2d0c552 100644 --- a/src/AcDream.App/Input/PlayerMovementController.cs +++ b/src/AcDream.App/Input/PlayerMovementController.cs @@ -52,13 +52,6 @@ public readonly record struct MovementResult( float? TurnSpeed, bool IsRunning = false, uint? LocalAnimationCommand = null, // which cycle to play on the local player (RunForward when running) - // K-fix5 (2026-04-26): cycle-pace multiplier for the LOCAL animation - // sequencer. Decoupled from ForwardSpeed so the wire can keep sending - // 1.0 for WalkBackward (ACE-compatible) while the animation plays at - // runRate × so the cycle visually matches the run-speed velocity. - // Forward+Run = runRate (same as ForwardSpeed); Backward+Run, Strafe+Run - // = runRate (where ForwardSpeed is 1.0 / null); everything else = 1.0. - float LocalAnimationSpeed = 1f, bool JustLanded = false, // true on the single frame we transitioned airborne → grounded float? JumpExtent = null, // non-null when a jump was triggered this frame Vector3? JumpVelocity = null); // world-space launch velocity (sent in jump packet) @@ -563,18 +556,6 @@ public sealed class PlayerMovementController HeartbeatDue = false; } - // K-fix5 (2026-04-26): local-animation-cycle pacing. Visual rate - // should match the actual movement speed. For Forward+Run this is - // already runRate (it equals ForwardSpeed). For Backward+Run and - // Strafe+Run it must be runRate too even though the wire keeps - // those at 1.0. Picking runMul (already computed above) keeps the - // math in one place. - bool anyDirectional = input.Forward || input.Backward - || input.StrafeLeft || input.StrafeRight; - float localAnimSpeed = (input.Run && anyDirectional) - ? (_weenie.InqRunRate(out float vrrAnim) ? vrrAnim : 1f) - : 1f; - return new MovementResult( Position: Position, CellId: CellId, @@ -588,7 +569,6 @@ public sealed class PlayerMovementController TurnSpeed: outTurnSpeed, IsRunning: input.Run && input.Forward, LocalAnimationCommand: localAnimCmd, - LocalAnimationSpeed: localAnimSpeed, JustLanded: justLanded, JumpExtent: outJumpExtent, JumpVelocity: outJumpVelocity); diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 48c0326a..ddbfb348 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -4726,12 +4726,7 @@ public sealed class GameWindow : IDisposable // command is unchanged but speed changed, we must still propagate // so the sequencer can MultiplyCyclicFramerate — keeping the run // loop smooth without restart. - // K-fix5 (2026-04-26): use LocalAnimationSpeed (cycle pace) NOT - // ForwardSpeed (wire field) — backward+run + strafe+run keep - // ForwardSpeed/SidestepSpeed at 1.0 for ACE compatibility but - // need the local cycle to play at runRate × so the animation - // matches the actual movement velocity. - float newSpeed = result.LocalAnimationSpeed; + float newSpeed = result.ForwardSpeed ?? 1f; bool sameCmd = animCommand == _playerCurrentAnimCommand; bool sameSpeed = MathF.Abs(newSpeed - _playerCurrentAnimSpeed) < 1e-3f; if (sameCmd && sameSpeed) return; @@ -4786,19 +4781,19 @@ public sealed class GameWindow : IDisposable // Sequencer path: SetCycle handles adjust_motion internally // (TurnLeft→TurnRight with negative speed, etc.) // - // Speed scaling: K-fix5 (2026-04-26) — use LocalAnimationSpeed - // (the PlayerMovementController-computed cycle pace) instead of - // the wire ForwardSpeed. Forward+Run = runRate; Backward+Run = - // runRate (where ForwardSpeed is the ACE-compatible 1.0); - // Strafe+Run = runRate (where SidestepSpeed is 1.0). Anything - // not in run = 1.0. The animation cycle now visually matches - // the movement velocity in every direction. + // Speed scaling: use the MovementResult's ForwardSpeed for + // locomotion cycles. This mirrors what the server broadcasts for + // remote observers, and keeps our own character's animation rate + // in sync with movement velocity (a 1.5× RunRate player's anim + // plays 1.5× as fast — matching retail). if (ae.Sequencer is not null) { uint fullStyle = 0x80000000u | (uint)NonCombatStance; - float animSpeed = result.LocalAnimationSpeed > 0f - ? result.LocalAnimationSpeed - : 1f; + float animSpeed = 1f; + if (result.ForwardSpeed is { } fs && fs > 0f) + { + animSpeed = fs; + } // ACDREAM_ANIM_SPEED_SCALE: optional visual-pacing knob. Retail's // animation framerate scales linearly with speedMod (r03 §8.3), // and our speedMod = runRate. If the visual feel doesn't match