BOSSES

— / 10
LOADING...

Boss entrance

A boss is not entered like a wild encounter. Pressing the challenge in the den plays a themed entrance first, and the battle only becomes playable when it finishes. It is deliberately longer than the wild intro — roughly 4.2s against 2.65s — and it is skippable with a click at any point.

Sequence

StageAtWhat plays
00.0sThe screen drops to near-black behind a radial veil and the whole overlay shakes three times. The boss art sits at 15% opacity, oversized, waiting.
11.1sThe sigil ignites: an N-pointed star in the boss's own type colour, scaling up from 55% and turning slowly, with a contracting ring around it. 110 particles burst outward in the same palette. The boss art rises to full opacity.
22.4sThe art settles from ×1.14 to ×1.00 and starts breathing. The name plate drops in: floor number, boss name, and its type line.
—4.2sThe entrance ends and the phase becomes select. The action menu arms 0.4s later.

The entrance phase is bintro. It is never persisted — persistBattle only writes from select onward — so a reload during the entrance cannot strand a player in it. A click anywhere calls skipBossIntro(), which clears the timers and jumps straight to select.

Theme

The palette and the sigil's point count come from the boss's primary type (Boss_Type_Primary in bosses.csv), through the BOSS_THEME table in the client. Each entry is two colours — a body colour and a brighter highlight — plus the number of points on the star. Every type in creatures.csv has a row; an unmapped type falls back to the codex gold. Examples:

TypeColoursSigilBoss
Aquatic#2f7fd0 / #8fd8ff5-pointFloor 20 — Pelagos, the Trench Warden
Serpent#4f9a5c / #9fe0a87-pointFloor 30 — Sethek, the Ossuary King
Amphibian#3f9a7a / #9fe8cf5-pointFloor 70 — Morast, the Bogfather
Construct#8a8f9a / #dfe6f04-pointFloor 100 — The Godforge

Retuning a type is a one-line edit to BOSS_THEME; no art is involved, the sigil is a CSS clip-path polygon generated by sigilPoly(points).

Preview any boss's entrance without spending a key: /dev/?scene=bossintro on the floor below that boss.

Boss Names — Full vs Short

Every boss carries two authored names and they are not interchangeable:

The short name is AUTHORED, never derived. Splitting Boss_Character on its comma is wrong: floor 40 yields Mother Vesk, not Vesk. Any future boss must fill the column by hand. bossData() falls back to Boss_Character when the column is blank, so a missing value degrades to the old long-name behaviour rather than to an empty plate.

