*.VBS content

1.           Classes

a.  cvpmTimer class for switch pulsing and easy timer handling.

b.          cvpmBallStack class for ball tracking in stacks or saucers.

c.          cvpmDropTarget class for easy drop target bank handling

d.  cvpmNudge class for Tilt handling

e.          cvpmMagnet class for playfield Magnets

f.          cvpmTurntable class for playfield turntables

g.          cvpmCaptiveBall class for captive balls

h.  cvpmMech class for handling playfield mechanics

i.   cvpmVLock class for visible ball locks

j.          cvpmImpulseP class for Impulse Plungers using triggers

2.           Solenoid callback functions

a.  Flippers

b.  Diverters

c.  Walls

d.  Auto Plungers (kicker based)

e.  Gates

f.   Sound

g.  Flashers

h. Generic for any object

3.           Constants

a.  Common switches/Solenoids

4.           User interface

a.  Open options window (F1)

b.  Show keys help (F2)

c.  Reset emulation (F3)

d.  Toggle display lock status (F4)

Using the *.VBS files

To use the *.VBS files the file must be in the same directory as the table file. Add the following code at the top of the script

‘ Load VPinMAME and *.VBS file, check versions

LoadVPM "02000000", "S11.VBS", 2.4

Sub LoadVPM(VPMver, VBSfile, VBSver)

     On Error Resume Next

          If ScriptEngineMajorVersion < 5 Then MsgBox "VB Script Engine 5.0 or higher required"

          ExecuteGlobal GetTextFile(VBSfile, 1).ReadAll

          If Err Then MsgBox "Unable to open " & VBSfile & ". Ensure that it is in the same folder as this table. " & vbNewLine & Err.Description

          Set Controller = CreateObject("VPinMAME.Controller")

          If Err Then MsgBox "Can't Load VPinMAME." & vbNewLine & Err.Description

          If VPMver>"" Then If Controller.Version < VPMver Or Err Then MsgBox "VPinMAME ver " & VPMver & " required."

          If VPinMAMEDriverVer < VBSver Or Err Then MsgBox VBSFile & " ver " & VBSver & " or higher required."

     On Error Goto 0

End Sub

 

Class cvpmTimer

This class is used to simplify timed events required for VPinMAME.

A single instance of this class is available as “vpmTimer”.

·        Method: .PulseSwitch switch, time, command

·        Method: .PulseSw sw

Pulses (quick on-off) switch and then execute command after time has elapsed.

switch:          switch to pulse

time:          time until callback is called in ms (1/1000s)

command:          Execute this string when timer expires.
switch number will be added at the end

Example:

              1. Walls do not have UnHit events.

Sub Wall10_Hit : vpmTimer.PulseSw 10 : End Sub

              2. Under playfield handling. Trigger switch 8, wait 0.5s and then call
              SubwayHandler

vpmTimer.PulseSwitch 8,500,”SubwayHandler”

Sub SubwayHandler(swNo)

   If swNo = 8 Then ...

 

·        Method: .AddTimer time, command

Execute command after time has elapsed

time:           Time until callback is called 1/1000s

command:          Execute this string when timer expires.
switch number “0” will be added at the end

Example:

              1. Call “delayedSub” after 1 second

vpmTimer.AddTimer 1000,”DelayedSub”

Sub DelayedSub(swNo)   ‘swNo is always 0 for AddTimer events

              2. Kick out the ball from a kicker after 2 seconds

‘Note the “’” at the end to ignore the added “0”

vpmTimer.AddTimer 2000,”Kicker.Kick 90,10 ’”

Class cvpmBallStack

This class implements all kind of ball handling where kickers are involved.

It can be used in two different ways:

Stack      Balls are destroyed as they enter the stack and created when leaving.
              Up to 10 balls can be in the stack at the same time.

Saucer    Balls are not destroyed (i.e stays visible) and only one ball can be in the stack at any point in time.

Example:

Set bsTrough = New cvpmBallStack

Set bsSaucer = New cvpmBallStack

 

Stack version

·        Method: .InitSw entrySw,sw1,sw2,sw3,sw4,sw5,sw6,sw7

Initialize the switches used in the stack.

entrySw:          switch triggered when a ball enters the stack (e.g. an outhole)
If an entry switch is specified, balls will keep the switch activated until the entry solnoid is fired.
If entry switch is 0 balls will go directly into the stack.

sw1-sw7:          Switches activated when balls are in the stack. Next ball to leave the stack will activate sw1, second ball sw2 etc

 

Example:

              1. A Trough with an outhole switch and 3 switches

bsTrough.InitSw swOutHole, swRTrough, swCTrough,_
swLTrough,0,0,0,0

              2. A Lock with 2 switches

bsLock.InitSw 0,swLock1,swLock2,0,0,0,0,0

 

·        Method: .InitKick kicker, direction, force

Initialise the kicker used to kick out balls from the stack.

If the kicker is not initialized the stack work as normal but no ball will be kicked out (It is still removed from the stack)

kicker:                    kicker object

direction:          kickout direction

force:                    kickout force

Example:

              Kickout from the “BallRelease” kicker direction 90 and power 5

bsTrough.InitKick BallRelease, 90, 5

 

·        Method: .InitNoTrough kicker, switch, direction, force

Simplified init function for single ball games without a trough. Number of balls is automatically set to 1

kicker:                    kicker object

switch:          outhole switch

direction:          kickout direction

force:                    kickout force

Example:

              Single ball game

bsTrough.InitNoTrough BallRelease, swOuthole, 90, 5

 

·        Property: .KickBalls = x

Specifies the maximum number of balls that can be kicked out at the same time. Default = 1.

First ball will be kicked out with 100% power, 2nd with 80%, 3rd with 64%…

Example:

              Kick out maximum 2 balls at a time

bsLock.KickBalls = 2

 

·        Method: .InitEntrySnd ballSound, sound

Specify the sound used when the entry solenoid is fired.

ballSound:          sound to play if a ball is kicked

sound:                    sound to play if no ball is kicked

Example:

bsTrough.InitEntrySnd “Outhole”, “SolenoidOn”

 

 

Saucer version

·        Method: .InitSaucer kicker, sw, direction, force

Initialize a saucer

kicker:          kicker object used for the saucer

sw:          switch activated when a ball is in the saucer

direction:          direction of kickout

force:          force of kickout

Example:

bsSaucer.InitSaucer saucerkicker, swSaucer, 90, 10

 

Common to Stacks and Saucers

·        Property: .KickForceVar = forceVar

·        Property: .KickAngleVar = angleVar

Randomly vary the kickout force and angle by “var” units (default 0)

Example:

              Kick out balls with force 10 +/- 2 (i.e. 8-12) and angle 85-95

bsLock.InitKick lockKicker, 90, 10

bsLock.KickForceVar = 2

bsLock.KickAngleVar = 5

 

·        Property: .KickZ = angle

Specify the vertical angle for kickout

angle:                    vertical angle in radians (PI/2 = vertical)

Example:

              Kickout ball in a 45 degree angle towards the playfield

bsTrough.KickZ = 3.1415926/4

 

·        Method: .InitAltKick direction, force

Specify an alternative kickout direction and force. Used mainly with saucers that can kick the ball out in two different directions.

direction:          direction of kickout

force:          force of kickout

Example:

              Kickout ball either up or down

bsSaucer.InitSaucer saucerKicker, swSaucer, 0, 5

bsSaucer.InitAltKick 180,5

SolCallback(sSaucerUp) = ”bsSaucer.SolOut”

SolCallback(sSaucerDown) = ”bsSaucer.SolOutAlt”

 

·        Method: .InitExitSnd ballSound, sound

Same as .InitEntrySnd but for the Exit solenoid

ballSound:          sound to play if a ball is kicked

sound:          sound to play if no ball is kicked

Example:

bsTrough.InitExitSound “BallRelease”, “SolenoidOn”

 

·        Method: .AddBall kicker

Add a ball into the Stack or Saucer. If a kicker is specified the ball will be destroyed for a Stack (not for Saucers*).  If an entry switch is specified balls will not be put into the stack until the entry solenoid is fired (see .SolIn)

* Balls are always kicked out from the kicker specified with the .InitSaucer method. If a different kicker is specified in the .AddBall method the ball will be moved (destroyed and created with the same properties) to the normal kicker at kickout. This can be used to simulate a vertical up kicker (VUK).

kicker:          Kicker where ball is

Example:

              1. Add a ball currently in the outhole kicker

Sub Outhole_Hit : bsTrough.AddBall Me : End Sub

              2. Add a ball in a Saucer

Sub Saucer_Hit : bsSaucer.AddBall 0 : End Sub

 

·        Property: .Balls = x

Fill stack with balls. Any existing balls will disappear.

Example:

              Put 3 balls in Trough

bsTrough.Balls = 3

 

Solenoid handlers

·        Method: .SolIn enabled

·        Method: .EntrySol_On

Kicks a ball waiting on the entry Switch into the stack (not applicable for Saucers).

SolIn can be specified as a solenoid handler.

Example:

              1. Directly from solenoid callback

SolCallback(sOuthole) = “bsTrough.SolIn”

              2. From procedure

