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>
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>
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>
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>
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>
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>
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>
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>