fix(input): Phase K live-test fixes pt3 — fly→chase round-trip, Shift coexists, run-speed for backward + strafe
Four issues from the K-fix2 launch (2026-04-26 user report): 1. Can't return from free-fly to player view. CameraController.ToggleFly only swaps Fly↔Orbit, so a user who flew out of player mode landed in orbit (Holtburg) on toggle-back instead of the chase camera. Added ToggleFlyOrChase() helper that prefers Fly→Chase / Chase→Fly when _playerMode is true and a chase camera is available; falls back to the original Fly↔Orbit toggle for offline / pre-login flows. Wired into all three free-fly entry points: keyboard shortcut (Ctrl+Shift+F), Camera menu item, and DebugPanel button. 2. Shift while moving STOPS instead of dropping to walk. Root cause: InputDispatcher.IsChordHeld required _keyboard.CurrentModifiers to match chord.Modifiers EXACTLY. So with W bound as (W, None), holding W and then pressing Shift made CurrentModifiers=Shift mismatch chord (None) → IsActionHeld(MovementForward) returned false → Forward flag dropped → player stopped. Fixed by relaxing IsChordHeld: when chord.Modifiers is None, Shift is allowed to coexist (it's the retail walk-modifier). Other modifiers (Ctrl, Alt, Win) still mismatch strictly so Ctrl+W stays a distinct chord from W. +2 tests pinning the new permissive-Shift / strict-Ctrl semantics. 3. Backwards too slow when running. forwardCmdSpeed for the WalkBackward branch was hardcoded to 1.0; localY was hardcoded to -(WalkAnimSpeed * 0.65). Neither honored input.Run. With Run=true (default), backward now scales by runRate (~2.4×) so X = "run backwards" matches the forward run pace × the 0.65 backward animation cycle ratio. 4. Strafe too slow when running. localX for SideStepLeft / SideStepRight was hardcoded to ±SidestepAnimSpeed regardless of Run. Same fix: when Run is held, scale by runRate so strafe at default speed matches the run-forward pace. Tests: 1220 → 1222 (the two new IsChordHeld tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6481169cb9
commit
785dd92378
4 changed files with 130 additions and 28 deletions
|
|
@ -106,6 +106,47 @@ public class InputDispatcherIsActionHeldTests
|
|||
Assert.False(dispatcher.IsActionHeld(InputAction.None));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsActionHeld_None_chord_remains_held_when_user_adds_Shift()
|
||||
{
|
||||
// K-fix3 (2026-04-26): Shift is the walk modifier in retail AC.
|
||||
// The user holding W (default = run) and then pressing Shift
|
||||
// should drop them to walk speed, NOT stop forward motion. Prior
|
||||
// to this fix, IsChordHeld required CurrentModifiers to match
|
||||
// chord.Modifiers EXACTLY — so (W, None) failed to match while
|
||||
// CurrentModifiers=Shift, and the player stopped on Shift-press.
|
||||
// Now: when chord requires no modifiers, Shift is allowed to
|
||||
// coexist (other modifiers — Ctrl, Alt, Win — still mismatch).
|
||||
var (dispatcher, kb, _, bindings) = Build();
|
||||
bindings.Add(new Binding(new KeyChord(Key.W, ModifierMask.None), InputAction.MovementForward));
|
||||
|
||||
kb.EmitKeyDown(Key.W, ModifierMask.None);
|
||||
Assert.True(dispatcher.IsActionHeld(InputAction.MovementForward));
|
||||
|
||||
// User now holds Shift while still holding W. CurrentModifiers
|
||||
// becomes Shift; W is still physically down.
|
||||
kb.CurrentModifiers = ModifierMask.Shift;
|
||||
Assert.True(dispatcher.IsActionHeld(InputAction.MovementForward));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsActionHeld_None_chord_does_not_fire_when_user_adds_Ctrl()
|
||||
{
|
||||
// Counterpart to the Shift test above: Ctrl is NOT a movement
|
||||
// modifier, so Ctrl+W should be a different chord. Without an
|
||||
// explicit (W, Ctrl) binding the action stays inactive — that's
|
||||
// what makes Ctrl+F* / Ctrl+1-9 / etc. distinct from the bare
|
||||
// F* / 1-9 chords.
|
||||
var (dispatcher, kb, _, bindings) = Build();
|
||||
bindings.Add(new Binding(new KeyChord(Key.W, ModifierMask.None), InputAction.MovementForward));
|
||||
|
||||
kb.EmitKeyDown(Key.W, ModifierMask.None);
|
||||
Assert.True(dispatcher.IsActionHeld(InputAction.MovementForward));
|
||||
|
||||
kb.CurrentModifiers = ModifierMask.Ctrl;
|
||||
Assert.False(dispatcher.IsActionHeld(InputAction.MovementForward));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsActionHeld_does_not_check_WantCaptureMouse()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue