Skip to content

The Goonies

Scripting-heavy original table development with 3D art, troubleshooting, game logic debugging, release process, and multiplayer state management.

Build Guide

Future Pinball to VPX Conversion

When converting FP tables to VPX, expect extensive code cleanup. FP-to-VPX conversion leaves many broken code paths, unused variables, orphaned timers, and subroutines from donor table.

Methodology: systematically remove unused code in batches of 3, save, test, repeat until something breaks, then roll back. Use GitHub to track VBS script versions for easy diff comparison.

3D Insert Double-Light Technique

Double-light technique uses 3D primitive inserts with light underneath and light on top. Primitive insert sits between two lights. When light state changes, both lights update together. Gives inserts more realistic depth appearance compared to flat playfield inserts.

Pioneered on tables like Black Rose and Transporter before being applied to Goonies.

Scripting

NFozzy LiveCatch Code Must Be Active

NFozzy livecatch code allows player to trap ball on flipper by holding button at right moment. If commented out or missing, ball bounces off flipper uncontrollably.

Check that livecatch code is active in flipper collision subs. Can be missed when integrating from multiple tutorial versions.

RDampen Timer Must Be 10

RDampen timer interval controls flipper rubber dampening behavior:

  • Setting to 1 (as in some Fleep tutorials) is overkill
  • Setting to 100 (typo) causes post-pass to fail - ball hits post and stops dead
  • Correct value is 10 (as specified in NFozzy docs)

This single timer value dramatically affects ball behavior on post-pass shots.

Multiplayer State Management Pattern

For multiplayer VBS tables, create state array: Dim PlayerState(50, 4) to store up to 50 variables for 4 players.

Three key subroutines needed:

  1. SavePlayerStats - stores current player's light states, mode progress, ramp counts into array
  2. LoadPlayerStats - restores from array
  3. ResetAll - clears everything for new game

Between player turns: save current player state, run ResetForNewPlayerBall, load next player state.

For ball locks in multiplayer: track per-player lock progress with lockplayer(playernum) - if player hasn't locked enough balls, destroy locked ball instead of starting multiball.

Ball Destroy/Create Pattern and Flipper Array Cleanup

When destroying balls (ball enters kicker, gets destroyed, new ball created at different location), NFozzy flipper trigger arrays may retain reference to destroyed ball object.

Before destroying ball, call RemoveBall on both LF and RF objects, or call LF.PolarityCorrect activeball and RF.PolarityCorrect activeball to clean up.

Same issue can cause "rolling sound persists after drain in multiball" bug.

Primitive Ramps as Performance Bottleneck

Primitive meshes used as ramps create huge performance bottlenecks. Wire ramp primitive was ~90,000 polygons and skull ramp was ~18,700.

Solution: replace primitive ramps with invisible VPX ramps for ball physics, keep primitive visible but non-collidable for visuals. Result: +20 FPS improvement after "Operation Ramps."

FlexDMD Render Lock Removal Fixes VSync Stutter

FlexDMD score display froze/lagged when VSync enabled but worked fine with VSync off.

Root cause: excessive RenderLock/RenderUnlock calls in FlexDMD update code, plus frame-skip check that dropped DMD updates during slow frames.

Fix:

  1. Remove all RenderLock/Unlock calls outside initial DMD creation phase
  2. Remove late-frame skip logic so DMD always updates

MP3 Preloading at Startup

First-time MP3 playback caused frame stutter because media player loads new instances to memory.

Fix: play 10 MP3 files at near-zero volume during table startup to pre-cache them. Frame spikes disappeared after implementing preload.

FlexDMD

Built-in Font Resources

FlexDMD has built-in bitmap fonts accessed via FlexDMD.Resources.<fontname>.fnt. Available fonts listed in FlexDMD GitHub repo at /FlexDMD/Resources/.

Example:

Set FontScoreActive = FlexDMD.NewFont("FlexDMD.Resources.udmd-f7by13.fnt", RGB(255, 222, 0), RGB(1, 1, 1), 1)

Last parameter (1) enables text border using second color.

Splash Screen Priority System