SolCallback(sOuthole) = “SolOuthole”

Sub SolOuthole(enabled)

   If enabled Then

      bsTrough.EntrySol_On

 

·        Method: .SolOut enabled

·        Method; .ExitSol_On

Kicks out a ball from the stack or saucer .

SolOut can be specified as a solenoid handler.

Example:

              1. Directly from solenoid callback

SolCallback(sBallRelease) = “bsTrough.SolOut”

              2. From procedure

SolCallback(sBallRelease) = “SolBallRelease”

Sub SolBallRelease(enabled)

   If enabled Then

      bsTrough.ExitSol_On

·        Method: .SolOutAlt enabled

·        Method; .ExitAltSol_On

Kicks out a ball from the stack or saucer in the alternative direction.

SolOutAlt can be specified as a solenoid handler.

Example:

              See .InitAltKick method

Class cvpmDropTarget

This class is used to handle drop target banks.

 

·        Method: .InitDrop targets, switches

Initializes the targets and the switches for the drop targets.

targets:          Droppable walls. Arrays/Collections can be used if each target consists of more than one wall.

switches:          Switches connected to each target. If Nothing the switches will be taken from the TimerInterval property of the targets.

Example:

              1. Single target

dtDrop.InitDrop Target, swTarget

              2. Multiple targtes

dtDrop.InitDrop Array(Target1, Target2, Target3), Array(sw1,sw2,sw3)

              3. Multiple targets with two walls for each target

dtDrop.InitDrop Array(Array(T1Front,T1Back),Array(T2Front,T2Back)), Array(sw1,sw2)

              4. Targets where switch number is set in the TimerInterval property

dtDrop.InitDrop Array(Target1,Target2,Array(T3Front,T3Back)),Nothing

 

·        Method: .CreateEvents instance

Creates the events for the drop targets. “Sub Target_Hit …”

instance:          The name of the cvpmDropTarget object.

Example:

dtDrop.InitDrop Array(Target1, Target2, Target3), Array(sw1,sw2,sw3)

dtDrop.CreateEvents “dtDrop”

 

·        Property: .AnyUpSw = switch

·        Property: .AllDownSw = switch

·        Property: .LinkedTo = dropTargetBanks

Some drop target banks have switches indication if all targets are up or down. Use these properties to specify the switches.

Sometimes games have common swicthes for several drop target banks. The .LinkedTo property specifies drop target banks that have a common AnyUpSw or AllDownSw. (note that drop target banks must be linked both ways)

DropTargetBanks          Drop target bank (or array) which share an AnyUp or AllDn switch

Example:

              1. Normal drop target bank

dtDrop.AnyUpSw = 25

dtDrop.AllDownSw = 30

              2. Three banks with a common AllDownSw

dtLDrop.AllDownSw = 34

dtLDrop.LinkedTo = Array(dtCDrop,dtRDrop)

dtCDrop.LinkedTo = Array(dtLDrop,dtRDrop)

dtRDrop.LinkedTo = Array(dtLDrop,dtCDrop)

 

·        Method: .InitSound drop, raise

Specify sound connected to drop targets

drop:          sound when a target is hit

raise:          sound when targets are raised

Example:

dtDrop.InitSound “DropTarget”,”RaiseTarget”

 

·        Method: .Hit targetNo

·        Method: .SolHit targetNo, enabled

A drop target has been hit. .SolHit can be specified as a solenoid handler.

targetNo:          The target that has been hit (1,2,3...)

Example:

              1. Target 2 has been hit

Sub Target2_Hit : dtDrop.Hit 2 : End Sub

              2. Solenoid for target 3

SolCallback(sTarget2) = “dtDrop.SolHit 3,”

 

·        Method: .SolDropUp enabled

·        Method: .DropSol_On

Raise target handler. Restores all drop targets and switches in the bank

.SolDropUp can be specified as a solenoid handler

Example:

              1. Directly from solenoid callback

SolCallback(sRaiseDrop) = “dtDrop.SolDropUp”

              2. From procedure

SolCallback(sRaiseDrop) = “SolRaiseDrop”

Sub SolRaiseDrop(enabled)

   If enabled Then

      dtDrop.DropSol_On

 

·        Method: .SolDropDown enabled

Drop all targets. Can be specified as a solenoid handler

Example:

SolCallback(sDropDown) = “dtDrop.SolDropDown”

 

·        Method: .SolUnhit targetNo, enabled

Raise one target. Can be specified as a solenoid handler

targetNo:          The target that should be raised (1,2,3...)

Example:

SolCallback(sRaiseDrop3) = “dtDrop.SolUnhit 3,”

 

Class cvpmNudge

This class is used to handle nudging and Tilts.

 

·        Property: .TiltSwitch = swNo

Specifies switch to be triggered when a Tilt occurs.

Example:

vpmNudge.TiltSwitch = swTilt

 

·        Property: .Sensitivity = sens

Specifies the tilt sensitivity between 0 (low) – 10 (high).

Example:

vpmNudge.Sensitivity = 5

 

·        Property: .TiltObj = Objects

Specifiy objects (bumpers and slingshots) affected by a tilt.

Example:

vpmNudge.TiltObj = Array(Bumper1, Bumper2,LeftSling,RightSling)

 

·        Method: .DoNudge direction, force

Nudge the table

direction:          Direction of nudge.

force:          Nudge force

Example:

vpmNudge.DoNudge 85, 2

 

·        Method: .SolGameOn enabled

Activates or deactivates bumpers and slingshots

Example:

SolCallback(sGameOn) = “VpmNudge.SolGameOn”

Class cvpmMagnet

This class is used to handle playfield magnets. The magnet itself is one or more triggers covering the area where the magnet can affect the ball. By default the magnet use vpmTimer for updates. On slow computers this might cause erratic switch behaviour. Performance can be improved by adding an extra timer called “vpmFastTimer”. Magnets will automatically use “vpmFastTimer” if it exists.

 

·        Method: .InitMagnet trigger, strength

Initializes the magnet.

trigger:          Trigger(s) used to simulate the magnet

strength:          Magnet strength at center

Example:

MLeft.InitMagnet LeftMagnet, 10

MLeft.InitMagnet Array(LeftMagnet1, LeftMagnet2), 14

 

·        Method: .CreateEvents instance

Creates the magnet events “Sub Magnet_Hit …”

instance:          The name of the cvpmMagnet object.

Example:

MLeft.InitMagnet LeftMagnet, 10

MLeft.CreateEvents “MLeft”

 

·        Property: .Solenoid = sol

Specifies the solenoid that controls the magnet. If not set or set to 0 the magnet is controlled with the .MagnetOn property.

sol:          Solenoid number

Example:

MLeft.Solenoid = sLeftMagnet

 

·        Property: .X = xPos

·        Property: .Y = yPos

·        Property: .Strength = strength

·        Property: .Size = radius

Changes the magnet properties. Note that the trigger is not moved so the new magnet position must remain within the area covered by the trigger(s).

xPos, yPos:          Playfield coordinates

strength:          Magnet strength at center

radius:          Magnet reach

Example:

MLeft.X = MLeft.X + 5

Mleft.Strength = 12

 

·        Property: .GrabCenter = True/False

The cvpmMagnet class updates the ball based on a timer. This might cause the ball to “vibrate” at the center of the magnet. .GrabCenter forces the ball to stop immediately on the center.

Example:

MLeft.GrabCenter = False

 

·        Method: .AddBall ball

A ball has entered the magnets reach. Usuall called from the magnet trigger’s hit event.

ball:          Ball object

Example:

Sub LeftMagnet_Hit : MLeft.AddBall ActiveBall : End Sub

 

·        Method: .RemoveBall ball

A ball has left the magnets reach. Usuall called from the magnet trigger’s unhit event.

ball:          Ball object

Example:

Sub LeftMagnet_UnHit : MLeft.RemoveBall ActiveBall : End Sub

 

·        Property: .Balls

An array of all balls currently in the magnets reach.

Example:

BallsOnMagnet = Ubound(mLeft.Balls)

 

·        Property: .MagnetOn enabled

Turn the magnet on or off. Only works if no solenoid is specified.

enabled:          True to turn magnet on

Example:

MLeft.MagnetOn = True

SolCallback(sLeftMagnet) = “MLeft.MagnetOn=”

 

·        Method: .AttractBall ball

Calculate and perform a magnets effect on a specific ball.

ball:          Ball object

Example:

MLeft.AttractBall ActiveBall

 

Class cvpmTurnTable

This class is used to handle rotating objects like turntables. The turntable itself is a trigger covering the area where of the turntable. By default the turntables use vpmTimer class for updates. On slow computers this might cause erratic switch behaviour. Performance can be improved by adding an extra timer called “vpmFastTimer”. Turntables will automatically use the “vpmFastTimer” if it exists.

 

·        Method: .InitTurntable trigger, maxSpeed

Initializes the turntable.

trigger:          Trigger used to simulate the turnTable

maxSpeed:          Maximum turntable speed

Example:

ttCenter.InitTurnTable CenterTable, 40

 

·        Method: .CreateEvents instance

Creates the turntable events “Sub TurnTable_Hit …”

