How to implement a complex staged multiball sequence

180 views
Skip to first unread message

Olivia Helm

unread,
Oct 10, 2021, 4:14:40 PM10/10/21
to MPF Users

I am having some trouble figuring out how to implement the following sequence --

Player locks a ball in a saucer
We hold the ball there, launch another ball, player has some objectives
If the player drains before completing the objectives, we release the ball from the saucer and the sequence ends
If the player completes the objectives and gets the ball in one of two other saucers, we add an additional ball, with new objectives.  This should, in effect, start as a 3 ball multiball, with the ball in play (the second one that you just locked in a saucer) being ejected,  the ball from the saucer being ejected, and one more auto launched ball from the trough.
If the player drains all balls without completing objectives, the sequence and ball end.
If the player completes objects, and locks a ball into the original saucer that started it all, we want to 
  * hold the ball in the saucer
  * drain all remaining balls on the playfield 
  * play some shows
  * end the whole multiball sequence
  * kick the ball out of the saucer returning to single ball play

Trying to understand what the right way to do this sort of thing in MPF would be.  I have it nearly working, except I cannot seem to get it to hold the ball at the end... no matter what I do it ejects the ball from the saucer as soon as the ball device detects the ball in the saucer.

Right now, I am doing this with the following setup --

* all three saucers are defined as ball devices.  For the saucer that starts and ends the sequence, auto fire on unexpected ball is false
* I am using ball holds at the start and end to hold the balls
* I am starting a 2 ball multi ball to add a ball for the first part of the sequence, keeping the original ball in the saucer with a ball hold
* When you enter the second saucer I am ending the 2 ball multiball and starting a 3 ball multiball, using the first saucer as a ball lock, immediately ejecting the second saucer ball, and ending the ball hold first saucer locked ball when the 3 ball multball starts
* I am then using another ball hold on the original saucer that should successfully end the sequence.  This is what isn't working.  In the devices window, the ball hold device actually shows its holding a ball, even after the coil fires to release the ball.  The MPF log shows the ball device is ejecting the ball.

I can share code, logs, etc... but I was thinking before I asked anyone to look at that, if I am on the right track with how I am trying to implement this, since it feels really complicated...maybe there is a better way to go at implementing this rule.

james cardona

unread,
Oct 10, 2021, 4:41:30 PM10/10/21
to MPF Users
post your def file for the saucer please

Olivia Helm

unread,
Oct 10, 2021, 5:21:20 PM10/10/21
to MPF Users
I'm really looking for a sanity check on how I'm implementing this sequence, but I can share some setup.

This is how the saucer that is meant to start and end the sequence is defined as a ball device --

bd_escape_saucer:
ball_switches: s_saucer_treasure_chamber
eject_coil: c_saucer_trasure_chamber
eject_events: zzz_none, chase_multiball_qualified
# eject_timeouts: 500ms, 1s, 2s, 4s
auto_fire_on_unexpected_ball: false
debug: true

* I have tried this both with eject_timeouts commented and no commented, this has no effect on the behavior.
* The event "chase_multiball_qualified" is thrown at this step of the sequence --
"If the player completes the objectives and gets the ball in one of two other saucers, we add an additional ball, with new objectives.  This should, in effect, start as a 3 ball multiball, with the ball in play (the second one that you just locked in a saucer) being ejected,  the ball from the saucer being ejected, and one more auto launched ball from the trough."
* The event "zzz_none" is never thrown, its a place holder and will eventually be replaced with an event indicating we are ready to "* kick the ball out of the saucer returning to single ball play", the very last step in the sequence.

This is the ball hold in effect for the "We hold the ball there, launch another ball, player has some objectives" part of the sequence, which is working as expected.

ball_holds:
chase_hold:
balls_to_hold: 1
hold_devices: bd_escape_saucer
release_one_events: release_chase_hold
disable_events: multiball_chase_multiball_started

This is the ball hold in effect during the 3 ball multiball.  Curiously, when looking at the device monitor, even after I see the eject ball events, this still shows its holding one ball.

