Skip to content

F-14 Tomcat

F-14 Tomcat is a Williams table with a scripting-heavy VPW build featuring Flupper-style flasher domes, Octane-rendered wire ramps, nFozzy physics, and a themed VR room with animated F-14 models. Development involved 6+ contributors across physics, 3D art, and scripting.

Build Notes

nFozzy Rubber Dampening

The nFozzy rubber dampening system implements a precise elasticity curve. Objects are separated into two collections: aPhysicsRubberPosts and aPhysicsRubberSleeves. Sleeves have lower elasticity than posts. Bands use standard VP settings and are not part of the dampening system.

Sub dPosts_Hit(idx)
    RubbersD.dampen Activeball
    RubbersHit
End Sub

Sub dSleeves_Hit(idx)
    SleevesD.Dampen Activeball
    RubbersHit
End Sub

Flipper Calibration

Flipper length should be approximately 147 VP units. When changing flipper length, also adjust the endpoint primitives for trajectory correction. All flippers should use consistent end radius values (11.5). Flipper power: lower flippers 3000, upper flippers 2200.

Staged flipper support was added in VPW version 013 by Primetime5k, enabling partial flipper shots and more nuanced ball control.

Kicker Hit Height for Saucers

Instead of using enable/disable code for saucers, set the kicker's hit height to 8. This prevents the kicker from grabbing the ball until it has actually fallen into the saucer. Combined with properly sized playfield mesh holes (wider than 50 VP units), this is more reliable than the older velocity-checking method.

VUK Curved Ramp Technique

To create a smooth curved ball path for a VUK, rotate a standard VPX wire ramp on its side, align it to the desired profile, then export as a mesh/primitive. Cyberpez created the mesh by stripping the relevant section from the actual ramp object.

Blender Pivot Point

The pivot point for VPX meshes exported from Blender is at XYZ coordinates 0,0,0 in Blender. Setting the mesh origin to (0,0,0) ensures the pivot imports correctly into VPX without manual adjustment.

VR Room Setup

F14 implements a 3-way VR room switch: desktop/cabinet mode, plane VR room (with animated F-14 models by DJRobX), and minimal VR room. All VR room geometry is set non-visible when VR is off for zero performance overhead.

For VR room performance: reduce texture sizes, keep the VR room bundled with the main table, and make all VR geometry non-visible when not in VR mode. A simple inverted sphere with a texture works well for minimal rooms.

Scripting

Flipper Polarity / Trajectory Correction

The AddPt "Polarity" code controls flipper trajectory correction:

AddPt "Polarity", 0, 0, 0
AddPt "Polarity", 1, 0.05, -5
AddPt "Polarity", 2, 0.4, -5
AddPt "Polarity", 3, 0.6, -4.5
' ... continues to tip
AddPt "Polarity", 12, 1.1, 0

Position 0.4 is a shot from cradle. This tuned version drops correction faster near the tip to widen shot trajectories.

BlendDisableLighting for Collections

Sub DisableLightingColl(coll, DLintensity, ByVal aLvl)
    for each p in coll
        DisableLighting p, DLintensity, aLvl
    Next
end Sub

Usage with NF Lampz callback: Lampz.Callback(110) = "DisableLightingColl ColTest, 25,"

Ball Shadow Improvements

BallShadow(b).X = BOT(b).X - (TableWidth/2 - BOT(b).X)/20
BallShadow(b).Y = BOT(b).Y + 10

If BOT(b).Z > 22 and BOT(b).Z < 35 Then
    BallShadow(b).visible = 1
Else
    BallShadow(b).visible = 0
End If

Dividing by 20 instead of 7 reduces lateral shadow offset at table edges. The Z-range 22-35 hides the shadow when the ball is in a kicker or airborne.

Flipper Coil Ramp-Up Modes

Two modes: (0) Static -- recommended for underpowered systems. (1) Dynamic -- better tap pass simulation, requires a fast system. VolFlip controls flipper sound volume. ReflipAngle (set to 20) determines the threshold for reflip vs full attack sounds.

Flupper FlasherFlash Timer

Sub FlasherFlash14_Timer()
    FlashFlasher(14)
    pBulbTest.BlendDisableLighting = 25 * ObjLevel(14)
End Sub

VUK Kicker Code with Animation

Sub sw24_hit()
    Controller.Switch(24) = 1
End Sub

Sub SolTopHole(Enabled)
    If Enabled Then
        sw24.Kick 0,50,1.50
        sw24.timerinterval = 10
        sw24.timerenabled = 1
        sw24.uservalue = 1
    End If
End Sub

The timer sub uses a step counter (Case 0-10) to animate the kicker primitive's TransY. Sound effects should be in Case 1, not Case 0, because Case 0 may not re-trigger on subsequent kicks.

Relay-Driven GI with PWM

F14's GI is relay-driven (on/off). For the VPW update, the old Lampz-based GI was replaced with PWM-compatible code using SolModCallbacks.

Ramp Sound Entry/Exit Pattern

Sub Ramp1_Enter_Hit
    If activeball.vely < 0 Then WireRampOn False
End Sub

Sub Ramp1_Enter_UnHit
    If activeball.vely > 0 Then WireRampOff
End Sub

Fires "on" sound only when ball moves upward, "off" sound only when ball moves downward. Prevents false triggers.

Options Menu

Configurable defaults include: intro music toggle, plastic decal visibility, VR room mode, savage kicker strength, and F14 toy plane visibility.

3D & Art

Transparent Flasher Domes (Flupper Rig)

Flupper's flasher dome rig uses textures that always face the player/camera. When making domes transparent: delete the back faces so texture doesn't tile onto the rear, and the lit mesh should be slightly larger than the base mesh. A separate filament mesh inside uses BlendDisableLighting to simulate glow.

Wire Ramp Rendering with Octane

The F14 wire ramps were rendered using Blender with Octane, producing high-quality metallic reflections.

Global GI Technique (Giant Overhead Flasher)

A large overhead flasher tied to the GI circuit creates global illumination dimming. Does not interfere with player-applied LUTs (unlike LUT-based GI dimming). F14's 12 domes create significant combined flood effect.

Troubleshooting

LUTs in VR

LUTs apply to the entire VR room, not just the playfield. The global GI flasher technique is preferred for VR.

Playfield_Mesh Case Sensitivity

playfield_mesh is case-sensitive. Naming it Playfield_Mesh causes VPX to fall back to a flat surface. VBScript in general is not case-sensitive, making this a special case.

Wall SideImage Limitations

Programmatically changing .Sideimage applies the image as "world" coordinates instead of "wrap." Workarounds: multiple wall objects with visibility toggling, flasher objects, or UV-mapped primitives.

PWM UseVPMModSol=2 DOF Issues

UseVPMModSol = 2 causes erroneous DOF solenoid activation at startup. Switch to UseVPMModSol = 1. Diverter solenoids should be removed from DOF configs. Use MAX duration values (e.g., S5 MAX100) as safety measures.

VPX Save Corruption

Save corruption during crashes causes FPS drops and broken collections. Check: collections for incorrect object membership, VR room objects being rendered when hidden, playfield reflection values.

Game Knowledge

Crosshair Insert Correction

The large crosshair insert is white, not green. The green appearance comes from green rubber bulb covers on the GI bulbs underneath. When white flasher bulbs fire, they obliterate the green. This error dates back to the JP Salas VP9 version.

Resources

  • F14 development pioneered the VPW check-in/check-out workflow system
  • Version control with 6+ contributors and frequent WIP exchanges