instance:          The name of the cvpmTurnTable object.

Example:

ttCenter.InitTurnTable CenterTable, 40

ttCenter.CreateEvents “ttCenter”

 

·        Property: .MaxSpeed = maxSpeed

·        Property: .Speed = speed

·        Property: .SpinUp = acc

·        Property: .SpinDown = ret

·        Property: .SpinCW = spinDir

Changes the turntables properties. Note that the acceleration and retardation will affect the speed. Set .SpinUp = 0 and .SpinDown = 0 to control speed directly.

maxSpeed:          Maximum turntable speed

speed          Turntable speed

acc:          Spin up acceleration [speed units/0.5s]

ret:          Spin down retardation

spinDir:          True for clockwise spin, false for counter clockwice (does not change motor state)

Example:

TtCenter.maxSpeed = 50

ttCenter.SpinUp = 20

ttCenter.SpinDown = 5

 

·        Method: .AddBall ball

A ball has entered the turntable reach. Usuall called from the turntable trigger’s hit event.

ball:          Ball object

Example:

Sub CenterTable_Hit : ttCenter.AddBall ActiveBall : End Sub

 

·        Method: .RemoveBall ball

A ball has left the turntable. Usuall called from the tunrtable trigger’s unhit event.

ball:          Ball object

Example:

Sub CenterTable_UnHit : ttCenter.RemoveBall ActiveBall : End Sub

 

·        Property: .Balls

An array of all balls currently in the turntables reach.

Example:

              Make all balls on the turntable red

For Each ball In ttCenter.Balls : ball.Color = vbRed : Next

 

·        Property: .MotorOn = enabled

·        Method: .SolMotorState clockWise, enabled

Control the motor status of the turntable.

clockWise:          True = Turntable spinning clockwise

enabled:          True = Table motor is on

Example:

              1. Solenoid handlers

SolCallback(sCenterCW) = “ttCenter.SolMotorState True,”

SolCallback(sCenterCCW) = “ttCenter.SolMotorState False,”

              2. Direct control

ttCenter.MotorOn = False

 

 

·        Method: .AffectBall ball

Calculate and perform a turntable’s effect on a specific ball.

ball:          Ball object

Example:

ttCenter.AffectBall ActiveBall

 

Class cvpmMech

This class is used to create a handler of playfield mechanics including motors. The class will calculate the position of the mechanics, update switches and call a user-defined function whenever the poosition changes.

 

·        Property: .MType = type

Specifies the mechanics type. The type is consists of four groups:

1. How the motor is controlled

vpmMechOneSol – A single solneoid controls the power to the motor. One direction only.

vpmMechOneDirSol – The first solenoid controls the power to the second solenoid controls the direction.

vpmMechTwoDirSol – The first solenoid controls clockwise movement and the second solenoid controls counter-clockwise movement.

vpmMechStepSol – Two solenoids control a step motor

2. How the mechanic controlled by the motor moves

vpmMechCircle – The mechanic moves in a circle and comes back to the starting point

vpmMechReverse – The mechanic moves from one end to the other and then moves back without the motor changing direction

vpmMechStopEnd – The mechanics stops when it reaches either end point.

3. The speed of the mechanic

vpmMechLiner – The mechanic moves at a constant speed from one end to the other (default)

vpmMechNonLinear – The mechanics speed is slow at the endpoints and fast in the middle

4. Mech handler properties

vpmMechSlow – Normal handler. Updated ~60 times per second. (default)

vpmMechFast – A fast handler. Sometimes required for very fast puls controlled mechanics (e.g. step motors). Update speed is ~240 times per second.

vpmMechStepSw – The switches are updated based on mechanincs “step” value (default)

vpmMechLengthSw – The switches are updated based on mechanics “length” value.

 

The type field is a combination of the above values

Example:

              Terminator 2 Gun

mGun.Type = vpmMechOneSol + vpmMechReverse + vpmMechNonLinear

 

·        Property: .Sol1 = solNol

·        Property: .Sol2 = solNol

Specifies the solenoids used to control the playfield mechanics.

Example:

              Monster Bash Dracula

mDracula.Sol1 = 41

mDracula.Sol2 = 42

 

·        Property: .Length = x

Specifies the length from one end to the other or a full circle (vpmMechCircle). The length parameter is the number 1/60th second the motor must be on.

Example:

              Terminator 2 Gun. ~3.5s at full speed.

mGun.Length = 200

 

·        Property: .Steps = x

The number of the positions reported back by the mechanic handler.

Example:

              Terminator 2 Gun. 20 different positions

MGun.Steps = 20 ‘one position for every 10 “length” units

 

·        Property: .Acc = acc

·        Property: .Ret = ret

Specifies the acceleration and retardation of the mechanic.

acc:          “Length” units required to reach full speed

ret:          number of times slower retardation is than acceleration

Example:

              World Cup Soccer ’94 Soccer ball. Takes 3 seconds to speed up and the same to stop

mSoccerBall.Acc = 180

mSoccerBall.Ret = 1

 

·        Method: .AddSw = swNo, startStep, endStep

Specifies a switch to be automatically updated by the mechanics handler.

swNo          switch number

startStep          First step position where the switch is activated

endstep          Last step position where the switch is activated

Example: Terminator 2 Gun. Home position at 0, Mark position at 8-9

mGun.AddSw swGunHome, 0, 0

mGun.AddSw swGunMark, 8, 9

 

·        Method: .AddPulseSw = swNo, interval, length

Specifies a switch to be automatically pulsed when mech is moving.

swNo          switch number

interval          Length between pulses (in steps)

length          Length of each pulse (in steps)

Example: Pulse switch every 5 steps

mGun.AddPulseSw swMech, 5, 1

 

·        Property: .Callback = callback

Specifies function called whenever the position of the mechanic changes. The function must take three argument.

NewPos          Current position (step) of mechanics

Speed          Current speed of mechanic

LastPos          Previous position (step) of mechanics

Example:

mGun.Callback = GetRef(”UpdateGun”)

Sub UpdateGun(aNewPos, aSpeed, aLastPos)

   GunWalls(aLastPos\2).IsDropped = True

   GunWalls(aNewPos\2).IsDropped = False

End Sub

 

·        Property: .Start

Sets up the mechnics handler and starts it.

Example:

Set GunMech = New cvpmMech

With gunMech

   .Sol1 = sGunMotor

   .Length = 200

   .Steps = 58 ' 29 walls

   .MType = vpmMechOneSol + vpmMechReverse + vpmMechNonLinear

   .AddSw swGunHome, 0, 1

   .AddSw swGunMark, 20, 21

   .Callback = GetRef("UpdateGun")

   .Start

End With

 

·        Property: .Position

·        Property: .Speed

The current position and speed of the mechanic.

The position is in the range 0 to Steps-1 (e.g. ,Steps = 58 means position is 0-57).

Speed is 0 (stopped) to .Acc (full speed) (e.g. .Acc=10 means speed is 0-10)

Class cvpmCaptiveBall

This class is used to handle captive balls on the playfield. The handler takes the hitting balls velocity and angle into account when moving captive ball.

The Captive Ball requires the following elements:

1. One or two kickers for the moving ball. (If two kickers are specified the ball will rest in the first and the second will be used to kick out the ball)

2. A wall that holds the captive ball back

3. A trigger in front of the wall. (To estimate the ball speed).

 

·        Method: .InitCaptive trigger, wall, kickers, ballAngle

Initialises the captive ball obejcts (Does not create the ball).

trigger          Trigger placed in front of the captive ball. (optional but operation will be much better if it there)

wall          Wall holding the captive ball back.

kickers          One or two kickers for the normal captive ball + kickers for “nailed” balls.

ballAngle          The angle the captive ball should move.

Example:

cbCaptive = New cvpmCaptiveBall

cbCaptive.InitCaptive CaptiveTrigger, CaptiveWall, Array(Captive1,Cative2)

·        Property: .NailedBalls = nailedballs

Specify the number of nailed balls. (default 0). One extra kicker must have been specified in the InitCaptive method for each nailed ball.

nailedBalls:          0-n

 

·        Method: .Start

Start the captive ball handler, i.e. create the moving ball. Note that if “nailed” ball is used, the actual ball must be created manually

Example:

              Captive Ball with a red “nailed” ball

cbCaptive.InitCaptive CaptiveTrigger, CaptiveWall, Array(Captive1,Cative2,Captive3)

cbCaptive.Start

Captive1.CreateBall.Color = vbRed

 

·        Property: .ForceTrans = fTrans

·        Property: .MinForce = minForce

Controls the movement of the captive ball.

fTrans          The amount of the hitting balls speed that is transferred to the captive ball (0-1). Note that the hitting ball’s speed is not reduced. Use the elasticity of the wall to control the hitting balls speed.

minForce          The minimum force applied to the captive ball. If set to low the captive ball might not return to its resting position. (depends on the distance between the moving ball’s kickers and table slope.)

Example:

cbCaptive.ForceTrans = 0.4

cbCaptive.MinForce = 3.5

 

·        Property: .RestSwitch = swNo

Switch activated when the ball is in the resting position

Example:

cbCaptive.RestSwitch = swCaptiveResting

 

·        Method: .CreateEvents instance

Creates the events required for the captive ball

instance:          The name of the cvpmCaptiveBall object.

Example:

cbCaptive.CreateEvents “cbCaptive”

 

·        Method: .TrigHit ball

·        Method: .BallHit ball

·        Method: .BallReturn kicker

Called from the events of captive ball objects. All these event are automatically generated with the .CreateEvents method.

Example:

Sub CaptiveTrigger_Hit : cbCaptive.TrigHit ActiveBall : End Sub

Sub CaptiveTrigger_UnHit : cbCaptive.TrigHit 0 : End Sub

Sub CaptiveWall_Hit : cbCaptive.BallHit ActiveBall : End Sub

Sub Captive2_Hit : cbCaptive.BallReturn Me : End Sub

 

Class cvpmVLock

This class is used to create a ball lock where the balls are visible. The balls are kept in kickers and can be either be kicked out at the top (entrance) or be let out through the bottom.

The setup is a combination of kickers and triggers. One kicker is required for each ball that can enter the lock and each kicker must be covered by a trigger. A kicker has radius 25 so the trigger must have a radius of at least 26. The trigger/kicker pairs should be placed as closed to each other without overlapping but if the lock can release one ball at a time some distance between the trigger/kicker pairs might be needed for the timing.

 

·        Method: .InitLock triggers, kickers, switches

Initialises the visible lock.

triggers          Triggers for the lock from bottom to top

wall          Kickers for the lock matching the triggers

Switches          Switches activated at each lock position. If 0 or Nothing the switches will be fetched from the triggers TimerInterval property

Example:

Set Lock = New cvpmVLock

Lock.InitVLock Array(LTrig1,LTrig2,LTrig3),    Array(LKick1,LKick2,LKick3), Array(swLock1,swLock2,swLock3)

 

·        Method: .InitSnd ball, noBall

Initialises the sounds to play when exit solenoid is actiavted.

ball          Sound to play when at least one ball is in the lock

noBall          Sound to play when the lock is empty

Example:

Lock.InitSnd ”BallKick”, ”Solenoid”

 

·        Method: .CreateEvents instance

Creates all events for triggers and kickers required for the lock

Example:

              Single ball lock (stupid example)

Lock.InitVLock LTrigger, LKicker, swLock

Lock.CreateEvents ”Lock”

 

·        Method: .TrigHit ball, no

·        Method: .TrigUnHit ball,no

·        Method: .KickHit no

Called from the events of the lock triggers and kickers. All these event are automatically generated with the .CreateEvents method.

Example:

Sub LTrigger_Hit : Lock.TrigHit ActiveBall, 1 : End Sub

Sub LTrigger_UnHit : Lock.TrigUnHit ActiveBall, 1 : End Sub

Sub LKicker_Hit : Lock.KickHit 1 : End Sub

 

·        Property: .ExitDir = direction

·        Property: .ExitForce = force

·        Property: .KickForceVar = var

Specifies the kickout for the lock.

direction          Angle for kickout

force          Force of kickout. If 0 the balls will roll out the bottom (default)

var          Variation in kickout force

Example:

Lock.ExitDir = 10 ’ slightly to the right

Lock.ExitForce = 20

Lock.KickForceVar = 3 ‘ vary between 17-23

 

·        Property: .Balls

Number of balls currently in the lock (read-only)

Example:

   If Lock.Balls = 3 Then MsgBox “3 balls in lock”

 

·        Method: .SolExit enabled

Kicks balls out of lock. Can be specified as a solenoid handler.

Example:

SolCallback(sLockKickout) = “Lock.SolExit”

 

 

Class cvpmImpulseP

This class is used to replace the default VP plunger object in order to increase plunger resolution and allow more possible trajectories. It can function as both an autoplunger or a manual plunger.  It can be used with any visual representation you wish to provide including using the VP plunger object for the visible animation (do not allow it to actually touch the ball, though).  The plunger itself is a VP trigger covering the area where the plunger is to affect the ball.  Typically, that will be a normal 25 sized round trigger, but it can be reshaped for other effects (e.g. to provide a buffer zone for a kickback plunger in order to give VPM time to syncronize itself).  This trigger can also be defined to trip a switch when the ball rolls over it, thus elminating the need for a separate shooter lane type rollover switch.  Unlike the kicker-based plungers out there, this plunger object allows the ball to move freely as it sits in the plunger lane.

 

·        Method: .InitImpulseP trigger, strength, time

Initializes the magnet.

trigger:          Trigger used to simulate the impulse plunger

strength:          Plunger strength at maximum

time:          Total time for plunger to reach full strength (0 = AutoPlunger)

Example:

PlungerIM.InitImpulseP PlungerRight, 28, 0.6

 

·        Method: .CreateEvents instance

Creates the plunger events “Sub Plunger_Hit …”

instance:          The name of the cvpmImpulseP object.

Example:

PlungerIM.InitImpulseP PlungerRight, 28

PlungerIM.CreateEvents “PlungerRight”

 

·        Method: .AddBall ball

A ball has entered the plunger’s reach. Usually called from the plunger trigger’s hit event.

ball:          Ball object

Example:

Sub RightPlunger_Hit : PlungerIM.AddBall ActiveBall : End Sub

 

·        Method: .RemoveBall ball

A ball has left the plunger’s reach. Usually called from the plunger trigger’s unhit event.

ball:          Ball object

Example:

Sub RightPlunger_UnHit : PlungerIM.RemoveBall ActiveBall : End Sub

 

·        Method: .Pullback

Pull the plunger back.  Usually called from the VP script KeyDown sub

 

Example:

  Sub TableName_KeyUp(ByVal keycode)

    If keycode = PlungerKey Then

        Plunger.Pullback : PlungerIM.Pullback

    End If

  End Sub

Note: Plunger.Pullback activates VP’s regular plunger to syncronize an animation with the plunger object.  It would not appear if you provide your own animation.  PlungerIM.Pullback activates the Impulse Plunger.

 

·        Method: .Fire

Fire the plunger.  Usually called from the VP script KeyUP sub.

 

Example:

  Sub TableName_KeyDown(ByVal keycode)

    If keycode = PlungerKey Then

        Plunger.Fire : PlungerIM.Fire

    End If

  End Sub

Note: Plunger.Fire activates VP’s regular plunger to syncronize an animation with the plunger object.  It would not appear if you provide your own animation.  PlungerIM.Fire activates the Impulse Plunger.

 

·        Method: .AutoFire

Fire the plunger as an AutoPlunger.  Usually called from a VP solenoid callback sub.  Note that this method fires the plunger at the maximum strength instantly (it can also be done by providing a timing value of zero when initating the impulse plunger and using the regular fire function).  This basically makes it easy to combine a manual and AutoPlunger into one object for tables that combine them together.  You don’t have to adjust the timing to use the plunger as an autoplunger.

 

Example:

 

SolCallback(1)      = "AutoFire"                      ' Auto Plunger

 

  Sub AutoFire(enabled)

    If enabled Then PlungerIM.AutoFire

  End Sub

 

·        Method: .Random Value

Randomize the plunger strength by this multiplier value.  A value of 1 will provide a small amount of random variation in the plunger’s behavior.  A value of 0 will result in no variance at all.  Values between 0 and 1 will provide even smaller variances.  Values over 1 will multiply the random variance to much larger levels (i.e. 2 = 2x the variance of 1 whereas 0.5 would be ½ the variance of 1). 

 

Example:

 

IMPlunger.Random 1

 

·        Method: .Switch Value

If a value is specified using this call, that VPM switch will be activated when a ball rolls onto the trigger and deactivated when it rolls off.  This basically replaces the need for separate lane switch.  

 

Example:

 

IMPlunger.Switch 27

 

·        Method: .InitEntrySnd  sound

Specify the sound used when the entry solenoid is fired.

sound:                    sound to play as plunger is pulled back

Example:

PlungerIM.InitEntrySnd “PlungerPullSound”

 

 

·        Method: .InitExitSnd ballSound, sound

Specify the sound used when the entry solenoid is fired.

ballSound:          sound to play if a ball is present on the trigger (ball hit)

sound:                    sound to play if no ball is present on the trigger  (no  ball hit)

Example:

PlungerIM.InitExitSnd “BallHitSnd”, “PlungerSpringSound”

 

 

Complete example: Timer

Alternate two switches

Sub Test1(swNo)

   vpmTimer.PulseSwitch 1, 500, ”Test2”

End Sub

Sub Test2(swNo)

   vpmTimer.PulseSwitch 2, 500, ”Test1”

End Sub

Or (Advanced version)

Sub Test(newSw, lastSw)

   vpmTimer.PulseSwitch newSw,500,”Test “ & lastSw & “,”

End Sub

Open a message box after 5 seconds

‘ The last ‘ is to ignore the switch number added at the end

vpmTimer.AddTimer 5000,”MsgBox “”5 seconds””’”

 

Complete example: Stack (trough)

 

Dim bsTrough

