cinderBombs
require("@me::hazard.cinderBombs")
The lava-bomb hazard. The crater throws molten blocks at whoever is on the mountain; this module launches them, flies them, lands them, and reports each landing.
Driven entirely by CinderDirector — it owns no clock:
local bombs = require("@me::hazard.cinderBombs")
bombs.reset() -- at the top of every run
bombs.update(dt, onHitPlayer) -- every tick
bombs.count() -- how many are in the air
bombs.intervalAt(progress) -- seconds between launches at that progress
How a bomb behaves
It leaves the vent from a random point inside the caldera floor, above whatever
the lava level is at that moment, and arcs over the rim on a fixed
CFG.bombFuseSeconds fuse. The aim leads the player: it targets where they
would be if they kept walking the way they are walking, plus an error that
tightens from TUNE.scatterStart to TUNE.scatterEnd as the eruption peaks.
Changing direction is therefore a dodge; standing still is not.
Every bomb carries a ground marker at its landing point that grows to the full
blast width as the fuse runs out, so a hit is always something the player was
shown in time to move out of. The interval tightens from
CFG.bombIntervalStart to CFG.bombIntervalEnd with cinder.progress(), and
past TUNE.burstProgress the vent throws pairs. CFG.maxLiveBombs caps what
can be in the air, and cinder.state.liveBombs always matches.
What it emits
bomb.spawned — on launch:
{ entity, id, marker, x, y, z, targetX, targetY, targetZ, fuse }
entity is the live entity proxy; id and marker are the raw ids of the
bomb and its landing marker. target* and fuse are there so a look or a
sound can lead the impact rather than react to it.
bomb.impact — on landing:
{ x, y, z, hitPlayer }
hitPlayer is true when the landing caught the player — inside
CFG.bombRadius horizontally and TUNE.hitVertical vertically, so a bomb on
the rim does not hit somebody on the flank directly below it. The bomb and its
marker are despawned before the event fires, so anything dressing the impact
owns the ground it lands on.
Its own numbers
M.TUNE holds what shapes the bomb itself — scatter, lead, arc height, marker
size, spin, vent placement. cinder.CFG holds what the whole game shares:
interval, radius, fuse and the live cap. Nothing else edits either.
Cleaning up
reset() sweeps by entity name (cinder_bomb_*) rather than by its own list,
so a hot reload that dropped the list still cannot leave a bomb hanging in the
sky. The director calls it at the start of a run, at the end of one, and when
it is destroyed.
Scoped to this part · feeds back into the world's score.