Skip to content

Game of Thrones

Major build with 3D art, best practices, scripting, build guide, troubleshooting, and extensive game knowledge. One of the most documented VPW tables.

Build Guide

SPIKE1 ROM Extraction

Skillman wrote Perl-based SPIKE1 ROM extractor: GitHub.com/stevehillman/spike. Extracts sounds, images, DMD data from Stern SPIKE1 ROMs. Tested on GoT, Kiss, Ghostbusters.

Approach: wrap image.bin in 44khz WAV header, send to VLC to find audio offset, hex-dump to find index table pointers. Images found by searching for 4-bit pixel sequences. Does NOT work on SPIKE2 (encrypted).

nFozzy Physics Implementation

Key notes:

  • If playfield dimensions true to real life, nFozzy should "just work"
  • Must use specific VPW physics materials file (PhysicsMaterials.mat) - cannot just update values in existing JP materials
  • Collidable rubbers need their own separate layer
  • nFozzy upper playfield flippers too, with polarity corrections
  • Flipper endpoint triggers flush with flipper ends
  • RightFlipper.timerinterval should be 1, not 5

VPW Physics Values Reference

Standard values:

Table: - Gravity 0.97 - PF Friction 0.15-0.25 - PF Elasticity 0.25 - Scatter 0 - Default Element Scatter 2

Flippers (mid-90s+): - Mass 1 - Strength 3200-3300 - Elasticity 0.88 - Elasticity Falloff 0.15 - Friction 0.9 - Return 0.055 - Coil Rampup 2.5 - EOS Torque 0.275, Angle 6

Bumpers: - Force 9.5-10.5 - Hit Threshold 1.6-2 - Scatter 2

All rubber posts/sleeves/walls: Hit Threshold 0.5.

Playfield Friction Impact

Playfield friction of 0.025 (inherited from JP) is way too low. VPW standard is 0.15-0.25. Low friction causes: overly bouncy rubbers, ball "floating" without rotating, inability to post-pass, ball feeling too light.

Scripting

AudioPan Bug During Multiball

AudioPan function throws exception because tableobj.x is undefined during frantic multiball. Cause: object passed has no x/y coordinates, or VPX lost track of ActiveBall.

