From a36856e5264a46142dfb8e95ab943e4254b85256 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sat, 29 Aug 2026 17:46:24 +0200 Subject: [PATCH] fix(game): allow launcher input while tilted Preserve the original launcher path when a nudge tilts a game before launch. The Win16 press and release handlers process scan code 0x50 without consulting `game_tilted`, so Tilt disables flippers and scoring but does not strand a ball in the shooter lane. Remove the extra Rust gate, retain the original launch sound suppression during Tilt, and add regression coverage for the waiting-ball case. Test Plan: - `just test` -- passed (138 Rust tests and 3 highscore-server tests) - `just clippy` -- passed - `cargo +nightly fmt --all -- --check` -- passed - `git diff --check` and `git diff --cached --check` -- passed --- tdkpin-rs/src/game.rs | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/tdkpin-rs/src/game.rs b/tdkpin-rs/src/game.rs index edb2730..f6b9277 100644 --- a/tdkpin-rs/src/game.rs +++ b/tdkpin-rs/src/game.rs @@ -540,7 +540,10 @@ impl Game { self.flipper_inputs.right_raised = controls.right_flipper && !self.tilted && !self.flipper_release_latch[1]; - if self.ball.in_launcher && !self.tilted { + // The original key handlers keep accepting the launcher key while + // tilted; Tilt disables flippers and scoring, but must not strand a + // ball that is still waiting in the shooter lane. + if self.ball.in_launcher { if controls.launch_down { if self.launcher_was_down { self.launcher_hold_seconds += frame_time.min(0.05); @@ -563,7 +566,9 @@ impl Game { } else if self.launcher_was_down { self.fire_launcher(); events.push(Event::Launch); - events.push(Event::Sound(2002)); + if !self.tilted { + events.push(Event::Sound(2002)); + } } } if !self.tilted && controls.nudge != Nudge::None { @@ -4928,4 +4933,38 @@ mod tests { assert!(game.tilted); assert!(game.ball.in_launcher); } + + #[test] + fn tilted_waiting_ball_can_still_be_launched() { + let mut game = Game::new_with_seed(1, 7); + + for _ in 0..2 { + game.update( + 0.0, + 3, + Controls { + nudge: Nudge::Right, + ..Controls::default() + }, + ); + } + assert!(game.tilted); + assert!(game.ball.in_launcher); + + game.update( + 0.0, + 3, + Controls { + launch_down: true, + ..Controls::default() + }, + ); + assert!(game.launcher_frame() > 0); + + let events = game.update(0.0, 3, Controls::default()); + assert!(events.contains(&Event::Launch)); + assert!(!events.contains(&Event::Sound(2002))); + assert!(!game.ball.in_launcher); + assert!(game.tilted); + } }