Visual Pinball Code Examples and Explanations


back to index         -         previous page         -         next page

- Bonus Routine
- Hi-Score
- Add Score or Bonus
- Multiple Blinking Lights
- Background Music
- Music during Event





A Simple Bonus Routine


In the latter part, some timers are used of existing objects (build-in timers).
I prefer to use these, because they are already there, wich gives less objects and increases performance.
Don't forget to keep the Enabled box unchecked, because you only want it to start when you tell it to.


Needed at the start of script:
These are defined variables that are kept in memory, even if the sub-routine has finished.
A simple reminder... Dim = Dump in Memory.
Each script has to begin with all variable definitions, Dim's.

Dim Score
Dim HiScore
Dim Bonus
Dim BonusTemp
Dim BonusStep
Dim Turn
Dim ExtraBallCount

In the Drain sub-routine:
This is the code I use in a multi-ball table.
The Bonus routine starts only if all balls are gone.
In this example, it is important that the new turn number is set before the bonus routine.
When the last ball is gone, this directly shows the won bonus in the text box.
You might want to add something different before that, but for this example, it's good enough.

Sub Drain_Hit()
BallInPlay=BallInPlay-1
If BallInPlay=0 Then     This happens when the last ball in play hits the drain.
Drain.DestroyBall
If ExtraBallCount=0 Then     The turn only has to increase when there are no extra balls.
Turn=Turn+1
End If
MainText1.Text="BONUS " & Bonus & " points"     (shows as: Bonus 25750 points)
BonusStep=0
BonusTimer1.Enabled=True
Exit Sub
End If
Drain.DestroyBall     This happens when there is more than 1 ball in play.
End Sub


The Bonus Timers + actual Bonus routine:
This example uses 2 timers, placed somewhere on the table, named BonusTimer1 and BonusTimer2.
The time is set at 2000ms, but you have to experiment with it to find your prefered setting.
The routine switches forth and back between the timers.
It takes a lot of scrolling, but it seems to work better in my tables.
This way, the routine of one timer can completely finish before it's started again.
Also, each sub-routine is shorter. In a complete table, I prefere using 4 timers.


    the start of bonustimer 1:

Sub BonusTimer1_Timer()
BonusTimer1.Enabled=False
BonusStep=BonusStep+1     This increases the BonusStep automaticly with just 1 line of code.

This part adds the bonus of 1 event (BonusStep1 + BonusStep2).Duplicate it with higher bonusstepnumbers and
different variables to add more bonus items. BonusStep=3 becomes 5, 7, 9 etc... If there is nothing scored,
the first bonustimer routine just keeps on going to the end part of the Bonus event without delay.

If BonusStep=1 Then
If CargoFlightCount>0 Then     This only shows when there is actualy scored.
MainText1.Text=CargoFlightCount&" CARGO FLIGHTS"
BonusTimer2.Enabled=True
    BonusTimer2 is activated and there the bonusstep increases to 2.
Exit Sub
End If
BonusStep=3     If there is 0 scored, the bonusstep increases to 3 and this routine keeps on going.
                To work, the "If BonusStep=3" part has to come after this in the routine.

End If

If BonusStep=3 Then     This is the endpart of the routine, after this, it's checking for all sort of things.
MainText1.Text="TOTAL BONUS " & Bonus & " points"
AddScore(Bonus)     At this point, the Bonus is added to the Score.
If ExtraBallCount>0 Then     This checks for extra balls.
BonusStep=49     If there are extra balls, bonustimer 2 will increase the bonusstep to 50, otherwise it wil increase to 4.
End If
BonusTimer2.Enabled=True
Exit Sub
End If

If BonusStep=51 Then
ExtraBallCount=ExtraBallCount-1
ExtraBallBox.Text=ExtraBallCount     To show the new amount of extra balls in a textbox.
BonusStep=3     Because BonusTimer2 starts, the bonusstep increases to 4.
BonusTimer2.Enabled=True
End If

If BonusStep=55 Then
BonusStep=3     Because BonusTimer2 starts, the bonusstep increases to 4.
BonusTimer2.Enabled=True
Exit Sub
End If

End Sub

    The end of bonustimer 1.


    The start of bonustimer 2.

Sub BonusTimer2_Timer()
BonusTimer2.Enabled=False
BonusStep=BonusStep+1     This increases the BonusStep automaticly with just 1 line of code.

If BonusStep=2 Then
BonusTemp=(CargoFlightCount*1000)     The total score for this bonus item is calculated here.
MainText1.Text=BonusTemp&" points"     It now shows the total bonus gained for this bonus item.
Bonus=Bonus+BonusTemp     Here the score of the bonus item is added to the total bonus.
BonusTimer1.Enabled=True
    BonusTimer1 starts, increasing the bonusstep to 3.
Exit Sub
End If

If BonusStep=4 And BonusHeldLight.State=1 Then     This checks if the bonus should be held instead if being reset to zero.
If Turn=4 Then     This happens if it's the last turn and there are no more balls following.
BonusHeldLight.State=0
MainText1.Text="YOU HAVE EARNED EVEN MORE BONUS"
BonusStep=0     This restarts the bonus routine from the beginning, BonusTimer1 starts and the bonusstep is increased to 1.
                The starting bonus now used, is the previous total bonus.

