ddidderr 158936577a fix(divergence): replace a full wheel immediately during multiball
Bug: filling the fifth wheel hole with several balls in play awarded the
transfer, multiplier, and extra ball, but did not run the wheel
replacement. The original deferred the 281-frame panel until a later
launcher reset, which with crazy-mode balls could be a long time, while
the full wheel kept every hole closed.

Requirement: a full wheel must be replaced with the same animation and
scoring as in single-ball play. Balls still in play keep moving, with
the wheel's outer border as a solid boundary and no hole captures until
the replacement is done.

Changes:
- complete_lock_hole starts the panel for a multiball fill too (if one
  is not already running). The single-ball path is unchanged and still
  restarts it unconditionally, as in the original. Scoring was already
  identical and is untouched.
- timer_tick only freezes physics during the panel while every ball
  waits in the launcher. That is always the case for the single-ball
  replacement (the locking ball was reset), so it is frozen exactly as
  before; during multiball the balls in play keep integrating.
- While the panel runs, check_lock_holes captures nothing and
  retain_wheel_rim adds a circle around the wheel hub (record 134's
  center, 48 px ball-center radius, enclosing the five hole posts) with
  the hub's material. It only repels balls moving towards it, so a ball
  already inside rolls out instead of being caged.
- Stress runs then showed balls trapped for good at the bottom of a hole
  pocket, cradled between the hub and a post, after another ball filled
  that hole or the panel closed it. The pocket bottom lies outside the
  hole's capture zone, so nothing ever moved them. A filled or closed
  hole now kicks such a ball (more than 4 px inside its rim) out of its
  center, radially away from the hub at 3 px/step, a path that clears
  both neighbouring posts. Balls arriving from outside are reflected by
  the rim before getting that deep.
- A lock or special-hole capture that removes the last remaining ball
  of a multiball callback now resets it to the launcher (or finishes it
  when tilted), exactly like the single-ball capture, instead of ending
  the player's ball.

Test Plan:
- cargo test (164 tests), including
  full_wheel_during_multiball_replaces_it_while_balls_play_on (rim
  bounce, no captures, balls move, wheel cleared after the panel),
  filled_or_closed_lock_hole_kicks_out_a_ball_resting_in_its_pocket
  (the exact trapped position seen in stress runs), and the updated
  fifth_multiball_lock_starts_the_panel_and_caps_survivor_reaward.
- A temporary release-mode stress run (not committed): 40 seeded
  two-player games with crazy mode, autoplay flippers, and nudges all
  finished; 62 wheel replacements happened during multiball; no
  invariant violations.
- Manual: in crazy mode fill the fifth wheel hole; the replacement
  animation plays while the other balls keep moving and bounce off the
  wheel instead of dropping into its holes.
2026-10-10 11:46:28 +02:00
S
Description
No description provided
13 MiB
0 Stars 1 Watchers 0 Forks
Languages
C 73.2%
Rust 14.6%
C++ 5%
Python 4.1%
Shell 1.4%
Other 1.6%