Skip to content

title: Recipe: Skillshot (with Auto-Rotate)

Recipe: Skillshot (with Auto-Rotate)

This guide shows you how to build an MPF config for a skillshot with automatically-rotating targets. When the player's turn starts the target shots will rotate one "lit" shot rapidly, and when the ball is plunged the rotation will stop and the lit shot will flash as the skillshot target.

Step 1. Create a skillshot mode and shots

Skillshots are a self-contained set of rules, so it's wise to create a separate mode that can be started when a player's ball starts and ended after the skillshot is hit (or missed).

#config_version=5
modes:
  - skillshot_with_auto_rotate
switches:
  s_dropbank_1:
    number: 1
  s_dropbank_2:
    number: 2
  s_dropbank_3:
    number: 3
  s_dropbank_4:
    number: 4
  s_dropbank_5:
    number: 5
lights:
  l_dropbank_1:
    number: 1
  l_dropbank_2:
    number: 2
  l_dropbank_3:
    number: 3
  l_dropbank_4:
    number: 4
  l_dropbank_5:
    number: 5

##! mode: skillshot_with_auto_rotate
# mode will be defined below

The first thing our mode needs is shots:. Each possible target will be a shot (in this example, we'll have five). Each shot has a switch, a light, and a shot profile to track its state. The sample code below uses dropbank switches for the skillshot, but you are free to use any switches you like.

Each shot will also have unique advance_events configured, which will be explained in detail in section 4. What's important to note now is that the first shot includes advance_events: mode_skillshot_started so that this shot will automatically light when the mode starts, as the first shot in the rotation.

#! switches:
#!   s_dropbank_1:
#!     number: 1
#!   s_dropbank_2:
#!     number: 2
#!   s_dropbank_3:
#!     number: 3
#!   s_dropbank_4:
#!     number: 4
#!   s_dropbank_5:
#!     number: 5
##! mode: skillshot_with_auto_rotate
#! shot_profiles:
#!   skillshot_profile:
#!     states:
#!       - name: off
mode:
  start_events: start_mode_skillshot_with_auto_rotate
  stop_events: stop_mode_skillshot_with_auto_rotate
  priority: 1000

shots:
  skillshot_drop_1:
    switch: s_dropbank_1
    advance_events: mode_skillshot_with_auto_rotate_started, advance_skillshot_1
    profile: skillshot_profile
    show_tokens:
      leds: l_dropbank_1
  skillshot_drop_2:
    switch: s_dropbank_2
    advance_events: advance_skillshot_2
    profile: skillshot_profile
    show_tokens:
      leds: l_dropbank_2
  skillshot_drop_3:
    switch: s_dropbank_3
    advance_events: advance_skillshot_3
    profile: skillshot_profile
    show_tokens:
      leds: l_dropbank_3
  skillshot_drop_4:
    switch: s_dropbank_4
    advance_events: advance_skillshot_4
    profile: skillshot_profile
    show_tokens:
      leds: l_dropbank_4
  skillshot_drop_5:
    switch: s_dropbank_5
    advance_events: advance_skillshot_5
    profile: skillshot_profile
    show_tokens:
      leds: l_dropbank_5

Step 2. Create a profile for the targets

We can create a shot profile for the targets that starts with the light off, lights it solid after one advancement, and makes it flash 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.

When the mode starts, all shots will be in the first profile state "off". The first shot will immediately advance to the "on" state (from the advance_events: mode_skillshot_with_auto_rotate_started noted above). Every time the shot group rotates, the next shot in sequence will shift to "on". This creates the rotation effect of the lit shot moving across the targets.

When the ball is plunged, whichever shot is in the "on" state will be advanced to the "lit" state and its light will flash. When any shot is hit, we'll check whether it is "lit" or not to know whether the skillshot should be awarded.

##! mode: skillshot_with_auto_rotate
shot_profiles:
  skillshot_profile:
    advance_on_hit: false
    states:
      - name: off
        show: off
      - name: on
        show: on
      - name: lit
        show: flash

Step 3. Create a shot_group for the lanes, and a rotation timer

To tell MPF that the five shots are related to each other, we create a shot group with all the shots in it.

Shot groups are powerful because they control behavior of all the shots together. In this case, we'll use our shot group control the rotation of the shots, and a timer to trigger a rotation every half-second.

#! switches:
#!   s_dropbank_1:
#!     number: 1
#!   s_dropbank_2:
#!     number: 2
#!   s_dropbank_3:
#!     number: 3
#!   s_dropbank_4:
#!     number: 4
#!   s_dropbank_5:
#!     number: 5
##! mode: skillshot_with_auto_rotate
#! shots:
#!   skillshot_drop_1:
#!     switch: s_dropbank_1
#!   skillshot_drop_2:
#!     switch: s_dropbank_2
#!   skillshot_drop_3:
#!     switch: s_dropbank_3
#!   skillshot_drop_4:
#!     switch: s_dropbank_4
#!   skillshot_drop_5:
#!     switch: s_dropbank_5

shot_groups:
  skillshot:
    shots:
      - skillshot_drop_1
      - skillshot_drop_2
      - skillshot_drop_3
      - skillshot_drop_4
      - skillshot_drop_5
    rotate_events: timer_skillshot_rotate_tick

timers:
  skillshot_rotate:
    tick_interval: 500ms
    start_running: true
    control_events:
      - event: s_plunger_lane_inactive
        action: stop

The rotate_events will move the state of the shots each time the timer ticks, and the ball leaving the plunger lane will stop the timer and thus stop the rotation.

Step 4. Flash the lit shot when the rotation stops

When the timer stops, one of the shots will be in the "on" state. Whichever shot this is should be advanced to the "lit" state so the light is flashing, and we can use conditional events to listen for the timer stop and advance only the lit shot.

Shot profile states are numbered starting with zero, so our "off" state is number 0 and the "on" state is number 1. The following code will only post the advance event for a shot if that shot is in state number 1, a.k.a. "on".

##! mode: skillshot_with_auto_rotate
event_player:
  timer_skillshot_rotate_stopped:
    - advance_skillshot_1{device.shots.skillshot_drop_1.state==1}
    - advance_skillshot_2{device.shots.skillshot_drop_2.state==1}
    - advance_skillshot_3{device.shots.skillshot_drop_3.state==1}
    - advance_skillshot_4{device.shots.skillshot_drop_4.state==1}
    - advance_skillshot_5{device.shots.skillshot_drop_5.state==1}

Each shot configured in step 1 above has advance_events that correspond to its shot number, so the above event player will trigger the correct shot to advance to its "lit" state.

Step 5. Rewards for skillshot

When the player hits the lit shot, they get an award of points. We can use the variable_player: for this.

When a shot in a shot group is hit, the shot group will post an event with the state name of the shot that was hit. This way, we can check when any shot is hit rather than having to check each shot individually.

##! mode: skillshot_with_auto_rotate
variable_player:
  skillshot_lit_hit:
    score: 20_000

Step 6. End the mode on skillshot hit, or any other hit

After any skillshot shot is hit, the skillshot mode should end. We can again use the shot group to detect any shot being hit, but we'll use a hit event without a state name because it doesn't matter whether the shot was lit or not.

We also want to end the skillshot mode if any other switch on the playfield was hit, which we can detect from the playfield_active event. However, when the skillshot is hit the playfield_active event will post before the skillshot_lit_hit event, so if we end the mode immediately then no score will be awarded. Instead, we add a 1 second delay after playfield activation before ending the mode.

##! mode: skillshot_with_auto_rotate
event_player:
  # Add these lines after timer_skillshot_rotate_stopped (defined above)
  skillshot_hit: stop_mode_skillshot
  playfield_active: stop_mode_skillshot|1s

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/skillshot_with_auto_rotate


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