Visual PinMAME Scripting 104 - Mechanics Handlers (TOYS! Part 1 of 3)
--------------------------------------------------------------
Most later model games have custom playfield objects which are motorized or unique for that specific game.
These are playfield toys. Like everything else, they can range from simplistic to ludicrously complex.
A lot of thought goes into these devices. You have a few different classifications available.
Is it for show only - such as the pole dancers in Sopranos?
Must it be synchronized to audio like the talking fish?
How much of the object is designed to move - the eyes, mouth, and eyebrows of rudy?
Does it eat the ball, interact with some ball lock or subway system, entirely rotate like the Judge Dredd Dead World?
Does it pick up the ball and allow full player control like the Johnny Mneumonic glove?
Generally, the more complex the toy is, the more attractive a machine can be to draw in a casual player.
However, the more complex the toy is, the higher the chance will be of a mechanical problem, and it could be quite difficult to repair.
As usual, this tutorial will not cover every available toy that has ever been created. The purpose of this tutorial is simply
to ease the frustration resulting from attempts to get a toy working for a pinball simulation using Visual PinMAME and Visual
Pinball. You will quickly discover that making a toy in VP, without a romset, is a whole lot easier than having to satisfy a romset and
prewritten game logic.
The absolute first thing to do when recreating a table that has a playfield toy, is to see if it has been correctly emulated before.
If it has been done correctly before you can save a lot of time by using the proven method. There is no reason to reinvent the wheel
and possibly screw it up in the process. Most playfield toys can ONLY WORK ONE WAY when there is a romset involved. As for the
visual presentation and animation, feel free to handle that however you like, but as far as scripting and methods go, if you make
changes to how it operates, it could fail during a game, under specific conditions, or entirely provide inaccurate results.
A broken toy could be a game breaking problem, and will cost you, or someone else, a lot of time trying to fix it.
With Visual Pinball, you have THREE ( 3 ) options to choose from when deciding to implement simulation of a playfield toy device.
Choice 1 - Use a built-in, precoded mechanics handler that is already available in the Visual PinMAME DLL file
Choice 2 - Create a custom mechanics handler in the script yourself
Choice 3 - Use standard visual basic code with timers or other methods to get the toy 'working'
If you go with Choice 2 - the custom mechanics handler, then whenever you make changes to the scripted toy it is a good idea to
delete the nvram file before testing your new changes. This way the old settings will not interfere with the current ones in use.
I'll go over that a little bit better later in this tutorial.
OK, so to start I'll cover choice 1 - prebuilt 'internal' mechanics handlers. They are internal because to change them you would
need to recompile Visual PinMAME. And in order for your table to work the same on everyone's computer, you would need to ensure
that they have the same DLL you used. Usually this is not a problem as most of the internal mechanics handlers are correct already.
If one is in fact, not correct, you can either fix it in the source code and submit it to the SVN repository to correct it for
everyone in a newer release of Visual PinMAME, or you can not use it and make adjustments to your custom scripted mech handler, or use
choice 3 - standard visual basic code with timers or other methods.
Before there was Visual PinMAME, back when there was simply WPCMAME to emulate games with, the original PinMAME dev team created what
they called "Simulators" for PinMAME. This allowed anyone to insert coins, toggle switch contacts, and see playfield 'lights' and
DMD animations, and hear the sounds of a game by pressing key combinations on the keyboard. In effect, simulators allow you to
'play' a game without using a visual pinball table or external software. The simulators are still included in every version of
PinMAME as well as Visual PinMAME. For Visual PinMAME, load a table and change the "ShowDMDOnly=" line to FALSE and then run the
table. Games that have internal simulators will have some keys listed. To use a simulator with Visual PinMAME, change the
"HandleKeyboard=" line to TRUE. This way any keys you press will be picked up by the Visual PinMAME window.
It is most common to have simulators available for WPC games - as they were the first games to be emulated in PinMAME. There are also
a few simulators done for other game platforms - such as the mini flipper for Stern's Monopoly. You can see which games have simulators
by looking at the source code for Visual PinMAME here:
http://pinmame.svn.s...k/src/wpc/sims/
For our current purposes, click on the link for "wpc". You will see two folders - one is called "full" and one is called "prelim".
For the most part, "full" is nearly entirely playable in the simulator. "Prelim" only has a few options. Click on "full".
Now click on "ij.c" - this is the wpc driver and simulator for Williams' Indiana Jones. Next click on Revision 1824's VIEW link.
This will give you the file on the screen with line numbers.
Most internal mechanics handlers are located at the end of the file - so scroll down to line number 720 and you'll see "handlemech".
This is the section we are concerned with.
if ((mech & 0x01) && core_getSol(sCenterDropUp))
This means the internal mech handler #1 is the center drop target bank
Mech #2 is the Totem Drop Target which goes up and down
Mech #4 is the tilting Path of Adventure
Mech #8 is the rotating Idol toy
To use these internal mechanics handlers in your script, you need to add this code to table_init:
Why 15? Because 1+2+4+8=15
If you just wanted to use the internal handlers for the Path of Adventure and the Idol then it would be 12.
Now, this is where it becomes a little confusing, so please try to pay attention. What the internal mechanics handlers do is they
handle the switches, monitor solenoids, and provide some kind of feedback to the table script or display to make the game think the
toy is real, and that it is operating correctly. By closing/opening switch contacts at the appropriate times, the game is fooled
into thinking everything is working as designed. There isn't a way to 'push' data to visual pinball through Visual PinMAME, so to
use the internal mechanics handlers, you must have something to query the status for you at regular intervals. This can be done
with an enabled timer object, or one of the standard callback routines: MotorCallback, LampCallback, or GICallback.
GICallback is only called when the General Illumination level changes on the table - which shouldn't be used for this as the toy will
usually change state without the GI changing. LampCallback is updated 60 times per second ( 60hz ) and is only called when a lamp state
changes. MotorCallback is called every time a solenoid and/or lamp changes, so MotorCallback is both reliable and efficient.
Usually, for playfield toys, I prefer using MotorCallback, or using standard VP timer objects.
In the script to add MotorCallback, you would add this line.
Set MotorCallback=GetRef("UpdateToys")
While you can use both methods, a callback and a timer, using both will not have a significant improvement in the speed of execution.
Pick one or the other for ease of debugging.
For a timer, you want it to be set to 1ms and enabled so it is called as fast as possible.
For even faster updates, you can add an enabled timer object to the table called vpmFastTimer with an interval of 1. This will have an
extreme impact on custom scripted mech handlers.
In our MotorCallback example, you will be using similar code to the following:
Dim OldIdolPos,CurIdolPos
OldPOAPos=0
OldIdolPos=0
Sub UpdateToys
CurPOAPos=Controller.GetMech(2)
CurIdolPos=Controller.GetMech(3)
If CurIdolPos<>OldIdolPos Then UpdateIdol
If CurPOAPos<>OldPOAPos Then UpdatePOA
End Sub
If you look at the source code again for the IJ Mech Handler - lines 762+, you see you only get script access to mechanic numbers
2 and 3. The first mechanic handler 0x01 for the ENT targets is Controller.GetMech(0), the second one for the Totem drop target 0x02 is
Controller.GetMech(1). The Path of adventure 0x04 is Controller.GetMech(2), and the Idol Position 0x08 is Controller.GetMech(3).
For the GetMech command, it checks if it is being asked for #2. If yes, it returns the POA position, if no, it returns the idol position.
In our script example above, it queries the current data for the POA and the Idol, compares them to the last result, and if they are
different, it updates the screen display with UpdateIdol or UpdatePOA, as needed. At the end of those routines they will copy the
current status to the old variable with something like OldIdolPos=CurIdolPos or OldPOAPos=CurPOAPos. If both values are different for
CurPOAPos and CurIdolPos, both update routines will be executed - UpdateIdol followed by UpdatePOA.
Naturally, UpdateIdol's subroutine would have Visual Pinball update walls, change an emreel, move balls from kicker to kicker, etc,
and UpdatePOA would change the image and/or ball physics values to handle the Path of Adventure.
Since we are only truly using the mech handler for the idol and POA in this section, go back and change the handlemechanics value from
15 to 12. 12 would be 0x04 + 0x08 for mechanics 3 and 4.
Let's do one more internal mech handler example and then I'll go on to Choice 2 (custom scripted mechanics handlers).
Open corv.c
It is in the WPC/Prelim folder
For revision 2518 click on view and scroll down to the end.
Line 398 has a drawmech line which tells us we have 3 handlers here - one for the blue car, one for the red car, and one for the engine.
The blue car is mech 0x01, red car is 0x02, and engine is 0x04
Line 474 is the getmech routine which has all three script accessible - 0x01 is GetMech(0), 0x02 is GetMech(1), and 0x04 is GetMech(2)
So to get the current Blue Car position you would use Controller.GetMech(0) in your query routine.
For the HandleMech line in the script, to use all three it would be Controller.HandleMechanics=7 ' 1+2+4
Dim OldBlue,CurBlue
Dim OldRed,CurRed
Dim OldEng,CurEng
OldBluePos=0
OldRedPos=0
OldEng=0
Sub UpdateToys
CurBlue=Controller.GetMech(0)
CurRed=Controller.GetMech(1)
CurEng=Controller.GetMech(2)
If CurBlue<>OldBlue Then UpdateBlue
If CurRed<>OldRed Then UpdateRed
If CurEng<>OldEng Then UpdateEng
End Sub
Again, the update routines "UpdateBlue" and "UpdateRed" and "UpdateEng" would change the graphics on the screen, and update the values of
OldBlue, OldRed, and OldEng with OldBlue=CurBlue, OldRed=CurRed, and OldEng=CurEng. The internal simulator itself handles all the
related solenoids and switches involved for the playfield toy being simulated for you all by itself.
If you need to, you can still use the SolCallbacks the simulator uses to add other changes to the presentation with Visual Pinball.
An example would be SolCallback(17)="TextBox1.Text="
Solenoid 17 in Corvette is the Race Direction solenoid. If you wanted to see if that was enabled, that line will toss the word
"TRUE" or "FALSE" into a textbox called Textbox1 in your table. You are still limited to one MotorCallback in your script -
meaning, whatever one was defined last overrides all the others. Try to be neat and don't duplicate lines of script.
You are also limited to one SolCallback line per solenoid number. So having two SolCallback(17)'s will only utilize the last one
declared.
If possible, try to keep all, or most of your code together for playfield toys - it makes debugging a lot easier if it's all in one
place. ie - the code above is good, and go ahead and stick the Sub updateBlue, in its entirety, directly below the updatetoys
subroutine, followed by the routine for UpdateRed and UpdateEng.
If you want to create more internal simulators for Visual PinMAME, it is open source, so feel free to do so. As far as I know - we
have never turned down an additional simulator for inclusion.
In the rare cases that an existing internal simulator isn't accurate, or in the more common cases, that a simulator isn't available
internally for your current project, you can make your own through the script itself. If it is done in your script you have direct
access to change it at any time, you can save and restore values yourself if desired through the script, and the internal simulators
will not have any influence on how your game works in the future. ie if an internal simulator is changed or updated, your game will
still work exactly as it did before even with newer versions of Visual PinMAME. This brings me to choice 2 - custom mechanics handlers.




Top
Contributor



















are all trademarks of VPFORUMS.