Fix: play kicker sounds BEFORE destroying ball in kicker. Best practice: never destroy balls (#savetheballs). For vertical ball transport (elevator mechanic), look at how LOTR handles back-left VUK.

vpmTimer Inaccuracy Warning

vpmTimer.addTimer is horribly inaccurate: 50ms timer fires anywhere from 2-40ms after being set. Lampz only updates state every 20ms. Timer of 16ms (one 60hz cycle) may never fire.

There's also limit on how many vpmTimers can be active - they silently fail when exceeded. Best practice: never use vpmTimers for precise timing. Use dedicated VPX timers for flashers and critical effects.

VBScript Boolean Gotcha

VBScript boolean quirk: Not 0 = -1 (True), but Not 1 = -2 (not True!). When Service Menu settings change booleans to 0/1 integers, If Not cabinetmode breaks.

Fix: use explicit comparison like If cabinetmode = 0 or If cabinetmode <> 1.

3D & Art

GI Shadow Technique Using Flasher Layers

HauntFreaks' shadow technique: create flasher layer with shadow image cast onto PF (done in Photoshop). Faster than shaping each VPX light individually and produces soft edges without hard lines - "the cheap man's blender render." Shadow controlled by GI state and drop target hits via script.

VPX Primitive Insert Lighting

For non-rendered tables with primitive inserts: use two primitives per insert (off and on). Off insert shows normally; on insert faded up with DisableLighting and normal light turned up. Secondary light at ~+1 provides faint soft glow.

BlendDisableLighting ranges from 0 (fully dark) to 1 (fully lit) and beyond (no negatives). Invented by Flupper.

Blender Toolkit First Bake

Steps:

  1. Delete everything visible in VPX and prep file
  2. Run 1K batch first as test (~1hr)
  3. RGB LED inserts must be baked full white for tinting afterward in VPX (10.7.2 feature)
  4. Inserts need to be "split" in Blender (separated into on/off)
  5. Primitive names can't be too long - combined with lightmap suffixes they get truncated
  6. All objects that interact with ball remain invisible and collidable; visual-only objects come from Blender

Ball Reflections from Inserts

For insert ball reflections: create dedicated reflection-only lamps below PF at -10 depth. Use depth bias to make invisible to everything except ball reflection. Remove ball reflection setting from every other light element. Ball can show max 8 reflections.

Troubleshooting

Transparent/Ghost Ball Fix

Transparent/ghost ball issue caused by insert primitives having wrong depth bias, wrong settings, and wrong materials. Diagnostic clue: ball flashing on/off when light was flashing.

Fix involved: moved collidable rubbers to separate layers, filled ball-trap holes (walls "NO" blocks rather than relying on plastics layer), removed old duplicate primitives, removed secondary GI doubling up with toolkit renders.

Blender Crash During Bake

Blender crashing during bake on specific plastic objects. Root cause: "Apply Decal - NoExp Node" modifier. Workaround: change margin settings from "Adjacent faces" to "Extend" (may cause artifacts) or lower margin size. Alternatively, try newer Blender version.

FlexDMD Race Condition

FlexDMD can crash with "Could not find file" errors during multiball when multiple DMD scenes fire rapidly. This is race condition in FlexDMD's scene creation - NewSceneWithVideo fails, then fallback to PNG also fails because no PNG exists.

Crash not reproducible on demand. Workaround: do NOT add fallback PNG files as that masks root issue. FlexDMD caching improvement PR exists but hasn't been merged.

SwordMask Infinite Loop Bug

Sword collection random selection could freeze game in infinite loop. Root cause: SwordMask (bitmask tracking collected swords) was not reset between games and not properly preserved between players.

Once all 8 swords collected across any combination of players/games, random selection loop would never find uncollected sword.

Fix: 1. Reset SwordMask on new game 2. Properly save/restore SwordMask in PlayerState 3. Replace retry-random with linear scan from random starting index (guarantees termination in max 8 iterations)

Released as v1.2.1 - critical fix for skilled players who collect many swords per game.

Software Setup

FlexDMD Setup for Non-ROM Tables

Stern SPIKE system is not emulated in VPinMAME, so FlexDMD is used for DMD display. FlexDMD needs:

  1. FlexDMD installed (v1.8+)
  2. Separate gameofthrones.FlexDMD folder with image assets placed in Tables directory
  3. VPX file and FlexDMD folder are separate downloads

Common error: "Object required" at FlexDMD init line means folder is missing.

Options Menu in VR

VPVR can only display one FlexDMD window at a time. If table uses second FlexDMD instance for options menu, it creates duplicate DMD window in VR.

Fix: rewrite options code to use same backpanel DMD instance instead of separate FlexDMD object. Alternatively, put VR-specific options in script header or Service Menu.

Game Knowledge

GoT Combo Multiplier System

Each shot increases combo multiplier for certain OTHER shots, never itself (except dragon shot which boosts all):

  • Left orbit boosts dragon and center ramp
  • Dragon boosts all
  • Right ramp boosts left 3 shots
  • Right orbit boosts center 3 shots

Hitting lit combo shot before timer expires scores multiplied score AND increases combo multiplier by one for affected shots. ChuckWurt's 7-part YouTube series is most detailed rules source.

Targaryen Drogon Battle

4-wave battle: 4 waves of 4 shots. Each shot knocks one segment off Drogon's 15-segment health bar. If HurryUp times out, 1 health bar added back and 3 new shots light. On last wave, must complete all 4 shots even if health already zero.

WiC + BWMB Stacking Rules

Tested on real machine: you cannot combine Winter is Coming (WiC) hurry-up with Blackwater Multiball (BWMB). When center ramp shot would start both simultaneously, game disables/ignores WiC and starts standard BWMB with battle choice.

Resources

  • SPIKE1 ROM Extractor: GitHub
  • ChuckWurt's gameplay series (7 parts, 2hrs each) for complete rules
  • IPDB entry: Game of Thrones