combat — crates and missiles
The ammunition on the road and the weapon it loads.
Ten crates hover on the racing line, alternating side to side so a lap offers a choice of line. Any racer that drives through one is armed, the crate goes dark, and it comes back eight seconds later. A held round is spent with Space: it leaves the chair, follows the road at 72 m/s, snakes through the corners after the racer ahead, and detonates on it. The victim loses control for a little over two seconds, which on a lap this long is a place.
What the scene calls
Combat.build() -- lay the crates, build the missile and blast pools
Combat.update(dt) -- pickups, triggers, flight, impacts
Combat.teardown() -- clear everything the slice spawned
Two read-only extras, useful from a console or a HUD:
Combat.inFlight() -- rounds in the air right now
Combat.status() -- slice clock, crates live/away, next crate back, pool size
How it is put together
Everything that moves comes out of a pool built once in build():
six missiles, five blasts, ten crates, all parented to combat_root.
Adding a Model component costs milliseconds, so nothing is spawned at
the moment a trigger is pulled — a sleeping body is woken, flown, and put
back. combat_root is marked temporary, so none of it is saved into the
scene; it is rebuilt from code every load.
Guidance runs in two phases. Far from the target the round reads the
racing line ahead of itself and slides across toward the victim's line,
so it follows the circuit instead of driving into a barrier. Inside
lockRange it abandons the road and flies straight at where the chair
will be, leading its speed. The barriers contain a round rather than
killing it — it scrapes the wall and is turned back down the road, so a
shot fired from a chair a metre onto the run-off still counts.
Impact is a swept proximity fuse: at 72 m/s a frame is three metres, so the test is the closest approach along the whole step, not the point where the step happened to end.
The slice keeps its own clock. Crate respawns and rival reload timers
are measured against it and not GP.state.clock, which the race director
rewinds to zero at every start.
Rivals shoot too
A rival holding a round takes the shot at whoever is in front of it,
after a moment of hesitation and with a cooldown between shots — so the
field fights among itself and a place is never safe. Turn it off with
GP.TUNE.missile.aiFire = false.
Firing with nobody ahead
Leading the race, the trigger keeps the round and the HUD is told
NOTHING AHEAD. A missile is only worth spending at something.
Range
A round burns out after lifetime seconds, which at speed is about
430 metres of road. That is far more than the gap between two racers in a
real race, and less than a full lap — a racer half a circuit ahead is out
of reach, which is the point.
The numbers
All of them live in GP.TUNE.missile and GP.TUNE.pickup and are read
live, so a change is felt without a reload.
Scoped to this part · feeds back into the world's score.