/** Called by the trough when a ball has entered it. * The intent is to signal that there is one less live ball than before. */ void device_remove_live (void) { /* If any balls were missing, and now one is rediscovered in the * trough, then just hold onto it. This condition was seen when * the game thought 1 ball was in play, but 2 were on the playfield. */ if (missing_balls > live_balls) { callset_invoke (missing_ball_found); missing_balls--; } else if (live_balls > 0) { /* Decrement the count of balls in play. Now what? */ live_balls--; if (in_game && !in_bonus) { /* Notify that the ball count changed */ callset_invoke (ball_count_change); /* See if this qualifies as a ball drain. Any event receiver can return FALSE here if it is not to be treated as a drain; e.g., when a ballsaver is active. In these cases, the event function is also responsible for putting the ball back into play. */ if (!callset_invoke_boolean (ball_drain)) return; /* OK, at this point, it is a true ball drain event. See how many balls are in play now. */ switch (live_balls #ifdef DEVNO_TROUGH + device_entry (DEVNO_TROUGH)->kicks_needed #endif ) { case 0: /* With zero balls in play, this is end of ball. This function usually does not return; it will stop just about every task running to reset for the next ball. */ end_ball (); return; case 1: /* Multiball modes like to know when single ball play resumes. */ callset_invoke (single_ball_play); break; default: break; } } } }
/** A monitor task that checks whether or not a ball search is necessary. This task periodically bumps a counter, which is normally reset as scoring switches are triggered. If the counter reaches a threshold, and ball search is allowed to run, then it is initiated. This task is also responsible for incrementing the ball time statistic, when ball search is not necessary. */ void ball_search_monitor_task (void) { ball_search_timer_reset (); while (in_game) { task_sleep (TIME_1S); /* Step the ball search timer as long as a game * is in progess. But don't allow a ball search in * some situations: * * - ball is on the shooter switch * - either flipper button is held */ if (in_live_game && !in_bonus && (live_balls || !valid_playfield) #ifdef MACHINE_SHOOTER_SWITCH && !switch_poll_logical (MACHINE_SHOOTER_SWITCH) #endif && !switch_poll_logical (SW_LEFT_BUTTON) && !switch_poll_logical (SW_RIGHT_BUTTON)) { ball_time++; ball_search_timer_step (); if (ball_search_timed_out ()) { ball_search_count = 0; while (ball_search_timer != 0) { if ((ball_search_count >= 5) && chase_ball_enabled ()) { /* If chase ball is enabled, after the 5th ball search we will force endball. */ audit_increment (&system_audits.chase_balls); end_ball (); return; } else { /* Perform a ball search */ ball_search_run (); } /* After the third ball search, cancel the tilt lamp effect, to help the player find the missing ball. */ if (ball_search_count == 3) leff_stop (LEFF_TILT); if (ball_search_count < 10) { /* Delay a small amount for the first few ball searches */ task_sleep_sec (12); } else { /* Delay longer after many ball searches */ task_sleep_sec (20); } /* After a while, just give up -- but don't do that in tournament mode or on free play; this is just to keep a location game from cycling continuously. */ if (ball_search_count >= 25 && !price_config.free_play && !system_config.tournament_mode) { fatal (ERR_BALL_SEARCH_TIMEOUT); } } /* A ball was seen -- clear the counter and exit */ ball_search_count = 0; } } } task_exit (); }