When multiple DMD events fire rapidly (e.g., ramp hits during multiball), priority system prevents lower-priority splashes from overriding important ones.

Implementation: add priority and duration parameters to splash calls. Check if new priority > current priority OR if current timer expired. Store current priority and only reset when splash reaches 0 or higher-priority event arrives.

Background Image with Animated Overlays

For rich FlexDMD displays, use dark background image with transparent PNG overlays for animations. Create multiple PNG frames for effects like skull flash, ship sailing, cannonball flying.

Each overlay controlled independently. Use FlexDMD.NewGroup("Content") for layered actors. Keep images exactly 128x32 pixels. DMDUpdate timer should run at ~17ms for smooth animation.

Performance

Collidable Primitive Audit

Identified collidable primitives (GuiaSling2 at 9000 polygons, Primitive6 at 1164 polygons) that should be replaced with walls or made non-collidable.

Rule: primitives used only for visuals should have collision disabled. GetBalls is expensive and should be minimized.

Timer Interval Best Practices

VPX frame rate is ~17ms (60fps). Timer intervals below 17ms provide no benefit and waste cycles. cannonRecoil timer at 1ms changed to 10ms. Even disabled timers are "dirt under the rug" - clean up unused timer subs.

At 120Hz, sub-17ms timers can have effect, but for 60Hz targets they're wasteful.

Performance Stuttering at 4K

At 4K resolution on "super beefy" system (5600X + 2070 Super + 32GB RAM), multiball release caused severe stuttering.

Contributing factors: 5 GetBalls calls running frequently (reduced from 7), dynamic ball shadows, and FlexDMD operations. Disabling dynamic ball shadows was first diagnostic step.

Game Design

Wizard Mode Design Patterns

Wizard mode for Goonies: triggered by completing "Never Say Die" letters (11 letters from various modes). Implementation: 5-ball multiball (3 initial + 2 ball saves after drain), 30-second ball saver, all ramps/orbits award jackpots with progressive scoring.

Critical code requirement: add bWizard=True check throughout all mode-start subroutines to prevent other modes from activating during wizard.

DATA Skillshot Dominance

DATA skillshot is dominant over all other options in both 3-ball and Do or Die modes. DATA provides: jackpot doubling, 250k x 6 marbles bonus, and extra ball opportunity.

Team decided not to rebalance - "the masses will do pops or lock" even though DATA is mathematically best. Different skill levels create natural variety.

Troubleshooting

Tilt Handling Complexity

Tilt handling in complex original table extremely challenging. Issues discovered:

  • Tilting during EOB bonus called EndOfBall twice
  • Tilting during wizard mode didn't reset wiz5ball counter causing infinite ball launches
  • Tilting after locking ball broke the game
  • Tilting with ball in plunger lane killed the game

Fixes required: enableKeys = False at EOB start, modename = "" on tilt, close trap door, reset ballsaver, add temporary tilt block during ball lock, autofire ball from plunger on tilt.

Even after extensive fixes, motto became "dont tilt this table."

Duplicate Subroutine Bug

Two Sub TiltRecoveryTimer_Timer() definitions existed in script. VBScript silently uses first definition and ignores second, so changes made to second one never executed.

Lesson: as tables accumulate code from multiple developers, duplicate subs can creep in. Periodically run duplicate-sub checker.

Release Process

Release flow: internal versions (v87-v96 over 2 days) > RC builds (RC5-RC7) > v1.0 release > post-release patches (v1.06-v1.10).

Release artifacts: table .vpx, B2S backglass, FlexDMD assets, APNG loading animation, all in one ZIP.

Testing checklist for display modes:

  1. PuP + PuPDMD
  2. No PuP + FlexDMD only
  3. PuP + FlexDMD
  4. Both PuP and FlexDMD disabled

Streamer Reveal Lessons

Issues:

  • Streamer rushed home from cancelled flight, didn't test setup beforehand
  • Midnight streams miss European team members (5am for Scandinavians)

Lessons:

  1. Give streamer early access to test before going live
  2. Don't schedule streams same day as major disruptions
  3. Watch for bugs exposed during play

Resources

  • VPUniverse release page
  • IPDB: The Goonies (if official version existed)