VPX Scripting — Part 6 (End Sound)

Star Dust backglass.
Backglass for Star Dust by the user Hauntfreaks.

22 Apr 2024

I’ll be honest, a lot of what we have been doing has been grunt-work. But the code isn’t going to improve itself. The code is a lot cleaner now and a maybe a little more approachable because of our efforts. And if you play the table at this point, it now sounds much better. If you have an SSF (surround-sound feedback) capable setup, you will especially appreciate the sound improvements.

But lets wrap up the work on the sound for Teacher’s Pet. But let’s have a little bit of fun adding a feature or two before we close up shop.


Maybe you recall that the plunger in the script for Teacher’s Pet has figured a little in our sound work.

Existing plunger code.

The above code comes from the Table1_KeyUp routine (I underlined the EM Sound call we switched over to). In fact there are two more plunger-related calls in EM Sounds that we are currently ignoring: EMSPlayPlungerPullSound and EMSPlayPlungerReleaseNoBallSound.

The first routine we should probably be calling in the Table1_KeyDown routine when the player presses down the plunger button (play the pull sound). And the latter call is for the special case when the player releases the plunger but there is no ball in the plunger lane.

Let’s figure out where and how to include these sounds in Teacher’s Pet.


Let’s look back at the Table1_KeyDown routine in our table script, find where it handles the plunger key.

Existing plunger-down code.

The two lines of code between If and End If is all that it does. It calls the PullBack routine on the Plunger object and it sets the global PlungerPulled to a non-zero value (not “False”, “True”).

Nothing is simpler than inserting one line of code to also play the EMSPlayPlungerPullSound.

Plunger code changes.

You should be familiar with script “diffs” by now. The diff above shows that I inserted a single line of code (Line 329).

You may be wondering why we pass the Plunger object to EMSPlayPlungerPullSound. I’ll explain in more detail in a later post, but the Plunger is used simply for its “X” and “Y” location on the table. EM Sounds will pan the sound of the plunger to the right since that is where the Plunger object is on the table and the sound will be “faded” (front and back pan) such that it is heard close to the player. Even a modest Visual Pinball setup should have stereo speakers so you will hear that the plunger is on the right — the front to back effect requires the more elaborate SSF (surround-sound feedback) to appreciate.


Knowing when to call EMSPlayPlungerReleaseNoBallSound is a little more complicated. Somehow we have to know whether the plunger is being released in an empty plunger lane or if it is hitting a ball.

Let’s go back to the original Table1_KeyUp plunger code. I made a change.

Plunger psuedo-code.

Above, I underlined an obvious fake line of code. But it makes the point of what we want to accomplish.

There are a few ways I have seen this done. The way we’re going to do it is the simplest I think.

VPX has an object called the ActiveBall. As you might guess it represents the ball in play. So one way we could determine if the plunger was being released with a ball in its path is if we looked at the “X” and “Y” location of the ActiveBall and determined it was in the plunger lane, ready to be struck.

Recall that in Part 4 we used the debugger window for VPX. We will bring up the debugger again.

To examine the X and Y position of the ActiveBall I started up Teacher’s Pet and began a game so that a ball was sitting in the plunger lane. Typing “D” brought up the debugger window. There I typed “Print ActiveBall.X” and the X value was displayed. I typed “Print ActiveBall.Y” to get the Y value.

Debug window.

X was 906.4888. The left edge of the pinball table represents smaller values of X, the right side larger. We can assume that if the ActiveBall.X is greater than, let’s say 900 or maybe 890, then the ball is in the plunger lane somewhere. There is a little wiggle room for the ball, so we don’t want to trust exactly 906.4888.

Above we saw that Y was 1716.568. The Y values near the backglass are smaller, Y values near the player larger. So if we test to see that Y is greater than 1700, then the ActiveBall is near the bottom of the table.

If both of the above are true, we can be fairly certain the pinball is ready to be hit by the plunger. Let’s see how that might look in code.

Trying some code out.

That will work but there is one caveat: sometimes the ActiveBall object does not exist. One example is when the ball enters the drain, before it has reappeared on the playfield. Trying to check ActiveBall.X in the script at this moment would actually cause the table to halt in VPX and an error to come up stopping the player’s game.

I have found a way to protect against this though but it’s a little ugly.

Trying some code out.

Line 467 defines two new variables, they are initialized to zero on the following lines.

Now the line On Error Resume Next is a Visual Basic call you make just before you think you might be about to step on a land mine. It tells Visual Basic to resume if an error is encountered.

And lines 471 and 472 could cause an error if, as I mentioned, ActiveBall does not exist. By adding the error directive on Line 470 we will not cause VPX to halt — we can still do our check on Line 473 without worrying about VPX halting.

The only thing I would change in the code above is to use constants for the 890 and 1700. It’s generally frowned upon to use hard-coded values in code and with constants we can use names that are a little more descriptive than 890.


Teacher’s Pet handles the nudge keys but plays no sound for the nudge. Since EM Sounds has a call EMSPlayNudgeSound, why not use it?

New nudge code added.

The diff above shows three lines of code added. That was all that was involved to add that feature.

Ball Control