BonusTimer1.Enabled=True
Exit Sub
End If
MainText1.Text="BONUS SAVED"     This happens when there is another turn/extra ball comming.
BonusHeldLight.State=0
BonusStep=54     BonusTimer1 starts, increasing the bonusstep to 55.
BonusTimer1.Enabled=True
End If

If BonusStep=4 And BonusHeldLight.State=0 Then     This happens when there is no more bonus comming.
If Turn=4 Then
MainText1.Text="--- GAME OVER ---"
Bonus=0     This resets the bonus to zero for a new round.
TurnBox.TimerEnabled=True     This starts the Hi-Score check, using the timer of an existing object.
Exit Sub
End If
    This part happens when there is another turn comming.
TurnBox.Text=Turn     This shows the new turn number in a textbox somewhere.
Plunger.CreateBall
BallInPlay=1
DoSkillshot()     The skillshot routine is started for the new ball.
PlaySound "Plunger"     A sound is played for the new created ball, in my case the sound of a dropping ball.
Exit Sub
End If

If BonusStep=50 Then     Continuation of Extra Ball part.
MainText1.Text="Extra Ball"
BonusTimer1.Enabled=True
    BonusTimer1 starts, increasing the bonusstep to 51.
End If
End Sub

    The end of bonustimer 2.
    The next HiScore part is also a part of this bonus & end-game routine


- Go to Menu


Hi-Score

Hi-Score check:
Obviously, this checks if the current score is the highest score.
Unfortunatly, I have no idea on how to keep the highscore even when the table is closed.

Sub TurnBox_Timer()     Here I use the timer of an existing object, it uses a slightly different code.
TurnBox.TimerEnabled=False
If Score=>HiScore Then
HiScore=Score
HiScoreBox.Text=FormatNumber(HiScore,0,-1,0,-1)     This shows the hi-score in a textbox somewhere as 712,500,650
MainText1.Text="HI-SCORE, CONGRATULATIONS !"
HiScoreTimer.Enabled=True     A regular timer is started to keep the message on screen for a given time.
Exit Sub
End If
Start1stTurn()     The FirstTurn routine starts here, if there is no hi-score.
End Sub


Sub HiScoreTimer_Timer()     Here I use a regular timer.
HiScoreTimer.Enabled=False
Start1stTurn()     The first turn starts here after a hi-score.
End Sub

- Go to Menu


Add Score or Bonus

The used routines to add score or add bonus:
The variable named between the brackets, like
points , is only used in the sub-routine.
It doesn't matter how it's named, you have to type the exact name to use it.
The number comes from another routine where this routine is activated with:
AddScore(1000)
It can be used multiple times within the same sub-routine,
but this value will be lost when the sub-routine has finished.

Sub AddScore(points)
Score = Score + points
ScoreBox.Text = FormatNumber(Score,0,-1,0,-1)    This shows the new score in a textbox as 1,258,060
End Sub


Sub AddBonus(ICPMS)
Bonus = Bonus + ICPMS
End Sub

- Go to Menu


Multiple Blinking Lights

To create a vertical row of lights, you need to be creative with the hight/depth of the table.
I created lights with a custom shape on a high surface (height about 250).
Ofcourse, the lights don't have to be on the actual surface, so they are "floating" in the air.
In the table edit screen, they don't seem to be on the palmtree, but under it (even floating over other objects).
When you start the table, it gives the illusion that they are on the palmtree.

The routines I used for a lightsequence on a Palmtree:
This example uses 8 lights. Light 8 isn't part of the actual sequence, but is there to give an impression of
the light reflecting on the top of the tree. This makes it look more realistic.
There are 4 options: 0=off, 1=on, 2=blinking, 3 is the actual sequence with the light moving from bottom to top.
It also uses a regular timer placed somewhere on the table, named PalmTimer.
The Blink Interval of the lights determens the speed at wich the light blink (...state=2)
The Timer Interval of the PalmTimer determens the speed at wich the lights move up.

Dim palmLS     This number needs to be kept in memory for the routine to work. Place at beginning of the script.


Sub Palm(lampies)     It's simple to choose the sequence in a routine, with a line like Palm(2)
If lampies=0 Then     This switches off all lights on the tree.
PalmTimer.Enabled=False     This makes sure the upward sequence is stopped if active.
PalmLight1.State=0
PalmLight2.State=0
PalmLight3.State=0
PalmLight4.State=0
PalmLight5.State=0
PalmLight6.State=0
PalmLight7.State=0
PalmLight8.State=0
Exit Sub
End If
If lampies=1 Then     This switches on all lights on the tree.
PalmTimer.Enabled=False     This makes sure the upward sequence is stopped if active.
PalmLight1.State=1
PalmLight2.State=1
PalmLight3.State=1
PalmLight4.State=1
PalmLight5.State=1
PalmLight6.State=1
PalmLight7.State=1
PalmLight8.State=1
Exit Sub
End If
If lampies=2 Then     This makes all lights blink simultaniously.
PalmTimer.Enabled=False     This makes sure the upward sequence is stopped if active.
PalmLight1.State=2
PalmLight2.State=2
PalmLight3.State=2
PalmLight4.State=2
PalmLight5.State=2
PalmLight6.State=2
PalmLight7.State=2
PalmLight8.State=2
Exit Sub
End If
If lampies=3 Then     This starts the upward sequence of lights on the tree.
palmLS=0     This starts the first step of the sequence in the timer routine
PalmTimer.Enabled=True     This starts the actual timer.
Exit Sub
End If
End Sub