Set bsTrough = New cvpmBallStack : With bsTrough

  .InitSw swOutHole,swTrough1,swTrough2,swTrough3,0,0,0,0

  .InitKick kickBallRelease,90,4

  .InitEntrySound “SolenoidOn”, “SolenoidOn”

  .InitExitSound “BallRelease”, “SolenoidOn”

  .Balls = 3

  .CreateEvents “bsTrough”, Outhole

End With

SolCallback(sOuthole)     = “bsTrough.SolIn”

SolCallback(sBallRelease) = “bsTrough.SolOut”

Complete example: Stack (Ball lock)

 

Dim bsLock

Set bsLock = New cvpmBallStack : With bsLock

  .InitSw 0,swLock1,swLock2,0,0,0,0,0

  .InitKick kickLock,90,4

  .InitExitSound “LockRelease”, “SolenoidOn”

  .KickBalls = 2

  .CreateEvents “bsLock”, Lock

End With

SolCallback(sLockRelease) = “bsLock.SolOut”

Complete example: Saucer

 

Dim bsHole

Set bsHole = New cvpmBallStack : With bsHole

  .InitSaucer holeKicker,swHole,180,8

  .InitForceVar = 2 ‘ force 6-10

  .InitAngleVar = 5 ‘ 175-185

  .InitExitSound “SolenoidOn”, “SolenoidOn”

  .CreateEvents “bsHole”, Hole

End With

SolCallback(sHoleKickout) = “bsHole.SolOut”

Complete example: VUK

 

Dim bsVUK

Set bsVUK = New cvpmBallStack : With bsVUK

  .InitSaucer topVUKKicker,swVUK,180,8

  .InitExitSound “VUKSound”, “SolenoidOn”

  .CreateEvents “bsVUK”, bottomVUKKicker

End With

SolCallback(sVUKKickout) = “bsVUK.SolOut”

Complete example: Drop target bank

 

Dim dtBank

Set dtBank = New cvpmDropTarget : With dtBank

   .InitDrop Array(Target1,Target2,Target3), Array(swTarget1,swTarget2,swTarget3)

  .InitSound “TargetDown”, “TargetUp”

  .CreateEvents “dtBank”

End With

SolCallback(sDropReset) = “dtBank.SolDropUp”

Complete example: Tilt handling

 

vpmNudge.TiltSwitch = swTilt

vpmNudge.Sensitivity = 5

vpmNudge.TiltObj = Array(Bumper1,Bumper2,Bumper3,LeftSling,RightSling)

SolCallback(sGameOn) = “VpmNudge.SolGameOn”

 

Complete example: Magnet

 

Dim mMagnaSave

Set mMagnaSave = New cvpmMagnet : With mMagnaSave

   .InitMagnet MagnaSave, 12

   .CreateEvents “mMagnaSave”

   .Solenoid = sMagnaSave

End With

 

Complete example: TurnTable

 

Dim ttSoccerBall

Set ttSoccerBall = New cvpmTurnTable : With ttSoccerBall

   .InitTurnTable SoccerBall, 50

   .CreateEvents “ttSoccerBall”

End With

 

SolCallback(sBallCW) = “ttSoccerBall.SolMotorState True,”

SolCallback(sBallCCW) = “ttSoccerBall.SolMotorState False,”

Complete example: Visible ball lock

Dim Lock

Set Lock = New cvpmVLock : With Lock

   .InitVLock Array(LockTrig1,LockTrig2),Array(LockKick1,LockKick2),0

   .InitSnd “Solenoid”, “Solenoid”

   .ExitForce = 20

   .CreateEvents “Lock”

End With

 

Generic Solenoid handlers

A set of generic functions that can be called directly from the solenoid handlers. All handlers can use arrays or collections except “vpmSolFlipper”, “vpmSolDiverter” and “vpmSolAutoPlunger”.

·        vpmSolFlipper flipper1, flipper2, enabled

“Flip” a flipper. Reduces speed on back stroke.

flipper1:          flipper object

flipper2:          second flipper object if more than one flipper is connected to the same solenoid handler

Example:

              1. Separate solenoid handlers for upper and lower flipper

SolCallback(sLLFlipper) = ”vpmSolFlipper LeftFlipper,Nothing,”

SolCallback(sULFlipper) = ”vpmSolFlipper ULeftFlipper,Nothing,”

              2. Same solenoid handler for upper and lower flipper

SolCallback(sLRFlipper) = ”vpmSolFlipper RightFlipper, URightFlipper,”

 

·        vpmSolDiverter diverter, sound, enabled

Move a diverter implemented with a flipper object

diverter:          “flipper” diverter to move

sound:          Sound to make, True for standard sound, False for no sound

Example:

SolCallback(sRampDiverter) = “vpmSolDiverter RampDiv,True,”

SolCallback(sRampDiverter) = “vpmSolDiverter RampDiv,””RampOpen””,”

 

 

·        vpmSolWall wall, sound, enabled

Raise or drop a wall(s). e.g. a diverter implemented as a wall.

wall:          Wall(s) to raise/Drop

sound:          Sound to make, True for standard sound, False for no sound

Example:

              1. Single wall

SolCallback(sDiverter) = “vpmSolWall diverterWall,True,”

‘ This does the same thing

SolCallback(sDiverter) = “diverterWall.IsDropped =”

              2. Multiple walls

SolCallback(sDiverter) = “vpmSolWall Array(w1, w2),””Diverter””,”

 

·        vpmSolToggleWall wall1, wall2, sound, enabled

Toggle between walls (raise one and drop another)

wall1:          Wall(s) to drop if enabled is True

wall2:          Wall(s) to drop if enabled is False

sound:          Sound to make, True for standard sound, False for no sound

Example:

SolCallback(sDiverter) = “vpmSolToggleWall Diverter,Array(div1,div2),False,”

 

·        vpmSolAutoPlunger plunger, variation, enabled

Plunge an automatic plunger or kickback

plunger:          plunger object

variation:          kick variation in % (i.e. 10 = ± 10%)

Example:

SolCallback(sKickBack) = ”vpmSolAutoPlunger kickback,10,”

 

·        vpmSolGate gate, sound, enabled

Open or close a one-way gate

gate:          gate object

sound:          Sound to make, True for standard sound, False for no sound

Example:

SolCallback(sGateOpen) = ”vpmSolGate gate,””GateOpen””,”

 

·        vpmSolSound sample, enabled

Play a sound when enabled is True

sample:          Sound to play

Example:

SolCallback(sBumper) = “vpmSolSound “”Bumper””,”

 

·        vpmFlasher flasher, enabled

Light flasher(s)

flasher:          flasher object to light

Example:

              1. Single flasher

SolCallback(sFlasher1) = “vpmFlasher Flasher1,”

              2. Multiple flashers

SolCallback(sFlasher1) = “vpmFlasher Array(Flash1,Flash2),”

 

·        vpmSolToggleObj obj1, obj2, sound, enabled

This is the big one! It will toggle almost any objects (Wall, Bumper, Light, Kicker, Trigger,Timer,Gate,Switch)

obj1:          Object(s) to drop/enable/light if enabled is True

obj2:          Object(s) to drop/enable/light if enabled is False

sound:          Sound to make, True for standard sound, False for no sound

Objects are handled as:

Wall:          Drop/Raise

Bumper          Light/Unlight

Light          Light/Unlight

Kicker          Enable/Disable

Trigger          Enabled/Disable

Timer          Enabled/Disabled

Gate          Open/Close

Switch          Activate/Deactivate

 

Example:

              1. Drop Wall1 and light Flasher3 on flasher solenoid

SolCallback(sFlasher) = “vpmSolToggleObj Array(Wall1,Flasher3),Nothing,False,”

              2. Enable kicker1, kicker2, set switch 14 and raise Wall3

Sub Trigger_Hit

   VpmSolToggleObj Array(kicker1,kicker2,14),Wall3,”Noise”,True

End Sub

              3. All objects in one variable

objects = Array(Array(kicker1,kicker2,14),Array(Wall3))

vpmSolToggleObj objects,Nothing,False,True

Misc functions

·        vpmKeyUp(keyCode)

·        vpmKeyDown(keyCode)

Handles all general keys except the plunger. Returns True if the key was handled

Example:

              1. Manual Plunger

Sub Table_KeyUp(ByVal keycode)

   If vpmKeyUp(keycode) Then Exit Sub

   If keycode = PlungerKey Then Plunger.Fire

End Sub

Sub Table_KeyDown(ByVal keycode)

   If vpmKeyDown(keycode) Then Exit Sub

   If keycode = PlungerKey Then Plunger.Pullback

End Sub

              2. Automatic Plunger

Sub Table_KeyUp(ByVal keycode)

   If vpmKeyUp(keycode) Then Exit Sub

   If keycode = PlungerKey Then Controller.Switch(swPlunger) = False

End Sub

Sub Table_KeyDown(ByVal keycode)

   If vpmKeyDown(keycode) Then Exit Sub

   If keycode = PlungerKey Then Controller.Switch(swPlunger) = True

End Sub

·        vpmKeyName(keyCode)

Convert a keycode to a readable name of the key

Example:

MsgBox “key 5 = “ & vpmKeyName(5)

