Skip to content

Hook

Hook (Data East 1992) is a complete VPW table build covering physics, lighting, ramp engineering, plastics, inserts, AO workflow, Fleep sounds, flasher systems, skull primitive fading, and performance optimization. A highly collaborative effort across iaakki, sixtoe, benji084, skitso, tomate80, cyberpez, sheltemke, and oqqsan.

Build Notes

Playfield Material Setup

The playfield material must be set to "active" with opacity around 0.99 for objects beneath the playfield to render correctly. Without an active material, under-playfield elements like inserts and kickers become invisible.

AO Baking Workflow

The Ambient Occlusion workflow renders a separate AO pass image, multiplied over the playfield image at around 80% in Photoshop/GIMP. Rendering AO at 2K resolution is sufficient since slightly fuzzy shadows help realism. The team found that baking AO into the playfield produces more consistent results than a separate flasher layer, because two alpha layers stacking produces incorrect rendering in VPX.

Fleep Sound Integration

Fleep integration requires assigning each collidable object to the correct sound collection by material type (metal, rubber, plastic, wire). Invisible collidable objects don't export from VPX to 3D apps, making it difficult to trace collision paths. One approach: open the table in a 3D app and move the camera through like the ball.

Arch Sounds

In Fleep sound packages, "arch" sounds are specifically for the ball hitting and rolling along the top metal arch after the plunge. Assign to the metal arch collection, not general "metal walls."

Ramp Collidable Primitives vs VPX Ramps

VPX native ramps allow per-section friction settings (e.g., 0 at entrance, 0.3 at top), critical for fine-tuning. For ramps that barely accept the ball (like Hook's main ramp), the VPX ramp approach with per-section friction is preferred despite geometry approximation.

Solenoid Callback Mapping

When the manual doesn't list flasher solenoid numbers, circuit diagrams are the primary reference. Lamp numbers above the matrix range in scripts are arbitrary assignments by previous authors. Use vpmTimer.PulseSw <number> to trigger switch events for testing.

Falloff Power for Ball Reflections

Falloff power directly controls ball reflection strength. For inserts with low intensity (~5), use falloff power 2-3. For brighter lamps (intensity ~50), use falloff power 1 or less.

Scripting

Skull Primitive Fading

For translucent objects like the Hook skull, duplicate the primitive at slightly smaller scale inside the original. The inner primitive uses higher DL values. A timer-driven fading function uses cubic easing (flashLevel^3) to smoothly fade both primitives' BlendDisableLighting. Incorporate the GI level variable to prevent apparent size changes with GI state.

Custom Dampener for Plastic Collisions

For lane guides with plastic walls, create a custom Dampener that copies rubber coefficients but scales them down (e.g., 95%). Gives more realistic bounce off plastic surfaces.

Ramp Speed Propulsion Hack

When ramp geometry prevents completing a shot at realistic flipper strength, add a small speed propulsion at a trigger point. Check if VelY is within a range and apply a multiplier (e.g., 1.15x) capped at max speed. Avoids changing flipper strength globally.

FadeDisableLighting Pattern

FadeDisableLightingD 53, L81P1, 30, 1

Parameters: lamp number, primitive, LIT DL value, UNLIT DL value. Actual lit value is LIT + UNLIT (additive). Must not set FadingLevel to 0 or 1 prematurely.

GI-Driven Ramp DL Fading

Primitive_MainRamp.blenddisablelighting = gilevel * 0.12 + 0.03

Minimum DL of 0.03 when GI is off (ramp shape remains visible), ramps up to 0.15 when GI is fully on.

Diverter Animation

Uses two separate timer subs (DivOpen/DivClose) rotating a primitive by steps (e.g., 9 degrees per tick). Closing is delayed using vpmTimer.addtimer 1500, "DiverterTimer.enabled = 1'".

Warning

Timer interval matters critically: changing from 10 to 100 makes the animation appear as a slideshow.

3D & Art

Insert Cutout Edge Overlap

Insert cutout edges should overlap slightly into the playfield image to prevent visible seams. Playfield alpha mask value (typically 0.99 opacity) controls insert light bleed-through.

Skitso-Style 3D Inserts

Created by editing the playfield image around insert areas for a dimensional appearance. Quality depends heavily on playfield image resolution.

UV Map Quick Fix

For primitives with incorrectly mapped faces, select the bad faces in the UV editor and drag them outside the texture area to a 40% opaque gray region.

Troubleshooting

Ramp Roof Gap

When a ramp has a "roof" primitive, the gap must exceed ball diameter (50 units). A 45-unit gap causes the ball to move as if through glue. Roof friction should never be 1.

VPX Lamp Fading Speed

Fading speed is linked to intensity. Higher intensity lamps fade more slowly. 1990s-era inserts should fade slowly like incandescent bulbs.

Duplicate Rubber Objects

Duplicated slingshot rubbers on different layers silently break sound effects. The duplicates lack collection assignments, so VPX hits them first without triggering sounds.

Material "Active" Flag

Non-active materials cause primitives to not respond to BlendDisableLighting changes from GI scripts. Setting back to active restores correct DL behavior.

Triggers on Ramp Surfaces

A trigger's center point must be within the ramp boundaries when its surface is assigned to that ramp. Otherwise it takes height from the playfield instead.

Light Clipping from GI Overlap

GI lights with very high intensity that overlap cause additive clipping, turning areas black. Use small falloff areas with high falloff strength rather than high intensity.

Game Knowledge

Data East ROM Volume

Press 7 to enter audits, continue pressing 7 until "Expand Adjustments" appears, press 1 to change to Yes, then continue to "Volume Adjustment." Alternative: VPinMAME hidden menu via tilde (~).

EOS Return Values by Era

EOSReturn values: 0.055 for EMs, 0.045 for late 70s to mid-80s, 0.035 for mid-80s to early 90s, 0.025 for mid-90s+.

Resources

Performance Tips

  • Timer interval -1 = "once per frame" (not every millisecond)
  • Moving cor.update from 1ms timer to frametimer recovered 20-30 fps
  • Disable reflections on non-visible objects to recover 20-30 FPS
  • Remove unused full-res images to save 50MB+ per image
  • F11 shows script performance metrics
  • Stop major changes after Release Candidate to prevent regression