Skip to content

title: Recipe: Sequential Drop Target Banks

Recipe: Sequential Drop Target Banks

This guide shows you how to build an MPF config for a drop target bank with targets that must be hit in a specific order.

The mode starts with one target flashing as the correct target to hit, and all the rest off. Hitting the correct target will keep the hit target down, hold the light on, and flash the next target. Hitting an incorrect target will reset that target's coil and keep the light off.

Step 1. Create a sequential_drops mode and lane shots

We'll create a separate mode called sequential_drops to manage the game logic. Separate modes keep the code clean and make it easy to turn the drop sequence on and off as needed (e.g. during a multiball or wizard mode).

The first thing our mode needs is shots:. Each drop target will be a shot (in this example, we'll have four). Each shot has a switch, a light, and a shot profile to track its state.

Each shot will also have unique advance_events configured, which will advance the shot (from "off" to "lit") when its predecessor is hit, and again advance the shot (from "lit" to "down") when it is hit. The final shot does not need to advance from "lit" to "down" because the sequence resets when it's hit.

Each shot also has reset_events configured, so that the entire sequence can be reset after completion.

#! switches:
#!   s_drop_1:
#!     number: 1
#!   s_drop_2:
#!     number: 2
#!   s_drop_3:
#!     number: 3
#!   s_drop_4:
#!     number: 4
#! lights:
#!   l_drop_1:
#!     number: 1
#!   l_drop_2:
#!     number: 2
#!   l_drop_3:
#!     number: 3
#!   l_drop_4:
#!     number: 4
#! shot_profiles:
#!   drop_sequence:
#!     states:
#!       - name: off
#!       - name: lit
#!       - name: down
##! mode: sequential_drops

mode:
  start_events: start_mode_sequential_drops
  stop_events: stop_mode_sequential_drops
  priority: 200

shots:
  drop_1:
    advance_events: advance_drop_1, drop_1_lit_hit
    reset_events: reset_drop_sequence
    switch: s_drop_1
    profile: drop_sequence
    show_tokens:
      led: l_drop_1
  drop_2:
    advance_events: drop_1_lit_hit, drop_2_lit_hit
    reset_events: reset_drop_sequence
    switch: s_drop_2
    profile: drop_sequence
    show_tokens:
      led: l_drop_2
  drop_3:
    advance_events: drop_2_lit_hit, drop_3_lit_hit
    reset_events: reset_drop_sequence
    switch: s_drop_3
    profile: drop_sequence
    show_tokens:
      led: l_drop_3
  drop_4:
    advance_events: drop_3_lit_hit
    reset_events: reset_drop_sequence
    switch: s_drop_4
    profile: drop_sequence
    show_tokens:
      led: l_drop_4

Step 2. Create a profile for the targets

We can create a shot profile for the targets that starts with the light off, flashes it after one advancement, and keeps the light on solid after a second advancement. By default, a shot will advance its profile when the shot is hit, but we don't want that here so we'll set advance_on_hit: false.

This profile uses three built-in shows, off, flash, and on. These shows accept the show_tokens from our shots. In this case, it is the LED we wish to control. You can create your own shows to change LED color, play sounds, etc.

##! mode: sequential_drops

shot_profiles:
  drop_sequence:
    advance_on_hit: false
    states:
      - name: off
        show: off
      - name: lit
        show: flash
      - name: down
        show: on

Step 3. Create a Sequence Logic Block to track the progression

MPF includes a number of convenient ways for tracking progress called Logic Blocks, including the sequence that we can use to require a series of events to occur in a specific order.

The below sequence requires all four drop target shots to be hit, but only registers a hit if the shot is in the "lit" state. This allows us to track where we are in the sequence without having to monitor each shot individually.

The sequence also has restart_events so we can restart when the mode starts and when the sequence completes. All logicblocks have a default completion event called logicblock_(name)_complete so we don't need to explicitly define any completion event.

##! mode: sequential_drops

sequences:
  drop_sequence:
    restart_events: reset_drop_sequence
    events:
      - drop_1_lit_hit
      - drop_2_lit_hit
      - drop_3_lit_hit
      - drop_4_lit_hit

Step 4. Start, advance, and reset the shots

We will use events to manage the behavior of the shots and the drop targets. The first step is to identify all the rules of how the sequence and shots behave.

  • Rule 1: When the mode starts, reset the drop sequence
  • Rule 2: When the sequence is completed, reset the drop sequence

On a reset, all of the shots will be in their "off" state. We need the first target to be "lit" in order for the sequence to start.

  • Rule 3: When the sequence resets, advance the first target from "off" to "lit"

When a shot is in the "off" state and gets hit, we want to fire the reset coil for the target so that the target stays up.

  • Rule 4: When an "off" shot is hit, reset its coil

We can apply all of these rules based on the corresponding events, like follows.

##! mode: sequential_drops

event_player:
  # When the mode starts, reset the drop sequence
  mode_sequential_drops_started: reset_drop_sequence

  # When the sequence is completed, reset the drop sequence
  logicblock_drop_sequence_complete: reset_drop_sequence

  # When the sequence resets, advance the first target
  reset_drop_sequence: advance_drop_1

  # When an "off" shot is hit, reset its coil
  drop_1_off_hit: reset_drop_1
  drop_2_off_hit: reset_drop_2
  drop_3_off_hit: reset_drop_3
  drop_4_off_hit: reset_drop_4

The above configuration requires that each drop target coil has the corresponding reset events, as configured below.

#! switches:
#!   s_drop_1:
#!     number: 1
#!   s_drop_2:
#!     number: 2
#!   s_drop_3:
#!     number: 3
#!   s_drop_4:
#!     number: 4
#! coils:
#!   c_drop_1:
#!     number: 1
#!   c_drop_2:
#!     number: 2
#!   c_drop_3:
#!     number: 3
#!   c_drop_4:
#!     number: 4

drop_targets:
  drop_1:
    switch: s_drop_1
    reset_coil: c_drop_1
    reset_events: ball_starting, machine_reset_phase_3, reset_drop_1
  drop_2:
    switch: s_drop_2
    reset_coil: c_drop_2
    reset_events: ball_starting, machine_reset_phase_3, reset_drop_2
  drop_3:
    switch: s_drop_3
    reset_coil: c_drop_3
    reset_events: ball_starting, machine_reset_phase_3, reset_drop_3
  drop_4:
    switch: s_drop_4
    reset_coil: c_drop_4
    reset_events: ball_starting, machine_reset_phase_3, reset_drop_4

Step 5. Rewards for progression and completion

When a drop target is hit, The sequence logic block keeps track of whether it is the part of the sequence or not. We can easily award points for progression with the logicblock_(name)_hit event (when a lit target is hit) and the logicblock_(name)_complete event (when the full sequence is completed).

##! mode: sequential_drops

variable_player:
  logicblock_drop_sequence_hit:
    score: 1000
  logicblock_drop_sequence_complete:
    score: 50_000

Full Example Code

The full code from this example can be found as a fully-working game template in the MPF Examples repository.

https://github.com/missionpinball/mpf-examples/tree/dev/cookbook/sequential_drop_banks


Something missing or wrong? You can fix it!

This website is edited by people like you! Is something wrong or missing? Is something out of date, or can you explain it better?

Please help us! You can fix it yourself and be an official "open source" contributor!

It's easy! See our Beginner's guide to editing the docs.

Page navigation via the keyboard: < >

You can navigate this site via the keyboard. There are two modes:

General navigation, when search is not focused:

  • F , S , / : open search dialog
  • P , , : go to previous page
  • N , . : go to next page

While using the search function:

  • Down , Up : select next / previous result
  • Esc , Tab : close search
  • Enter : go to highlighted page in the results