ExtraKeyHelp = vpmKeyName(keyBuyIn) & vbTab & “Buy In button”

 

·        vpmShowHelp

Display a window showing all keys defined for the game

Example:

VpmShowHelp

 

·        vpmMoveBall ball, fromKick, toKick

Moves a ball from a kicker to another preserving colour and image properties

Example:

Sub TeleportKick_Hit : vpmMoveBall ActiveBall, Me, TeleportEndKick : End Sub

Constants used

The following constants must be used for the *.VBS files to work properly.

·        UseSolenoids = True/False

Set to True to enable Solenoid callbacks via the SolCallback() variable

 

·        UseLamps = True/False

Set to True to enable Lamp updating. Lamps must be defined in Lights() variable. If UseLamps is set to false the “LampCallback” will be called on each update allowing a custom lamp handler.

 

·        SSolenoidOn, SSolenoidOff, SFlipperOn, SFlipperOff, SCoin

Standard sounds used by *:VBS files

SSolenoidOn/SSolenoidOff:Solenoid activated/deactivated.

Used in vpmSolDiverter, vpmSolWall, vpmSolToggleWall, vpmSolAutoPlunger.

SflipperOn/SflipperOff: Flipper activated/deactivated

Used in vpmSolFlipper

SCoin: Coin inserted

 

·        vpmMultiLights()

An array of lights that are updated together. The second, third… light is set to the same state as the first.

ReDim vpmMultiLights(2)

vpmMultiLights(0) = Array(Lamp22, Lamp22a, Lamp22b)

vpmMultiLights(1) = Array(Lamp23, Lamp23a)

vpmMultiLights(2) = Array(Lamp24, Lamp24a)

 

 

·        LampCallback

Function to call when at least one Lamp has changed state. Main purpose is to handle cases where more than one lamp is connected to a single output (UseLamps = True) or to implment a custom lamp handler (UseLamps = False).

 

Example;

              1. Two lamps connected to the same wire.

UseLamps = True

Set LampCallback = GetRef(“UpdateLamps”)

Sub UpdateLamps

   Lamp22a.State = Lamp22.State

End Sub

              2. A custom lamp handler is required to handle blending of two lights

UseLamps = False

Set LampCallback = GetRef(“MyLampHandler”)

Sub MyLampHandler

   Dim chgLamp, ii

   ChgLamp = Controller.ChangedLamps

   If IsEmpty(ChgLamp) Then Exit Sub

   On Error Resume Next

   For ii = 0 To UBound(ChgLamp)

      ‘Light 1 is red, light 2 is yellow

      ‘If both are lit light an orange light (65)

      If ChgLamp(ii, CHGNO) = 1 Or ChgLamp(ii, CHGNO) = 2 Then

         With Controller

            Lights(65).State = .Lamp(1) And .Lamp(2)

            Lights(1).State = .Lamp(1)

            Lights(2).State = .Lamp(2)

         End With

      Else

         VpmDoLights ChgLamp(ii, CHGNO), ChgLamp(ii, CHGSTATE)

      End If

   Next

   On Error Goto 0

End Sub

 

·        GICallback

Function to update GI lamps. Only WPC games have special GI circuit

Callback function must take two arguments

StringNo:          GIString that has changed state (0-4)

Status:          New status of GI string

Example:

Set GICallback = GetRef(“UpdateGI”)

Sub GICallback(giNo, status)

   Select Case giNo

      Case 0   GI0.State = Abs(status)

      Case 1   GI1.State = Abs(status)

 

·        MotorCallback

Function called after every update of solenoids and lamps (i.e. as often as possible). Main purpose is to update table based on playfield motors.

It can also be used to override the standard solenoid callback handler. One reason is to handle multiplexed solenoids.

Note that this function may be called hundred of times per second. Keep it quick!

Example:

              1. Motor Update

Set MotorCallback = GetRef(“UpdateGun”)

Sub HandleGunMotor

  Dim newGunPos

  If Controller.Solenoid(sGunMotor) Then

              2. Multiplexed solenoid handling. (Solenoid 11 multiplexes solenoid 1-10)

UseSolenoids = False

Set MotorCallback = GetRef(“UpdateSolenoids”)

Sub UpdateSolenoids

   Dim Changed, Count, funcName, ii, sol11, solNo

   Changed = Controller.ChangedSolenoids

   If Not IsEmpty(Changed) Then

      sol11 = Controller.Solenoid(11)

      Count = UBound(Changed, 1)

      For ii = 0 To Count

         solNo = Changed(ii, CHGNO)

         If SolNo < 11 And sol11 Then solNo = solNo + 32

         vpmDoSolCallback solNo, Changed(ii, CHGSTATE)

      Next

   End If

End Sub

 

Full Table Example: BadCats

This example is taken from the BadCats table. Shows table with drop targets and kickouts. The constant declarations for switches and solenoids and the lamparray initialisation has been left out.

LoadVPM "00990400", "S11.VBS", 2.0

Const cGameName = "bcats_l5" ' PinMAME short game name

Const UseSolenoids    = True

Const UseLamps        = True

'Standard sound

Const SSolenoidOn   = "SolOn"  'Solenoid activates

Const SSolenoidOff  = "" 'Solenoid deactivates

Const SFlipperOn    = "FlipperUp"   'Flipper activated

Const SFlipperOff   = "FlipperDown" 'Flipper deactivated

Const SCoin         = "Quarter"   'Coin inserted

'Callbacks

Set LampCallback      = GetRef("UpdateMultipleLamps")

 

Sub LoadVPM(VPMver, VBSfile, VBSver)

   On Error Resume Next

      If ScriptEngineMajorVersion < 5 Then MsgBox "VB Script Engine 5.0 or higher required"

      ExecuteGlobal GetTextFile(VBSfile, 1).ReadAll

      If Err Then MsgBox "Unable to open " & VBSfile & ". Ensure that it is in the same folder as this table. " & vbNewLine & Err.Description

      Set Controller = CreateObject("VPinMAME.Controller")

      If Err Then MsgBox "Can't Load VPinMAME." & vbNewLine & Err.Description : Err.Clear

      If VPMver > "" Then If Controller.Version < VPMver Or Err Then MsgBox "VPinMAME ver " & VPMver & " required." : Err.Clear

      If VPinMAMEDriverVer < VBSver Or Err Then MsgBox VBSFile & " ver " & VBSver & " or higher required."

   On Error Goto 0

End Sub

 

Sub Badcats_KeyDown(ByVal keycode)

   If vpmKeyDown(keycode) Then Exit Sub

   If keycode = PlungerKey Then Plunger.Pullback

End Sub

Sub Badcats_KeyUp(ByVal keycode)

   If vpmKeyUp(keycode) Then Exit Sub

   If keycode = PlungerKey Then Plunger.Fire

End Sub

 

Const cCredits  = "Williams(R) Badcats(TM)”

Dim bsTrough,dtMilk,bsDogHouse,bsTrashCan,dtBird

Sub Badcats_Init

   VpmInit Me

   On Error Resume Next

   With Controller

      .GameName = cGameName

      If Err Then MsgBox "Can't start Game" & cGameName & vbNewLine & Err.Description : Exit Sub

      .SplashInfoLine = cCredits

      .HandleMechanics = 0

      .ShowDMDOnly = True : .ShowFrame = False : .ShowTitle = False

      .SetDisplayPosition 0,0,GetPlayerHWnd

      .Run

      If Err Then MsgBox Err.Description

   End With

   On Error Goto 0

   ' Nudging

   vpmNudge.TiltSwitch = swTilt

   vpmNudge.Sensitivity = 5

   vpmNudge.TiltObj = Array(Bumper1,Bumper2,Bumper3,LeftslingShot,RightslingShot)

   ' Ballstacks

   Set bsTrough = New cvpmBallStack : With bsTrough

      .InitNoTrough BallRelease,10,160,4 ‘ Single ball game

      .InitExitSnd "BallRelease","SolOn"

      .CreateEvents “bsTrough”,OutHole

   End With

   SolCallback(sBallRelease) = "bsTrough.SolOut"

   ' Milk targets

   Set dtMilk = New cvpmDropTarget : With dtMilk

      .InitDrop Array(Milk1,Milk2,Milk3),Array(37,38,39)

      .InitSnd "DropDown","DropUp"

      .CreateEvents “dtMilk”

   End With

   SolCallback(sMilkBank) = "dtMilk.SolDropUp"

   ' Doghouse

   Set bsDogHouse = New cvpmBallStack : With bsDogHouse

      .InitSaucer doghousekicker,22,180,20

      .InitExitSnd "BallRelease","SolOn"

      .CreateEvents “bsDogHouse”, DogHouseKicker

   End With

   SolCallback(sDogHouse) = "bsDogHouse.SolOut"

   ' TrashCan

   Set bsTrashCan = New cvpmBallStack : With bsTrashCan

      .InitSaucer TrashCan,24,95,15

      .InitExitSnd "BallRelease","SolOn"

      .CreateEvents “bsTrashCan”, TrashCan

   End With

   SolCallback(sGarbageCan) = "bsTrashCan.SolOut"

   ' Birdie targets

   Set dtBird = New cvpmDropTarget : With dtBird

                .InitDrop Array(Birdie1,Birdie2,Birdie3,Birdie4,Birdie5),_ Array(25,26,27,28,29)

      .InitSnd "DropDown","DropUp"

      .CreateEvents “dtBird”

   End With

   SolCallback(sBirdBank) = "dtBird.SolDropUp"

   ' You can't set the bumper state to on in VP editor

   Bumper1.State = LightStateOn

   Bumper2.State = LightStateOn

   Bumper3.State = LightStateOn

