title: Recipe: Attack From Mars Super Jets
Recipe: Attack From Mars Super Jets
This guide shows you how to build an MPF config for Attack From Mar's Super Jets feature. The idea is you can use this as a guide to implement a similar feature in your machine.
Note
This recipe requires MPF 0.33 or newer.
This guide uses the following concepts in MPF that you should be familiar with:
You can find the complete runnable machine config for this recipe in the
cookbook/AFM_super_jets
folder of the mpf-examples
repository on GitHub.
What is a Super Jets mode?
In Attack From Mars, Super Jets occur when the player hits the jet bumpers in the top right of the playfield 100 times in the course of a game. The effect of Super Jets is that once the mode is active, each jet bumper hit is worth 3,000,000 points instead of 1,000,000. The mode stops when the ball drains, but once achieving it, it only takes 25 more jet bumper hits to restart it.
Here are the specific rules we need to implement:
Super Jets
- Jet Bumper hits are initially 1,000,000 per hit.
- Each completion of the two inlanes above the jet bumpers add 50,000 to each jet bumper hit (1,050,000, 1,100,000, and so on.)
- Lit inlanes are movable with the flippers.
- One the inlane value reaches 2,000,000 per it, the inlanes stop adding 50,000 when completed.
- Super Pops occur when 100 jet bumper hits occue in the game. The amount of hits carry over to the next ball.
- Once the Super Pops mode has been made, the mode is active until the ball drains.
- Super Pops can be restarted by hitting the jet bumpers 25 more times.
- Once Super Pops have been made, the Super Pops insert on the playfield turns on and stays on.
Step 1. The machine-wide prerequisites
Before we dig into how to handle the mode itself, we need to create a machine-wide config that has all the devices we'll need, including the switches for the jet bumpers and lanes.
Here's what our machine config looks like. (Note that this is complete in terms of what we need to make this recipe work, but if you have a real Attack From Mars then you'll probably have a lot more than this in your machine config file. Also, the coil, switch, and light numbers are generic and need to be changes for a real machine.)
Notice the "player_vars" section. It has a player variable named "sj_active". We will explain this later on, but for now we'll just say that it is how we will tell if we are starting Super Jets for the first time or resuming it after starting it but draining.
#config_version=5
player_vars:
sj_active:
value_type: int
initial_value: 0
modes:
- super_jets_setup
- super_jets
switches:
s_left_flipper:
number: 0
tags: left_flipper
s_right_flipper:
number: 71
tags: right_flipper
s_credit:
number: 6
tags: start
s_outhole:
number: 8
tags:
s_left_bumper:
number: 17
tags: jets
s_middle_bumper:
number: 18
tags: jets
s_right_bumper:
number: 19
tags: jets
s_right_rollover:
number: 22
tags: playfield_active, right_rollover
s_left_rollover:
number: 23
tags: playfield_active, left_rollover
s_trough_5:
number: 36
tags:
s_trough_4:
number: 37
tags:
s_trough_3:
number: 38
tags:
s_trough_2:
number: 39
tags:
s_trough_1:
number: 40
tags:
virtual_platform_start_active_switches: s_trough_1 s_trough_2 s_trough_3 s_trough_4 s_trough_5
coils:
c_flipper_left_main:
number: 0
default_pulse_ms: 20
c_flipper_left_hold:
number: 1
allow_enable: true
c_flipper_right_main:
number: 2
default_pulse_ms: 20
c_flipper_right_hold:
number: 3
allow_enable: true
c_trough_eject:
number: 4
allow_enable: true
c_left_bumper:
number: c01
label:
tags:
default_pulse_ms: 25
c_middle_bumper:
number: c02
label:
tags:
default_pulse_ms: 25
c_right_bumper:
number: c03
label:
tags:
default_pulse_ms: 25
c_ball_eject:
number: c12
label:
tags:
default_pulse_ms: 20
c_outhole:
number: c14
label:
tags:
default_pulse_ms: 20
lights:
l_right_rollover:
number: 5
l_left_rollover:
number: 7
l_super_jets:
number: 9
ball_devices:
bd_drain:
ball_switches: s_outhole
eject_coil: c_outhole
eject_targets: bd_trough
tags: drain, outhole
bd_trough:
ball_switches: s_trough_1, s_trough_2, s_trough_3, s_trough_4, s_trough_5
eject_coil: c_ball_eject
tags: trough, home
autofire_coils:
left_jet:
coil: c_left_bumper
switch: s_left_bumper
mid_jet:
coil: c_middle_bumper
switch: s_middle_bumper
right_jet:
coil: c_right_bumper
switch: s_right_bumper
playfields:
playfield:
default_source_device: bd_trough
tags: default
##! mode: super_jets_setup
# mode will be defined below
##! mode: super_jets
# mode will be defined below
Step 2. Add Super Jets values
We'll start off with the easier mode first as all the heavy lifting is handled by the setup mode for Super Jets. In super_jets.yaml, we set up our starting events for the mode itself, the values of the jet bumpers when Super Jets are active, and also a call to show a slide stating that Super Jets are active.
##! mode: super_jets
mode:
start_events: Super_Jets_Go, Super_Jets_Resume_Go
priority: 300
variable_player:
s_left_bumper_active:
score: 3000000|block
s_middle_bumper_active:
score: 3000000|block
s_right_bumper_active:
score: 3000000|block
show_player:
mode_super_jets_started:
super_jets_startup:
loops: 0
Super_Jets_on:
show_tokens:
lights: l_super_jets
Stepping through how we're using each setting:
start_events: Super_Jets_Go, Super_Jets_Resume_Go
The way the super_jets mode is called is if either "Super_Jets_Go" or "Super_Jets_Resume_Go" are posted.
s_left_bumper_active:
score: 3000000|block
Everytime "s_left_bumper_active" is seen, the score has 3,000,000 points added onto it. The |block is used to prevent any other instances that awards points for hitting "s_left_bumper_active" from adding points as well.
This code is used for all three jets.
show_player:
mode_super_jets_started:
super_jets_startup:
loops: 0
The Show Player shows the slide names "super_jets_started" at the start of the mode. The settings in super_jets_started.yaml dictate the size, font, and duration of the slide being used.
Super_Jets_on:
show_tokens:
lights: l_super_jets
Plays the show called "Super_Jets_on" when this mode starts, lighting the Super Jets light on the playfield.
Step 3. Create an setup mode for Super Jets
Next we need to create a mode called "super_jets_setup" to control when to call the "super_jets" mode. There's lot going on here, but we'll go through it step by step.
##! mode: super_jets_startup
#config_version=5
mode:
start_events: ball_starting
priority: 200
shots:
jets:
switch: s_right_bumper, s_left_bumper, s_middle_bumper
right_rollover:
switch: s_right_rollover
show_tokens:
light: l_right_rollover
left_rollover:
switch: s_left_rollover
show_tokens:
light: l_left_rollover
shot_groups:
rollover_lanes:
shots: right_rollover, left_rollover
rotate_left_events: s_left_flipper_active
rotate_right_events: s_right_flipper_active
reset_events:
rollover_lanes_lit_complete: 1s
counters:
lb_jets_count:
count_events: jets_hit
starting_count: 0
count_complete_value: 100
count_interval: 1
direction: up
persist_state: true
events_when_complete: Super_Jets_Go
debug: true
lb_jets_resume:
enable_events: mode_base_started{current_player.sj_active>0}
count_events: jets_hit
starting_count: 0
count_complete_value: 25
count_interval: 1
direction: up
persist_state: false
events_when_complete: Super_Jets_Resume_Go
debug: true
reset_on_complete: true
lb_rollover_complete_count:
count_events: rollover_lanes_complete
events_when_hit: rollover_lanes_done
starting_count: 0
count_complete_value: 40
reset_on_complete: false
direction: up
persist_state: false
event_player:
Super_Jets_Go:
start_mode_super_jets
Super_Jets_Go_Again:
start_mode_super_jets
variable_player:
s_left_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
s_middle_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
s_right_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
rollover_lanes_complete:
score: 1000
mode_super_jets_started:
sj_active:
int: 1
action: set
show_player:
mode_super_jets_setup_started{current_player.sj_active>0}:
Super_Jets_on:
show_tokens:
lights: l_super_jets
Let's look at each of these settings:
start_events: ball_starting
Here, we are saying that we want "super_jets_setup" to start as soon as the game starts a ball, including extra balls.
shots:
jets:
switch: s_right_bumper, s_left_bumper, s_middle_bumper
right_rollover:
switch: s_right_rollover
show_tokens:
light: l_right_rollover
left_rollover:
switch: s_left_rollover
show_tokens:
light: l_left_rollover
This section establishes our shots. Any time "s_right_bumper", "s_left_bumper", or "s_middle_bumper" is activated, the shot "jet" will register a hit.
"right_rollover" and "left_rollover" will show a hit any time their associated switch is made. Also, when their shots are made, their corresponding insert will also light up because we have a "show_tokens" section listing a light.
shot_groups:
rollover_lanes:
shots: right_rollover, left_rollover
rotate_left_events: s_left_flipper_active
rotate_right_events: s_right_flipper_active
reset_events:
rollover_lanes_lit_complete: 1s
This section is to set up the behavior of our rollover lanes. First, we list our shots, "right_rollover" and "left_rollover". Then we designate our left flipper as a switch to rotate our shots left, and the right flipper to rotate the shots right. This is how we can use the flippers to move a lit rollover to the other lane to try and get the ball to go into an unlit rollover lane and complete the rollovers. "reset_events" is used to pause the shot group for 1 second as the rollover lanes are reset so they are both off again.
counters:
lb_jets_count:
count_events: jets_hit
starting_count: 0
count_complete_value: 100
count_interval: 1
direction: up
persist_state: true
events_when_complete: Super_Jets_Go
debug: true
lb_jets_resume:
enable_events: mode_base_started{current_player.sj_active>0}
count_events: jets_hit
starting_count: 0
count_complete_value: 25
count_interval: 1
direction: up
persist_state: false
events_when_complete: Super_Jets_Resume_Go
debug: true
reset_on_complete: true
lb_rollover_complete_count:
count_events: rollover_lanes_complete
events_when_hit: rollover_lanes_done
starting_count: 0
count_complete_value: 40
reset_on_complete: false
direction: up
persist_state: false
This is the heart of the mode. There are three counters here to help control the program.
"lb_jets_count" is the main counter. It is set up to increment from 0 to 100 every time the jets shot registers a hit, which is set up to include all the jet bumpers. By using "persist_state: true" we have the program not reset the count to 0 if the ball drains. If it takes all 3 balls for the player to hit 100 hits, they can still get Super Jets to start. When the counter hits 100, it causes the event "Super_Jets_Go" to post, and the event player later in the code handles what needs to be done now that it has posted.
"lb_jets_resume" is a similar counter, but it has a few very important differences. First, it has an "enable_events" requirement. If "sj_active" is not greater than 0, this counter will not run. That means that the previous counter, "lb_jets_count", had to start the super_jets mode first, and that the variavle "sj_active" has to somehow be set to greater than 0. When it is active, the counter counts up from 0 to 25. At 25, the counter stops and posts the "Super_Jets_Resume_Go" event. Another important difference is that we use "persist_state: false" to reset the counter on every ball. For example, a player can't get 12 hits in the jets, drain, and then expect Super Jets to start by hitting the jets just 13 more times. It has to be 25 without draining.
The final counter is for the rollover lanes, "lb_rollover_complete_count". We use this to track how many times the rollovers are comeplete, form 0 to 40. We use 40, because 50,000 * 40 = 2,000,000 which is the maximum addition of points we can add to the jets if not in Super Jets mode. By using "persist_state: false" we reset the count on the end of every ball back to 0.
event_player:
Super_Jets_Go:
start_mode_super_jets
Super_Jets_Go_Again:
start_mode_super_jets
Here is where we call our modes depending on what events are posted by the mode. Both events, "Super_Jets_Go" and "Super_Jets_Resume_Go" call the same mode to start, "super_jets", but because we have two different counters calling the mode under different conditions, we have to set it up like this.
variable_player:
s_left_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
s_middle_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
s_right_bumper_active:
score: 1000000 + (device.counters.lb_rollover_complete_count.value * 50000)
rollover_lanes_complete:
score: 1000
mode_super_jets_started:
sj_active:
int: 1
action: set
This is how the scoring is handled before Super Pops is active. Each jet bumper hit is worth 1,000,000 at the start. But, we also have to add 50,000 points for each time the rollovers are completed. To do that, we take the value of the counter, "lb_rollover_complete_count" and multiply it by 50000. Then we add that value to the standard 1,000,000. Remember in "super_jets" that we added |block to the end of the scoring? That was in part to keep these lines from continuing to add to the score, and to just have the scoring from "super_jets.yaml" to appear.
We also have a small score for when the rollover lanes are completed.
What is "sj_active"? This is a player variable set up previously to help with determining when to use which counter to activate super jets. Initially, the game sets "sj_active" to an integer value of 0. But, when Super Pops are activated by "lb_jets_count" because we hit the target of 100 hit, the variable player sets "sj_active" to an integer of 1 as the mode starts. Now, if the ball drains, and a new ball is launched, "lb_jets_resume" will be enabled to start counting, and because its count ends at 25 instead of 100, it will call super_jets before "lb_jets_count". "sj_active" will also stay at a value of 1 because every time the super_jets mode is called, we set "sj_active" is set to 1.
show_player:
mode_super_jets_setup_started{current_player.sj_active>0}:
Super_Jets_on:
show_tokens:
lights: l_super_jets
When "sj_active" has been set to 1, it is greater than 0. Now, the light for Super Jets will stay on from now on whenever a ball starts, and the super_jets_setup mode starts.
Step 4. Set up your Super Jets Slide
Here we set up a quick slide that pops up on the DMD when we've started Super Pops.
##! mode: super_jets_startup
- duration: 2s
slides:
super_jets_startup:
widgets:
- type: text
text: SUPER JETS
font_size: 20
y: 60%
priority: 200
Step 5. Add the light for Super Jets
And finally, we set up a lightshow for turning on the Super Jets insert on the playfield.
##! mode: Super_Jets_on
- time: 0
lights:
l_super_jets: ff
At this point you should have a working Super Pop mode. If any of this feels unclear or I've muddied up the explanation, feel free to join the discussion in the forum.
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