Example #1
0
/** 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;
			}
		}
	}
}
Example #2
0
/** 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 ();
}