Sub PalmTimer_Timer()
PalmTimer.Enabled=False
PalmLight8.State=1     This is the "Reflection-Light", wich always shows during the upward sequence.
If palmLS=0 Then     This resets all lights at the start of the sequence.
PalmLight1.State=0
PalmLight2.State=0
PalmLight3.State=0
PalmLight4.State=0
PalmLight5.State=0
PalmLight6.State=0
PalmLight7.State=0
palmLS=1     Without any time delay, the routine continues at step 1
End If
If palmLS=1 Then     This is the 1st step of the loop, lighting the bottom light.
PalmLight7.State=0     The previous light is switched off.
PalmLight1.State=1     The next light is switched on.
palmLS=2
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=2 Then
PalmLight1.State=0
PalmLight2.State=1
palmLS=3
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=3 Then
PalmLight2.State=0
PalmLight3.State=1
palmLS=4
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=4 Then
PalmLight3.State=0
PalmLight4.State=1
palmLS=5
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=5 Then
PalmLight4.State=0
PalmLight5.State=1
palmLS=6
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=6 Then
PalmLight5.State=0
PalmLight6.State=1
palmLS=7
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=7 Then
PalmLight6.State=0
PalmLight7.State=1
palmLS=8
PalmTimer.Enabled=True
Exit Sub
End If
If palmLS=8 Then
PalmLight7.State=0
PalmLight8.State=0
palmLS=1     This makes sure the 1st step starts, looping the sequence.
PalmTimer.Enabled=True
Exit Sub
End If
End Sub

- Go to Menu


Background Music

The music as mp3-files has to be in the /music directory of Visual Pinball for it to work.
Don't use big wave-files or looped samples as backgroundmusic in the table, this decreases performance.
The only thing that worked properly for me are the mp3-files.
Be sure to stop the music with
EndMusic each time before you start another song.
PlayMusic does not stop the active song.

The Routine uses a different song for each ball/turn.
This is about the easiest way to create a simple music routine that stops the
current music and plays the standard backgroundmusic.
Mostly used at the start of a turn or after an event in the table that has it's own music.



Dim Muziek
Dim BallNumber
This needs to be kept in memory for the routine to work. Place at beginning of the script.
A variable can also contain text. Calling upon a variable just puts the current content of the variable
in the script (text or number).



Sub ResetMuziek()
If BallNumber=1 Then
Muziek="Techno Witch - Concerto L Diablo.mp3"
End If
If BallNumber=2 Then
Muziek="Techno Witch - Dream of the Universe.mp3"
End If
If BallNumber=3 Then
Muziek="Techno Witch - Adverse TacTics.mp3"
End If
EndMusic
PlayMusic Muziek
End Sub

This sub-routine restarts the music when the active song has finished.
By using the variable (Dim) Muziek, it automaticly plays the right background song or
the song related to an event happening on the table.
You can also do all sorts of other things, it's up to you.

Sub Table1_MusicDone()
PlayMusic Muziek
End Sub

- Go to Menu


Music during an Event

The music as mp3-files has to be in the /music directory of Visual Pinball for it to work.
Don't use big wave-files or looped samples as backgroundmusic in the table, this decreases performance.
The only thing that worked properly for me are the mp3-files.

If you have an event going on in the game, like an adventure, a quest or something of the likes,
it always sounds great if it has it's own special music.
You can also create a mp3-file with apropiate samples and/or sounds.
In the sub-routine of the start of the event, you 1st have to set the variable Muziek with the right song.
Then you have to stop the current music and start the event music with PlayMusic Muziek.
Because the eventsong is set in the variable, the Table1_MusicDone() routine restarts the event music.
It's all just a matter of adding the following lines:

Muziek="Event1.mp3"
EndMusic
PlayMusic Muziek


After the event has finished, you can stop the event music and start the background music
with a sub-routine like given in the example above.
ResetMuziek()


It is possible to have the event end when the mp3-file has finished.
This way, the event will always be in sync with the music.
Call upon the routine that ends the event in the MusicDone routine.
The AdventureFinished routine resets the music by calling upon ResetMusic(),
therefore the MusicDone routine must not start the music again.
To prevent this from happenening, there is the Exit Sub command in the If/Then part.

Sub Table1_MusicDone()
If AdventureLight.State=1 Then
AdventureFinished()
Exit Sub
End If
PlayMusic Muziek
End Sub


- Go to Menu