ball_holds:
boar_hold:
balls_to_hold: 1
hold_devices: bd_escape_saucer
enable_events: boar_six_pack_complete
release_one_events: zzz_boar_final_display

Note that the event zzz_boar_final_display is a placeholder event (like zzz_none above) and would eventually be replaced with an event indicating we are ready to  "* kick the ball out of the saucer returning to single ball play", the very last step in the sequence.

I also use a ball save device during this first phase, where the ball is locked in the saucer, and you are attempting to complete objectives with another ball I put onto the playfield -- 

ball_saves:
pre_chase_ballsave:
enable_events: start_chase_sequence
disable_events: release_chase_hold
only_last_ball: true

If we drain to one ball, I kill the ball save, return the held ball, and you are back to normal single ball play.  I did it this way mainly because I don't want the state to carry ball to ball or have the ball locked for the next player.  If you fail to start the 3 ball multiball, you should be back in single ball play, no balls held in the saucer... this is all working as expected.

Here are the multiball definitions --

multiballs:
pre_chase_multiball:
ball_count: 1
ball_count_type: add
start_events: start_chase_sequence
stop_events: end_chase_sequence
chase_multiball:
ball_count: 2
ball_count_type: add
ball_locks: bd_escape_saucer
start_events: start_chase_multiball
stop_events: ball_save_ball_save_boars_nest_timer_start

I was wondering if this might have been related to my use of bd_escape_saucer as a ball lock device, but this behavior occurs with and without its use as a ball lock device.  If I don't use it as a ball lock device, I get more balls launched than I wanted.

Note that the various indent levels are not shown when I copy and paste the code here.

I am throwing the events to stop the "pre_chase_multiball" as soon as I start the "chase_multiball".  I am throwing the event to stop the "chase_multiball" pretty much as soon as it launches its balls... another mode handles the rules for this sequence, which I want to continue even if the multiball portion end... this other mode also handles the multi-ball ball saver as a ball_save device rather than using the multiball's own ball save device.  

I've tried this a couple of different ways (not ending the multiball, not using the ball lock, etc)., and still it seems like the "boar_hold" ball_hold just...won't...hold....

I've thought about a single multiball with an add-a-ball event... but just haven't tried that approach yet.

Anyway, I suspect these code snippets would likely lead to more questions... that's why I was looking for a sanity check on my initial scheme.

I wonder if there is a way to add a ball to the playfield without starting a multiball?  Sort of like in Stern Star Trek, where a certain number of warp ramp hits can trigger "add-a-ball", whether or not you are in a multiball.... if you aren't it just throws another ball on the playfield.... 

kaydeeH

unread,
Oct 10, 2021, 9:20:10 PM10/10/21
to MPF Users
Hi Jan,