Okay, at this point I’m looking at wrapping up the sound code changes and getting this table ready to share. But there was something I mentioned in a previous post that I wanted to attend to before we make the table with our changes public.

There were a number of subroutines under a code banner Object sounds. We had broken these routines by removing the Vol function. We caught some of them being called and found substitute EM Sound routines we could call instead. (Maybe you remember when we were coding through crashing.)

A portion of the script is shown below. You can see that we saw that Metals2_Hit is called from time to time and we added EMSPlayMetalHitSound at Line 3186.

Object sounds code.

But above that routine there are routines to handle hits to plastics, pins, targets, etc. I’ve played now perhaps twenty or thirty games of Teacher’s Pet and have not yet had one of those routines get called and halt VPX. But as I said earlier, uploading the table with a potential crasher is a bad idea.

I am going to defuse these routines because they seem to be boilerplate routines carried over from another Loserman76 table. Aside from the twenty or thirty games I have played though, there is another interesting way we can test our table and maybe feel more comfortable that these calls are indeed orphaned.

Back in the debugger window we have now seen a few times, there is a checkbox labeled Ball Control. When you check this box you can literally drag the ball around the table with the cursor of your mouse. You can slam into walls, rails, bumpers, etc.

Ball Control checkbox.

Give it a try. I know the sounds the table makes are horrible, but try to go around the entire table and slam into every surface you can think of. This will make it more likely that you will find missing sounds (reported in the debugger console) and more likely to fire off one of those broken routines in Object sounds.

Another Missing Sound

While I was trying Ball Control on Teacher’s Pet, another missing sound message showed up. In the previous post when we first experimented with the debugger we saw a missing sound reported and we addressed that one. This extra test of using Ball Control seems to have been more thorough and revealed another sound that is perhaps not as frequent when actually playing the table.

Another missing sound is reported.

The sound is called postup and, like the previous sound scoopexit, I could not find the sound in the original Teacher’s Pet. Further, like before, the closest sound file I could find with a similar name is called fx_postup. Again, I have uploaded the sound on Github for you to download.

Go back to the previous post if you need to, but I followed the same steps for fx_postup that I had done for the previous sound that was discovered missing. I imported the new sound into the table’s Sound Manager and then found in the script where it was requesting "postup" and changed it to refer to "fx_postup".

But back to Ball Control, it was useful this time in identifiying another missing sound. If it had triggered one of the Object sounds routines and caused VPX to halt, I would have replaced the code with a substitute call from EM Sounds. The missing sound though was the only problem I found.

Playing It Safe

Look at the diff below to see what I did to make the Object sounds routines safe to share.

Diff showing safer Object sounds code.

All the code with PlaySound is gone (red highlight) and instead replaced with just a comment ' Not called. (highlighted in green). It is probably okay to also have simply stripped all the routines out, but remembering Chesteron’s Fence, I thought it was better to leave them (even if they are only orphaned placeholders) but make sure they can cause no harm.

Orphaned Code and Resources

I’m sorry to say that the final steps involve some cleanup and it is another one of those kind of tedious tasks.

We dropped in over 500 lines of code when we added EM Sounds to the script of Teacher’s Pet. We are not calling everything in that code drop. Further, we imported nearly 200 sounds files — many of which we are also not making use of. Like Loserman76 we could just leave the extra code and unused sounds. As I may have mentioned in an earlier post, I would rather not needlessly add to the stoarge/download size of our table with unused sounds and I don’t want the next person who comes into the script to have to deal with orphaned clutter.

The best time to clean up is when you think you are done. I will start by going down to the EM Sounds routines and looking for ones that we are not using in Teacher’s Pet.

There are a lot of routines in EM Sounds that we should not remove — they provide the core funtionality. Rather than list those though, let me list the routines that, if not needed, you should remove.

I’ll begin with the “begin game” sounds.


We used all of the above but for the last two in Teacher’s Pet. We can remove those two routines and also the sound resources associated with them. That would be any sound beginning with "BallRelease" and the "RotateThruPlayers" sound.

A bunch of flipper sound routines follow. We used all of them.

Playfields sounds follow:


We did not need EMSPlayGateHitSound. Also, we only made the call to the “middle” bumper routine so we can delete EMSPlayTopBumperSound and EMSPlayBottomBumperSound. Finally, EMSPlayTargetHitSound is not needed either. That means we can also remove sounds: "gate4", sounds beginning with "Bumpers_Top" and "Bumpers_Bottom" and "Target_Hit".

The last sound routines are kind of “other” sounds:


Teacher’s Pet does not have chimes, it has bells. Therefore, we did not call EMSPlayChimeSound and so can remove that routine as well as the sound resources that begin "SJ_Chime".

The rest of the sound routines we called.


And … we’re done adding sound to Teacher’s Pet. Along the way though we learned about DOF and cleaned up that related code. We also played with the debugger a bit, did some linting … began to feel comfortable in the script of a VPX table. The cleaned up script, as usual, is on Github.

I’ll have more posts coming where I’ll make some other improvements to Teacher’s Pet, delve into more esoterica. But in the meantime, go enjoy playing your improved pinball table.