Commit Graph

18 Commits

Author SHA1 Message Date
m3ultra
fd1218621b The Garage: shit-tier upgrade economy
Earn bucks from every mode (takedowns, outruns, escapes, derby kills, medals,
a cut of crash damage) and spend them on performance parts of deeply
questionable provenance: K-MART MEGA WING, GO-FASTER STRIPES, SERVO FLAME KIT,
BLINGY MAGS, SERVO NEONS, BUNNINGS DRAINPIPE, TURBO THRU THE BONNET. Every
part gives a real stat bump AND bolts a procedural eyesore onto the car, sized
off the model AABB so the same tat fits a BUBBLA or a Kingswood. Fully kitted:
+35% power, +1.1 grip, +0.55 boost.

Per-car, persistent (user://garage.save), player-only -- stats apply to a
DUPLICATE of the shared CarStats so tuning your Lazza doesn't secretly tune
every Lazza in the city, and the save path is redirectable so the smoke test
can never wipe real progression. Bolt-ons attach after the deformer snapshot:
the wing survives every crash, as is right and proper.

GARAGE button + bucks readout in the menu; shop screen with prices, blurbs and
FITTED states. Smoke covers the earn/buy/duplicate-stats roundtrip.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 10:50:55 +10:00
m3ultra
63c32928ee Road Rage, oncoming boost, a real Crashbreaker fireball, title screen
The last two design-doc gameplay items land:
- Road Rage: 90 s, wreck as many rivals as you can. They recover on their own
  (no hold_wreck) so the supply never dries up, and a 220 m leash teleports
  strays back to the road ahead of the player. Bronze/silver/gold at 4/8/12.
- Oncoming: driving against the RacePath tangent while actually on the road
  (within 7 m of the line, above 12 m/s, heading dot < -0.55) trickles boost
  with a periodic toast. Runs in cruise, race and rage.

Crashbreaker finally looks the part: layered Fx.explosion (70-particle additive
fire bloom, rising smoke, 60-spark shower) inside a thin additive shockwave
shell -- the old opaque orange bubble drowned the fire out completely, so it
became a fast-fading front-culled dome instead. Plus a 0.8 camera shake.

Menu is a title screen: FLUX-generated key art (battered sedan, flying hubcap,
bridge, jacarandas -- the hubcap is canon now) behind a scrim, outlined golden
title. Art prompt asks for no lettering; the plate gibberish is FLUX being FLUX.

Smoke coverage for both mechanics. The oncoming test taught a harness lesson:
setting global_position on a continuous_cd body SWEEPS it there, wrecking the
car before the test began -- teleport via PhysicsServer3D.body_set_state.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 11:39:00 +10:00
m3ultra
589e99c727 Procedural sound kit: the whole game has audio, no recordings
Every WAV is synthesized from maths by tools/gen_sounds.py (run through Blender
for its bundled numpy) -- sines, noise and envelopes, seeded and reproducible,
licence-free by construction. Loops (engine, skid, boost, siren) are built from
integer-Hz components over exactly 1 s so the seam is mathematically silent;
noise beds get a crossfaded seam. Seam continuity is verified numerically.

Wiring: pitch-tracked engine loop on every car (idle burble to top-end scream,
bump while boosting), skid loop off slip, player boost whoosh, small/big crash
by jolt with glass on wrecks, two-tone siren on pursuit cops (derby brawlers
stay silent), Crashbreaker boom, gearbox clunk/bog, win/lose stings on
takedowns, outruns, escapes, busts and derby eliminations.

Loop flags live in code (sfx.gd), not per-file .import settings, so a
regenerated wav never silently loses its loop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 13:05:48 +10:00
m3ultra
aac4384c05 Per-junction medal targets, measured; fix the last unplayable junction
Medal targets are no longer one uniform 15/35/60k guess across every event.
tools/tune_junctions.gd plays each junction 12 times with varied launches and
sets bronze/silver/gold at the 35th/65th/88th percentile of actual damage, so
they now range from $4k at Cliffs Corner to $73k gold at Melbourne x Merivale.
The old numbers made half the events impossible and the other half trivial.

Grey x Glenelg scored $0 in 12/12 runs and took three fixes, each found by
measuring rather than reading:
- The launch sat on the street centreline, so the car drove cleanly BETWEEN the
  two convoy lanes -- closest pass 2.9 m, almost exactly the 2.7 m lane offset.
  It now launches in a lane. (The first attempt offset the wrong way and widened
  the pass to 5.5 m, which is how the sign error announced itself.)
- int(L / headway) floors to one car on a short clipped stream, so that junction
  fielded 9 convoy cars against the usual 20-25. Minimum 3 per stream, evenly
  spaced to fit.
Result: $0 -> $91k, convoy 9 -> 18, and 0 of 9 junctions now unplayable.

The tuner has turned out to be the event validator as much as a balance tool --
"scores nothing in every run" is an unplayable event, not a tuning problem.

Also from the review: the deformer no longer crumples det_* panels after they've
been shed onto their own body, and notes that rebuilding an ArrayMesh drops any
imported LODs.

Honest gap: Cliffs Corner and Bridge Approach show median == max at ~$4.7k --
winnable and correctly tuned, but the run ends on scenery before the convoy is
reached. Both are curved approaches; they want better crossings picked by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:15:05 +10:00
m3ultra
0c13c82eac Pursuit, drag and derby modes; crash-damage paint; junction fixes
Three new modes, all our own code:
- Pursuit (Simpsons Hit & Run's meter): smashing in cruise fills heat, at full
  the police hunt you. Open 250 m for 6 s to escape, get pinned 4 s to be busted.
  Heat decays, so picking a fight is a choice not a timer.
- Drag (NFSU2's): the gearbox IS the event. The builder finds each level's
  longest genuinely straight run of wide road (442-628 m across the five OSM
  levels) and drops DragStart/DragEnd, so no level needs hand-authored coords.
- Derby: five opponents in the carpark, last one running. Reuses the pursuit AI,
  each hunting a different car so it's a brawl not a mob.

Crash damage now shows: total control-point travel drives paint dulling,
roughness and a scratch layer, so scuffs and crumple can never disagree.

Junction generator fixes, all found by measurement rather than inspection:
- streams[:6] truncated after street A's ways, so junctions where A yielded 3+
  usable ways shipped with ZERO cross traffic. Interleaved before capping;
  every event now has 2-4 crossing streams.
- RADIUS 170 -> 95 spread the convoy over a 340 m window, so you threaded the
  intersection through a 20 m gap. Margaret x Edward was unwinnable: 27 convoy
  cars alive, zero collisions, $0.
- Launch points now walk the street to exactly SPAWN_DIST and pick the busiest
  shared node, and _clear_spawn() unblocks a buried start. Albert x Adelaide
  went from $0 (drove 1 m into a building) to $91k.
- build_all_junctions.sh records the street pairs, which existed nowhere before.

Fixes from an adversarial review (23 confirmed findings), the worst being:
- Derby could only ever be LOST: wrecked opponents un-wrecked 2.2 s later via
  Car._recover, so "last one running" was unreachable and the kill bounty could
  be farmed to the boost cap off one revived car. They now hold their wreck.
- Drag reported WON to a beaten player: the AI's lookahead wrapped on a 2-point
  path, U-turning before the line so its distance-to-finish grew again.
- The scratch layer used BLEND_MODE_MIX, whose mask defaults to white -- it
  replaced the paint entirely rather than scuffing it. Now MUL.
- Drag on a level with no strip left the car at the origin, half-buried, unable
  to end. Cop spawns used an unflattened basis. Stale "WANTED" HUD text.

Test harness: smoke covers all seven modes, and failures now exit instead of
hanging -- a failed assert in a headless SceneTree halts the script but leaves
the tree spinning, which cost 53 minutes of wall clock to notice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 23:07:41 +10:00
m3ultra
59202c222c Crash deformation: control-hull vertex displacement from the design PDF
Implements the algorithm the README has listed as "still to come" since v0.
A 3x3x5 lattice of control points encloses the car; an impact shoves nearby
points inward and mesh vertices follow via inverse-distance weighting
(W_i = 1/||p_j - c_i||^alpha, alpha=2), clamped to the PDF's bounding-box
safety limit so panels crumple rather than fold through themselves.

The weights depend only on original positions, so they're precomputed once per
car at setup -- each impact is then a plain weighted sum at 0.3 ms, with no
per-frame cost at all. Meshes are deep-copied per car so deforming one Kingswood
doesn't dent every other Kingswood sharing the GLB.

Measured on the Lazza: a hard nose-on hit displaces 11.9 cm, accumulating to
18.2 cm over repeat hits, well inside the 42 cm clamp. Only the player and
rivals carry a deformer; traffic and parked cars stay plain bodies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 19:01:43 +10:00
m3ultra
e9717326f4 Smashable street furniture; fix levels losing every texture on rebuild
Street lamps, bollards and bins are no longer baked scenery. The builder emits
SL_/BO_/WB_ markers off the OSM nodes and game.gd spawns them as RigidBodies
with a low centre of mass, so clipping a lamp at 100 topples it instead of
driving through a painted pole. ~206 physics bodies per level (58 parked cars,
60 lamps, 88 bollards/bins), all asleep until hit. Verified by ramming one:
23.6 deg tilt, launched at 18 m/s.

Fixes a self-inflicted trap from the last commit: level_*.jpg are Godot's
extraction of the GLB's embedded textures, NOT Blender output. build_all
cleared them to avoid orphans but left level.glb.import, so Godot's cache
decided nothing had changed and never re-extracted -- queen_st_mall shipped
with 0 of its 31 textures, loading fine but rendering untextured. The .import
now goes with them.

Also confirmed the Wheel of Brisbane pivot really does turn (0.086 rad over
120 frames, 0.000 m centre drift) -- it was previously untested.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 18:53:05 +10:00
m3ultra
1db71420a3 Scenery v4: traffic signals, power lines, local FLUX fallback
Taps the last big unused seam in the OSM data: 140 highway=traffic_signals per
CBD level become pole + mast arm + two lantern heads with emissive lenses.
Timber power poles with catenary-sagging wires run down one side of every
residential street. Billboards now cycle three fictional ad designs.

Cloudflare's free tier (10k neurons/day) ran out mid-session, so flux_texture.sh
now falls back to the local MODELBEAST farm automatically -- transparent, same
output contract. tools/crop_poster.py trims generated billboards to the poster
face by saturation, since FLUX renders them in situ with sky and support pole
however the prompt is worded.

Fixed: signal lenses were built as 0.04 m beams and beam() bails under 0.05 m,
so they silently never existed -- caught by inspecting the exported GLB, not
the screenshot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 17:21:35 +10:00
m3ultra
6808710f31 Scenery v3: smashable street life, Brisbane colour, Southbank landmarks
Every OSM level now spawns 50 shuntable parked fleet cars + 40 wheelie bins
from builder-emitted PP_/WB_ markers (kerbside + real amenity=parking rows;
asleep until rammed, absent in junctions to keep the puzzles deterministic).
Traffic bumped in cruise/crash.

Brisbane pass: red busway asphalt, jacaranda canopies on a fifth of the street
trees, Queenslander weatherboard + corro on building=house, art deco + glass
apartment facade variants, fictional shop-fascia signs above awnings, rooftop
billboards. Southbank gets the Wheel of Brisbane (by its mapped ticket office)
and the Grand Arbour's bougainvillea tendrils along the mapped footway.

Verified: smoke green, 50+40 smashables counted on southbank, screenshots of
the wheel, arbour trail, red busway, and one authentic parked-car rear-ending.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 16:42:14 +10:00
m3ultra
81ed13b1ff FLOORED LAZZA 1.5: John's actual first car, '82 KA Laser hatch
Built from his photos: white 5-door wedge, black bumpers + belt-line rubbing
strip, amber corner indicators, wide dark grille bezel (pale headlights vanish
on white paint without it), and the crown jewel -- rear hatch louvres, five
slats that shed one by one on impact like a dropped pie. New optional spec
keys: louvres, indicators, side_strip, wide_grille; build_cars.py now takes
`-- <id>` to rebuild a single car; screenshot harness gains cam=rear.

Reversed-stats rule applied: 54 kW carby IRL -> 21.0 power / 860 kg / 7.8 grip
here. Second-quickest thing in the game behind the Excel, and the chuckable-est.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 16:16:32 +10:00
m3ultra
da63829e9e Outrun mode: NFSU2-style roaming 1v1 duels in cruise
Two rivals now lap the RacePath in free roam. Pull alongside one at speed and
the duel arms: first to gap the other by 250 m wins. Straight-line distance
decides when it ends (side-street escapes are real); path order decides who
won (reversing away is a loss). Rubber-banded chase, takedown-tier boost
payout, R mid-duel forfeits, 8 s re-arm cooldown. Mechanics only -- no assets
from anywhere near an EA disk. Smoke test arms a duel and settles the win path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 14:18:20 +10:00
m3ultra
82dae637a1 Scenery overhaul: real OSM street furniture, FLUX texture set v2, lighting pass
Builder now uses the furniture OSM already carries (footways, lamps, benches,
bins, bollards, bus stops, crossings): raised chamfered footpaths, shopfront
bands, awnings in three fabrics, parapets, layered fig/palm trees, zebra bars,
dashed centre lines, Queen St Mall winged canopies. ACES tonemap + SSAO + fog
in game.gd. flux_texture.sh gains size/luma clamping (FLUX renders "pale" as
blown-out white); gen_textures.sh + check_textures.py manage the set. Woolies
carpark rebuilt textured, parking the real fleet. Fixes: fractional OSM layer
tag crash, zero-length-normal UV projection, blood-red mall pavers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 14:13:29 +10:00
type-two
565caa6f85 Crash Mode junctions: scripted convoys, Aftertouch, Crashbreaker, medals
9 junction events across 6 levels, auto-generated from real OSM intersections
(tools/osm_junction.py): each crossing street's ways become lane-offset convoy
streams, deterministic speeds/intervals/models -- learnable puzzles, not dice.
Menu lists CRASH JCT entries; crash -> 9s settle with camera-relative
aftertouch on the wreck and a one-shot crashbreaker shockwave (blast() on
traffic, radial impulse on debris, orange boom). Damage tally vs
bronze/silver/gold targets. Fixed zero-normal UV projection that striped
roads. Smoke test drives a full junction run to tally (k, gold).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 00:14:33 +10:00
type-two
7fd11f3806 Four more Brisbane levels + FLUX textures: these scenes pop
southbank, albert_parklands, story_bridge, kangaroo_point + queen_st_mall
rebuilt textured. Level builder now does: FLUX facade/road/grass/water/rock/
steel materials with box-projected UVs (roofs split to plain grey), parks,
multipolygon river water (solid, cars skim it), tree nodes as low-poly cones,
natural=cliff walls, and a procedural steel cantilever truss along a named
bridge way (Story Bridge / Bradfield Highway, 338m). osm_xml_to_json.py
assembles water relations; osm_level_args.py gains trace: mode for race paths
that follow one iconic road. 11 textures via Cloudflare Workers AI
flux-1-schnell (tools/flux_texture.sh, creds from .env never printed).

Data (c) OpenStreetMap contributors, ODbL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 23:48:55 +10:00
type-two
d9b69e688e Brisbane: Queen Street Mall crash-run level from OpenStreetMap
tools/build_level_osm.py extrudes OSM buildings (-col), lays road strips,
Spawn + RacePath empties; osm_level_args.py computes a building-clear spawn on
a named way and race-loop corners from street intersection nodes. game.gd
builds Path3D from GLB RacePath empties, sanitizes spawn bases, and places
bodies BEFORE add_child. Three real bugs fixed: mall canopies (building=roof)
extruded as solid blocks, underground busways rendered at surface, and the
km-wide ground trimesh breaking suspension raycasts (now -convcol). Cars get
continuous_cd for thin building shells. tests/probe.gd is the physics
raycast debugger that found it.

Data (c) OpenStreetMap contributors, ODbL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 23:33:51 +10:00
type-two
4c5323ba60 Reversed stats pass + real-model import pipeline (CASSEROLA DX, MORRY)
Stats quietly inverted: shitboxier IRL = better in game. Excel X3 is now the
fastest car; TURDRUNNER is the slowest. tools/import_shitbox.py converts
downloaded models (glb/gltf/fbx/obj/blend) to game GLBs -- normalizes scale,
yaw, ride-height origin. First two imports: Corolla mk7 and Morris Mini.
shitboxes/ stash gitignored + .gdignore'd (its .blend files broke Godot's
headless import scan).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 22:24:36 +10:00
type-two
eb7c189c9f Gameplay systems + procedural Blender car fleet
Modes: Cruise / Crash Mode (60s damage dollars) / Race (3 laps, rubber-banded
rivals). Burnout loop: boost earned by drift, near miss, smash; takedowns refill
and grow the meter to 4x; hard crashes shed det_* panels and trigger Impact Time
slow-mo. Traffic follows the level RacePath frozen-kinematic and goes dynamic
when whacked. tools/build_cars.py builds six Aussie shitbox GLBs (profile
extrusion + detachable doors/mirrors/bumpers/bonnet/boot). Smoke test covers
all three modes headless.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 21:29:42 +10:00
type-two
1c0b7efb32 Engine v0: Godot 4.6 data-driven arcade racer scaffold
Drop-in content: cars/<id>/stats.tres (+optional car.glb), levels/<id>/level.glb
or .tscn with a Spawn marker. Raycast arcade car (boost, drift, drift-earns-boost),
chase cam, HUD, menu built from registry scan. Placeholder Woolies carpark with
shuntable parked cars. Headless smoke test + windowed screenshot harness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 21:03:45 +10:00