- View New Content
-
Getting Started
-
Tutorials
Tutorial Categories
Tutorials Main Page Installation and Setup Downloadable TutorialsROM Adjustments
Number of Balls Adjustments Volume Adjustments
-
Visual Pinball Tables
VP 8 Desktop Tables
All VPM Recreations VP Recreations VP/VPM MODs VP Originals ROMsVP 9 Desktop Tables
All VPM Recreations VP Recreations VP/VPM MODs VP Originals ROMsVP9 Cabinet Tables
All Full Screen Cabinet Full Screen B2S Cabinet Spanned Cabinet Tables Media Packs ROMsVPX Tables
All VPinMAME Recreations VPX- - /VPinMAME - MOD Tables VPX Recreations VPX Originals Media Packs ROMs VR
-
Frontend Media & Backglass
Media Packs
Complete Media Packs Wheel Logos VideosBackglasses
dB2S Animated Backglasses UVP Animated Backglasses Topper Images
- Future Pinball Tables
-
Design Resources
Main Resources
Table Templates Playfield Images Image Library Sound Library Key CodesVP Guides
VP8 Guide - English VP8 Guide - Deutsch VP9 Guide - English VP9.1.x Guide - English VP Object Guide VPM DocumentationFuture Pinball Resources
Playfield Images 3D Model LibraryFuture Pinball Guides
FP Script Guide Big Draco Script Guide FP Table Design Guide FP DMD Guide
- Other Features
- Bug Tracker
- Image Gallery
- Blogs
-
More
Visual PinMAME Scripting 102
Started By
destruk
, Jan 07 2010 09:15 AM
12 replies to this topic
#1
Posted 07 January 2010 - 09:15 AM
Visual PinMAME Scripting 102 - Ballstacks and Subway Systems
--------------------------------------------------------------
Joe had wanted more information on ballstacks, and since I was going to do subway systems, they go together.
From the previous article, we have this code:
Set bsTrough=New cvpmBallstack
bsTrough.InitSw 0,67,0,0,0,0,0,0
bsTrough.InitKick BallRelease,90,3
bsTrough.InitExitSnd "ballrel","solon"
bsTrough.Balls=1
That sets up a single ballstack with the switch # of 67, the exit kicker as BallRelease, kicking the ball at
an angle of 90 degrees and a force of 3.
For a single ball game, we can condense that a little bit.
Set bsTrough=New cvpmBallstack
bsTrough.InitNoTrough BallRelease,67,90,3
bsTrough.InitExitSnd "ballrel","solon"
This would accomplish the same thing. bsTrough.Balls=1 is assumed for NoTrough.
For a multiple ball game, the switch sequence can make all the difference.
This is code from Black Knight.
Set bsTrough=New cvpmBallStack
bsTrough.InitSw 20,17,18,19,0,0,0,0
bsTrough.InitKick BallRelease,60,6
bsTrough.InitExitSnd"BallRel","SolOn"
bsTrough.Balls=3
The far left value of the InitSw line is reserved for the trough entry switch number. When a ball is added to the
trough on some games, it sits on the trough entry/outhole switch. This allows the game to notice a ball is in the
outhole, and tells it to fire a trough entry solenoid to kick it into the trough. I never found a good reason for
this type of operation. Gottlieb games are well known for cutting costs in manufacture - they use 1 or 2 switches
for their trough no matter how many balls the game has - just an entry switch and a trough switch at most. Some games
just have a single switch for the trough. And a few games have no trough switches at all.
To move the ball from the entry switch and into the actual trough switch area, the rom must fire the entry solenoid.
When used as a SolCallback routine, the shortened version for this example is "bsTrough.SolIn"
If used as a subroutine callback, you would use bsTrough.EntrySol_On
Either of those will clear the entry switch and move the ball to the far right (Position 8) of the actual trough stack.
Then the ball flows left like a river triggering all non-zero switches along the way until it stops, hitting another
virtual ball if present, or ending up on the left switch (Position 2) and closing switch 17.
Anyway, when a ball hits the outhole, and you add the ball to the trough ballstack with "bsTrough.AddBall Me", the ball is
dropped into the first switch position, in this case switch 20 is closed. When the Entry solenoid fires, switch 20 is
cleared and the ball is added to the end of the switch list. This would stick the ball on switch 0, position 8 in the list.
If the bsTrough now has fewer than 7 balls in it, the ball moves to position 7. If there are fewer than 6 balls, it moves
to position 6. If there are fewer than 5 balls, it moves to position 5. If there are currently fewer than 4 balls, it moves
to position 4. 3 to 3, and 2 to 2. The ball will not hit position 1 as that is reserved for the entry switch number. All
switches are closed and opened along the way, even if it's switch 0.
The first ball to be released from the trough will be position 2 - and when the ball there is ejected, the switch is opened,
then the remaining balls trickle down like a river to fill the freed spot and close the switch again. Bally Strange Science
has a visible trough system that shows how this works in detail. http://www.actionpin...science/pf2.jpg
As the balls move and occupy spots in the trough, the requisite switches are closed and opened to let the game know the balls moved,
and that the solenoids are working as designed. One quick note is the path of ball movement through the scripted ballstack is
the reverse of the physical movement on a real machine. Balls travel towards the shooter lane when passing through a physical
trough.
When you press B to add or remove a ball from the trough, adding a ball adds it to the entry switch, if present. If the entry
switch is 0 then the ball is added to the end of the stack and rolls forward until it is blocked by an existing ball. When you
remove a ball from the trough using the B key, it is removed from the end of the stack - the last position that has a ball is
cleared and the virtual ball is destroyed. Again, when a ball is ejected with either bsTrough.SolOut or bsTrough.ExitSol_On, the
new ball is always removed from position 2 - the first trough switch and put into play from the specified kicker, then all the remaining
balls roll down to fill the empty position.
When you use bsTrough.AddBall Me, the ball is destroyed from the screen and a virtual ball is added to the trough.
When you use bsTrough.AddBall 0, the ball is not destroyed, but remains in the kicker and a virtual ball is added to the trough.
Generally you would want to use AddBall 0 for a saucer type ballstack where you require the ball to close the switch but not be
removed from the screen, and Me for a trough or subway system where you want the switch to be triggered but also want the ball to
disappear. When the ball is destroyed from the screen, any references you had to that ball are gone forever - meaning you can't modify
the ball's properties anymore such as color, user value, decals, image, velocity or position. It is destroyed permanently. Once
destroyed, with no valid reference, any attempt to modify any of its properties will fail and crash your table script.
This brings us to subway systems. A subway system is an underplayfield passage from one hole in the playfield to another location under
the playfield. A subway can be complex, with diverters to direct balls to multiple places, or it could be a simple direct point A to point
B tunnel.
Star Trek the Next Generation has a complex underplayfield subway system; No Good Gofers has a less complex multiple subway system; Ripley's
Believe it or Not has what I would call a plain HOLE with a solenoid to push the ball(s) back into play. :) I will cover the simplistic to
the more complex. You should have no trouble with simple subways. One thing to emphasize is that timing is important. Some games require specific
timing in order to direct the ball to the right place, at the required speed. Other games compensate for variable time. At each stage of a
subway system, good designers place checkpoint switches to monitor how fast the ball is being delivered to its destination and they can be used
to operate under playfield diverters. These switches can be relied upon to ensure the balls do not jam under the playfield.
The Simplistic Subway - example - Ripley's.
Ripley's Believe it or not has a "Believe it or Not" hole, and behind that is a small skill shot subway passage. This is one of the few times you
will want to use a deprecated feature of core.vbs. The vpmTimer.PulseSwitch(XX),Y,"Subroutinename" command. From the previous tutorial,
vpmTimer.PulseSw Switchnumber is a quick closure of the switch, followed by opening the switch. What the full PulseSwitch command does - is it pulses
the switch XX, followed by a delay of Y in milliseconds, and then calls the subroutine within the quotes. So VpmTimer.PulseSwitch(28),100,"AddToSkill"
--=-- pulses switch 28, waits 100ms, then calls the subroutine AddToSkill.
Sub Kicker3_Hit:Kicker3.DestroyBall:vpmTimer.PulseSwitch(28),100,"AddToSkill":End Sub
Because the ball hits a kicker, and is going to be entering a subway, we need to remove the ball from the table. The kicker destroys the ball, then
executes the pulseswitch command, and then calls the subroutine.
Sub AddToSkill(swNo):bsSkill.AddBall 0:End Sub
The swNo is required - but the name in parenthesis can be anything you want it to be. It is short for Switch Number, which is simply a reference to the
switch pulsed in the original calling command. In this case we are going to ignore the value passed to the routine - it's not needed for what we're doing,
but you do have access to it if you wanted to know what switch number was involved. bsSkill.AddBall 0 adds a virtual ball to the skill ballstack and closes
the required switch if needed. Switch 28 being pulsed tells the rom that the ball entered the skill shot subway, and ended up in the skill shot kicker, as
opposed to being hit directly into the bottom hole. This allows the rom to play a skill shot animation if necessary.
Set bsSkill=new cvpmBallStack
bsSkill.InitSw 0,29,0,0,0,0,0,0
bsSkill.InitKick Kicker2,180,8
bsSkill.InitExitSnd "Popper","SolOn"
bsSkill.KickZ=1.1344645'65 Degrees
Because the hole can hold more than one ball, we do NOT use a saucer ballstack here. A saucer ballstack can only keep track of a single ball at one time.
A full ballstack or standard multiball trough ballstack can manage up to 7 balls all by itself, plus one ball on the trough entry switch if required. If you
have more than 7 balls, I very highly recommend coding the trough by hand and NOT using a ballstack. I have found it to be more reliable when dealing with
8+ balls to do it manually so you always know exactly where the balls are and what is happening. Also, if you try to push a ball into a ballstack when it is
already at the maximum allowed balls you will get an error and script crash - out of range. You can easily duplicate this issue by repeatedly pressing B and
adding balls to the trough.
When the first ball enters the bsSkill stack, it goes to the entry switch (position 1) which is 0, then default to the end of the stack. It tracks the number
of balls present and the ball flows like a river again to the left through positions 7, 6, 5, 4, 3 etc etc triggering all specified switches along the way until
it hits a ball present, or gets to position 2. On position 2, it closes switch 29 and holds it closed until a ball is released. Again, if there is one ball
present, and it is released, the switch is opened, and remains open. If there is more than one ball, and one ball is released, the switch is opened, the ball
is kicked out from kicker2, and the next ball in line rolls over and parks itself on switch 29 closing it again.
When a ball is kicked out of the bsSkill ballstack, it is kicked from Kicker2 at 180 degrees with a force of 8. The KickZ variable kicks the ball upwards on
the Z axis at 1.1344645 radians, which is the same as 65 degrees. To get the radian value you can use the formula of pi/180*degree. I usually just pull up
www.allmeasures.com and let the online converter do it for me. With VP9 it is possible that the KickZ angle could accept an actual degree number - I use radians
because that is what worked originally. If you do use a degree number for the kick value, it must be >pi in order to be valid. This allows you to kick a ball
through 180 degrees of vertical range.
In the above example, no delay is needed if the ball is shot directly into the bottom hole. The ball is destroyed and added the the stack immediately, closing
the switch if no ball was present, or stacking in line behind the ball already on the closed switch. The game sees the switch closure first and therefore knows
the ball entered through the bottom hole. Now, wait, you might ask a good question here -- what happens if there is already a ball on the switch, and another ball
enters! Well, paying attention I see your point. Here is the answer. The rom only sees one switch closed - switch 29. The machine is constantly tracking where
each ball is on the playfield at all times. It knows how many balls should be in the machine and it adds up the number of balls in the main trough, the number of
balls in locks, the ball (if present) in the VUK near the right ramp, and it tracks a ball that might be hitting a switch with an internal timing mechanism. For
Ripleys there are a total of 4 balls, so this isn't very challenging for the rom to do. Anyway, for our test scenario here, let's say we hit the bottom hole. Let
us also suggest we are in multiball. We hit the second ball into the bottom hole - the ball hits switch 0 (entry switch) then jumps to the right position 8 and
trickles down to just behind switch 29, waiting again on switch 0 that doesn't exist. The rom finishes whatever animation on the dmd it was doing originally, then
it kicks out the first ball. Switch 29 is open and immediately (milliseconds later) the second ball rolls from the nonexistent placeholder onto switch 29 again.
The rom knows either the solenoid kicker failed to successfully eject the first ball, or that there was a second ball waiting, and it fires the solenoid again to kick
out the second ball.
Now if you have a single ball on switch 29 in the stack, and you hit a second ball into the skill shot kicker - it pulses switch 28 first, a short
delay later it ends up on switch 0 in the stack next to the ball that is on top of switch 29, and the rom knows that now there are two physical balls
in the stack, for sure. In this instance, it could run the bozo dog animation, a jackpot animation, or simply kick both balls out in the case of a tilt
condition. The machine is quite intelligent in this regard, and those switches and the timing involved is quite important for their sequencing. If a
switch is missed, or it takes too long to trigger, or the ball ends up in the wrong place at the wrong time, the game will start a ball search, firing
all solenoids to figure out where the missing/lost ball went. In most cases, having a ball show up where it's not supposed to be is preferable to a
ball search because it makes it easier to diagnose and locate the error.
Moving on to our next table, No Good Gofers.
No Good Gofers has a right ball lock which ejects to the top right orbit. It also has a left Ball Lock hole which ends up in the "putt out" chasm - a really big hole. ;)
It has the hole in one shot which goes to the "putt out" hole. The "Putt Out" hole itself can kick balls immediately back into play, or send them to the left pop bumpers.
The right ball lock
Sub Kicker2_Hit:Me.DestroyBall:vpmTimer.PulseSwitch(45),100,"HandleRightGofer":End Sub
The right ball lock is simple - the ball hits the gofer, the gofer drops, leaving the right ramp in the raised position. The ball hits the hole and is destroyed, then
the script pulses switch 45. It waits 100ms and then it calls "HandleRightGofer"
Sub HandleRightGofer(swNo):bsUR.AddBall 0:End Sub
HandleRightGofer receives the switch number of the calling routine - but again, we're not going to make use of that number. It simply adds a virtual ball to the bsUR
ballstack, first hitting the entry switch (0), then going to the end of the position list and rolling to the left, closing switch 46. In case at some point a second ball
manages to enter that ballstack we are using a full one again, not a saucer. With hectic multiball action, it could 'possibly' accept two balls before the ramp is dropped,
or if a ball were to fall through the ramp it could end up there, so it's a basic bug prevention system. You do want to do everything in your power to prevent 'lost' balls
- it's a game crasher if it happens.
The left ball lock is similar
Sub Kicker1_Hit:Me.DestroyBall:vpmTimer.PulseSwitch(67),100,"HandlePuttOut":End Sub
If a ball hits the left gofer, the left gofer drops and leaves the ramp in the up position for the lock to be accessible. When the ball hits the left lock hole, the ball
is destroyed, and the script pulses switch 67. Then it waits 100ms and calls the HandlePuttOut routine. HandlePuttOut tracks the switch number, again, which we don't use
for anything, and adds a virtual ball to the bsPuttOutPopper. The ball goes to the entry switch, sees a zero, and automatically goes to the end of the switch position list
- rolling to the left over each switch until it stops. The ball closes switch 44 only if there are no balls in the bsputtoutpopper already.
Again the game can differentiate where the ball came from - it came from the left lock because it saw switch 67 close for a short timeframe.
Sub S44A_Hit:bsPuttOutPopper.AddBall Me:End Sub
Because the "putt out" popper hole is so large, I used 5 kickers for that. You can enter it from the back loop as well as anywhere from the front area.
Each kicker, when hit, destroys the ball and adds it virtually to the bsputtout ballstack. The AddBall Me instructs the script to destroy the ball that
triggered the hit event for you. Again if bsPuttout doesn't have any balls, the ball added will hit the entry switch, push to the right end of the stack
switch position list, and roll to the left triggering any non zero switches along the way.
The left jet popper kicker is an exit only hole - however, if a ball was to hit that kicker somehow (Tilt maybe?) the ball would go to the entry switch, then to the right end,
and rolls left, over switch 25 and end up at 38 if the stack was empty, and wait to be kicked out again.
Now the final subway to explain - the Hole in One shot. This is the most valuable in-game shot the No Good Gofers machine has. It advances holes, pays off jackpot awards, and
is quite satisfying to make. The only way to get the ball up there for this shot is by hitting the slam ramp hard enough, and aiming for the hole on the upper playfield. When
Holemade is hit, it destroys the ball, then it pulses switch 68. It waits 100ms, then it goes to HandleTopHole. HandleTopHole tracks the switch number, which we won't utilize
here, it pulses switch 67 (Left Lock Hole), waits yet another 100ms, and sends the ball to the "PuttOut" hole. The "PuttOut" hole simply adds the ball to the puttoutpopper.
Now there is one thing left to handle - the "PuttOut" Hole actually has two exit conditions. One solenoid sends the ball from the putt out area toward the flippers, and one
solenoid sends the ball to the pop bumpers on the left. It is entirely up to the game to decide where the ball goes. While it is possible (frustrating but possible) for you to
force the ball to go where you think you want it to go through the script, you do not want to waste time fighting the rom. If the rom is appearing to send balls to the wrong
places then there is either a rom emulation problem, or most likely you are trying to do it incorrectly. The game will not play the way it should, it'll lose track of where balls
are, it'll do ball searches and refuse to end the current ball in play, as well as a host of other possible issues if you try to force anything. Anyway, when switch 44 is closed
(bsPuttoutpopper), the game will run whatever animations it wants, play some sounds possibly, and allow the game to continue. When the rom wants to kick that ball back into play,
it will either fire solenoid 3 or it will fire solenoid 24.
Solenoid 3 is "SolPuttOut"
Sub SolPuttOut(Enabled):If Enabled Then:If bsPuttOutPopper.Balls Then:bsPuttOutPopper.InitKick S44D,170,12:PlaySound"Popper":End If:bsPuttOutPopper.ExitSol_On:End If:End Sub
When Solenoid 3 fires, the script checks if there is a ball present in the puttoutpopper ballstack. If there is, then it sets the initial kick to a kicker named S44D, and the
initial kick will be set to 170 degrees with a force of 12. Then it will play a sound for the ball exiting. Then it will Create and kick the ball out into play. If there is
no ball in the bsputtoutpopper, then it simply fires the exit routine, which the ballstack is set up to play a different sound "SolOn" without kicking a ball, because there isn't
one to kick. :)
Solenoid 24 calls the routine "SolUNP"
Sub SolUNP(Enabled):If Enabled Then:If bsPuttOutPopper.Balls Then:bsPuttOutPopper.InitKick Kicker4,180,3:bsPuttOutPopper.ExitSol_On:End If:End If:End Sub
This is simiilar - it checks for the ball present, if it is then it sets the initial kick to Kicker4, angle 180, force 3, and simply creates and kicks a ball from there. Kicker 4
is under the apron at the bottom/front of the table in VP. This creates a physical ball and starts it rolling with the table slope towards the front of the machine. It creates an
actual delay in the ball travel without using a set millisecond timeframe.
A short time later the ball will hit Kicker5 which is also under the apron. It has no choice but to hit that kicker because kicker 4 is disabled (can't accept hit events), and there
are physical walls around every other possible exit from the physical tunnel. When the ball hits kicker 5, it is destroyed (addball Me) and added to the bsJetPopper Ballstack. It
hits the entry switch 0, jumps to the right end, rolls to the left, rolls over switch 25 and ends up on switch 38 if there are no balls. The game has two switches here because it
wants to kick them out one at a time, and in heavy multiball play you can get a bunch of balls at varying speeds. So this way it knows if there is one ball or two balls present
waiting to be kicked. It will kick them when it pleases. Balls are pushed out back into play into the jet bumpers, and eventually, the game ends with all balls drained and back
in the main trough.
Star Trek The Next Generation's underplayfield subway system is even more complex than this is - and extremely sensitive to timing. If you truly require that to be explained, let me
know - otherwise, find a table with it working reliably (there are 3 or 4 of them that are perfect) and copy the existing script.
Hopefully you get the idea of how all this fits together now. Subways are rarely done anymore due to the increased cost and planning requirements. It is much cheaper and easier to
simply stick a ramp on the playfield than to spend time keeping the playfield unobstructed while retaining the transportation of balls from point A to B to F. :)
--------------------------------------------------------------
Joe had wanted more information on ballstacks, and since I was going to do subway systems, they go together.
From the previous article, we have this code:
Set bsTrough=New cvpmBallstack
bsTrough.InitSw 0,67,0,0,0,0,0,0
bsTrough.InitKick BallRelease,90,3
bsTrough.InitExitSnd "ballrel","solon"
bsTrough.Balls=1
That sets up a single ballstack with the switch # of 67, the exit kicker as BallRelease, kicking the ball at
an angle of 90 degrees and a force of 3.
For a single ball game, we can condense that a little bit.
Set bsTrough=New cvpmBallstack
bsTrough.InitNoTrough BallRelease,67,90,3
bsTrough.InitExitSnd "ballrel","solon"
This would accomplish the same thing. bsTrough.Balls=1 is assumed for NoTrough.
For a multiple ball game, the switch sequence can make all the difference.
This is code from Black Knight.
Set bsTrough=New cvpmBallStack
bsTrough.InitSw 20,17,18,19,0,0,0,0
bsTrough.InitKick BallRelease,60,6
bsTrough.InitExitSnd"BallRel","SolOn"
bsTrough.Balls=3
The far left value of the InitSw line is reserved for the trough entry switch number. When a ball is added to the
trough on some games, it sits on the trough entry/outhole switch. This allows the game to notice a ball is in the
outhole, and tells it to fire a trough entry solenoid to kick it into the trough. I never found a good reason for
this type of operation. Gottlieb games are well known for cutting costs in manufacture - they use 1 or 2 switches
for their trough no matter how many balls the game has - just an entry switch and a trough switch at most. Some games
just have a single switch for the trough. And a few games have no trough switches at all.
To move the ball from the entry switch and into the actual trough switch area, the rom must fire the entry solenoid.
When used as a SolCallback routine, the shortened version for this example is "bsTrough.SolIn"
If used as a subroutine callback, you would use bsTrough.EntrySol_On
Either of those will clear the entry switch and move the ball to the far right (Position 8) of the actual trough stack.
Then the ball flows left like a river triggering all non-zero switches along the way until it stops, hitting another
virtual ball if present, or ending up on the left switch (Position 2) and closing switch 17.
Anyway, when a ball hits the outhole, and you add the ball to the trough ballstack with "bsTrough.AddBall Me", the ball is
dropped into the first switch position, in this case switch 20 is closed. When the Entry solenoid fires, switch 20 is
cleared and the ball is added to the end of the switch list. This would stick the ball on switch 0, position 8 in the list.
If the bsTrough now has fewer than 7 balls in it, the ball moves to position 7. If there are fewer than 6 balls, it moves
to position 6. If there are fewer than 5 balls, it moves to position 5. If there are currently fewer than 4 balls, it moves
to position 4. 3 to 3, and 2 to 2. The ball will not hit position 1 as that is reserved for the entry switch number. All
switches are closed and opened along the way, even if it's switch 0.
The first ball to be released from the trough will be position 2 - and when the ball there is ejected, the switch is opened,
then the remaining balls trickle down like a river to fill the freed spot and close the switch again. Bally Strange Science
has a visible trough system that shows how this works in detail. http://www.actionpin...science/pf2.jpg
As the balls move and occupy spots in the trough, the requisite switches are closed and opened to let the game know the balls moved,
and that the solenoids are working as designed. One quick note is the path of ball movement through the scripted ballstack is
the reverse of the physical movement on a real machine. Balls travel towards the shooter lane when passing through a physical
trough.
When you press B to add or remove a ball from the trough, adding a ball adds it to the entry switch, if present. If the entry
switch is 0 then the ball is added to the end of the stack and rolls forward until it is blocked by an existing ball. When you
remove a ball from the trough using the B key, it is removed from the end of the stack - the last position that has a ball is
cleared and the virtual ball is destroyed. Again, when a ball is ejected with either bsTrough.SolOut or bsTrough.ExitSol_On, the
new ball is always removed from position 2 - the first trough switch and put into play from the specified kicker, then all the remaining
balls roll down to fill the empty position.
When you use bsTrough.AddBall Me, the ball is destroyed from the screen and a virtual ball is added to the trough.
When you use bsTrough.AddBall 0, the ball is not destroyed, but remains in the kicker and a virtual ball is added to the trough.
Generally you would want to use AddBall 0 for a saucer type ballstack where you require the ball to close the switch but not be
removed from the screen, and Me for a trough or subway system where you want the switch to be triggered but also want the ball to
disappear. When the ball is destroyed from the screen, any references you had to that ball are gone forever - meaning you can't modify
the ball's properties anymore such as color, user value, decals, image, velocity or position. It is destroyed permanently. Once
destroyed, with no valid reference, any attempt to modify any of its properties will fail and crash your table script.
This brings us to subway systems. A subway system is an underplayfield passage from one hole in the playfield to another location under
the playfield. A subway can be complex, with diverters to direct balls to multiple places, or it could be a simple direct point A to point
B tunnel.
Star Trek the Next Generation has a complex underplayfield subway system; No Good Gofers has a less complex multiple subway system; Ripley's
Believe it or Not has what I would call a plain HOLE with a solenoid to push the ball(s) back into play. :) I will cover the simplistic to
the more complex. You should have no trouble with simple subways. One thing to emphasize is that timing is important. Some games require specific
timing in order to direct the ball to the right place, at the required speed. Other games compensate for variable time. At each stage of a
subway system, good designers place checkpoint switches to monitor how fast the ball is being delivered to its destination and they can be used
to operate under playfield diverters. These switches can be relied upon to ensure the balls do not jam under the playfield.
The Simplistic Subway - example - Ripley's.
Ripley's Believe it or not has a "Believe it or Not" hole, and behind that is a small skill shot subway passage. This is one of the few times you
will want to use a deprecated feature of core.vbs. The vpmTimer.PulseSwitch(XX),Y,"Subroutinename" command. From the previous tutorial,
vpmTimer.PulseSw Switchnumber is a quick closure of the switch, followed by opening the switch. What the full PulseSwitch command does - is it pulses
the switch XX, followed by a delay of Y in milliseconds, and then calls the subroutine within the quotes. So VpmTimer.PulseSwitch(28),100,"AddToSkill"
--=-- pulses switch 28, waits 100ms, then calls the subroutine AddToSkill.
Sub Kicker3_Hit:Kicker3.DestroyBall:vpmTimer.PulseSwitch(28),100,"AddToSkill":End Sub
Because the ball hits a kicker, and is going to be entering a subway, we need to remove the ball from the table. The kicker destroys the ball, then
executes the pulseswitch command, and then calls the subroutine.
Sub AddToSkill(swNo):bsSkill.AddBall 0:End Sub
The swNo is required - but the name in parenthesis can be anything you want it to be. It is short for Switch Number, which is simply a reference to the
switch pulsed in the original calling command. In this case we are going to ignore the value passed to the routine - it's not needed for what we're doing,
but you do have access to it if you wanted to know what switch number was involved. bsSkill.AddBall 0 adds a virtual ball to the skill ballstack and closes
the required switch if needed. Switch 28 being pulsed tells the rom that the ball entered the skill shot subway, and ended up in the skill shot kicker, as
opposed to being hit directly into the bottom hole. This allows the rom to play a skill shot animation if necessary.
Set bsSkill=new cvpmBallStack
bsSkill.InitSw 0,29,0,0,0,0,0,0
bsSkill.InitKick Kicker2,180,8
bsSkill.InitExitSnd "Popper","SolOn"
bsSkill.KickZ=1.1344645'65 Degrees
Because the hole can hold more than one ball, we do NOT use a saucer ballstack here. A saucer ballstack can only keep track of a single ball at one time.
A full ballstack or standard multiball trough ballstack can manage up to 7 balls all by itself, plus one ball on the trough entry switch if required. If you
have more than 7 balls, I very highly recommend coding the trough by hand and NOT using a ballstack. I have found it to be more reliable when dealing with
8+ balls to do it manually so you always know exactly where the balls are and what is happening. Also, if you try to push a ball into a ballstack when it is
already at the maximum allowed balls you will get an error and script crash - out of range. You can easily duplicate this issue by repeatedly pressing B and
adding balls to the trough.
When the first ball enters the bsSkill stack, it goes to the entry switch (position 1) which is 0, then default to the end of the stack. It tracks the number
of balls present and the ball flows like a river again to the left through positions 7, 6, 5, 4, 3 etc etc triggering all specified switches along the way until
it hits a ball present, or gets to position 2. On position 2, it closes switch 29 and holds it closed until a ball is released. Again, if there is one ball
present, and it is released, the switch is opened, and remains open. If there is more than one ball, and one ball is released, the switch is opened, the ball
is kicked out from kicker2, and the next ball in line rolls over and parks itself on switch 29 closing it again.
When a ball is kicked out of the bsSkill ballstack, it is kicked from Kicker2 at 180 degrees with a force of 8. The KickZ variable kicks the ball upwards on
the Z axis at 1.1344645 radians, which is the same as 65 degrees. To get the radian value you can use the formula of pi/180*degree. I usually just pull up
www.allmeasures.com and let the online converter do it for me. With VP9 it is possible that the KickZ angle could accept an actual degree number - I use radians
because that is what worked originally. If you do use a degree number for the kick value, it must be >pi in order to be valid. This allows you to kick a ball
through 180 degrees of vertical range.
In the above example, no delay is needed if the ball is shot directly into the bottom hole. The ball is destroyed and added the the stack immediately, closing
the switch if no ball was present, or stacking in line behind the ball already on the closed switch. The game sees the switch closure first and therefore knows
the ball entered through the bottom hole. Now, wait, you might ask a good question here -- what happens if there is already a ball on the switch, and another ball
enters! Well, paying attention I see your point. Here is the answer. The rom only sees one switch closed - switch 29. The machine is constantly tracking where
each ball is on the playfield at all times. It knows how many balls should be in the machine and it adds up the number of balls in the main trough, the number of
balls in locks, the ball (if present) in the VUK near the right ramp, and it tracks a ball that might be hitting a switch with an internal timing mechanism. For
Ripleys there are a total of 4 balls, so this isn't very challenging for the rom to do. Anyway, for our test scenario here, let's say we hit the bottom hole. Let
us also suggest we are in multiball. We hit the second ball into the bottom hole - the ball hits switch 0 (entry switch) then jumps to the right position 8 and
trickles down to just behind switch 29, waiting again on switch 0 that doesn't exist. The rom finishes whatever animation on the dmd it was doing originally, then
it kicks out the first ball. Switch 29 is open and immediately (milliseconds later) the second ball rolls from the nonexistent placeholder onto switch 29 again.
The rom knows either the solenoid kicker failed to successfully eject the first ball, or that there was a second ball waiting, and it fires the solenoid again to kick
out the second ball.
Now if you have a single ball on switch 29 in the stack, and you hit a second ball into the skill shot kicker - it pulses switch 28 first, a short
delay later it ends up on switch 0 in the stack next to the ball that is on top of switch 29, and the rom knows that now there are two physical balls
in the stack, for sure. In this instance, it could run the bozo dog animation, a jackpot animation, or simply kick both balls out in the case of a tilt
condition. The machine is quite intelligent in this regard, and those switches and the timing involved is quite important for their sequencing. If a
switch is missed, or it takes too long to trigger, or the ball ends up in the wrong place at the wrong time, the game will start a ball search, firing
all solenoids to figure out where the missing/lost ball went. In most cases, having a ball show up where it's not supposed to be is preferable to a
ball search because it makes it easier to diagnose and locate the error.
Moving on to our next table, No Good Gofers.
No Good Gofers has a right ball lock which ejects to the top right orbit. It also has a left Ball Lock hole which ends up in the "putt out" chasm - a really big hole. ;)
It has the hole in one shot which goes to the "putt out" hole. The "Putt Out" hole itself can kick balls immediately back into play, or send them to the left pop bumpers.
The right ball lock
Sub Kicker2_Hit:Me.DestroyBall:vpmTimer.PulseSwitch(45),100,"HandleRightGofer":End Sub
The right ball lock is simple - the ball hits the gofer, the gofer drops, leaving the right ramp in the raised position. The ball hits the hole and is destroyed, then
the script pulses switch 45. It waits 100ms and then it calls "HandleRightGofer"
Sub HandleRightGofer(swNo):bsUR.AddBall 0:End Sub
HandleRightGofer receives the switch number of the calling routine - but again, we're not going to make use of that number. It simply adds a virtual ball to the bsUR
ballstack, first hitting the entry switch (0), then going to the end of the position list and rolling to the left, closing switch 46. In case at some point a second ball
manages to enter that ballstack we are using a full one again, not a saucer. With hectic multiball action, it could 'possibly' accept two balls before the ramp is dropped,
or if a ball were to fall through the ramp it could end up there, so it's a basic bug prevention system. You do want to do everything in your power to prevent 'lost' balls
- it's a game crasher if it happens.
The left ball lock is similar
Sub Kicker1_Hit:Me.DestroyBall:vpmTimer.PulseSwitch(67),100,"HandlePuttOut":End Sub
If a ball hits the left gofer, the left gofer drops and leaves the ramp in the up position for the lock to be accessible. When the ball hits the left lock hole, the ball
is destroyed, and the script pulses switch 67. Then it waits 100ms and calls the HandlePuttOut routine. HandlePuttOut tracks the switch number, again, which we don't use
for anything, and adds a virtual ball to the bsPuttOutPopper. The ball goes to the entry switch, sees a zero, and automatically goes to the end of the switch position list
- rolling to the left over each switch until it stops. The ball closes switch 44 only if there are no balls in the bsputtoutpopper already.
Again the game can differentiate where the ball came from - it came from the left lock because it saw switch 67 close for a short timeframe.
Sub S44A_Hit:bsPuttOutPopper.AddBall Me:End Sub
Because the "putt out" popper hole is so large, I used 5 kickers for that. You can enter it from the back loop as well as anywhere from the front area.
Each kicker, when hit, destroys the ball and adds it virtually to the bsputtout ballstack. The AddBall Me instructs the script to destroy the ball that
triggered the hit event for you. Again if bsPuttout doesn't have any balls, the ball added will hit the entry switch, push to the right end of the stack
switch position list, and roll to the left triggering any non zero switches along the way.
The left jet popper kicker is an exit only hole - however, if a ball was to hit that kicker somehow (Tilt maybe?) the ball would go to the entry switch, then to the right end,
and rolls left, over switch 25 and end up at 38 if the stack was empty, and wait to be kicked out again.
Now the final subway to explain - the Hole in One shot. This is the most valuable in-game shot the No Good Gofers machine has. It advances holes, pays off jackpot awards, and
is quite satisfying to make. The only way to get the ball up there for this shot is by hitting the slam ramp hard enough, and aiming for the hole on the upper playfield. When
Holemade is hit, it destroys the ball, then it pulses switch 68. It waits 100ms, then it goes to HandleTopHole. HandleTopHole tracks the switch number, which we won't utilize
here, it pulses switch 67 (Left Lock Hole), waits yet another 100ms, and sends the ball to the "PuttOut" hole. The "PuttOut" hole simply adds the ball to the puttoutpopper.
Now there is one thing left to handle - the "PuttOut" Hole actually has two exit conditions. One solenoid sends the ball from the putt out area toward the flippers, and one
solenoid sends the ball to the pop bumpers on the left. It is entirely up to the game to decide where the ball goes. While it is possible (frustrating but possible) for you to
force the ball to go where you think you want it to go through the script, you do not want to waste time fighting the rom. If the rom is appearing to send balls to the wrong
places then there is either a rom emulation problem, or most likely you are trying to do it incorrectly. The game will not play the way it should, it'll lose track of where balls
are, it'll do ball searches and refuse to end the current ball in play, as well as a host of other possible issues if you try to force anything. Anyway, when switch 44 is closed
(bsPuttoutpopper), the game will run whatever animations it wants, play some sounds possibly, and allow the game to continue. When the rom wants to kick that ball back into play,
it will either fire solenoid 3 or it will fire solenoid 24.
Solenoid 3 is "SolPuttOut"
Sub SolPuttOut(Enabled):If Enabled Then:If bsPuttOutPopper.Balls Then:bsPuttOutPopper.InitKick S44D,170,12:PlaySound"Popper":End If:bsPuttOutPopper.ExitSol_On:End If:End Sub
When Solenoid 3 fires, the script checks if there is a ball present in the puttoutpopper ballstack. If there is, then it sets the initial kick to a kicker named S44D, and the
initial kick will be set to 170 degrees with a force of 12. Then it will play a sound for the ball exiting. Then it will Create and kick the ball out into play. If there is
no ball in the bsputtoutpopper, then it simply fires the exit routine, which the ballstack is set up to play a different sound "SolOn" without kicking a ball, because there isn't
one to kick. :)
Solenoid 24 calls the routine "SolUNP"
Sub SolUNP(Enabled):If Enabled Then:If bsPuttOutPopper.Balls Then:bsPuttOutPopper.InitKick Kicker4,180,3:bsPuttOutPopper.ExitSol_On:End If:End If:End Sub
This is simiilar - it checks for the ball present, if it is then it sets the initial kick to Kicker4, angle 180, force 3, and simply creates and kicks a ball from there. Kicker 4
is under the apron at the bottom/front of the table in VP. This creates a physical ball and starts it rolling with the table slope towards the front of the machine. It creates an
actual delay in the ball travel without using a set millisecond timeframe.
A short time later the ball will hit Kicker5 which is also under the apron. It has no choice but to hit that kicker because kicker 4 is disabled (can't accept hit events), and there
are physical walls around every other possible exit from the physical tunnel. When the ball hits kicker 5, it is destroyed (addball Me) and added to the bsJetPopper Ballstack. It
hits the entry switch 0, jumps to the right end, rolls to the left, rolls over switch 25 and ends up on switch 38 if there are no balls. The game has two switches here because it
wants to kick them out one at a time, and in heavy multiball play you can get a bunch of balls at varying speeds. So this way it knows if there is one ball or two balls present
waiting to be kicked. It will kick them when it pleases. Balls are pushed out back into play into the jet bumpers, and eventually, the game ends with all balls drained and back
in the main trough.
Star Trek The Next Generation's underplayfield subway system is even more complex than this is - and extremely sensitive to timing. If you truly require that to be explained, let me
know - otherwise, find a table with it working reliably (there are 3 or 4 of them that are perfect) and copy the existing script.
Hopefully you get the idea of how all this fits together now. Subways are rarely done anymore due to the increased cost and planning requirements. It is much cheaper and easier to
simply stick a ramp on the playfield than to spend time keeping the playfield unobstructed while retaining the transportation of balls from point A to B to F. :)
Build a fire, vipers love the heat.
#3
Posted 07 January 2010 - 01:06 PM
I don't think even a race of hyper-intelligent pan-dimensional beings who built a computer named Deep Thought could calculate that equation Dan!! 
Best Regards,
Todd.
p.s. obligatory "42" thrown in for posterity.
Best Regards,
Todd.
p.s. obligatory "42" thrown in for posterity.
[proud owner of a Williams Solar Fire]
- It's called "The American Dream" because you have to be asleep to believe it.
George Carlin
- Truly great madness cannot be achieved without significant intelligence.
Henrik Tikkanen
- "Reality check, Michelle, Talk about composure, Total lack of. He's a man-- About-- 12 Feet Tall--"
Carrie Kelly
- It's called "The American Dream" because you have to be asleep to believe it.
George Carlin
- Truly great madness cannot be achieved without significant intelligence.
Henrik Tikkanen
- "Reality check, Michelle, Talk about composure, Total lack of. He's a man-- About-- 12 Feet Tall--"
Carrie Kelly
#4
Posted 07 January 2010 - 01:15 PM
QUOTE (Wizards_Hat @ Jan 7 2010, 08:01 PM) <{POST_SNAPBACK}>
Thanks for this.
I've never looked into scripting pinmame, and these tutorials give me the opportunity to go for it.
Now I just need a tutorial on how to find the time to actually do it
Regards,
Dan.
I've never looked into scripting pinmame, and these tutorials give me the opportunity to go for it.
Now I just need a tutorial on how to find the time to actually do it
Regards,
Dan.
Actually you really want to take time out sometime to look into the .vbs files, some really neat and amazing bit of coding, the way it all fits together, hats off to all involved. Sure all the local/global and other needed constructs can be somewhat overwhelming but when you look into the coding it is very clever indeed. Start at core.vbs, most impressed on how it all works and some really useful coding in there when it comes to spinning discs/magnets and how it all fits together.
#7
Posted 12 January 2010 - 01:09 AM
I'm not sure I understand your question Joe. Can you rephrase it? I don't know of any games that lock balls in the main trough. Speaking of Ball locks - that is going to be the next tutorial as it was ( are you psychic Joe? )
Build a fire, vipers love the heat.
#8
Posted 13 January 2010 - 04:06 AM
QUOTE (destruk @ Jan 11 2010, 07:09 PM) <{POST_SNAPBACK}>
I'm not sure I understand your question Joe. Can you rephrase it? I don't know of any games that lock balls in the main trough. Speaking of Ball locks - that is going to be the next tutorial as it was ( are you psychic Joe? )
Some sega games fake lock balls there.
#10
Posted 13 January 2010 - 10:20 PM
QUOTE (destruk @ Jan 12 2010, 11:51 PM) <{POST_SNAPBACK}>
Do you have an example, like name one of these sega games with fake ball locks in the main ball trough?
A13, Baywatch and a few others.
#11
Posted 14 January 2010 - 12:18 AM
QUOTE (Joe @ Jan 13 2010, 03:20 PM) <{POST_SNAPBACK}>
QUOTE (destruk @ Jan 12 2010, 11:51 PM) <{POST_SNAPBACK}>
Do you have an example, like name one of these sega games with fake ball locks in the main ball trough?
A13, Baywatch and a few others.
Apollo 13 is not a standard situation - it is unique. The only other game I know of that is considered actual pinball with anything similar to Apollo 13 would be Stern's Indiana Jones with 8 balls. I think what you mean here is virtual ball locks? If that is the case, then there really isn't much that needs to be done as the rom is handling all of the logistics and counts for you. Typically the ball will hit a switch, or kicker in vp, the rom notices and displays the ball locked message, and then kicks the ball back into play again. When you have enough virtual locks to start a multiball mode, it needs to fire the ball release solenoid the required number of times to get the physical balls into play, which the rom also handles for you by firing the solenoid. There is no scripting trick to make that work - you just need the right solenoid numbers, right switch numbers, in the correct order and placement.
Baywatch allows you to lock 3 physical balls with a trapdoor device like Guns n Roses and launches those 3 balls out and adds two more from the main trough AFAIK. Again, nothing special here - you have the usual 3 ball physical lock and it kicks out two more balls with the ball release solenoid. If you mean something else, please say so.
Build a fire, vipers love the heat.
#12
Posted 14 January 2010 - 02:24 AM
QUOTE (destruk @ Jan 13 2010, 06:18 PM) <{POST_SNAPBACK}>
QUOTE (Joe @ Jan 13 2010, 03:20 PM) <{POST_SNAPBACK}>
QUOTE (destruk @ Jan 12 2010, 11:51 PM) <{POST_SNAPBACK}>
Do you have an example, like name one of these sega games with fake ball locks in the main ball trough?
A13, Baywatch and a few others.
Apollo 13 is not a standard situation - it is unique. The only other game I know of that is considered actual pinball with anything similar to Apollo 13 would be Stern's Indiana Jones with 8 balls. I think what you mean here is virtual ball locks? If that is the case, then there really isn't much that needs to be done as the rom is handling all of the logistics and counts for you. Typically the ball will hit a switch, or kicker in vp, the rom notices and displays the ball locked message, and then kicks the ball back into play again. When you have enough virtual locks to start a multiball mode, it needs to fire the ball release solenoid the required number of times to get the physical balls into play, which the rom also handles for you by firing the solenoid. There is no scripting trick to make that work - you just need the right solenoid numbers, right switch numbers, in the correct order and placement.
Baywatch allows you to lock 3 physical balls with a trapdoor device like Guns n Roses and launches those 3 balls out and adds two more from the main trough AFAIK. Again, nothing special here - you have the usual 3 ball physical lock and it kicks out two more balls with the ball release solenoid. If you mean something else, please say so.
the manual for A13 say that balls rocket UP and moon magnet go to the super VUK (under arch) and are added to the Trough. other games use that are as well.
#13
Posted 14 January 2010 - 03:36 AM
ok, Apollo 13 still is not the norm. You have your 8-ball lock trough in the back left corner, and you have a trapdoor subway system through the rocket ramp to deposit some locked balls into the main trough. The game can tell between what should be a locked ball or not in the main trough, with switch 48. If 48 is pulsed then the ball is locked, if the ball is simply dropped through the outhole then it goes directly to switch 10.
Build a fire, vipers love the heat.



Top













are all trademarks of VPFORUMS.