Olivia and I went through this in detail trying a million little and big changes, hoping to figure out what's going on. We've simplified things quite a bit from Olivia's first posts to ease troubleshooting, but long story short... Two ball holds exist. Both work as expected until the multiball starts. Once the multiball starts, one of the two continue to work normally, but the other... the one behind the inline drops... stops working normally. If the ball hits that hold again, it will increment to show one ball in the hold, but immediately eject it and continue to show one ball in the hold. Some other things get weird for a moment too, more on that later. This is completely reproducible on our source (with or without hardware enabled) as follows:

  1. Start a game with the monitor running. Using the monitor right-click deselect the shooter lane switch to "launch" the ball.
  2. Knock down the four inline drop targets with right-click selects. The last drop target starts the mode that contains the multiball.
  3. Right-click select the switch in the saucer behind the inline drop targets... the game will hold it and eject another ball from the trough. -- This ball hold is working as expected at this point.
  4. Hit a playfield switch repeatedly (easiest to do, hit an upper pop bumper 8 times) until the score displays show a "speed" of greater than 120 mph and the displays say "escape roscoe".
  5. Right-click select either of the two remaining saucers, both balls are ejected from the saucers, a third ball is ejected, and now you're in the heart of the multiball.
  6. The inline drops reset and now you need to collect 6 achievements to cause the inline drops to be knocked down again (you might even be able to skip the achievements and get the same result, but that's not how the game will be played):
    1. Left saucer
    2. Right saucer
    3. Far right rollover
    4. 3 drop target bank on the right all down
    5. 1 spinner hit
    6. 1 pop hit
  7. At that point your goal is to get the ball into the original saucer behind the inline drops, so right-click on that saucer switch.
    1. Ball immediately ejects, ignoring the ball hold
    2. Ball hold continues to show 1 ball is held on the monitor despite the eject.
    3. Playfield shows 2 balls again, despite the ball hold claiming otherwise.
    4. Events show that the ball device ejected the ball, not the ball hold.
  8. The ball hold on the other left-side saucer continues to work as expected (ball goes in, hold count goes up to 1, expected events happen, ball ejects, hold count goes down to zero) if you right-click them, but repeated hits to the saucer/hold behind the inlines causes an immediate eject and the ball hold count remains stuck at 1.
  9. Drain one of the balls so multiball ends by right-clicking it's position in the multiball trough. -- Ball hold saucer behind the inlines remains dysfunctional as above.
  10. Drain the remaining ball. Here's where something else strange happens.
    1. (Only on actual hardware) the game will sit idle for a period of time (several seconds) before starting the next ball.
    2. (With or without hardware) the ballsave for your next ball never activates (right-click the shooter lane switch to launch, then hit any switch) and the inline saucer remains dysfunctional.
  11. Drain your second ball.
    1. Third ball gets the ballsave back, but the saucer remains dysfunctional.
    2. If you go through the multiball sequence again, the mode starts, but essentially doesn't work at all. Once that ball hold dies, the whole game gets messed up.
You can check out our source here: https://github.com/kaydeeH/OutpostKodelia-DoH

The whole thing is still rough and needs a lot of refinement and further development, but until we can get past this step, there's no way to test much after the multiball starts. I should mention, too, that we have two other multiballs in the game that use the two saucers that aren't behind the inline drops, and they work perfectly fine. We don't see any events happening that should be causing the ball hold to eject or turn dysfunctional. We're stumped. I hope this doesn't amount to something silly that we're missing, but it feels like this may need to be debugged and we're just not up to that level with Python and the MPF framework yet.

Thanks in advance for any help you can give us!
Kaydee and Olivia

jabdoa

unread,
Oct 11, 2021, 8:55:29 AM10/11/21
to MPF Users
From a quick glance it look like you are using multiballs together with ball_holds. The issue with that is that those balls are still technically in play. In contrast, multiball_locks replace balls with new ones when you lock them do not have this issue. I suspect that the multiball is stealing balls from your ball_holds and logic gets confused. This not currently supported this way. MPF does not currently track if a ball in a ball_device is in play or not.

Jan

Olivia Helm

unread,
Oct 11, 2021, 7:52:58 PM10/11/21
to MPF Users
I have another approach I could take that would get rid of ball holds for this mode... what I am missing is this --

Is there a way to "cancel" a lock and return the ball to the playfield?

Here is what I'd want to do --

Player locks a ball, is served up a new ball
Qualifying 2nd lock and locking 2nd lock starts 3 ball multiball
  or 
Draining all balls on playfield before qualifying 2nd lock does not end the ball, but cancels the lock, giving that ball back and continuing single ball play.

Thanks,
Kaydee & Olivia

Olivia Helm

unread,
Oct 11, 2021, 10:52:37 PM10/11/21
to MPF Users
So I have this working using a more brute force approach.... I got rid of the ball device for the saucer, and just wrote a mode to handle all cases where the saucer switch is active, including checking for a stray ball in attract mode...

Doesn't feel like an ideal solution... certainly open to better ideas... 

Anyway, thanks for looking...and if anyone has better ideas, I'd love to hear them!

cobra18t

unread,
Oct 12, 2021, 1:23:38 AM10/12/21
to MPF Users
I did something similar in a game where a ball was saved using a locked ball. If you had a ball locked and went down a lit outlane, it would immediately start a 2-ball multiball. The multiball_lock was the source device for the multiball. This acted like an early ball save. Once the ball hit the outlane switch, the lock eject was triggered. The outlane ball would drain shortly after, ending the multiball. https://youtu.be/IkQOwIsB0to?t=275 This is not exactly what you want since you also want to save the ball from the lock if someone drains down the middle where there is no switch.

One way would be to intercept the ball_drain relay event to add the ball from the lock to the playfield. See https://docs.missionpinball.org/en/dev/flowcharts/ball_end.html and https://docs.missionpinball.org/en/dev/config_players/queue_event_player.html

I think the "correct" way to handle this does not exist yet. I think this should be part of a ball_save. Right now a ball save only sources balls from the playfield source device (trough). A feature could be added to ball_saves to source the save from a specified device instead. This would be similar to how multiballs source from specified devices using the "ball_locks" config option before they try to source from the trough.

james cardona

unread,
Oct 12, 2021, 5:22:03 AM10/12/21
to MPF Users
KD and O, I didn't want to mention it but looks like you are going down the same path I went down in a way. I also had a lot of trouble with multiple ball holds as there are 4 such locations on no good gofers and when I couldn't get the yaml to work right my solutions was similar in that I deleted all of the yaml ball hold code and wrote a python program that does all of the ball control and manipulation logic. Using yaml just doesn't make that much sense to me when the complexity ramps up and python is so much easier to read in such cases. I suppose it could be done in yaml, I just couldn't get it to work.

jabdoa

unread,
Oct 12, 2021, 4:10:14 PM10/12/21
to MPF Users
The general idea here would be (for a 3 ball mb): Lock two balls using multiball_locks, load your mb mode when the lock is full (or enable the mb) and then start your mb on balldevice_xxx_ball_entered. That should result in exactly your desired behaviour. I implemented something like this in the state machine stream.

Jan

cobra18t

unread,
Oct 12, 2021, 5:16:46 PM10/12/21
to MPF Users
What Jan said gets you the multiball building behavior you want. 

I am going to add a feature in ball_saves to source the save from a lock. I have wanted this multiple times and now someone else wants it too. It should not be too difficult since multiballs have a similar feature. Will test over the next couple days.

Olivia Helm

unread,
Oct 12, 2021, 5:25:23 PM10/12/21
to MPF Users
Yes, I think the locks + ball save from a lock would get us there... thanks for looking into that!

cobra18t

unread,
Oct 14, 2021, 8:11:06 PM10/14/21
to MPF Users
Just an update, Olivia and Kaydee, I have ball_saves from a lock working on my machine and have a pull request open to incorporate it into MPF: https://github.com/missionpinball/mpf/pull/1607

It may take a little while to be reviewed and merged into the dev branch.

Using the new code, here is a simple example showing the addition of the ball_locks option to source a save from the lock. If there is no ball in the lock, the save comes from the trough. If you only want the save to come from the lock and not the trough, only enable the save when there is a ball in the lock.

ball_devices:
  bd_left_saucer:
    ball_switches: s_left_saucer
    eject_coil: c_left_saucer
    eject_timeouts: 1s

multiball_locks:
  left_lock:
    balls_to_lock: 1
    enable_events: mode_base_started
    lock_devices: bd_left_saucer
    locked_ball_counting_strategy: physical_only

ball_saves:
  default:
    enable_events: mode_base_started
    ball_locks: bd_left_saucer  # source from lock(s) if a ball is available, otherwise the trough
    balls_to_save: 1

cobra18t

unread,
Oct 18, 2021, 1:09:01 PM10/18/21
to MPF Users
Upgrade to the latest dev version for sourcing a ball save from a lock as previously described.

Brian Cox

unread,
Nov 8, 2021, 1:03:39 AM11/8/21
to MPF Users
Have you figured this out yet?

Sounds like an interesting problem, I might test it out on my latest game, it has two ball holds,



Reply all
Reply to author
Forward
0 new messages