Why it matters mechanically: the battle plate is a fixed 300px box and plateNameFs() shrinks the name to fit around the Lv chip and the type medals, down to a floor of 8px. A 28-character name drove the floor and rendered unreadably small — reported live on floor 40 (feedback #11). Short names sit at the 19px maximum.

Source: codex/bosses.csv — columns Boss_Name, Boss_Character, Boss_Short_Name

Respawn — the gravestone

Re-entering a boss room does not respawn the boss. After it dies a gravestone stands in its place and counts down from 10 seconds; at zero the boss returns in place. Keys are the rate limit, not the timer — the gravestone is a beat, not a gate.

Why the repaint is the whole fix (report #18). The respawn was always time-based, so re-entry never respawned anything. What was missing is that nothing repainted while it counted: challengeBoss() calls clearTimers(), so after the fight there was no timer left to redraw the room. It sat frozen on whichever second the fight ended on, and the boss appeared to return only after walking a floor and coming back — because the window had quietly elapsed on the way. Reported as "the CD to fight it again doesnt show and the game just stay there doing nothing".

The room has to say what it is waiting for. Until 2026-08-03 it did not. app.js computed challengeLabel — THE ALPHA STIRS… while the gravestone counts, ⚯ CHALLENGE THE BOSS when it is up, REQUIRES A BOSS KEY when it is up and you hold none — along with chOn, chColor, chBg, chBorder and chCursor, and the markup bound none of them. The only affordance in the room was the boss artwork itself. That is the rest of report #18: the gravestone fix restored the countdown, but nothing ever announced that the boss had returned, so the room still read as idle. The label is a sibling of both the bossPresent and bossRespawning gates, because it is the one element that must speak in every state.

Client: BOSS_RESPAWN, startGraveTick(), bossDownAtFor(), bossRespawning(), ensureTicker() in play/app.js. Probe: tools/probe_grave.py (6/6).

Where a boss win leaves you — the den, never the boss floor

A boss floor is a den only. It has no wild map and no spawn pool of its own, and travel() enforces that outright: any trip that computes an x0 target steps past it (“boss floors have no wild map — never land on them”). A boss win therefore leaves the player standing in the den, in phase:'bossroom', with the gravestone counting in front of them. floorNum stays on the approach floor it was on before the fight.

Why this was three separate bug reports (#38, #42, #45, measured 2026-08-07). The victory commit set floorNum to the boss floor and blanked floorPool, and toFloor() then opened that floor as an ordinary room. Three symptoms, one cause. The countdown never appeared — startGraveTick() was running the whole time (_graveT measured true) but the countdown lives in the den view and the den was not mounted. It appeared only after leaving and coming back — because coming back is what mounts the den. SPAWNS EXHAUSTED — 4/10 · NEXT IN 50s — the drought pill firing on a floor that has no spawns by design, against a pool that was empty and, measured over six seconds, was never going to fill. Reading the source would have found none of it; the room had to be opened and looked at.

Client: vicWasBoss, toFloor(), dispFloor, feedbackCtx() in play/app.js. Probe: tools/probe_bossreturn.py (9/9).

Reaching a den — the three doors

Every route into a boss den ends in enterBossRoom(), which derives its target from bossFloor() — the current floor's decade. It therefore cannot be called from another decade, and that constraint is what shapes all three doors.

Status: LIVE on release since 2026-08-06 (0.34). The key button first shipped landing on the approach floor whenever the player stood outside that boss's decade, and it said GO TO FLOOR N when it did. Reported the same day (D, 2026-08-05): “using the boss key button is taking me to the room below it instead”. Reproduced by driving the real button from floor 45 with a floor-20 key — it landed on floor 19, phase 'floor'. Verified by tools/probe_keyboss.py (8/8; the unfixed build fails three, including the approach-only case a strict gate would have refused outright).

None of the three spend the key. A key is consumed by challengeBoss(), at the challenge, not at the door — walking into a den and leaving costs nothing.

Client: itemDetBoss(), keyBossOk(), travelToBossRoom(), enterBossRoom() in play/app.js

Which key a boss takes

A boss on floor B takes the key that drops across the nine floors below it — B−1 down to B−9. The floor-10 boss takes the key found on floors 1–9, the floor-100 boss the key found on 91–99. Keys do not drop on boss floors themselves, which is why the drop table has no row for them.

Keys are strictly per zone. A key opens the boss it belongs to and no other. Until v0.34 a fallback counted any item tagged as a key whenever no zone row resolved — which was exactly on a boss floor — so a Grasslands key could open the floor-100 boss.

The count is asked of the boss, not of where you stand. The number shown, the challenge gate and the key actually spent all resolve against the boss being challenged. The older lookup used the floor the player occupied, which gives the right answer while climbing and the wrong one the moment a player stands past a boss and looks back at it — ten keys reading as zero from one floor above the boss they belonged to.

All ten of these bosses come back. The Void Apex postgame zone (floors 101–120) fights them again in mutant form, in the order they were first met — Vargr on floor 102 through Eskaton on floor 120 — at level 100 with Void quality, uplifted grades, tier-3 AI and one signature rule each. Kits and actives are inherited from the rows on this page unchanged; portraits are the deterministic mutant recolours of the art here. Data: the floor 102–120 rows of codex/bosses.csv — the separate uber_bosses.csv was folded into it and deleted, so one lookup resolves any boss by floor. LIVE on release since 0.48 (2026-08-13).

What a boss drops — and the odds, in the game

Every boss kill drops one piece of gear and one egg (boss_loot.csv Gear_Guaranteed_Per_Kill, Egg_Guaranteed_Per_Kill), resolved by the server. The gear's grade is rolled on drop_grade_weights.csv one floor band ahead of the boss's own band (Gear_Grade_Band_Rule = one_band_ahead; Apex rows are one floor wide, floor 120 reads itself; Divine and above never drop); the egg's line is weighted by rarity (Egg_Line_Weight_C…SSR, 30/30/20/10/10) and its grade is band-rolled and capped at Legendary. The full tables are on droptables.html.

Since 2026-10-22 the game shows the same numbers itself: the CODEX window opens with a BOSS DROPS strip for the next boss on the player's climb — the guaranteed counts, each grade with its percentage for the band the boss rolls, and the egg-line split — read off the same two CSVs at load, the way the hatch screen shows its odds. It is a display, never a draw; the roll stays the server's. No real money or Wraithgold buys a chance outcome anywhere in the game (Wraithgold buys slots, pens and timed boons at fixed prices), so no paid-draw disclosure is owed; this strip exists because D asked for boss drop odds to be visible.

Changelog