End Sub

 

SolCallback(sKnocker)     = "vpmSolSound ""Knocker"","

SolCallback(sTLJet)       = "vpmSolSound ""Bumper"","

SolCallback(sLSling)      = "vpmSolSound ""Sling"","

SolCallback(sTRJet)       = "vpmSolSound ""Bumper"","

SolCallback(sRSling)      = "vpmSolSound ""Sling"","

SolCallback(sBJet)        = "vpmSolSound ""Bumper"","

SolCallback(sLRFlipper)   = "vpmSolFlipper RightFlipper,Nothing,"

SolCallback(sLLFlipper)   = "vpmSolFlipper LeftFlipper,Nothing,"

SolCallback(sGameOn)      = "vpmNudge.SolGameOn"

 

 

' Slow down balls on ramp

Sub kicker3_hit : Me.kick 180,1 : End sub

Sub kicker4_hit : Me.kick 180,1 : End Sub

 

'SWITCH HANDLING

Sub TriggerO_Hit : Controller.Switch(12) = True : End Sub

Sub TriggerO_UnHit : Controller.Switch(12) = False : End Sub

Sub TriggerT_Hit : Controller.Switch(11) = True : End Sub

Sub TriggerT_UnHit : Controller.Switch(11) = False : End Sub

Sub TriggerY_Hit : Controller.Switch(13) = True : End Sub

Sub TriggerY_UnHit : Controller.Switch(13) = False : End Sub

Sub Shooter_Hit : Controller.Switch(14) = True : End Sub

Sub Shooter_UnHit : Controller.Switch(14) = False : End Sub

Sub FishBowlEntrance_Hit : Controller.Switch(16) = True : End Sub

Sub FishBowlEntrance_UnHit : Controller.Switch(16) = False : End Sub

Sub FishBowlScore_Hit : Controller.Switch(43) = True : End Sub

Sub FishBowlScore_UnHit : Controller.Switch(43) = False : End Sub

Sub TigerEntrance_Hit : Controller.Switch(23) = True : End Sub

Sub TigerEntrance_UnHit : Controller.Switch(23) = False : End Sub

Sub TigerScore_Hit : Controller.Switch(41) = True : End Sub

Sub TigerScore_UnHit : Controller.Switch(41) = False : End Sub

Sub BoneUs1_Hit : Controller.Switch(19) = True : End Sub

Sub BoneUs1_UnHit : Controller.Switch(19) = False : End Sub

Sub LeftOutlane_Hit : Controller.Switch(35) = True : End Sub

Sub LeftOutlane_UnHit : Controller.Switch(35) = False : End Sub

Sub LeftInlane_Hit : Controller.Switch(30) = True : End Sub

Sub LeftInlane_UnHit : Controller.Switch(30) = False : End Sub

Sub RightInlane_Hit : Controller.Switch(31) = True : End Sub

Sub RightInlane_UnHit : Controller.Switch(31) = False : End Sub

Sub RightOutlane_Hit : Controller.Switch(36) = True : End Sub

Sub RightOutlane_UnHit : Controller.Switch(36) = False : End Sub

' Bumpers/Slingshots

Sub Bumper1_Hit : vpmTimer.PulseSw 60 : End Sub

Sub Bumper2_Hit : vpmTimer.PulseSw 61 : End Sub

Sub Bumper3_Hit : vpmTimer.PulseSw 62 : End Sub

Sub RightSlingshot_Slingshot : vpmTimer.PulseSw 64 : End Sub

Sub LeftSlingshot_Slingshot : vpmTimer.PulseSw 63 : End Sub

' Rubbers

Sub Wall1_Slingshot : vpmTimer.PulseSw 34 : End Sub

Sub OuterWall_Slingshot : vpmTimer.PulseSw 40 : End Sub

Sub Wall6_Slingshot : vpmTimer.PulseSw 33 : End Sub

 

Full Table Example: Mr. & Mrs. PacMan

This example is taken from the Mr. MrsBadCats table. Shows table with custom solenoid and lamp handler, solenoid controlled drop targets and saucer with two kickout directions.

The constant declarations for switches and solenoids and the lamp array initialisation has been left out.

 

Option Explicit

LoadVPM "00990400", "Bally.VBS", 2.0

 

Const cGameName     = "m_mpac"   ' PinMAME short name

Const UseSolenoids  = False ‘ Using motorcallback for custom handler

Const UseLamps      = False ‘ Using lampcallback for custom handler

Set LampCallback = GetRef("UpdateLamps")

Set MotorCallback = GetRef("UpdateSolenoids")

' Standard Sounds

Const SSolenoidOn   = ""

Const SSolenoidOff  = ""

Const SFlipperOn    = "FlipperUp"

Const SFlipperOff   = "FlipperDown"

Const SCoin         = "Coin"

 

SolCallback(sKnocker)     = "vpmSolSound ""Knocker"","

SolCallback(sLSling)      = "vpmSolSound ""SlingShot"","

SolCallback(sRSling)      = "vpmSolSound ""SlingShot"","

SolCallback(sLJet)        = "vpmSolSound ""Bumper"","

SolCallback(sRJet)        = "vpmSolSound ""Bumper"","

SolCallback(sEnable)      = "vpmNudge.SolGameOn"

SolCallback(sGate)        = "vpmSolDiverter SaveGate,""Gate"","

SolCallback(sLLFlipper)   = "vpmSolFlipper LeftFlipper, Nothing,"

SolCallback(sLRFlipper)   = "vpmSolFlipper RightFlipper, UpperFlipper,"

 

Dim bsTrough, dtLDrop, dt3Drop, dtRDrop, bsPacMan,bsEject,Matrix(128)

 

Sub MrMsPacMan_Init

   vpmInit Me

   With Controller

      .GameName = cGameName

      .SplashInfoLine = cCredits

      .ShowTitle = False : .ShowDMDOnly = True : .ShowTitle = False

      On Error Resume Next

         .Run

         If Err Then MsgBox Err.Description

      On Error Goto 0

   End With

   ' Nudging

   vpmNudge.TiltSwitch = 15

   vpmNudge.Sensitivity = 4

   vpmNudge.TiltObj = Array(Bumper1,Bumper2,LeftSlingshot,RightSlingShot)

   Set dtLDrop = New cvpmDropTarget : With dtLDrop

      .InitDrop Array(Wall13,Wall16,Wall15,Wall14), Array(1,2,3,4)

      .InitSnd "DropTarget","TargetReset"

      .CreateEvents “dtLDrop”

   End With

   SolCallback(sTargetResetL)= "dtLDrop.SolDropUp"

   SolCallback(sLReset1)     = "dtLDrop.SolHit 1,"

   SolCallback(sLReset2)     = "dtLDrop.SolHit 2,"

   SolCallback(sLReset3)     = "dtLDrop.SolHit 3,"

   SolCallback(sLReset4)     = "dtLDrop.SolHit 4,"

   Set dtRDrop = New cvpmDropTarget : With dtRDrop

      .InitDrop Array(Wall17,Wall20,Wall19,Wall18),_ Array(25,26,27,28)

      .InitSnd "DropTarget","TargetReset"

      .CreateEvents “dtRDrop”

   End With

   SolCallback(sTargetResetR)= "dtRDrop.SolDropUp"

   SolCallback(sRReset1)     = "dtRDrop.SolHit 1,"

   SolCallback(sRReset2)     = "dtRDrop.SolHit 2,"

   SolCallback(sRReset3)     = "dtRDrop.SolHit 3,"

   SolCallback(sRReset4)     = "dtRDrop.SolHit 4,"

   Set dt3Drop = New cvpmDropTarget : With dt3Drop

      .InitDrop Array(Wall10,Wall12,Wall11),Array(22,23,24)

      .InitSnd "DropTarget","TargetReset"

      .CreateEvents “dt3Drop”

   End With

   SolCallback(sTargetReset3)= "dt3Drop.SolDropUp"

   ' Trough (or really just an outhole)

   Set bsTrough = New cvpmBallStack : With bsTrough

      .InitNoTrough Feed,5,90,2

      .CreateEvents “bsTrough”, Drain

   End With

   SolCallback(sBallRelease) = "bsTrough.SolOut"

   Set bsPacMan = New cvpmBallStack : With bsPacMan

      .InitSaucer PacManSaucer,8,170,5

      .InitExitSnd "Saucer","Saucer"

      .CreateEvents ”bsPacMan”,0

   End With

   SolCallback(sRSaucer)     = "bsPacMan.SolOut"

   Set bsEject = New cvpmBallStack : With bsEject

      .initSaucer EjectHole,7,260,10 'Default down

      .InitAltKick 80,10

      .InitExitSnd "Saucer","Saucer"

      .CreateEvents ”bsEject”,0

   End With

   SolCallback(sLSaucerL)    = "bsEject.SolOut"

   SolCallback(sLSaucerR)    = "bsEject.SolOutAlt"

