From 4bc370be121d0286c87297189a90b1166376de41 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sat, 22 Aug 2026 17:06:01 +0200 Subject: [PATCH] fix(game): ignore nudges while waiting to launch A cabinet nudge could still raise the tilt meter after a drain while the next ball was parked in the launcher. If that latched TILT, launching was correctly disabled but no active ball remained to drain and clear it, creating a new softlock. Only accept nudges for an active ball. This keeps the latched tilt rules intact while guaranteeing every waiting ball can be launched. Test Plan: - `cargo fmt -- --check` -- passed - `cargo test --all-targets` -- passed, including the waiting-ball regression - `cargo clippy --all-targets -- -D warnings` -- passed - `git diff --check` -- passed --- tdkpin-rs/src/game.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tdkpin-rs/src/game.rs b/tdkpin-rs/src/game.rs index 465481a..8831961 100644 --- a/tdkpin-rs/src/game.rs +++ b/tdkpin-rs/src/game.rs @@ -176,7 +176,11 @@ impl Game { if controls.launch_pressed && self.launch() { events.push(Event::Launch); } - if !self.tilted && controls.nudge.abs() > 0.1 && self.nudge_cooldown <= 0.0 { + if !self.tilted + && !self.ball.in_launcher + && controls.nudge.abs() > 0.1 + && self.nudge_cooldown <= 0.0 + { self.ball.velocity.x += controls.nudge * 55.0; self.nudge_meter += controls.nudge.abs() * 0.34; self.nudge_cooldown = 0.22; @@ -675,6 +679,7 @@ mod tests { #[test] fn tilt_latches_and_disables_flippers_and_scoring() { let mut game = Game::new(1); + assert!(game.launch()); game.bonus = 4_000; for _ in 0..4 { game.nudge_cooldown = 0.0; @@ -723,4 +728,26 @@ mod tests { assert!(!game.tilted); assert!(game.ball.in_launcher); } + + #[test] + fn waiting_ball_cannot_be_tilted() { + let mut game = Game::new(1); + + for _ in 0..12 { + game.nudge_cooldown = 0.0; + let events = game.update( + 1.0 / 60.0, + 3, + Controls { + nudge: 1.0, + ..Controls::default() + }, + ); + assert!(!events.contains(&Event::Nudge)); + assert!(!events.contains(&Event::Tilt)); + } + + assert!(!game.tilted); + assert!(game.launch()); + } }