Systems
The machinery underneath: how damage resolves, how score is earned, how the audio tracks a run, and how these pages are generated.
Combat
Two damage entry points
takeDamage is the one every weapon uses: it respects invulnerability frames,
shields, mitigation and the shield enemy's guard arc, and it returns whether the hit
landed. takeDamageRaw skips all of it and is for damage-over-time ticks
that have already been gated elsewhere. Anything that rewards you for hitting — life
steal, combo, on-hit procs — has to check the return value, or it pays out on hits that
were refused.
Invulnerability frames are shared
An enemy that has just been hit ignores further hits for a moment. This is what stops a multi-hit effect from deleting a boss in one frame, and it is also why an orb passing through a crowd does not double-dip on the enemy it is touching.
Every status ticks in one place
Burn, bleed, freeze, chill, stun, curse and root all tick in a single function on the base enemy, so every status a card applies is guaranteed to run.
Telegraphs match their hitboxes
Ground circles are drawn flattened for perspective, and every one is drawn at the radius its damage actually uses, so a boss slam or a meteor never hits outside the circle it drew.
Enemies go round trees by how much room there is
Everything rests on one number, clearance: how far a point is from the nearest solid
box.
Routes are planned for each body size. One distance-to-you map per size of body on
the field, over a 32px grid round you, where a cell is open only if a body that size fits
there and costs more the tighter it is. So a Brute is never sent at a gap only a Mushroom
fits through: it goes round. If you are somewhere it cannot reach at all, it waits in open
ground until you come out, rather than wedging itself in the mouth of the gap and corking
it for everything behind. A step between two cells only counts if the straight line
between them has room all the way along, so the front of a queue never backs in and out
of a gap it cannot take.
Steering keeps its distance. Every frame the body scores the headings round the one
it wants by how well they point and how much room they leave, so it swings wide of a trunk
early instead of meeting it and sliding.
Bodies are tested at their feet against the real obstacle boxes, not at the sprite
origin (which sits on the creature's head). Knockback and the drag of a Black Hole,
Singularity or Gravity Snap go through the same collision, so nothing is thrown through a
tree either.
The horde keeps its shape. Bodies ease apart rather than stacking, bigger ones
shouldering smaller ones aside, so a crowd forms a ring round you instead of a single pile
an orb could clear in one strike. Anything dashing is exempt, anything frozen or holding
you stands firm, and whatever a crowd-control card is dragging is left to be piled up.
Enemies arrive from just outside the camera's view — the real view, which stops at the
map's edge — and one left far out of sight for a few seconds is brought back to just off
screen ahead of you. Bosses are never moved. Once the wave has nothing left to send and
three or fewer remain, arrows at the screen edge point to them.
An orb that gets stuck lets itself out
Two obstacles with a narrow gap between them can hold a thrown orb indefinitely, because
nothing damps a wall bounce enough to end it. So the orb frees itself: if it has not
travelled more than a short distance for about a second and a half, it checks whether it is
in a pocket, and phases out through the scenery if it is.
Confinement is what marks a pocket, not speed, since a slow trapped orb comes to rest
inside the gap. It samples a ring round the orb: a flat wall the orb has rolled up
against blocks at most half of it and is reachable on foot; a gap or an inside corner blocks
more. An orb already at rest is nudged toward you as well, since phasing alone does nothing
for something with no momentum.
Recall does not phase. A recalled orb comes home round the scenery, bouncing and
sliding off it, and if a tree catches it you can step aside, since the pull comes from
wherever you stand. A pull that cannot arrive gives up after five seconds and the orb flies
on at the speed the pull gave it. The escape above stands down while the orb is being
recalled.
Hits land with weight, not lag
Each hit on an enemy freezes the game for a few hundredths of a second. Every freeze adds heat that drains over time and scales the next one down: a lone hit, or hits a second or more apart, get the full freeze; a rally goes 0.12, 0.06, 0.03, 0.01s and then nothing, and the punch comes back after a short breather. Screen shake fades the same way under rapid hits. Hitting a tree freezes and shakes nothing.
Damage numbers
Bigger hits climb a colour ladder: white under 20, yellow 20+, orange 50+, red 100+, magenta 200+, purple 350+, cyan 500+, blue 700+, gold 1,000+, white-hot with a red glow from 1,500, and cycling through the rainbow from 2,000. Each step is also drawn a little larger. Crits add a "!". Burn ticks, heals and damage you take keep their own fixed colours.
The combo ladder
Consecutive hits inside a window. Several cards scale off it, and the audio tracks it — every kill fires a confirm pitched to your current tier, so the sound of a run climbing is information rather than decoration.
| Tier | At | |
|---|---|---|
| COMBO | ×1 | where every combo starts — nothing is promoted into it |
| NICE | ×5 | promotes here: a banner, and the next rung of the streak |
| SLICK | ×12 | promotes here: a banner, and the next rung of the streak |
| WICKED | ×25 | promotes here: a banner, and the next rung of the streak |
| SAVAGE | ×45 | promotes here: a banner, and the next rung of the streak |
| RUTHLESS | ×75 | promotes here: a banner, and the next rung of the streak |
| BRUTAL | ×120 | promotes here: a banner, and the next rung of the streak |
| UNREAL | ×190 | promotes here: a banner, and the next rung of the streak |
| LEGENDARY | ×300 | promotes here: a banner, and the next rung of the streak |
| GODLIKE | ×500 | promotes here: a banner, and the next rung of the streak |
Score
Score comes from kills, weighted by what died and multiplied by the wave's modifier and composition, plus a survival term. An elite is worth more than the trash it spawned among; a boss is worth more again. Records persist between runs, and the difficulty a run was played on is recorded with it — a HARD score and an EASY score are not the same number and are not stored as though they were.
Sound
Crossing a tier fires the next rung of the streak ladder, built the way a Valorant kill streak is: one instrument, and every rung a clear step higher and a little bigger than the one before. Each is a quick run up to its note, from C5 at the first tier to C7 at the last, and the last one is an event of its own, with a chord that blooms underneath and sparkle off the top. There are six rungs and ten tiers: the first five promotions climb the first five rungs, BRUTAL, UNREAL and LEGENDARY replay the fifth pitched up to G6, A6 and B6 so the climb keeps rising, and GODLIKE keeps the last rung to itself.
Voices and rate limits are central, not per-caller. A pool of sources per sound key lets one overlap itself where that overlap is the feedback, and pins announcements to exactly one, since two wave-clears at once is always a mistake. Minimum spacing is enforced in one place, because the callers that get this wrong are exactly the ones that never think about audio — a per-frame branch in an enemy update, a damage tick in a crowd.
Sounds are placed where they happen — against the middle of the camera's view, with a gentle fade: full volume anywhere on screen, easing to about a third a screen or so beyond it, and a soft pan that never puts a sound hard in one ear. Your own orb's sounds keep a floor, so your weapon connecting is always audible. Every effect is made mono when it loads so this applies to all of them.
Nearly every sound in the game is synthesised by a Lua script in the repo rather than licensed, which is why they sit together tonally — including a voice of its own for every card that fires an effect: Void Pulse, Crescendo, Death Nova, Thunderclap, Volatile Core, Rupture, Aegis's parry, the Owl's strike and Slingshot's arming click. One bought sound was kept: the orb recall.
How this wiki is built
Two commands, run from this site's own repository against a checkout of the game.
tools/dump_main.lua runs under LÖVE, loads the game's own modules, and writes
every definition table to JSON — including the ones that are
file-local and therefore invisible to an ordinary dumper. Those are recovered
through debug.getupvalue, which is how unlock waves, spawn weights, stack caps
and prerequisites reach this site without anyone retyping them.
tools/build.mjs then renders docs/ from that JSON plus the
hand-written prose in content.mjs. The split is the point: if a fact could have
been derived and was typed instead, it is a bug waiting to drift.
Enemy portraits are not copied out of the sprite folder. 16
of the 23 types borrow another one's art, so tools/portraits_main.lua renders each frame through
the same recolour shader the game uses at draw time — a hue rotation in YIQ, or a multiply
tint for the sprites with no chroma to rotate. Copying the PNGs would produce a bestiary in
which a third of the roster is the same picture repeated.