End Sub

 

Sub MrMsPacMan_KeyUp(ByVal keycode)

   If vpmKeyUp(keycode) Then Exit Sub

   If keycode = PlungerKey Then PlaySound "Plunger" : Plunger.Fire

End Sub

 

Sub MrMsPacMan_KeyDown(ByVal keycode)

   If vpmKeyDown(keycode) Then Exit Sub

   If keycode = PlungerKey Then Plunger.Pullback

End Sub

 

‘ Lamp 87 is used to mux solenoids 9-16. remap them to 32-

Sub UpdateSolenoids

   Dim Changed, Count, funcName, ii, sel, solNo

   Changed = Controller.ChangedSolenoids

   If Not IsEmpty(Changed) Then

      sel = Controller.Lamp(87)

      Count = UBound(Changed, 1)

      For ii = 0 To Count

         solNo = Changed(ii, CHGNO)

         If SolNo >= 9 And SolNo <= 15 And sel Then solNo = solNo + 24

         funcName = SolCallback(solNo)

         If funcName <> "" Then Execute funcName & " CBool(" & Changed(ii, CHGSTATE) &")"

      Next

   End If

End Sub

‘ Handle blending in matrix

Sub UpdateLamps

   dim ii, Lamp1, Lamp2, stat1, stat2, chgLamp

   ChgLamp = Controller.ChangedLamps

   If IsEmpty(ChgLamp) Then Exit Sub

   On Error Resume Next

   For ii = 0 To UBound(ChgLamp)

      Lights(ChgLamp(ii, CHGNO)).State = ChgLamp(ii, CHGSTATE)

   Next

   On Error Goto 0

   Light8a.state = Light8.state

   Light9a.state = Light9.state

   Light10a.state = Light10.state

   Light25a.state = Light25.state

   Light41a.state = Light41.state

   Light42a.state = Light42.state

   Light57a.state = Light57.state

   Light71a.state = Light71.state

   For ii = 0 To UBound(ChgLamp)

      If IsObject(Matrix(ChgLamp(ii,CHGNO))) Then

         lamp1 = chgLamp(ii, CHGNO) And 63 : stat1 = Controller.Lamp(lamp1)

         lamp2 = lamp1 + 64 : stat2 = Controller.Lamp(lamp2)

         Matrix(lamp2+8).State = Abs(stat1 And stat2)

         If stat2 Then

            If Not stat1 Then Matrix(lamp1).state = 0 : Matrix(lamp2).state = 1

         Else

            Matrix(lamp2).state = 0 : Matrix(lamp1).state = 1

            If Not stat1 Then Matrix(lamp1).state = 0

         End If

      End If

   Next

End Sub

 

‘ Targets

Sub Wall22_Hit : vpmTimer.PulseSw 34 : End Sub

Sub Wall24_Hit : vpmTimer.PulseSw 35 : End Sub

Sub Wall23_Hit : vpmTimer.PulseSw 36 : End Sub

Sub Wall25_Hit : vpmTimer.PulseSw 38 : End Sub

Sub Wall27_Hit : vpmTimer.PulseSw 39 : End Sub

Sub Wall26_Hit : vpmTimer.PulseSw 40 : End Sub

Sub OuterWall_Slingshot : vpmTimer.PulseSw 29 : End Sub

 ‘ Triggers

Sub LeftInlane_Hit     : Controller.Switch(12) = True  : End Sub

Sub LeftInlane_UnHit   : Controller.Switch(12) = False : End Sub

Sub RightOutlane_Hit   : Controller.Switch(12) = True  : End Sub

Sub RightOutlane_UnHit : Controller.Switch(12) = False : End Sub

Sub RightInlane_Hit    : Controller.Switch(13) = True  : End Sub

Sub RightInlane_UnHit  : Controller.Switch(13) = False : End Sub

Sub LeftOutlane_Hit    : Controller.Switch(14) = True  : End Sub

Sub LeftOutlane_UnHit  : Controller.Switch(14) = False : End Sub

Sub Trigger1_Hit       : Controller.Switch(21) = True  : End Sub

Sub Trigger1_UnHit     : Controller.Switch(21) = False : End Sub

‘ Bumpers/Slingshots etc

Sub Bumper2_Hit : vpmTimer.PulseSw 17 : End Sub

Sub Bumper1_Hit : vpmTimer.PulseSw 18 : End Sub

Sub LeftSlingshot_Slingshot  : vpmTimer.PulseSw 19 : End Sub

Sub RightSlingshot_Slingshot : vpmTimer.PulseSw 20 : End Sub

Sub Spinner1_Spin : vpmTimer.PulseSw 30 : End Sub

Sub Spinner2_Spin : vpmTimer.PulseSw 30 : End Sub

 

Simplifying the script

If you want to minimize the coding required for a table there are several functions in the vbs files that can be used.

Using the functions described below is not necessary but they will simplify many tasks and they also eliminate many common errors such as misspelled and missing events. They also move a lot of work from the script to the Visual Pinball editor. Playfield objects such as lamps and triggers can be added/deleted/renamed in the editor without the need to change the script.

 

Note that bumpers can only be mapped automatically for lights or switches (unless they have the same switch and lamp number).

Automatic light mapping

All lights (and bumpers) on the playfield can be automatically mapped to the VPinMAME output.

  1. Put the lamp number for each playfield lamp in the “TimerInterval” field. Several lamps can have the same number.
  2. Put all lamps into a collection (e.g. a collection named “AllLamps”)
  3. Put the following line in the script

vpmMapLights AllLamps

Automatic switches

Almost all switches can be automatically mapped to VPinMAME. It works a bit different depending on the type of switch.

Bumpers, Triggers, Spinners, Targets (not Drop Targets), Gates and Slingshots

  1. Put the switch number of each object in the “TimerInterval” field. Several objects can have the same switch number
  2. Put all objects into all collection (e.g. “AllSwitches”)
  3. Put the following line in the script

vpmCreateEvents AllSwitches

Drop Targets

Normally a drop target consists of a single wall object but sometimes it is necessary to build it from several wall objects. Unfortunatly Visual Pinball can’t create collections of collections so if multiple walls are used for each drop target the implementation will be slight different.

Drop targets using the “SlingShot” event can’t be handled this way.

 

Simple case: A single wall per drop target.

  1. Put the switch number for the drop target in the “TimerInterval” field.
  2. Create a collection of all drop targets in the same bank (e.g. “LeftBank”)
  3. Use the cvpmDropTarget class for the handling

dtLeft = New cvpmDropTarget

dtLeft.InitDrop LeftBank,0

deLeft.CreateEvents “dtLeft”

  1. Don’t forget the solenoid handler for raising the drop targets.

 

Advanced case: Multiple walls per drop target

  1. Put the switch number for the drop target in the “TimerInterval” field. Several wall objects can have the same switch number. Make sure that wall objects not used doesn’t have the “Has hit event” checked.
  2. Create a collection for each drop target (e.g. “LeftBank1”, “LeftBank2”)
  3. Use the cvpmDropTarget class for the handling

dtLeft = New cvpmDropTarget

dtLeft.InitDrop Array(LeftBank1,LeftBank2,LeftBank3),0

deLeft.CreateEvents “dtLeft”

Magnets, TurnTables, Captive Balls and Visible locks

The events for magnets, turntables, captive balls and visible locks are very simple but they can also be generated automatically with the .CreateEvents method.

mMagnaSave = New cvpmMagnet

mMagnaSave.initMagnet magnetTrigger,10

mMagnaSave.Solenoid = sMagnaSave

mmagnaSave.CreateEvents “mMagnaSave”

Solenoid Handlers

The vbs files contains predefined functions for almost all playfield objects controlled by solenoids. There is no need to have more than one or two custom solenoid handler on a normal table. A few points to remember:

Multiple Objects

Almost all solenoid handlers can work with multiple objects. The objects can be specified using both arrays and collections.

“VpmFlasher Array(flasher1,flasher2,flasher3),”

Generic Function

There is very powerful function that can handle almost any object “vpmSolToggleObj”. The function takes two arguments where the first is an array (or collection) of objects to turn on/enable etc and the second argument is objects to turn off/disable etc. The objects can be mixed in any way.

 

Object                  On Action    Off Action

Wall                     Drop                            Raise

Bumper                Light on                         Light off

Light                     Light on                         Light off

Kicker                  Enable                           Disable

Trigger                  Enable                           Disable

Timer                    Enable                           Disable

Gate                     Open                            Close

Switch Number              Activate                          Deactivate

 

This means that a single function call can drop 2 walls, turn off a light, light up a bumper, disable a kicker and activate a switch.

VpmToggleObj Array(Wall1,Wall2,Bumper1,32),Array(Light1,Kicker1),True

Or

AllObj = Array(Array(Wall1,Wall2,Bumper1,32),Array(Light1,Kicker1))

VpmToggleObj AllObj,Nothing,True