The Last Fire
Reference · built from the game's own data

The Last Fire

A first-person sword-and-sorcery game for the browser: wave after wave of the dead in a procedural stone maze. This is its working manual, in six phases and an update log, with every figure read from the files the game runs on, and the October 2026 polish update (the sword swing, stamina, boss levels, the maze landmarks and the model fixes) in five more parts.

Play the game: public beta ›    The player's guide    The front door

Start hereOverview & System Flow

The game is the Endless Vigil: a sword in one hand, a shield in the other, a few spells, and a stone maze that fills with the dead wave after wave (Three.js, in the browser). This page is generated: every number and name below is read from the game's data files and source when you run npm run docs, so it says what the game does, not what it was once meant to do.

21 × 21cells in the maze, each 6 m across
5 sbreak between two waves
6rarity tiers, Common to Mythic
15swords and shields to carry
141events the systems talk through
71.glb files in the catalog

Seven fighters, five maidens

The opening screen: the five maidens in front, and behind them Iron Knight, Veiled Matron, Drowned Lich, Ember Tyrant, Forge Golem, Bone Colossus
The opening screen (a screenshot of data/title.json's diorama). Each of the five bosses that hold a maiden frees her the first time it falls, and she joins the middle of the maze. Iron Knight and Hollow King hold none. Once the ending has been seen in a browser, Hollow King stands veiled at the back of this screen too.
The fighters in order: the Iron Knight on every 5th wave that is not a boss wave, the bosses on waves 10, 20, 30, 40, 50, the Hollow King once on wave 60 and then the five round again from wave 70 (src/data/vigil.json waves)
FighterFirst waveHoldsWhat beats itFirst kill drops
Iron Knight5–bombs (×2.5 through its plates) and a perfect parry (2.5 s of stagger)Executioner's Greatsword, Dreadguard Damned Shield
Bone Colossus10● Golden Elfany spell that lands while it winds up an attack (3.5 s on its knees)Spire of the Drowned Lich, Pulsing Heart of the Colossus
Drowned Lich20● Silver Frost Elf3 Ice Shards freeze it, then a fireballRelic Sunblade, Aegis of the Forgotten
Veiled Matron30● Shadow Elflight: a fireball, a Moon Wave, a torch lit again beside it or the Veil-Piercing LensVeilbreaker Lantern, Shroud of the Matron
Ember Tyrant40● Emerald Elfits own fireball turned back by a mirror shield, and lightning for its platesTyrant's Ember Mace, Ember Crown
Forge Golem50● Crimson Elfa Rune Bomb that bursts in its furnace while it inhales (5 s on its knees)Forge Hammer, The Keepers' Songbook
Hollow King60–a different fire in each of its 5 pools: a fireball or Rune Bomb that bursts in him while he winds up his moonfall; any spell that lands while he winds up an attack; 3 Ice Shards (then a fireball thaws him for +40); light (a fireball, a Moon Wave, a torch lit beside him, or the Veil-Piercing Lens; once in 15 s); his own moonfire or moonbeam turned back by a mirror shieldThe Hollow King's Sword

The core loop

  1. Title screen. A diorama of the 5 rescued maidens, the 7 fighters behind them (Iron Knight, Veiled Matron, Drowned Lich, Ember Tyrant, Forge Golem, Bone Colossus, Hollow King) and the loot, with Continue (if a save exists) and New Game, under the title The Last Fire and its subtitle Vigil for the Dying Moon. The click that starts the game also unlocks the sound. The first time a new game is begun in a browser a short crawl tells the tale first (4 paragraphs of The First Watch, climbing a brick wall lit by two flickering torches: any click, Esc, Space or Enter skips it, and Read the tale on the title screen plays it again); the mouse is captured when the run begins.
  2. A wave. Wave n brings 3 + 2 × (n − 1) enemies, each placed where it could reach you within a few seconds of walking, so the early waves are never a long search through the maze.
  3. The fight. Slash, block, parry and bash; cast fire, ice or lightning with Shift + click; throw a Rune Bomb with G; use the item in the active slot (a stagger horn, a lantern that shows the Shades, a step through a wall) with V, when its cooldown allows. Potions and mana crystals lie in the maze every wave, and walking over them uses them.
  4. The wave is cleared. You score a bonus of 500 × the wave number, a checkpoint is saved (and written to the browser), and after 5 s the next wave starts.
  5. Every 5th wave the Iron Knight comes alone; every 10th a boss comes alone (Bone Colossus, then Drowned Lich, then Veiled Matron, then Ember Tyrant, then Forge Golem, then again). A fallen boss drops its exclusive loot, a maiden it held captive is freed and runs to the middle of the maze, and picking up the reward saves a checkpoint.
  6. A fall. A 3 s screen, then you stand up at the newest checkpoint with the health and mana you had then (at least 50%), carrying everything you carry. A fall before the first wave is cleared ends the run.

Controls

Controls (from src/data/player.json and the title screen)
ActionInputWhat it does
MoveW A S D and the mouse6 m/s; the mouse looks (the pointer is captured by the first click)
SprintShiftx1.6, 9.6 m/s, while the stamina lasts (part B). The same key turns a click into a cast
DashF4 m along the move keys (a backstep with none held) in 0.2 s, for 30 stamina, with 0.12 s of invulnerability (part B)
JumpSpaceJump force 8, gravity 20
AttackLeft clickA slash with the sword in hand: forehand, then backhand (Phase 1). On a marked enemy (staggered, guard-broken) the blow is an execution (part A)
BlockRight click (hold)Raise the shield. A block raised just before a blow is a perfect parry. Every blow the shield stops wears down the guard meter (100 points); at 0 the guard breaks and you are staggered for 1.2 s (Phase 1)
Lock onTab (tap: lock the nearest in front, tap again: the next, hold 0.3 s: let go)Z-targeting: the view turns to the target's chest, W / S walk at and away from it, A / D circle it, the dash becomes an orbit hop, a lunge or a backstep. Enemies in a 25° cone within 20 m; it lets go after 1.5 s behind a wall (Phase 1)
MapMThe corner radar grows into a big translucent map of the whole maze (85% of the screen) and back. The game does not pause: walk, look and fight with it open
Shield bashLeft click while blockingA short shove that breaks a raised guard
Cast a spellShift + Left clickCasts the selected spell. With too little mana nothing is launched and the shield does not move
Select a spell1 / E fire, 2 / Q ice, 3 lightningSelecting is free and can be done at any time; casting is the click
Throw a Rune BombGNeeds bombs in the bag (they are found in the maze)
Use the active itemVThe one item in the active slot (a stagger horn, a lantern that shows the Shades, a step through a wall) goes off, then its own cooldown runs; it does nothing while a choice of passive is open, on your knees or with nothing in the slot. Walking over one takes it; the use key swaps it
Pause` or EscThe world stays on screen, frozen. Losing the mouse also pauses
CodexC (and again, or `, to close)The book of what this run has met and found: the world is frozen behind it, the arrows Left/Right turn the tabs and Up/Down go down the list (a click works too)
Rise againROn the FALLEN screen (a fall before the first wave is cleared): a new run

The codex

Press C to open the codex: a book of what this run has met and found, 88 entries in 6 tabs, made from the same data as this page (creatures from enemies.json, items from items.json, places from the landmarks' own words in vigil.json). An entry reads ??? until its first kill, find or use; the first time is announced once in a small line ("Codex: Zombie (1/88)") and never again. An item is found by picking it up or by looking at it where it lies (the same nameplate as in the maze). The book is saved with the checkpoint, kept through a fall and empty in a new game. Its last tab, Lore, holds every line a maiden says and every stanza carved on the wall (Phase 6): they are entries of kind lore in codex.json, unlocked by lore:spoken and lore:carved.

The tabs of the codex (data/codex.json) and what unlocks their entries
TabEntriesHow to record oneUnlocked by
Creatures8Kill one to record itenemy:died
Champions and bosses7Bring one down to record itenemy:died
Items37Pick one up, or look at it where it liesitem:gained item:seen
Places11Find it, or use itstanding within 8 m of the ruins landmark:found bell:rung gate:changed
The Song6Find the Keepers' Songbook, then hear each verse sungsongbook:found verse:began
Lore19A maiden speaks when you first visit her; a stanza is cut when a boss fallslore:spoken lore:carved

Architecture in one page

The game is a small entity-component world. Entities are ids; components are plain data (Health, Transform, AI ...); systems are the only code that changes them. Systems never import each other: they read the world, listen to events (141 named facts such as hit, wave:cleared or checkpoint:saved, all in src/core/eventNames.js) and announce new ones. Each component has exactly one system that may write it, which is how "who changes the player's health?" always has one answer: Combat.

Game-flow states

  1. Title
  2. Vigil
  3. Paused
  4. Codex
  5. Results
  6. Settings

Title → Vigil. The Vigil hands over to Paused or Codex (and back) and to Results (the FALLEN screen). The loop runs logic at a fixed 60 Hz and draws once per screen frame, blending the last two ticks.

What runs every tick, in this order (src/scenes/VigilScene.js)

  1. Player
  2. Actives
  3. Stamina
  4. FlowField
  5. AI
  6. Combat
  7. Boss
  8. Spells
  9. Hazards
  10. Movement
  11. Collision
  12. Inventory
  13. Inspect
  14. Progression
  15. Marks
  16. Challenge
  17. Landmarks
  18. Torches
  19. Gates
  20. Waves
  21. Captives
  22. Hub
  23. Lore
  24. Ending
  25. Codex
  26. Corpses
  27. HitStop
  28. Animation
  29. FX
  30. Audio
  31. HUD

Input becomes intent (Player), enemies decide where to go (FlowField, AI), attacks start (Combat, Boss, Spells), things move (Movement), contacts are found (Collision), the rules react (Inventory, Waves, Captives), and last come the presentation systems (Animation, FX, Audio, HUD). Render runs once per drawn frame instead of per tick.

One swing, end to end

  1. Player: player:swing (windup)
  2. Player: player:strike
  3. Combat: a one-tick Hitbox
  4. Collision: contact:hit
  5. Combat: the damage rules
  6. hit / enemy:died
  7. Waves: loot and score
  8. Audio · FX · HUD · Animation react

One cleared wave, end to end

  1. Waves: wave:cleared
  2. Waves: checkpoint:saved (a snapshot)
  3. the scene writes SaveGame to localStorage
  4. HUD says "Checkpoint saved."
  5. break
  6. wave:started
Who may change what (src/components/index.js: the one-writer rule, checked live in dev builds)
ComponentThe only systems that may write it
TransformMovement Spawner
VelocityPlayer AI Captives Spawner
MotionMovement Spawner
ColliderActives Spawner
HealthCombat Spawner
PoiseCombat Spawner
GuardCombat Spawner
GuardMeterCombat Spawner
ComboCombat Spawner
HitboxCombat
ManaSpells Spawner
StaminaStamina Spawner
LevelProgression Spawner
PurseMarks Spawner
CodexCodex Spawner
GateGates
TorchTorches
HazardHazards Spawner
CorpseCorpses
NemesisSpawner
MinionSpawner
DownedCombat Spawner
EliteSpawner
BellChallenge
LandmarkLandmarks Spawner
ProjectileSpells Spawner
AIAI Spawner
BossBoss Spawner
HubHub
LoreLore
EndingEnding
CameraShotEnding
CaptiveCaptives Spawner
EnemySpawner
PlayerControlPlayer Spawner
EquipmentInventory Spawner
AlliedActives
ActiveActives Spawner
PickupSpawner
ModelAnimation Spawner
RunWaves Spawner
The data files: every number the game uses lives in one of these (src/data/*.json); the page you are reading is built from them
FileSizeWhat is in it
catalog.json16.2 KBEvery model file in assets/models, what it is called and how the game uses it: the single list behind the compendium in docs/index.html (npm run docs) and a check that every file has a name.
codex.json15.7 KBThe codex: a book of everything the player has met in THIS run. Entries are made from the game's own data (util/codex.js entriesOf): a creature from enemies.json, an item from items.json, a place from this file with its name and w ...
enemies.json69.0 KBEnemy definitions. Version 52 numbers for the zombie / skeleton / demon; the rest follow the roster in the Mechanics Design doc,
environment.json1.6 KBSky, fog, moon and lights (Version 52 numbers). Colours are sRGB hex strings.
items.json28.3 KBPickups. Everything the player can walk into and collect (XZ pickup radius 1.2 = 0.5 player + 0.7 item).
mobile.json1.6 KBThe phone's version (the page /m/, or ?device=mobile in `npm run dev`): the same game with its touch controls (ui/TouchControls.js, data/player.json touch) and a lighter picture. `overrides` is a list of 'path: value' written over ...
models.json2.9 KBEvery model file the game loads: key (what the code and src/data/*.json call it) -> file name in public/assets/models.
patchnotes.json14.2 KBPlayer-facing release notes, newest first (shown at /patch-notes/; tools/lib/patch-notes.mjs checks and renders them). build: the number of commits in git's history at the end of the release, the same number the foot of every page ...
player.json15.8 KBPlayer body, movement and camera (Version 52 numbers).
progression.json17.3 KBTHE SONGBOOK'S FIVE (30 Oct 2026 design, built 1 Nov 2026): a perk with `requires` names an artifact (items.json) the player must carry before it is offered, in a level's choice or in her swap (util/progression.js candidates). The ...
rarity.json3.1 KBThe six rarity tiers. rank orders them (the smart pickup compares ranks); color is the one colour of the tier everywhere: the name on the hover nameplate, the halo on the floor, the gear panel, the compendium.
settings.json11.6 KBThe settings screen (core/Settings.js owns the values, util/settings.js is the arithmetic, ui/Settings.js draws it, scenes/SettingsScene.js opens it from the title screen and from the pause).
sounds.json40.3 KBEvery recorded sound effect, made with ElevenLabs Sound Effects from the prompts in docs/SFX_LIST.md, files in public/assets/sounds.
spells.json2.7 KBPlayer spells (Version 52 numbers). Lightning is not in the Phase 1 design doc yet; kept so the port plays like V52.
title.json13.0 KBThe title screen's diorama (scenes/TitleStage.js): a moonlit dais with the five maidens in front, the five fighters (the Iron Knight, the Veiled Matron, the Drowned Lich, the Ember Tyrant and the Bone Colossus) in an arc behind th ...
vigil.json109.9 KBEndless Vigil: the procedural maze + wave survival mode (Version 52 maze and torch numbers; the roster, champions, bosses and rewards follow the Mechanics Design doc).
weapons.json22.8 KBFirst-person sword, shield and spell orb (positions are camera-space), plus the tiers the player can carry.

The game-ready models in public/assets/models are 71 files, 85 MB, made from the raw exports in assets/models by npm run optimize:models; the catalog in Phase 5 names every one.

Phase 1Combat & Vitals

100health to start with
100mana to start with
8 / smana regeneration, always
6 m/swalking; 9.6 sprinting
0.18 sperfect parry window
0.5 sbetween two spells

The sword: a slash, not a thrust

Left click is a slash. The hand draws the blade back and up, cuts across the view and carries through, and the next swing comes back the other way: odd swings are the forehand (high on the left to low on the right), even ones the backhand. The path is a short list of keyframes in weapons.json sword.slash, smoothed into a curve; a standard swing takes 0.36 s, a heavy weapon swings slower (its own swingTime). The swing has three beats (windup, strike, follow-through: see part A, Animation & Combat Polish) and the blow lands part-way through it, at 0.14 s for a standard swing: the hit volume exists for one tick and hits everything inside the weapon's reach and arc. The arc is a cone round the crosshair: ±73° for most blades (it used to be ±60°, a poke), wider for the Greatsword and a full sweep for the Spire.

Swords (src/data/weapons.json swords): what each tier does
SwordRarityDamagevs WornSwing everyDPSReachArcKnockbackPerks
Worn Iron SwordCommon #9E9E9E15×10.35 s432.6 m±73°0.8none
Footman's Flanged MaceUncommon #4ADE8020×1.30.36 s562.5 m±73°1.3none
Tempered Moonsteel BladeRare #38BDF828×1.90.33 s852.7 m±73°1.8chills to 60% for 2 s
Executioner's GreatswordEpic #A855F742×2.80.4 s1053 m±81°2staggers non-bosses 1 s
Cursed Damned BladeEpic #A855F744×2.90.36 s1222.8 m±73°1.6staggers non-bosses 0.6 s; chills to 60% for 2 s; Moon Wave at full health, 38 damage
Spire of the Drowned LichLegendary #F59E0B60×40.38 s1583.2 m±96°2.2chills to 45% for 2.5 s; cleave: more than a half-circle
Relic SunbladeMythic / Relic #EF444485×5.70.36 s2363 m±73°2.6staggers non-bosses 0.5 s; spells ×1.25
Tyrant's Ember MaceMythic / Relic #EF444495×6.30.44 s2163.3 m±84°3.2staggers non-bosses 0.8 s
Forge HammerMythic / Relic #EF4444100×6.70.5 s2003.1 m±84°3.4staggers non-bosses 1 s
The Hollow King's SwordMythic / Relic #EF4444110×7.30.4 s2753.2 m±73°2.4staggers non-bosses 0.5 s; chills to 50% for 2 s; spells ×1.25

Rarity and strength. The six tiers hit for Common 15, Uncommon 20, Rare 28, Epic 42–44, Legendary 60, Mythic 85–110 (the bands in rarity.json). The design list names the steps "base", "+25%", "+50%", "+100%", "+150%", "+200% or more"; its percentages and its damage bands do not quite agree, and the game follows the bands, so the "vs Worn" column is the real multiple.

The shield: block, bash, parry

Shields (src/data/weapons.json shields): what each tier does
ShieldRarityStopsGuard drainBash damageBash ready everyParry manaReflects spellsSpell power
Splintered Wooden ShieldCommon #9E9E9E80%×1100.8 s–––
Soldier's Iron ShieldUncommon #4ADE8085%×0.85140.68 s–––
Dreadguard Damned ShieldEpic #A855F792%×0.7250.6 s+15––
Moon-Mirror AegisLegendary #F59E0B95%×0.6300.56 s+15×2–
Aegis of the ForgottenMythic / Relic #EF444497%×0.5400.52 s+20×2.5×1.5

The guard meter

A raised shield has 100 points of guard. Each blow it stops takes the blow's damage times the shield's guard drain off the meter (the Splintered Wooden Shield pays all of it, the Aegis of the Forgotten half), and the blow that empties it breaks the guard: the shield drops, you are staggered for 1.2 s with the view sinking, and the shield cannot go up again until the meter has refilled to 20. It refills 25 a second once the shield is down and 1 s have passed since a blow. A perfect parry, a reflected spell and fire on the ground cost it nothing, so the answer to a slam is still to parry it, dodge it or be elsewhere. The bar sits under the health bar: steel blue, orange and pulsing when low, red and shaking with the words GUARD BROKEN while it is down. The guard meter is the player's own, in the GuardMeter component that only Combat writes; the enemy's Guard is a different thing (the shield a Shield Skeleton holds up).

The guard meter by shield (src/data/weapons.json guard and shields.<tier>.guardDrain): what a stopped blow of 30 takes off the meter, and how many of them break the guard
ShieldGuard drainA blow of 30 costsBlows of 30 to break the guardGets through to health
Splintered Wooden Shield×13046
Soldier's Iron Shield×0.8525.544
Dreadguard Damned Shield×0.72152
Moon-Mirror Aegis×0.61861
Aegis of the Forgotten×0.51570
The guard meter: the rules (weapons.json guard, systems/Combat.js, systems/Player.js, util/guard.js)
RuleValueNotes
The meter100 points, full at the start of a runa fall and a rise, a fountain and a loaded game fill it; guard.enabled false removes the whole rule (a raised shield holds for ever, as it did)
What drains ita blow the raised shield stops: its damage × the shield's guardDrainmelee, charges, slams, arrows and blasts alike. The share that still gets through to your health is the shield's block factor, as before
What costs nothinga perfect parry, a spell the Mirror shield throws back, fire on the grounda parry is no guard loss; the flames at the feet are not stopped by a shield at all
Refilling25 a second, 1 s after the last blow it took, with the shield DOWNa shield held up that nothing hits does not refill: holding it is not resting
The breakthe blow that empties it: PLAYER_GUARD_BROKENthe shield drops and you are staggered for 1.2 s: no walking, swinging, bashing, casting, throwing, jumping or dashing (the view stays free and sinks 0.16 m); a swing in progress is lost. Blows land at full damage while it is down
Raising it againonce the meter is back to 20after the stagger you can walk and swing at once, but the shield stays down until the meter has refilled to 20 (a tick on the bar marks it)
The feedbackthe bar, a red vignette, GUARD BROKEN, a crack and a joltthe bar is steel blue with ten pips, pulses orange below 25%, and turns red and shakes while the guard is broken; the view shakes (0.6) and the shield's crack sounds

Z-targeting: the lock-on

Mouse aim stays the default; Tab is for duels and bosses. A tap locks the nearest living enemy in the cone in front of you; the view turns to its chest and stays there, W and S walk at and away from it, A and D circle it, and the dash is an orbit hop, a lunge or a backstep. A chevron floats over the target with its poise as a row of diamonds.

Z-targeting (player.json lockOn, bindings.targetLock, systems/Player.js, util/lockon.js, fx/LockReticle.js)
RuleValueNotes
LockingTab: the nearest enemy in a 25° cone within 20 malive, not behind a wall, never the player's own ally or a Shade nobody can see; the cone is measured either side of where you look
Cycling and letting goa tap while locked: the next one in the cone, nearest first; hold 0.3 s: let goa tap with nothing in the cone lets go too
It lets go by itself1.5 s with a wall in the way, 26 m away, the target dead, or you falla clear moment starts the count again
The viewturns to the target's chest (60% of its height), eased at 8 a secondthe mouse still nudges the aim: at most 12° sideways and 8° up or down, and the view eases back
WalkingW / S at and away from it, A / D round itthe radius is kept exactly (an orbit, not a straight line that drifts out); you stop 0.6 m short of it
The dashA or D held: an orbit hop; W held: a lunge; nothing held: a backstepall measured from the target, not from the view, which is still turning
The reticlea chevron over its head and 5 poise pips under ita poise blow shatters a pip; an enemy that can be executed shows the red diamond instead. Only an enemy with a poise bar (the Iron Knight) has pips

Finding the way: the map and the boss trail

M opens a big see-through map of the whole maze and closes it again; nothing is paused. In a boss or champion wave a trail of pale motes drifts down the corridors towards the fighter, so the way to it can be found in a 21 × 21 maze.

The map and the boss trail (player.json map, vigil.json trail, ui/Minimap.js, systems/FX.js, util/trail.js)
PartWhat it doesNumbers
The radarthe corner map, centred on you, with the maze as stone walls (a dark outer line and a lighter inner one), paved floors with a faint tile pattern and an accent on every crossroads in the colour of its quarter180 px, 9 cells across; north #e0a43a, east #35b5aa, south #9a6ad8, west #c8343e
The big mapM: the whole maze, translucent over the world, with the quarters named; it does not pause the game85% of the shorter side, 0.2 s ease, the veil rgba(10, 12, 16, 0.72)
Markschokes (the stubs either side of a narrow way), portcullises (bars when down, a dim arch when up), shrines, vaults (a square with a keyhole), the boss as a pulsing skulla boss beyond the edge of the radar is pointed to on its rim
Youa gold arrow and the pale cone of what you can see73° wide
The trailin a boss or champion wave, once the fighter has walked in, pale motes drift along the corridors towards itthe route is read off the flow field every 1 s, the first 5 cells of it; a mote drifts 2 m/s for 2.5 s at 1 m; none within 14 m of the boss with a clear line to it
The trail's colourspale moonlight for the Bone Colossus and the Drowned Lich, crimson for the Iron Knight, amber for the Ember Tyrant, violet for the Veiled Matron● Bone Colossus, ● Drowned Lich, ● Iron Knight, ● Ember Tyrant, ● Veiled Matron, ● Forge Golem, ● Hollow King

Spells and bombs

Spells (src/data/spells.json)
SpellSelectManaDamageBesides
Fireball1 / E2535Fire. A burning bomb detonates at once; thaws a frozen Lich for +40
Ice2 / Q2025Slows what it hits to 50% for 3 s; three freeze the Drowned Lich
Lightning34050Lightning. Kept from Version 52; the heaviest and the dearest

A spell flies at 25 m/s for up to 3 s. Spell power multiplies a spell's damage: the Relic Sunblade ×1.25 and the Aegis of the Forgotten ×1.5 (they stack, ×1.88 with both). A Rune Bomb has a 3 s fuse, 60 damage in 4 m (less towards the edge, 50% of it to you), breaks a Shield Skeleton's guard, ignores the Iron Knight's armour, and a fireball sets it off at once. The bag holds 10 bombs, 20 with the Runesmith's Satchel.

The empty-mana gate

Casting is Shift + click and nothing else: it never touches the shield. If the selected spell costs more mana than you have, the cast is refused: no spell is launched, no mana is spent, the shield and the sword stay as they are, and the player is told three ways: the message "Not enough mana!", the mana panel flashes red and shakes, a low double-blip plays, and the spell orb flashes red. A refused cast locks the next one out for 0.35 s, so a held-down click does not sound the dud sixty times a second. A plain click with the shield up (no Shift) is the bash, which costs no mana.

Health, mana and healing

Phase 2Encounters & Scaling

How many, and when they arrive

The mix: the share of each wave by kind (waves.mix; a kind not listed is 0)
WavesZombieSkeletonGhoul HoundSkeleton ArcherShield SkeletonDemonWispShade
1–250%50%––––––
3–440%30%15%15%––––
5–630%20%15%15%10%10%––
7–920%15%15%15%10%10%10%5%
10–1415%10%15%15%12%13%10%10%
15+10%10%15%15%12%13%12%13%

A champion or boss wave is that fighter alone (waves 5, 10, 15, 20, 25, 30 ...): the mix does not apply to it, so the Shield Skeleton (listed from wave 5) is first met in wave 6, and the Demon (listed from wave 5) is first met in wave 6.

Enemies are not scattered at random. Each one aims for a random arrival time: it is put in a cell from which it would reach you after about that many seconds of walking (the flow-field distance over its speed; a flyer's straight line). The window is 8 s up to 25 s in wave 1 and widens by 6 s with each wave after. A boss or champion walks in after 20–45 s whatever the wave.

Arrival windows by wave
WaveEarliestLatest
18 s25 s
38 s37 s
58 s49 s
108 s79 s
208 s139 s
308 s199 s

Difficulty: the health ramp and the tier ramp-up

Enemy damage never changes with the wave; only their health does, because the player's weapons grow about six-fold from Common to Mythic (15 to 110 damage) and arrive on a schedule. The scale applies to ordinary enemies only; champions and bosses have their own health and repeat scaling (Phase 3).

03.26.49.612.816151020304050Iron KnightBone ColossusDrowned LichVeiled MatronEmber TyrantForge GolemHollow Kingwavehealth × data
The health scale of ordinary enemies by wave. The dashed lines are the first kills of the champion and the bosses, after each of which the player carries a better sword.
Health, the gear and the level of the time, and blows to kill a Zombie / a Demon
WaveScaleZombie hpDemon hpSword carriedDamageLevel (attack)BlowBlows (Z / D)Without the level
1×140100Worn Iron Sword151 (×1)153 / 73 / 7
3×1.560150Worn Iron Sword151 (×1)154 / 104 / 10
5×1.6566165Worn Iron Sword151 (×1)155 / 115 / 11
6×2.6104260Executioner's Greatsword422 (×1.04)443 / 63 / 7
10×3.12125312Executioner's Greatsword422 (×1.04)443 / 83 / 8
11×4160400Spire of the Drowned Lich603 (×1.08)653 / 73 / 7
20×5.8232580Spire of the Drowned Lich604 (×1.12)674 / 94 / 10
21×6240600Relic Sunblade855 (×1.16)993 / 73 / 8
30×8.7348870Relic Sunblade856 (×1.2)1024 / 95 / 11
40×11.74681,170Relic Sunblade858 (×1.28)1095 / 116 / 14
50×14.75881,470Tyrant's Ember Mace9510 (×1.36)1295 / 127 / 16

The level counts. Each boss or champion that falls gives the player a level, and each level adds to the attack of the sword, the bash and the spells (part C), so the blow is the sword's damage times the attack of the level the player has when the wave starts (the same rounding as Combat); the last column is what the table said before levels. A level arrives when the boss or champion of its wave falls, so that fight itself is met at the level the player had when the wave began (wave 30 at level 6, its reward making it 7).

CommonUncommonRareEpicLegendaryMythic / Relic
02468Wave 1: 3 blows of the Worn Iron Sword (15, 15 at level 1) to kill a 40-health zombie; 3 without the level31Wave 2: 3 blows of the Worn Iron Sword (15, 15 at level 1) to kill a 42-health zombie; 3 without the level3Wave 3: 4 blows of the Worn Iron Sword (15, 15 at level 1) to kill a 60-health zombie; 4 without the level4Wave 4: 5 blows of the Worn Iron Sword (15, 15 at level 1) to kill a 63-health zombie; 5 without the level5Wave 5: 5 blows of the Worn Iron Sword (15, 15 at level 1) to kill a 66-health zombie; 5 without the level5Wave 6: 3 blows of the Executioner's Greatsword (42, 44 at level 2) to kill a 104-health zombie; 3 without the level36Wave 7: 3 blows of the Executioner's Greatsword (42, 44 at level 2) to kill a 109-health zombie; 3 without the level3Wave 8: 3 blows of the Executioner's Greatsword (42, 44 at level 2) to kill a 114-health zombie; 3 without the level3Wave 9: 3 blows of the Executioner's Greatsword (42, 44 at level 2) to kill a 120-health zombie; 3 without the level3Wave 10: 3 blows of the Executioner's Greatsword (42, 44 at level 2) to kill a 125-health zombie; 3 without the level3Wave 11: 3 blows of the Spire of the Drowned Lich (60, 65 at level 3) to kill a 160-health zombie; 3 without the level311Wave 12: 3 blows of the Spire of the Drowned Lich (60, 65 at level 3) to kill a 168-health zombie; 3 without the level3Wave 13: 3 blows of the Spire of the Drowned Lich (60, 65 at level 3) to kill a 176-health zombie; 3 without the level3Wave 14: 3 blows of the Spire of the Drowned Lich (60, 65 at level 3) to kill a 184-health zombie; 4 without the level3Wave 15: 3 blows of the Spire of the Drowned Lich (60, 65 at level 3) to kill a 192-health zombie; 4 without the level3Wave 16: 3 blows of the Spire of the Drowned Lich (60, 67 at level 4) to kill a 200-health zombie; 4 without the level316Wave 17: 4 blows of the Spire of the Drowned Lich (60, 67 at level 4) to kill a 208-health zombie; 4 without the level4Wave 18: 4 blows of the Spire of the Drowned Lich (60, 67 at level 4) to kill a 216-health zombie; 4 without the level4Wave 19: 4 blows of the Spire of the Drowned Lich (60, 67 at level 4) to kill a 224-health zombie; 4 without the level4Wave 20: 4 blows of the Spire of the Drowned Lich (60, 67 at level 4) to kill a 232-health zombie; 4 without the level4Wave 21: 3 blows of the Relic Sunblade (85, 99 at level 5) to kill a 240-health zombie; 3 without the level321Wave 22: 3 blows of the Relic Sunblade (85, 99 at level 5) to kill a 252-health zombie; 3 without the level3Wave 23: 3 blows of the Relic Sunblade (85, 99 at level 5) to kill a 264-health zombie; 4 without the level3Wave 24: 3 blows of the Relic Sunblade (85, 99 at level 5) to kill a 276-health zombie; 4 without the level3Wave 25: 3 blows of the Relic Sunblade (85, 99 at level 5) to kill a 288-health zombie; 4 without the level3Wave 26: 3 blows of the Relic Sunblade (85, 102 at level 6) to kill a 300-health zombie; 4 without the level326Wave 27: 4 blows of the Relic Sunblade (85, 102 at level 6) to kill a 312-health zombie; 4 without the level4Wave 28: 4 blows of the Relic Sunblade (85, 102 at level 6) to kill a 324-health zombie; 4 without the level4Wave 29: 4 blows of the Relic Sunblade (85, 102 at level 6) to kill a 336-health zombie; 4 without the level4Wave 30: 4 blows of the Relic Sunblade (85, 102 at level 6) to kill a 348-health zombie; 5 without the level4Wave 31: 4 blows of the Relic Sunblade (85, 105 at level 7) to kill a 360-health zombie; 5 without the level431Wave 32: 4 blows of the Relic Sunblade (85, 105 at level 7) to kill a 372-health zombie; 5 without the level4Wave 33: 4 blows of the Relic Sunblade (85, 105 at level 7) to kill a 384-health zombie; 5 without the level4Wave 34: 4 blows of the Relic Sunblade (85, 105 at level 7) to kill a 396-health zombie; 5 without the level4Wave 35: 4 blows of the Relic Sunblade (85, 105 at level 7) to kill a 408-health zombie; 5 without the level4Wave 36: 4 blows of the Relic Sunblade (85, 109 at level 8) to kill a 420-health zombie; 5 without the level436Wave 37: 4 blows of the Relic Sunblade (85, 109 at level 8) to kill a 432-health zombie; 6 without the level4Wave 38: 5 blows of the Relic Sunblade (85, 109 at level 8) to kill a 444-health zombie; 6 without the level5Wave 39: 5 blows of the Relic Sunblade (85, 109 at level 8) to kill a 456-health zombie; 6 without the level5Wave 40: 5 blows of the Relic Sunblade (85, 109 at level 8) to kill a 468-health zombie; 6 without the level5Wave 41: 4 blows of the Tyrant's Ember Mace (95, 125 at level 9) to kill a 480-health zombie; 6 without the level441Wave 42: 4 blows of the Tyrant's Ember Mace (95, 125 at level 9) to kill a 492-health zombie; 6 without the level4Wave 43: 5 blows of the Tyrant's Ember Mace (95, 125 at level 9) to kill a 504-health zombie; 6 without the level5Wave 44: 5 blows of the Tyrant's Ember Mace (95, 125 at level 9) to kill a 516-health zombie; 6 without the level5Wave 45: 5 blows of the Tyrant's Ember Mace (95, 125 at level 9) to kill a 528-health zombie; 6 without the level5Wave 46: 5 blows of the Tyrant's Ember Mace (95, 129 at level 10) to kill a 540-health zombie; 6 without the level546Wave 47: 5 blows of the Tyrant's Ember Mace (95, 129 at level 10) to kill a 552-health zombie; 6 without the level5Wave 48: 5 blows of the Tyrant's Ember Mace (95, 129 at level 10) to kill a 564-health zombie; 6 without the level5Wave 49: 5 blows of the Tyrant's Ember Mace (95, 129 at level 10) to kill a 576-health zombie; 7 without the level5Wave 50: 5 blows of the Tyrant's Ember Mace (95, 129 at level 10) to kill a 588-health zombie; 7 without the level5
Blows to kill a Zombie in each wave with the sword the player is expected to carry and the attack of the level the player has by then, coloured by the sword's rarity. The ramp keeps it between 3 and 5 blows however far the waves go (3 to 7 before levels), which is the point of it.

Tier ramp-up: which gear arrives when

The high tiers come from bosses and nowhere else; the first kill of each fighter gives its exclusive items (Phase 3). Because every fighter must be killed before the wave is cleared, a player reaches wave 6 with the Executioner's Greatsword, wave 11 with the Spire and wave 21 with the Relic Sunblade.

The schedule of the best sword (derived from waves.drops, champion.every and bosses.every)
WaveFightDropsBest sword after itDamagevs Worn
1StartnoneWorn Iron Sword15×1.0
5Iron Knight, first killExecutioner's Greatsword, Dreadguard Damned ShieldExecutioner's Greatsword42×2.8
10Bone Colossus, first killSpire of the Drowned Lich, Pulsing Heart of the ColossusSpire of the Drowned Lich60×4
20Drowned Lich, first killRelic Sunblade, Aegis of the ForgottenRelic Sunblade85×5.7
30Veiled Matron, first killVeilbreaker Lantern, Shroud of the Matron–––
40Ember Tyrant, first killTyrant's Ember Mace, Ember CrownTyrant's Ember Mace95×6.3
50Forge Golem, first killForge Hammer, The Keepers' SongbookForge Hammer100×6.7
60Hollow King, first killThe Hollow King's SwordThe Hollow King's Sword110×7.3

A champion comes every 5th wave and a boss every 10th; on a wave that is both, the boss comes. Bosses repeat in the order Bone Colossus, Drowned Lich, Veiled Matron, Ember Tyrant, Forge Golem and grow tougher each time round (Phase 3).

Checkpoints and saves

What a checkpoint holds (Waves.snapshot: a plain object, so it survives JSON)
PartContents
The wavethe wave that starts after the checkpoint
The runscore, kills, time, captives freed, how many times each boss kind has fallen and dropped (drops), boss repeats
The playerhealth and maximum health, mana and maximum mana, the stamina pool, the level and the boss milestones won (part C), the sword and shield tier, bombs and bag size, artifacts, Moon Moths
The maidenswhich elves have been rescued
Rewards on the floora boss reward that was dropped but not yet picked up (laid down again after a Continue)

Phase 3Bosses & Loot Pools

The high tiers do not lie about in the maze: they are dropped by the champion and the bosses, which makes each of them a fight worth having. This part is read from waves.drops, waves.floorGear, enemies.json and weapons.json.

The fighters

Iron Knightno render
Iron_Knight.glb

Iron Knight Champion

Wave 5, then every 5th wave that is not a boss wave (5, 15, 25 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (479 in all)

No stun loop: a champion with plates. Three armour plates shrug off 40% of every sword hit; one falls at 66% health (25% shrugged off), one at 33% (10%), and it gets quicker each time (speed ×1.15, ×1.35). Bombs ignore the armour and hit for ×2.5. Poise 60: enough hits stagger it. A perfect parry staggers it for 2.5 s. Its slam (35 damage, 0.9 s red telegraph, every 5 s) cannot be parried.

  • blow: 25 damage, reach 2.2 m, every 1.6 s, 0.55 s wind-up
  • Slam: a ground slam, 35 damage in 3.2 m; 0.9 s telegraph, every 5 s / 4.2 s / 3.4 s (by phase)
Health in its repeats (hpScalePerRepeat 0.55)
WaveScaleHealthPhase pools
5×1480163 / 158 / 158
15×2.11,008343 / 333 / 333
25×3.21,536522 / 507 / 507
35×4.32,064702 / 681 / 681
Bone Colossusno render
Bone_Colossus.glb

Bone Colossus Boss

Wave 10, then every 50th wave (10, 70, 120 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (2,400 in all)

The stun loop. Outside a stun your hits only chip (25%). Any spell that lands while it winds up an attack (strike 0.95 s, slam 1.6 s, summon, volley) stuns it: it kneels for 3.5 s and everything does ×2 damage. Bombs are not spells and do not stun it. After it lands a blow it waits 1.2 s before starting another, so a slam is never followed at once by a strike. It walks at 1.3 m/s and never runs.

  • blow: 18 damage, reach 3 m, every 2 s, 0.95 s wind-up
  • Slam: a ground slam, 26 damage in 4.5 m; 1.6 s telegraph, every 7 s / 6 s / 4.5 s (by phase)
  • Summon: calls 3 Skeletons; 1.2 s telegraph, every 14 s, from phase 2
  • Volley: a fan of 5 boneshards, 7 damage each; 1.2 s telegraph, every 6 s, from phase 3
Health in its repeats (hpScalePerRepeat 1)
WaveScaleHealthPhase pools
10×12,400384 / 864 / 1,152
70×24,800768 / 1,728 / 2,304
120×37,2001,152 / 2,592 / 3,456
170×49,6001,536 / 3,456 / 4,608
Drowned Lichno render
Drowned_Lich.glb

Drowned Lich Boss

Wave 20, then every 50th wave (20, 80, 130 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (3,200 in all)

The stun loop. A water shield turns every blow aside: it is immune to everything but ice. 3 Ice Shards freeze it solid for 4 s; sword hits then shatter for ×2, and a fireball on the frozen Lich bursts to steam for +40 and thaws it at once.

  • blow: 22 damage, reach 2.4 m, every 1.8 s, 0.6 s wind-up
  • frostbolt: 14 damage at 11 m/s every 3 s, 0.8 s draw
  • Drown: calls 3 Zombies; 1.2 s telegraph, every 16 s, from phase 2
  • Tide: a shockwave that throws you 5 m, 20 damage in 6.5 m; 1.3 s telegraph, every 8 s, from phase 3
Health in its repeats (hpScalePerRepeat 0.5)
WaveScaleHealthPhase pools
20×13,2001,088 / 1,056 / 1,056
80×1.54,8001,632 / 1,584 / 1,584
130×26,4002,176 / 2,112 / 2,112
180×2.58,0002,720 / 2,640 / 2,640
Veiled Matronno render
veiled_matron.glb

Veiled Matron Boss

Wave 30, then every 50th wave (30, 90, 140 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (3,400 in all)

The stun loop. She is nearly invisible and snuffs every torch within 7 m as she passes; outside a stun your hits only chip (20%). Light lays her bare and stuns her for 5 s (×2 damage): a fireball or a Moon Wave that hits her, a torch lit again within 4.5 m of her, or the Veil-Piercing Lens in your pack while she winds up a blow. A light stun cannot be made again for 15 s, and it lifts her veil.

  • blow: 24 damage, reach 2.8 m, every 1.8 s, 0.7 s wind-up
  • Shades: calls 2 Shades; 1.3 s telegraph, every 15 s, from phase 2
  • Veil: lets the veil down: the light of the sky falls to 15% for 6 s, so only what burns still shines; 1.5 s telegraph, every 22 s, from phase 3
  • charge: 28 damage at 13 m/s after a 1 s howl, every 8 s; a wall stuns it 1.5 s
Health in its repeats (hpScalePerRepeat 0.6)
WaveScaleHealthPhase pools
30×13,4001,156 / 1,122 / 1,122
90×1.65,4401,850 / 1,795 / 1,795
140×2.27,4802,543 / 2,468 / 2,468
190×2.89,5203,237 / 3,142 / 3,142
Ember Tyrantno render
ember_tyrant.glb

Ember Tyrant Boss

Wave 40, then every 50th wave (40, 100, 150 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (2,600 in all)

The stun loop. Plates of burning iron shrug off 70% of every sword hit, then 50% and 25% as one falls at 66% and one at 33% health, and outside a stun your hits only chip (50%). It is immune to fire and takes ×1.5 from ice. A bolt of lightning breaks a plate off at once (lightning), ahead of the phase that would have taken it. Its own fireball turned back by a mirror shield (the Moon-Mirror Aegis, the Aegis of the Forgotten) stuns it for 5 s (×2 damage). Bombs ignore the plates (×2.5).

  • blow: 28 damage, reach 3.3 m, every 2.3 s, 0.8 s wind-up
  • Fireballs: a fan of 3 fireballs, 16 damage each; 1.2 s telegraph, every 7 s / 6 s / 5 s (by phase)
  • Slam: a ground slam, 30 damage in 4 m, and 5 patches of fire burn on for 6 s (7 every 0.5 s); 1.4 s telegraph, every 9 s / 8 s / 7 s (by phase)
  • Ring: a ring of fire 8.5 m across that closes in at 2.4 m/s with a 75° gap, 14 damage every 0.5 s to what it passes (a jump clears it, a shield does not turn it); 1.6 s telegraph, every 14 s, from phase 3
Health in its repeats (hpScalePerRepeat 0.6)
WaveScaleHealthPhase pools
40×12,600884 / 858 / 858
100×1.64,1601,414 / 1,373 / 1,373
150×2.25,7201,945 / 1,888 / 1,888
200×2.87,2802,475 / 2,402 / 2,402
Forge Golemno render
forge_golem.glb

Forge Golem Boss

Wave 50, then every 50th wave (50, 110, 160 ...). It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (3,400 in all)

The stun loop. Plates of hot iron shrug off 65% of every sword hit, then 45% and 20% as one cracks off at 66% and one at 33% health, and outside a stun your hits only chip (25%). A Rune Bomb that goes off in his furnace while he inhales (the wind-up of his inhale) stuns him for 5 s (×2 damage). Bombs ignore the plates (×2.5). Fire is almost nothing to him (×0.25); ice is ×1.5.

  • blow: 24 damage, reach 3.4 m, every 2.2 s, 0.9 s wind-up
  • Slam: a ground slam, 26 damage in 4.4 m, and 3 patches of fire burn on for 6 s (7 every 0.5 s); 1.5 s telegraph, every 9 s / 8 s / 7 s (by phase)
  • Slam: a ground slam, 26 damage in 4.4 m, and 3 patches of fire burn on for 12 s (9 every 0.5 s); 1.5 s telegraph, every 9 s / 8 s / 7 s (by phase), from phase 3
  • Inhale: a fan of 7 fireballs, 5 damage each; 2 s telegraph, every 11 s / 10 s / 9 s (by phase)
  • charge: 24 damage at 7.5 m/s after a 1 s howl, every 15 s; a wall stuns it 2.5 s
Health in its repeats (hpScalePerRepeat 0.6)
WaveScaleHealthPhase pools
50×13,4001,156 / 1,122 / 1,122
110×1.65,4401,850 / 1,795 / 1,795
160×2.27,4802,543 / 2,468 / 2,468
210×2.89,5203,237 / 3,142 / 3,142
Hollow Kingno render
hollow_king.glb

Hollow King Boss

Wave 60, once: the last fight of the Vigil, and he never comes again. It comes alone: it is the whole wave.

Phase 1 · Phase 2 · Phase 3 (6,500 in all)

The stun loop. Outside a stun your hits only chip (20%); a stun lasts 6 s and everything does ×2. A different fire opens him in each of his 5 pools, one for each maiden's fire, and a wrong tool only chips: it is never a trap.

  • Pool 1: a fireball or Rune Bomb that bursts in him while he winds up his moonfall
  • Pool 2: any spell that lands while he winds up an attack
  • Pool 3: 3 Ice Shards (then a fireball thaws him for +40)
  • Pool 4: light (a fireball, a Moon Wave, a torch lit beside him, or the Veil-Piercing Lens; once in 15 s)
  • Pool 5: his own moonfire or moonbeam turned back by a mirror shield

Each pool has an edge: a blow that would carry him through it stops at it, and the maiden of the fire he has just lost sings her verse for 7 s while he kneels and cannot be hurt (with the Songbook she sings it with its words and mends 15% of your health and 25% of your mana). He comes down from the Moonspire at wave 60 and never comes again.

  • blow: 18 damage, reach 2.9 m, every 1.6 s, 0.5 s wind-up
  • Charged: a ground slam, 26 damage; 1.1 s telegraph, every 6 s / 5.5 s / 5 s / 4.5 s / 4 s (by phase)
  • Moonfire: a fan of 1 moonfires, 14 damage each; 1 s telegraph, every 6 s / 5 s / 5 s / 4.5 s / 4 s (by phase)
  • Moonfall: a ground slam, undefined damage; 1.6 s telegraph, every 9 s / 12 s / 12 s / 12 s / 12 s (by phase)
  • Fan: a fan of 3 moonfires, 10 damage each; 1.2 s telegraph, every 7 s, from phase 2
  • Veil: lets the veil down: the light of the sky falls to 15% for 6 s, so only what burns still shines; 1.5 s telegraph, every 22 s, from phase 4
  • Moonbeam: a fan of 1 moonbeams, 20 damage each; 1.8 s telegraph, every 10 s, from phase 5
  • charge: 20 damage at 7 m/s after a 0.9 s howl, every 10 s; a wall stuns it 1 s

Drop tables

Each fighter has its own table. The first kill of a run gives its exclusive items, which exist nowhere else; later kills give one item each from the then list. The kills are counted per kind of fighter and the count goes back with a checkpoint, so a reward lost to a fall (the boss fell but you never picked it up) is dropped again when it comes round.

Iron Knight

Wave 5 and every fifth after
First kill of the run: always, whatever you carry
  • Executioner's GreatswordEpic
  • Dreadguard Damned ShieldEpic
Later kills: one item each, the next on the list you can use
  1. Cursed Damned BladeEpic
  2. Veil-Piercing LensLegendary
  3. Runesmith's SatchelRare
  4. Lunar Moth SigilLegendary
  5. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Bone Colossus

Wave 10
First kill of the run: always, whatever you carry
  • Spire of the Drowned LichLegendary
  • Pulsing Heart of the ColossusMythic / Relic
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Moon-Mirror AegisLegendary
  2. Lunar Moth SigilLegendary
  3. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Drowned Lich

Wave 20
First kill of the run: always, whatever you carry
  • Relic SunbladeMythic / Relic
  • Aegis of the ForgottenMythic / Relic
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Lunar Moth SigilLegendary
  2. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Veiled Matron

Wave 30
First kill of the run: always, whatever you carry
  • Veilbreaker LanternLegendary
  • Shroud of the MatronLegendary
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Veil-Piercing LensLegendary
  2. Lunar Moth SigilLegendary
  3. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Ember Tyrant

Wave 40
First kill of the run: always, whatever you carry
  • Tyrant's Ember MaceMythic / Relic
  • Ember CrownMythic / Relic
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Moon-Mirror AegisLegendary
  2. Lunar Moth SigilLegendary
  3. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Forge Golem

Wave 50
First kill of the run: always, whatever you carry
  • Forge HammerMythic / Relic
  • The Keepers' SongbookMythic / Relic
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Runesmith's SatchelRare
  2. Lunar Moth SigilLegendary
  3. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Hollow King

Wave 60
First kill of the run: always, whatever you carry
  • The Hollow King's SwordMythic / Relic
Every boss kill
  • Bound Vitality VesselLegendary

...and health and mana are refilled in full (bosses.fullRefill).

Later kills: one item each, the next on the list you can use
  1. Lunar Moth SigilLegendary
  2. Resonant Mana VesselLegendary

A sword or shield of a lower rarity than the one carried, an artifact already owned and a bag no bigger are skipped; the list ends in things that are always welcome.

Loot on the floor, and what it is worth

Floor loot of the low tiers (waves.floorGear): never Epic or above
ItemRarityLies in the maze fromChance each waveSkipped when
Footman's Flanged MaceUncommon #4ADE80wave 245%it would be no step up from what you carry
Soldier's Iron ShieldUncommon #4ADE80wave 245%it would be no step up from what you carry
Tempered Moonsteel BladeRare #38BDF8wave 545%it would be no step up from what you carry
Consumables lying in the maze, every wave
ItemRarityHow manyWhat it does
Minor Health DraughtUncommon #4ADE802 a wave+30 health on touch
Lesser Mana CrystalUncommon #4ADE802 a wave+40 mana on touch
Cache of Rune BombsRare #38BDF81 a wave from wave 3+3 Rune Bombs, if the bag has room

Damage and guard by rarity

CommonUncommonRareEpicLegendaryMythic / Relic
020406080100Worn Iron Sword: 15 damage (Common band 10–15)15Worn IronSwordFootman's Flanged Mace: 20 damage (Uncommon band 18–22)20Footman's FlangedMaceTempered Moonsteel Blade: 28 damage (Rare band 25–30)28Tempered MoonsteelBladeExecutioner's Greatsword: 42 damage (Epic band 40–45)42Executioner's GreatswordCursed Damned Blade: 44 damage (Epic band 40–45)44Cursed DamnedBladeSpire of the Drowned Lich: 60 damage (Legendary band 55–65)60Spire of theDrowned LichRelic Sunblade: 85 damage (Mythic / Relic band 80–110)85Relic SunbladeTyrant's Ember Mace: 95 damage (Mythic / Relic band 80–110)95Tyrant's EmberMaceForge Hammer: 100 damage (Mythic / Relic band 80–110)100Forge HammerThe Hollow King's Sword: 110 damage (Mythic / Relic band 80–110)110The HollowKing's Sword
Damage of each sword; the faint block behind a bar is the band its rarity allows (Common 10–15, Uncommon 18–22, Rare 25–30, Epic 40–45, Legendary 55–65, Mythic 80–110). A test checks every sword against its band.
050100150200250Worn Iron Sword: 43 damage per second43Worn IronSwordFootman's Flanged Mace: 56 damage per second56Footman's FlangedMaceTempered Moonsteel Blade: 85 damage per second85Tempered MoonsteelBladeExecutioner's Greatsword: 105 damage per second105Executioner's GreatswordCursed Damned Blade: 122 damage per second122Cursed DamnedBladeSpire of the Drowned Lich: 158 damage per second158Spire of theDrowned LichRelic Sunblade: 236 damage per second236Relic SunbladeTyrant's Ember Mace: 216 damage per second216Tyrant's EmberMaceForge Hammer: 200 damage per second200Forge HammerThe Hollow King's Sword: 275 damage per second275The HollowKing's Sword
Damage per second: the big weapons swing a little slower, never slowly enough to lose to the tier below (a test checks that too).
020406080100Splintered Wooden Shield: stops 80%80%Splintered WoodenShieldSoldier's Iron Shield: stops 85%85%Soldier's IronShieldDreadguard Damned Shield: stops 92%92%Dreadguard DamnedShieldMoon-Mirror Aegis: stops 95%95%Moon-Mirror AegisAegis of the Forgotten: stops 97%97%Aegis ofthe Forgotten
Share of a blow each shield stops (100% minus its block factor). There is no Rare shield: the one the design list names for it is the Shield Skeleton's own model file.
The six rarities (src/data/rarity.json): one colour everywhere
TierColourRankDesign listDamage bandBuilt damageReal stepStopsKnown for
Common#9E9E9E0base10–1515×175–80%Base weapon damage, baseline block.
Uncommon#4ADE801+25%18–2220×1.381–86%+25% damage; a shield that recovers quicker (shorter bash cooldown) and wears its guard meter out slower (a lower guardDrain: blocking costs no stamina, the shield has the guard meter; the one stamina pool is for the sprint).
Rare#38BDF82+50%25–3028×1.986–90%+50% damage and moderate knockback.
Epic#A855F73+100%40–4542–44×2.990–94%+100% damage and a heavy stagger on every hit. Dropped by bosses.
Legendary#F59E0B4+150%55–6560×494–96%+150% damage and innate elemental and cleave effects. Dropped by bosses.
Mythic / Relic#EF44445+200% or more80–11085–110×7.396–100%+200% damage or more, the best guard absorption and relic cast potency (spells cast with it hit harder). Dropped by the Drowned Lich and the end bosses.

Phase 4Bestiary & Characters

Thirteen creatures and the five rescued maidens. Names in the cards are the ones used here; the data label is shown beneath when the game calls the same creature something shorter. Health is the value in enemies.json at wave 1: ordinary enemies grow tougher with the wave (Phase 2), champions and bosses by their own rule (Phase 3).

Creatures

The rescued maidens

Phase 5Item Compendium

Every model file the game uses, with its name, rarity, .glb path, where it comes from and what it does, and the cursed relics, which are items with no model (a card each, from the data). The grid below holds 78 cards: 60 items, props and projectiles, and (under Bestiary) the 18 creatures and maidens, which Phase 4 describes in full. The buttons and the search combine; the page address remembers them.

Phase 6Hub & World Staging

The only “hub” in the Endless Vigil is the middle of the maze, where the rescued maidens wait and add something of their own; and the only staged sequence is the title screen.

The rescued elves' hub

The five maidens are held by the fighters, one each. When one falls, its maiden is freed where it died and, a little later, runs to a station and waits there. The stations are on a ring 4.3 m from the exact middle of the maze, under the Tree of Life in the courtyard (the 3 × 3 cells round the start, opened first, with a tree at its middle): each maiden has her own angle on the ring (Crimson Elf 306°, Golden Elf 18°, Silver Frost Elf 90°, Shadow Elf 162°, Emerald Elf 234°), the same in every maze, and she stands facing out (turning to a player who comes near). Her way along the corridors ends in the courtyard cell next to her place and never leads through the middle cell, where the trunks stand.

What each maiden adds to the middle

When a maiden settles at her station the courtyard gains a fixture in her colour on the same ring, 4.3 m from the middle and a metre to one side of her, and the Tree of Life glows a step brighter (full with all 5). It comes up with a flare and a line; a maiden freed earlier in the session, or in the saved game, has hers standing from the start. The fixtures are for looking at: nothing collides with them. With all 5 standing there the middle is a sanctuary: enemies cannot enter a circle of 5.6 m round it between waves (a ring on the floor shows it). A wave is cleared only when its last enemy falls, so a break has no enemies of its own: the sanctuary keeps out only what is called in a break (a vault's or a ring's wardens, a Trial's pack). hub.sanctuary.when: "always" holds it through a wave as well, and is left off.

The fixtures (vigil.json hub.fixtures)
MaidenFixtureColour
Crimson Elfbanner#ff3b4e
Golden Elfshrine#ffcf5a
Silver Frost Elflantern#b8e4ff
Shadow Elfmoss#9a6bff
Emerald Elfcrystals#0fb36b
What triggers what (src/systems/Captives.js, Animation.js, HUD.js)
TriggerWhat happens
A boss falls (boss:died)The maiden that fighter holds (the table below) is freed 2.6 m from the corpse, towards the player, inside a ring of light, and the HUD says “You freed the … from the …!”. A fighter the table does not name frees one still held, at random
The next wave startsShe has made her curtsy (once, then she stands and watches you) (Formal_Bow, Curtsy, Curtsey, Bow, Bowing), and lingers 4 s more
The dance is overShe runs along the corridors to her station (3 m/s), walking the last 9 m (1.4 m/s)
She reaches itShe stands there in her idle for good; the HUD says where she waits (captive:settled)
The player comes within 10 mShe turns to watch them; she looks ahead again when they go
A fighter falls again, and its maiden is free alreadyIts own maiden comes as a guest, dances the victory dance and slips away (fades over 2 s): she already stands in the middle
A new run after a fall (R)The rescued maidens are already standing in their places (they are kept for the play session)
Continue after a reloadThe rescued list comes back from the save: they stand in the places of the new maze
The 5 maidens (vigil.json captives.models) and the fighter that holds each (captives.heldBy)
MaidenHeld byModel fileRing of lightClips
Crimson ElfForge Golemcrimson_elf.glb■ #ff3b4edance, sing, idle, walk, run
Golden ElfBone Colossusgolden_elf.glb■ #ffcf5adance, sing, idle, walk, run
Shadow ElfVeiled Matronshadow_elf.glb■ #9a6bffdance, sing, idle, walk, run
Silver Frost ElfDrowned Lichsilver_frost_elf.glb■ #b8e4ffdance, sing, idle, walk, run
Emerald ElfEmber Tyrantemerald_elf.glb■ #0fb36bdance, sing, idle, walk, run

One line each, carved verses

A rescued maiden who stands in her place says one line the first time in a run that the player stays within 3 m of her for 1 s in a break (no key, and it waits while a swap or a passive is being chosen); the HUD shows it under her name and the codex keeps it. When a boss or champion falls, the first stanza of that creature's list that is not cut yet is carved on its creature's tombstone, one of 7 that stand in a ring 6.5 m from the Tree of Life (at most 1 for a wave; a creature whose list is spent leaves nothing). The stone is not there until its first stanza is carved: it then rises out of the ground (2.2 s), the first stanza on its front, which faces out, the second on its back, which faces the tree. Once risen a tombstone is solid. The Iron Knight's stone also keeps a tally of its falls, "Fallen: n", counted on every one even when its stanzas are all carved, and glows in the colour of the look the last one wore (crimson for the plain first fight). The stanzas and the tally are saved with the checkpoint, so Continue and a fall show the same stones. Each line and stanza is an entry of the codex's Lore tab (??? until heard or seen).

What each maiden says (vigil.json lore.maidens.lines)
MaidenCodex entryHer line
Crimson ElfThe Crimson Elf: the last fireThe Halls were lit to keep a vigil for the dying moon. Every fire here was lit for her, and mine is the last that obeys.
Golden ElfThe Golden Elf: the lightLight does not ask who has earned it. Drink, rest, and light the next seal: the moon is listening.
Shadow ElfThe Shadow Elf: the darkA Shade is only the dark that forgot whose it was. Keep a flame near, and it remembers.
Silver Frost ElfThe Silver Frost Elf: the coldThe Lich drowned the lower Halls to keep its dead from walking. Cold was never its cruelty; it was its only mercy.
Emerald ElfThe Emerald Elf: the mirrorThe Tyrant burned for a king who never came. Whatever she throws at you was meant for him: hold up something bright, and send it home.
The carved stanzas (vigil.json lore.wall.stanzas): the first of a creature's list that is not cut yet, when it falls
IdCreatureLines
ironknight-1Iron KnightThree plates he wore against the dark,
and none against the oath he swore.
He kept the gate until the gate
kept him. Now neither lets go.
ironknight-2Iron KnightThe headsman's blade, the headsman's shield:
he took them from a hand grown cold.
Whom did he serve? The dead recall.
The living see only the plates.
bonecolossus-1Bone ColossusA thousand keepers, one great heart,
stacked bone on bone and set to walk.
The fire in its ribs burns low
and brighter at each wound it takes.
bonecolossus-2Bone ColossusIt never runs. It has no need.
The Halls are patient, and so is bone.
Strike when it lifts its arm to fall:
the heart flares, and the bones forget.
drownedlich-1Drowned LichWhen the lower Halls were drowned
a keeper stood and would not sink.
The water answers to its staff;
only the cold may bid it be still.
drownedlich-2Drowned LichIt raises what the water kept
and calls each by a name long lost.
The staff it lost, it knows by sound.
Carry it in, and watch it listen.
veiledmatron-1Veiled MatronShe kept the lamps before the dark.
Now she walks the halls unseen
and snuffs each flame she passes by:
light one again beside her, and she shows.
veiledmatron-2Veiled MatronAt the last she lets the veil come down
and the Halls forget the shape of day.
Only what burns is left to see by:
a fireball, a torch, the Lens held high.
embertyrant-1Ember TyrantShe waited for a king who never came,
and forged his crown, and burned for him.
Three plates of iron hold her rage;
the lightning knows where each is hinged.
embertyrant-2Ember TyrantEach fire she hurls was meant for the king.
Hold up a mirror and send it home,
and watch the queen kneel to her own flame.
Then strike: the plates are only metal now.
forgegolem-1Forge GolemHe banked the last red fire in his forge
and grew the iron round her like a hearth.
When the furnace draws its breath to burn,
give it a bomb to swallow, and it kneels.
forgegolem-2Forge GolemThree plates of iron over a banked red fire;
the bombs know where each is riveted.
He runs when the bellows fill; the wall waits.
On a red floor, cast frost and stand on it.
hollowking-1Hollow KingHe went up the Moonspire to call her down
and left his queen to burn below.
He wears his crown over nothing at all,
and five fires open him, one by one.
hollowking-2Hollow KingHis glass shows the fire he cannot bear:
red, then gold, white, violet, green.
Answer the colour, and the maiden sings.
When the green is lit, send his own moon home.

The title sequence, step by step

  1. The page loads behind a loading screen while every model of models.json is fetched (71 files). A model that fails to load never stops the game.
  2. Game.boot lets each state prepare itself: TitleScene.prepare builds the diorama (TitleStage), compiles its shaders and draws one frame, so the first look does not stall; VigilScene.prepare builds the first maze and warms up every creature, pickup and projectile. If the diorama cannot be built, the menu goes on a plain dark screen and the game still starts.
  3. game.start('title'): TitleScene.enter reads the save (SaveGame) and shows the menu: Continue (the wave, the score, the sword and how long ago) and New Game if one exists, Click to Begin if not. The heads-up display stays hidden under it.
  4. Every frame the stage is updated and drawn instead of the Vigil: the camera sways round the dais and leans towards the mouse (the horizontal field of view is fixed, so a narrow window shows more above and below instead of cropping the cast), the maidens and bosses turn a little towards it, the braziers flicker and embers rise.
  5. The click (a button, or anywhere else: Continue if a save exists) leaves the choice in game.shared.resume, unlocks the sound, starts the ambience and captures the mouse (this is why it must be a click).
  6. TitleScene.update returns 'vigil'; TitleScene.exit hides the menu and disposes the diorama to free what it holds; VigilScene.enter hands the choice to Waves.begin: a new game starts wave 1, Continue restores the saved run.
60°horizontal field of view (fixed)
5maidens on the dais
7bosses behind them
4pieces of loot floating over the menu
4braziers
8ruined pillars, and a gate
The title diorama: who stands where (src/data/title.json; metres, the camera looks down −Z, yaw in degrees)
FigureKindPosition (x, y, z)YawDoes
Golden Elfmaiden-4.6, 0, 1.520her idle clip, turns a little towards the mouse
Emerald Elfmaiden-2.95, 0, 314her idle clip, turns a little towards the mouse
Crimson Elfmaiden-1.95, 0, 4.18her idle clip, turns a little towards the mouse
Silver Frost Elfmaiden1.9, 0, 4.1-8her idle clip, turns a little towards the mouse
Shadow Elfmaiden3.6, 0, 2.4-16her idle clip, turns a little towards the mouse
Iron Knightfighter-8.8, 0, -6.526its standing pose, breathing; scale ×1.1
Veiled Matronfighter-6.1, 0, -418its standing pose, breathing, dimmed to 62%; scale ×1.1
Drowned Lichfighter-4.4, 0, -2.512its standing pose, breathing; scale ×1.1
Ember Tyrantfighter5.7, 0, -5.2-20its standing pose, breathing, its plates breathing in their own light; scale ×1
Forge Golemfighter7.1, 0, -2.2-26its standing pose, breathing, its plates breathing in their own light; scale ×1
Bone Colossusfighter9.3, 0, -9.5-24its standing pose, breathing, heart beating; scale ×1.15
Hollow Kingfighter3.7, 0, -12.8-8its standing pose, breathing, dimmed to 50%, its plates breathing in their own light; scale ×1
Tyrant's Ember Maceloot-1.7, 2.1, 1.8–floats, bobs and turns like a pickup, without a lamp of its own
Moon-Mirror Aegisloot-3.1, 2.4, -1–floats, bobs and turns like a pickup, without a lamp of its own
Relic Sunbladeloot1.7, 2.1, 1.8–floats, bobs and turns like a pickup, without a lamp of its own
Veilbreaker Lanternloot3.1, 2.4, -1–floats, bobs and turns like a pickup, without a lamp of its own

The camera starts at (0, 1.2, 11.5) looking at (0, 2.4, 0); it sways by ±0.05 rad round the target every 45 s and leans up to 0.06 rad with the mouse. Everything is built the way the game builds it (the maidens like captives, the bosses by the enemy prefab, the loot by the pickup prefab), so a new model appears on the title screen by editing title.json.

Update 26 Oct 2026Animation & Combat Polish

The sword swing was reworked so it no longer snaps: it has a windup you can read, a strike that accelerates through the cut, and a follow-through that slows to a stop. The numbers below are read from src/data/weapons.json (sword.slash) and the curves are drawn by the same functions the game runs (src/util/slash.js).

0.36 sa standard swing, start to ready stance
137 msuntil the blow lands (hitAt 0.38 of the swing)
0.44 sthe Executioner's Greatsword swing
0.4 sthe Spire of the Drowned Lich swing
90 msthe blend when a swing starts in the last
3phases: windup, strike, follow-through

Windup, strike, follow-through

A click starts the swing (player:swing: the windup begins, the stamina pause restarts). The blow comes part-way through it (player:strike, at hitAt of the swing): that is when the one-tick hit box is made, the Moon Wave leaves and the whoosh sounds. A swing cut short by a fall never strikes. The click is no longer the same tick as the damage: about 137 ms of readable windup came in between, which is the price of a swing that looks like it has weight.

The three phases of a swing (weapons.json sword.slash.phases)
PhaseShare of the swingAt the standard 0.36 sArc coveredEasingWhat you see
Windup0–0.30 ms–108 ms0 → 0.32inOutSineDraws the blade back and up with a slow, loaded ease and comes to a hold at the top; the torso coils the other way. The easing is nearly still at the end: the pause that makes the strike readable.
Strike0.3–0.52108 ms–187 ms0.32 → 0.66inQuadReleased from the hold and speeding up all the way through the cut (the speed is greatest at the end, where the blow has landed and the blade is across the view). The slash trail is drawn behind the blade.
Follow-through & recovery0.52–1187 ms–360 ms0.66 → 1outCubicThe blade overshoots the cut a little and is slowed to a stop at the ready stance: a long, decelerating tail, so the hand never snaps to rest.
WindupinOutSineStrikeinQuadFollow-through & recoveryoutCubic00.250.50.7510 ms60 ms120 ms180 ms240 ms300 ms360 msblow lands: 137 mstime through the swing (the standard 0.36 s)position along the arc
The tempo curve, drawn with swingPath from the data: the gold line is how far along the arc the blade is, the dashed red line is its speed. It is nearly still at the end of the windup, fastest at the end of the strike (the step down just after it is the blade being checked at the end of the cut), then decays smoothly to nothing in the follow-through. The solid vertical line is the blow.

The path and the torso behind the hand

Where the hand goes (the path) is separate from how fast it goes there (the tempo above). Each key of the path holds the hand's offset, the blade's turn and a body channel: the yaw, pitch and roll of the torso behind the sword hand. In first person there is no body to see, so the camera takes it: the world leans away from the cut in the windup and into it in the strike, by no more than 3.4° of yaw and 2.1° of roll. The off hand (the shield) sways against it. sword.slash.bodyScale (1 by default) scales it, or turns it off with 0.

-4°-2°0°+2°+4°0 ms60 ms120 ms180 ms240 ms300 ms360 ms— forehand yaw— backhand yaw- - forehand roll
The torso twist the camera takes, in degrees: yaw of a forehand (gold) and a backhand (blue), and the roll of the forehand (dashed). The yaw changes sign across the strike: the body coils one way, then drives through. The dotted vertical lines are the phase ends.
The forehand path: one key per place along the arc (weapons.json sword.slash.forehand; the backhand is its mirror)
Arc positionHand moves (x, y, z in m)Blade turns (rad)Torso: yaw, pitch, roll
00, 0, 00, 0, 00°, 0°, 0°
0.1-0.02, 0.03, 0.050.06, 0.1, 0.180.7°, 0.3°, 0.6°
0.320.1, 0.34, 0.14-0.25, 0.45, 0.852.9°, 0.9°, 1.7°
0.490.4, 0.12, -0.3-0.9, -0.7, -0.7-0.7°, -1.3°, -0.3°
0.660.54, -0.12, -0.2-0.85, -1, -1.35-2.9°, -1.7°, -2°
0.820.57, -0.17, -0.1-0.72, -1.1, -1.5-3.2°, -0.9°, -1.7°
10, 0, 00, 0, 00°, 0°, 0°

Timing by weapon, and the blend

Swing times by sword (a tier may set its own swingTime; the heavy ones swing slower)
SwordSwing takesBlow lands atStrike ends atNext swing allowedCooldown against the swing
Worn Iron Sword0.36 s137 ms187 ms0.35 s10 ms: the next swing starts in the last of this one and is blended in
Footman's Flanged Mace0.36 s137 ms187 ms0.36 sready before the swing ends
Tempered Moonsteel Blade0.36 s137 ms187 ms0.33 s30 ms: the next swing starts in the last of this one and is blended in
Executioner's Greatsword0.44 s167 ms229 ms0.4 s40 ms: the next swing starts in the last of this one and is blended in
Cursed Damned Blade0.36 s137 ms187 ms0.36 sready before the swing ends
Spire of the Drowned Lich0.4 s152 ms208 ms0.38 s20 ms: the next swing starts in the last of this one and is blended in
Relic Sunblade0.36 s137 ms187 ms0.36 sready before the swing ends
Tyrant's Ember Mace0.46 s175 ms239 ms0.44 s20 ms: the next swing starts in the last of this one and is blended in
Forge Hammer0.46 s175 ms239 ms0.5 sready before the swing ends
The Hollow King's Sword0.34 s129 ms177 ms0.4 sready before the swing ends

Some cooldowns are shorter than their swings (the standard swing takes 0.36 s, a Moonsteel Blade can swing again after 0.33 s). A swing that begins while the hand is still in the last one, or one that is cut short, would make the hand jump. Instead the difference is carried and faded out over sword.slash.blend = 0.09 s with a smoothstep (inertialization), so the hand always flows from where it is into the new windup.

The slash trail

While the blade is between 34% and 90% of its arc (the strike and the first of the follow-through) a ribbon is laid down between the tip and 50% of the way down the blade, one slice per drawn frame, in the camera's own space. A slice glows for 0.15 s and fades; the tip edge is the hot one (brought towards white), the guard edge nearly black. It is added to the picture, so black is nothing: no sorting, no alpha. Its colour is the sword's own glow, steel white for a plain blade. Code: src/fx/SlashTrail.js.

ready stance (0)
ready stance (0)
windup, early (windup, 0.12)
windup, early (windup, 0.12)
top of the windup (0.28)
top of the windup (0.28)
strike: the blow lands near here (0.40)
strike: the blow lands near here (0.40)
end of the strike (0.52)
end of the strike (0.52)
follow-through (0.70)
follow-through (0.70)
recovery, nearly at rest (0.90)
recovery, nearly at rest (0.90)
  1. player:swing (windup starts)
  2. Stamina: the recovery pause restarts
  3. windup: the blade loads, the torso coils
  4. player:strike at 0.38
  5. Combat: the one-tick Hitbox
  6. Audio: the whoosh · Spells: the Moon Wave
  7. strike → follow-through → ready

Hit-stop and the slow-motion kill

A blow that connects has a weight you can feel: for a few milliseconds of real time the world holds still while the screen, the camera (it still looks where the mouse goes), the shake and the sound go on. It is the game's logic that stops, not its drawing: the loop runs the same 60 Hz step but feeds it speed × real time, and a speed of 0 means no ticks. A key pressed during the freeze is waiting for the first tick after it. Everything is player.json hitStop; intensity (1) multiplies every pause and the slow-motion's length, and is what a settings slider will change (add ?o.player.hitStop.intensity=0 to the page address to play without it).

What freezes the game and for how long (src/data/player.json hitStop; src/util/hitstop.js, src/systems/HitStop.js)
What happensThe game holds still forNotes
The player's sword or shield bash connects (hit, kind melee, bash)25+ damage: 40 ms; 40+ damage: 60 ms; 70+ damage: 80 msthe damage that landed, with the level, a perfect parry's double and a stunned boss's double counted: a heavy weapon, an empowered or a stun-time blow is a heavy hit
A blow killsat least 40 msso every kill has a beat, even with the Worn sword
A perfect parry (parried)80 msthe biggest single pause: the ring of the shield
A boss falls (boss:died, kind boss)0.5 s at 25% of full speedbegins when the killing blow's own freeze is over, and eases back to full speed in its last 0.15 s
Several blows in one tick (a cleave)one freeze, the longestthe system turns a tick's facts into one request
A freeze that would begin within 0.15 s of the lastnothinggame time, which does not pass during a freeze: a flurry cannot hold the game still for half a second
Not a hit: an enemy's blow on the player, a spell, a bomb, a blow the guard stopsnothingonly what the player's own sword and shield land
What each sword's blow freezes for, at level 1 (damage from weapons.json; a level adds 4% and may lift a blow to the next rung)
SwordDamageA blowAn empowered blow (×2) or one on a stunned boss (×2)A killing blow
Worn Iron Sword15–40 ms40 ms
Footman's Flanged Mace20–60 ms40 ms
Tempered Moonsteel Blade2840 ms60 ms40 ms
Executioner's Greatsword4260 ms80 ms60 ms
Cursed Damned Blade4460 ms80 ms60 ms
Spire of the Drowned Lich6060 ms80 ms60 ms
Relic Sunblade8580 ms80 ms80 ms
Tyrant's Ember Mace9580 ms80 ms80 ms
Forge Hammer10080 ms80 ms80 ms
The Hollow King's Sword11080 ms80 ms80 ms
00.20.40.60.810100200300400500600700milliseconds after the blowspeed of the game
The speed of the game over a boss's death blow with the The Hollow King's Sword, played through the game's own TimeScale in 2 ms steps: the blow's freeze (80 ms), then 0.5 s at 25% speed, climbing back to full in the last 0.15 s. On the screen every step is a drawn frame (16.7 ms at 60 Hz), so a freeze holds the frames that start inside it and never fewer than it asks for.
  1. Combat / Boss: hit · parried · boss:died (facts)
  2. HitStop: one request for the tick, the longest freeze
  3. ctx.time.slow → Loop.slow
  4. TimeScale: the speed of each drawn frame (the slowest wins)
  5. Loop: fewer ticks, or none; the frame is still drawn
  6. the camera look, the shake and the sound go on

Executions

An enemy that cannot act is marked: a pale diamond with a blade pointing down floats over its head for as long as it is staggered, has a broken guard or (a boss) is stunned. A sword blow on a marked enemy is a finisher instead of a hit: the player is held for 0.5 s and nothing can hurt them, the blow lands 0.14 s in, and the target dies outright, whatever health or guard it had. The click and its windup are exactly as before: it is the blow that is replaced, decided on the tick it lands. Everything is weapons.json execution.

Who can be executed, when, and what it gives back (src/data/weapons.json execution.kinds; src/util/execution.js)
KindExecutable whenGives back
Ordinarystaggered (a perfect parry, a broken poise, a wall, a heavy weapon) or its guard is broken (a bash, a bomb)15 health, 10 mana
Championstaggered (a perfect parry, a broken poise, a wall, a heavy weapon); and only in its last phase (a champion after its last plate, a boss in its last)30 health, 20 mana
Bossstunned (a boss: a spell in a wind-up, three Ice Shards); and only in its last phase (a champion after its last plate, a boss in its last); and at 20% health or less (the last stun)nothing extra: a boss's death refills everything
The finisher (src/data/weapons.json execution; systems/Combat.js, Player.js, Boss.js, Spells.js, Animation.js)
RuleValueNotes
Who is takenthe executable enemy nearest the crosshairof everything the sword reaches (its own reach and arc, not behind a wall); the others in reach are left alone: a finisher is one committed act
The playerheld 0.5 sno walking, blocking, swinging, casting, throwing, jumping or dashing; the view stays free; nothing hurts the player (no damage, no parry, nothing announced)
The swingits follow-through is stretched to fill the finisherthe swing's time and length grow together so the hand does not jump; a Cursed Damned Blade throws no Moon Wave: the finisher replaces the blow whole
The targetheld staggered (or its stun held) for 0.5 sdies 0.14 s in: a hit of kind execution for the rest of its health
The blow80 ms hit-stop and a shake of 0.5a boss's death adds the slow motion of the hit-stop section above
The mark■ #e8f0ff, 0.6 m, 0.45 m over the headpulses; one shared picture drawn from numbers; the sprite is part of the model and goes with it
in the game: a staggered zombie wears the mark (headless capture of the real game)
in the game: a staggered zombie wears the mark (headless capture of the real game)
in the game: the finisher, the blade driving through slowly
in the game: the finisher, the blade driving through slowly
  1. click: the swing and its windup (as ever)
  2. the blow lands: Combat asks what the sword reaches
  3. a marked enemy: execution:began (no hit box)
  4. Player: held 0.5 s · Boss / AI hold the target
  5. 0.14 s: execution:struck → Combat kills it
  6. executed: health, mana, the sting, 80 ms hit-stop

Wall-splats and swept shoves

Every blow of the player's shoves what it hits: a sword's knockback (the table of swords in Phase 1), the shield bash's 1.6 m and a Rune Bomb's 2.5 m. A shove is a displacement carried out in one tick, not a speed, so how hard an enemy hits a wall is how much of the shove the wall took. An ordinary enemy thrown into a wall, a pillar or the stub of a choke takes a wall-splat: a share of the blow's own damage for every metre the wall took, and a stagger (so it wears the execution mark). A wall torch near where it hit makes it worse. Bosses and champions are never shoved. Everything is weapons.json splat.

The rule (src/data/weapons.json splat; src/util/splat.js)
RuleValueNotes
How hardthe metres the wall took of the shoveall of it head on, about half in a 45° glance, none in the open or against another body; under 0.25 m is a graze and does nothing
Damage30% of the blow for each metre, at most 100%a share of the blow that did the shoving, so it grows with the weapon, the level, a stun's double and a parry's empowered strike; it ignores guard, armour and weaknesses
Stagger0.4 s + 0.5 s a metre, at most 1.6 sa staggered enemy can be executed (the section above)
A wall torchwithin 1 m of where it hit: +50% of the blow and +0.4 sthe scene gives the torches' places (ctx.level.torchPoints)
The surfacewall ×1, pillar ×1, choke ×1a maze wall, a pillar (the halls and the ruins) and a choke stub; the table is there to tune them apart
What each blow adds when it throws an enemy head on into a wall that stands right behind it (the whole shove is lost; damage at level 1)
BlowDamageShoveThe splatWith a wall torchStagger
Worn Iron Sword150.8 m+4+110.8 s
Footman's Flanged Mace201.3 m+8+181.05 s
Tempered Moonsteel Blade281.8 m+15+291.3 s
Executioner's Greatsword422 m+25+461.4 s
Cursed Damned Blade441.6 m+21+431.2 s
Spire of the Drowned Lich602.2 m+40+701.5 s
Relic Sunblade852.6 m+66+1091.6 s
Tyrant's Ember Mace953.2 m+91+1391.6 s
Forge Hammer1003.4 m+100+1501.6 s
The Hollow King's Sword1102.4 m+79+1341.6 s
Shield bash (Wooden Shield)101.6 m+5+101.2 s
Rune Bomb (60 in the middle of the blast)602.5 m+45+751.6 s
  1. a blow shoves: knockback (with the blow's damage)
  2. Movement: the shove is carried in steps and a wall stops it
  3. wall:impact: the metres lost, the surface, the place
  4. Combat: a splat (a share of the blow) and a stagger
  5. splatted: dust, a crunch, a shake
  6. a staggered enemy is a marked one: execute it

Update 26 Oct 2026Stamina & Movement

Sprinting now costs a stamina pool, and so does the dash. The pool drains while you sprint, drops you to a walk when it runs dry and comes back after a short pause. Everything below is read from src/data/player.json (stamina, bindings) and src/data/progression.json (the passives).

100stamina at level 1
18 / sdrain while sprinting: 5.56 s of sprint from full
25 / srecovery once rested
1.25 spause after a sprint, swing or bash
20refill needed before the sprint comes back
9.6 m/ssprint speed (walking 6)

Try it

This bar is driven by the same rules (the page copies Stamina.update and the sprint test in Player.js, with the numbers above). The Guard bar above it is the shield's meter (Phase 1): hold the shield up and take blows on it, and watch it drain by the blow times the shield's guard drain, break at 0 and refill only with the shield down. Hold the button, or hold Shift with the pointer over the demo, to sprint; let go and watch the pause, the recovery and the resume tick. Swing restarts the pause. The passives change the numbers as they do in the game; the level slider lengthens the pool.

1
Health100 / 100
Guard100 / 100
Stamina100 / 100
in the game: sprinting, the bar draining (headless capture of the real HUD)
in the game: sprinting, the bar draining (headless capture of the real HUD)
in the game: the pool ran dry: WINDED, the resume tick and the grey bar
in the game: the pool ran dry: WINDED, the resume tick and the grey bar

The rules

The rules (src/data/player.json stamina; src/systems/Stamina.js and Player.js)
RuleValueNotes
Pool100 at level 1milestone levels add to it (Leveling System); a checkpoint saves its size
Sprint keyShiftplayer.json bindings.sprint: a list of key codes, so it is configurable in the data
Sprint speed×1.6 = 9.6 m/swalking is 6 m/s; Fleet Stride adds 0.08 to the factor
Drain18 a secondonly while sprinting (Shift held and moving): 5.56 s from full; Light Feet makes it ×0.85
Drop-outat 0the sprint stops that tick (the player walks) and stays locked, whatever Shift does, until the pool reaches the resume point
Resume point20so a held Shift cannot stutter in and out at 0
Recovery delay1.25 scounted from the last sprint, sword swing or shield bash; Steady Breath makes it 1 s
Regeneration25 a secondafter the delay; Second Wind makes it ×1.2, the Moonlit Blessing ×1.5
Refillsat a checkpoint rise, a shrine, and when a level grows the poola milestone fills the added points at once
What the bar shows (src/ui/HUD.js setStamina, src/ui/hud.css)
StateWhenThe bar
Restedfull and untouchedsteps back to half strength so the HUD is quiet
SprintingShift held, moving, pool above 0drains 18 a second; the fill follows at once (a 0.09 s linear transition) and a pale ghost segment stays behind, then catches up
Recovering1.25 s after the last sprint, swing or bashfills 25 a second
Lowbelow 25% of the poolturns amber and pulses
WINDEDthe pool hit 0the bar goes grey, flashes and shakes red once, a WINDED tag appears and a tick marks the resume point (20); the sprint is locked until the pool is back there

How long a sprint lasts

Computed from the numbers above (duration = pool / drain; refill = pause + pool / regeneration, from empty)
WhoSprint from fullDistance runPauseBack to full from empty
No passives5.56 s53 m1.25 s5.25 s
A stamina build: Second Wind, Light Feet, Steady Breath (three choices)6.54 s63 m1 s4.33 s
...and Fleet Stride (a fourth)6.54 s66 m1 s4.33 s
No passives, under the Moonlit Blessing7.94 s76 m1.25 s3.92 s

The dash

A short burst of speed on F, the Vigil's answer to a charge: it takes the player 4 m along the move keys in 0.2 s, and for the first 0.12 s nothing can hurt them. It is the one thing besides the sprint that spends stamina, and it spends it as a price, not a rate.

The dash (src/data/player.json dash and bindings.dash; src/util/dash.js, Player.js, Stamina.js, Combat.js, Render.js)
RuleValueNotes
Switchdash.enabled truefalse: the key does nothing and the bar shows no notch
KeyFbindings.dash: a key code or a list of them
Distance and time4 m in 0.2 sthe speed eases off (falloff 1): 40 m/s at the start, 0 at the end, and the metres always add up to the distance exactly. Walls and bodies stop it as they stop a walk
Directionwhere the move keys pointfixed when it starts, whatever the player looks at after; with no key held idleDirection is 'back' (a backstep)
Price30 staminapaid when it starts, and only if the pool holds that much and is not winded: 3 dashes from a full pool at level 1. A refused dash costs nothing, does not lock the sprint, flashes the bar and plays the same dud as a refused spell. It restarts the recovery pause like a swing. A pool spent to exactly 0 is winded
Cooldown0.5 sfrom the start of one dash to the start of the next; a press inside it does nothing
Invulnerable0.12 s from the starta blow, charge, slam, arrow or blast that lands inside it does nothing and is not a parry (player:dodged); a charge that is dodged is spent and does not turn round and hit when the dash ends. It never outlasts the dash
The view+5° while it laststhe field of view widens at 16 a second and settles when the dash is over
The bara notch at 30dim while the pool is short of the price, bright when it can pay
010203040050100150200invulnerable until heremilliseconds into the dashmetres a second
How fast the dash goes while it lasts: the burst is at the start and eases off, so the first tick already carries the player 0.64 m. The dashed line is where the invulnerable moment ends.

The Ghoul Hound is what it is for: a dash sideways takes the player out of the charge line (the hound runs on and meets the wall), and a dash into the line lets the charge arrive inside the invulnerable moment and be dodged. The slam of the Iron Knight and the Bone Colossus is dodged the same way; none of it is a parry, so a parry's reward (an empowered next blow) is not earned by a dodge.

With the other moves

Update 26 Oct 2026Leveling System

There is no experience. The player's level goes up by one each time a boss or champion falls (the Iron Knight every 5th wave counts, as it is fought like a boss), and by nothing else: killing ordinary enemies never levels. Each level adds health, stamina and attack, and one passive. All of it is read from src/data/progression.json and worked out by src/util/progression.js.

40the highest level
every 5 wavesa milestone (a champion, or a boss every 2nd)
+10 / +10 / +4%health / stamina / attack a level, levels 2 to 10
+5 / +4 / +2%from level 11 on
190health at level 10 (before any Heart Container)
×1.36attack at level 10

The rules

0+0%50+25%100+50%150+75%200+100%250+125%1510152025303540levels get smaller from 11— bonus health— bonus stamina- - attack bonus (right axis)level
Total bonus from the milestones, by level: health and stamina (left axis) and the attack bonus (right axis, dashed). The kink is where the steps change.
The stat steps (progression.json steps: what ONE level gives, by the level reached)
LevelsHealth eachStamina eachAttack eachCount
2–10+10+10+4%9 levels
11–40+5+4+2%30 levels
Boss milestones: the level, the wave whose fighter gives it, what that level adds, the totals, and whether it owes a choice of passive (levels 2 to 12 and the cap)
LevelWaveFighter+Health+Stamina+AttackMax healthMax staminaAttackPassive
25Iron Knight+10+10+4%110110×1.04a choice of 3
310Bone Colossus+10+10+4%120120×1.08a choice of 3
415Iron Knight+10+10+4%130130×1.12a choice of 3
520Drowned Lich+10+10+4%140140×1.16a choice of 3
625Iron Knight+10+10+4%150150×1.2a choice of 3
730Veiled Matron+10+10+4%160160×1.24a choice of 3
835Iron Knight+10+10+4%170170×1.28a choice of 3
940Ember Tyrant+10+10+4%180180×1.32a choice of 3
1045Iron Knight+10+10+4%190190×1.36a choice of 3
1150Forge Golem+5+4+2%195194×1.38a choice of 3
1255Iron Knight+5+4+2%200198×1.4a choice of 3
40195Iron Knight+5+4+2%340310×1.96stats only

Choosing a passive

Before 27 October 2026 each of levels 2 to 9 unlocked one passive in a fixed order. Now every level owes a choice: when a boss or champion falls, 3 passives of the pools that are open (the core of 18, and 5 more for each maiden rescued) are put on the screen as cards and the player picks one with the number keys; the next wave waits for the pick. The stat steps above are unchanged. A passive does one of two things: it changes a number every system reads (an effect), or it grants something once (more maximum health, mana or stamina). The ten new ones each read one number where the thing they change happens: the dash, the bash, the kill, the wall-splat, the execution, the spell.

Choosing a passive (src/data/progression.json choice; util/progression.js offerFor; systems/Progression.js, Player.js, Waves.js, ui/HUD.js)
RuleValueNotes
What a level owesa choice of 3 of the pools that are openevery level from 2 until the open pools are empty (level 19 with the core alone; every rescued maiden adds her 5, and so more levels); never a passive already owned; fewer when fewer are left. The core (core) is always open; a maiden's pool opens when she is rescued, which is kept for the play session. A maiden widens what is offered; she adds no picks
How it is picked1 2 3 for the first, second and third cardwhile an offer is open the number keys pick instead of selecting a spell (nine keys are bound, for the swap's page of passives to lay down); the pointer is captured, so there is no click
The guard0.6 sa key pressed before the cards have been up this long counts for nothing, so a key from the fight does not choose
The next wavewaitsthe break does not count down while an offer is open, and a saved game that owes a pick holds its wave until it is made
What is offeredworked out, not rememberedofferFor draws the three from the run's seed, the level of the pick and what is owned, so a saved game shows the same three again
Savedplayer.level.perks and seedno save-version bump; a save from before choices has no list and is read in the old order (legacyOrder)
Switchchoice.enabled true, swap.enabled truefalse: the first eight are given one a level in the old order, with no choice; the swap is removed

The maidens give the branches

A freed maiden is a teacher. Each of the five has a pool of her own (fire, ice, stealth and the Shades, light and healing and loot, ward and growth); the pool opens when she is rescued (the fall that frees her already offers hers) and stays open for the play session with her. She also swaps: standing near her between waves, the player lays down one of their passives and takes one of hers in its place.

Swapping with a maiden (progression.json swap; systems/Progression.js; player.json bindings.swap, swapPage)
RuleValueNotes
Whoa rescued maiden standing in her placenot one still dancing where the boss fell; her pool is the one she gives
Whenin a break between wavesthe break does not count down while the panel is open; in a wave she says it will be in a quiet moment
Wherewithin 4 m of herthe first time the player comes that near in a break a line says so; the panel closes by itself 2 m further on
KeyT (again to leave)the page keys ← → (previous, next)
Step one: which to givea page of 9 of the player's passivesthe number keys pick; a passive that grants (maximum health, mana or stamina) cannot be given back, because what it raised is kept for good
Step two: what she gives3 of her own, none ownedworked out from the run's seed and the passive laid down (closing the panel and opening it again is no re-roll); it takes the old one's place in the list
How often1 a breakthe next wave gives the swap back
When she cannota line says why"the Crimson Elf will teach you in a quiet moment, between the waves", "the Crimson Elf has taught you all she can this break", "You have no passive to give the Crimson Elf", "the Crimson Elf has nothing more to teach you"
The pool (progression.json perks): 43 passives in 6 branches (18 in the core, always open, and 5 for each maiden once she is rescued); a key ending in Mult is multiplied in, one ending in Add is added, a grant is given once
#PassiveBranchWhat it doesEffectOrigin
1Second WindThe HallsStamina recovers 20% faster.staminaRegenMult 1.2one of the first eight
2Light FeetThe HallsSprinting drains 15% less stamina.sprintDrainMult 0.85one of the first eight
3Steady BreathThe HallsStamina starts to recover a quarter of a second sooner.regenDelayAdd -0.25one of the first eight
4Arcane WellThe HallsMana recovers 25% faster.manaRegenMult 1.25one of the first eight
5BulwarkThe HallsBlows taken on the raised shield do 10% less.blockFactorMult 0.9one of the first eight
6Fleet StrideThe HallsSprinting is a little faster (+0.08 of walking speed).sprintSpeedAdd 0.08one of the first eight
7Veteran's PoiseThe HallsThe perfect-parry window is 0.03 s longer.parryWindowAdd 0.03one of the first eight
8WellspringThe HallsWounds close by themselves, 1 point a second, after 8 s unhurt.woundRegenAdd 1one of the first eight
9Stout HeartThe Halls+30 maximum health, healed at once.grant health +30core, new (27 Oct)
10Deep ReservesThe Halls+40 maximum mana, filled at once.grant mana +40core, new (27 Oct)
11Second LungThe Halls+30 maximum stamina, filled at once.grant stamina +30core, new (27 Oct)
12Edge of the DamnedThe HallsEvery blow, bash and spell is 8% stronger.attackMult 1.08core, new (27 Oct)
13Quick HandsThe HallsThe shield bash is ready 25% sooner.bashCooldownMult 0.75core, new (27 Oct)
14NimbleThe HallsA dash costs 25% less stamina.dashCostMult 0.75core, new (27 Oct)
15BloodlettingThe HallsEvery kill heals 2 health.killHealAdd 2core, new (27 Oct)
16Brutal ImpactThe HallsEnemies thrown into walls take half again as much.splatMult 1.5core, new (27 Oct)
17Executioner's AppetiteThe HallsExecutions give back twice the health and mana.executionRewardMult 2core, new (27 Oct)
18SpellbinderThe HallsSpells hit 20% harder.spellPowerMult 1.2core, new (27 Oct)
19KindlingCrimsonFireballs hit 30% harder.fireballPowerMult 1.3the Crimson Elf's pool
20Ember HeartCrimsonFireballs cost 30% less mana.fireballCostMult 0.7the Crimson Elf's pool
21Crimson FuseCrimsonRune Bombs do 40% more damage.bombMult 1.4the Crimson Elf's pool
22Crimson FuryCrimsonSword blows and shield bashes are 15% stronger.meleeMult 1.15the Crimson Elf's pool
23HoarfrostSilver FrostIce shards hit 30% harder.icePowerMult 1.3the Silver Frost Elf's pool
24Deep WinterSilver FrostChill lasts 2 seconds longer.chillAdd 2the Silver Frost Elf's pool
25Glacial MindSilver FrostIce shards cost 40% less mana.iceCostMult 0.6the Silver Frost Elf's pool
26Rime WardSilver FrostBlows taken on the raised shield do 15% less.blockFactorMult 0.85the Silver Frost Elf's pool
27VeilsightShadowShades show themselves from 4 m further away.revealRangeAdd 4the Shadow Elf's pool
28Shade-BaneShadowShades take 60% more from everything you do.shadeMult 1.6the Shadow Elf's pool
29Phantom DashShadowA dash protects you for 0.08 s longer.dashInvulnAdd 0.08the Shadow Elf's pool
30Fleet ShadowShadowA dash is ready 40% sooner.dashCooldownMult 0.6the Shadow Elf's pool
31Gilded DraughtGoldenHealing draughts restore 40% more.potionMult 1.4the Golden Elf's pool
32Bountiful HallsGoldenOne more draught and one more crystal lie in the maze each wave.floorLootAdd 1the Golden Elf's pool
33SunwellGoldenMana crystals restore 50% more.crystalMult 1.5the Golden Elf's pool
34DawnlightGoldenA shrine's blessing lasts 60% longer.blessingMult 1.6the Golden Elf's pool
35ThornbarkEmeraldBlows taken on the raised shield do 12% less.blockFactorMult 0.88the Emerald Elf's pool
36Mirror GlintEmeraldThe perfect-parry window is 0.05 s longer.parryWindowAdd 0.05the Emerald Elf's pool
37Living WoundEmeraldWounds close by themselves, 2 points a second, after 8 s unhurt.woundRegenAdd 2the Emerald Elf's pool
38Greenwood StrideEmeraldStamina recovers 30% faster.staminaRegenMult 1.3the Emerald Elf's pool
39Hearth-SongCrimsonA fireball bursts into three embers where it lands; each burns on for 40% of the blow.fireballEmbersAdd 3the Crimson Elf's pool
40Lamp-SongGoldenA Healing Draught drunk under a third of your health restores double, and blows do half as much for 3 seconds.dyingPotionMult 2 dyingGuardAdd 3the Golden Elf's pool
41Frost-SongSilver FrostAn Ice Shard freezes what it hits outright for 1.5 seconds (a foe once every 6 s); a boss takes a stack and a half.iceFreezeAdd 1.5 iceStackAdd 0.5the Silver Frost Elf's pool
42Veil-SongShadowAfter a dash the dark takes you for 1.5 seconds: the dead lose you and bolts in the air miss. Ready every 8 seconds.veilAfterDashAdd 1.5the Shadow Elf's pool
43Mirror-SongEmeraldWhatever shield you raise throws bolts back; a mirror shield does it half again as hard.reflectAny 1 reflectMult 1.5the Emerald Elf's pool

The wave of milestone n is the nth boss or champion wave: with a champion every 5th wave and a boss every 10th (Bone Colossus then Drowned Lich then Veiled Matron then Ember Tyrant then Forge Golem), level L is reached at wave 5 × (L − 1), up to level 40 at wave 195.

The level crest and the banner

The crest (a gothic gem in a gold rim, src/ui/HUD.js setLevel) sits beside the health and stamina bars. Its ring fills as the next boss comes nearer: the share of the stretch between the last boss wave and the next that the current wave has reached, full while the boss lives (milestoneProgress). Under the bars a line names the next boss and how many waves away it is; hovering the crest says the same. When a level is won a gold flash crosses the screen, the crest pops and a banner states the level, the boss that fell, what it adds and Choose your passive, the three cards come up (key, name, what it does) and stay until one is picked, while the health and stamina bars lengthen to their new maximum (a width transition, a gold glow and a sheen along the bar).

1
Health100 / 100
Guard100 / 100
Stamina100 / 100
Level Up
in the game, a moment after a level was won (the gold flash still on the screen; the particles are boss-death sparks at the camera)
in the game, a moment after a level was won (the gold flash still on the screen; the particles are boss-death sparks at the camera)
The bars grow with the maximum (progression.json hud: 220 px at the start, +1 px a point, never over 460 px)
LevelMax healthHealth barMax staminaStamina bar
1100220 px100220 px
2110230 px110230 px
5140260 px140260 px
10190310 px190310 px
20240360 px230350 px
30290410 px270390 px
40340460 px310430 px

Update 26 Oct 2026Maze Generation & POIs

The maze is no longer only a spanning tree of identical corridors. After the walls are carved the planner breaks the sameness with wide halls, narrow gates, an open landmark and a few places worth a detour, and dresses every crossroads so the player can map their route. The plan is pure data (src/util/layout.js), seeded like the maze, so ?seed= replays it.

21 × 21cells, 6 m each (walls 4.5 m tall)
3 + 1halls, and the ruins
up to 12choke points (2.9 m gaps)
6points of interest: five shrines and the vault
59crossroads in the sample maze
4quarters, each with its colour and sigil

How a maze is made

  1. generateMaze: depth-first carve + 10% extra openings
  2. planLayout: ruins, halls (inner walls down)
  3. dead ends: the vault is walled up, shrines placed
  4. chokes and crossroads picked
  5. WallWorld: stubs, pillars, seal boxes
  6. MazeLevel + LevelDecor: the pictures
  7. Landmarks: shrines and the seal at run time
A real maze: seed 3 through the game's own generateMaze and planLayout. The player starts in the middle (white ring).
  • Overgrown ruins (3×3 cells)
  • Wide halls (2×3, 3×2, 2×2)
  • Choke points (8): the gold stubs
  • Moon Fountain (1)
  • Shrine of blessing (1)
  • Shrine of Trial (1)
  • Gambler's Well (1)
  • Blood Basin (1)
  • Sealed vault (1) and its seal (red wall)
  • Crossroads, by quarter (59)

Bone marks, and the shrines used on a key

Three shrines do nothing when the player walks in: they say what they ask, once per visit, and wait for X. They trade in bone marks, the currency of the Vigil (vigil.json marks, owned by systems/Marks.js, shown beside the score, saved in every checkpoint, kept through a fall like the score).

Where marks come from and where they go
WhereMarksNotes
Every enemy that dies+1whoever killed it
A champion or a boss+12 (champion), +25 (boss)on top of the kill
Shrine of Trial+35when the whole pack has fallen
Blood Basin+45 for 30 health3 times; never the last point of health
Gambler's Well−20, −30, −40a 60% chance of a gift each time

The maidens' song

With no maiden rescued the Halls have only the drone. Every maiden rescued adds one layer of a song over it (the set outlives the run). While a wave is fought the song is ×1.35 quicker and ×1.4 louder, more for a boss; in a break it is calm.

Layers (vigil.json song.layers)
MaidenVoiceWhat it plays
the Crimson Elfdruma pattern of 16 steps (7 notes)
the Golden Elflutea pattern of 32 steps (15 notes)
the Shadow Elfchoira chord of three held 16 steps, 4 chords round
the Silver Frost Elfbella pattern of 32 steps (5 notes)
the Emerald Elfpipea pattern of 32 steps (8 notes)

Gates at the chokes

4 of the 12 chokes have a portcullis and a lever on each side. The use key at a lever drops the gate (1 s): it stops bodies, not sight or shots, holds for 12 s and rises by itself (the lever sticks for 20 s). Enemies cut off by it batter it: a 0.9 s telegraph, then twice their damage off its 300 health; a broken gate is mended after 45 s. Flyers pass over.

Moon phases

Each run is under one phase of the moon, rolled when a new game begins (the title screen shows tonight's; Continue keeps the saved run's): Full Moon (30%): Moon Wave ×1.35, Shades seen at 30%, the Moon Fountain also blesses for 30 s, light at 125%; Half Moon (40%); New Moon (30%), 1 more potion and crystal a wave, floor gear ×1.5, light at 55%.

Light matters

A Wisp that flies past a lit wall torch (within 3.2 m) snuffs it, one torch each 8 s; a fireball of the player's that flies past an unlit one (within 3.4 m) lights it again, one torch for each; a torch left dark for 120 s catches by itself. A Shade within 5 m of a lit torch is seen.

Attack tokens and infighting

At most 2 ordinary enemies attack at once: a melee blow or a charge needs a token (held for its wind-up and 0.7 s after a blow with none); an enemy refused one circles the player and asks again. Bosses and champions need none. A fireball that meets another ordinary enemy hurts it for 50% of its damage and turns it on the shooter for 6 s (it strikes back at 50% damage and the shooter turns on it); it ends at 14 m or out of sight.

Bosses that adapt

A boss or champion that falls leaves a lesson for the next of its kind in the same run: what stunned it most, or (for the Iron Knight, which has no stun) what did it the most damage. The next one remembers it and says so: fire (fireball): 40% less damage, and a hit counts for 0.5 of a stun; frost (ice): 30% less damage, and a hit counts for 0.5 of a stun; lightning (lightning): 40% less damage, and a hit counts for 0.5 of a stun; the blade (melee): 20% less damage; the bombs (bomb): 40% less damage. A fall in the boss's wave forgets that fight.

The stolen staff

Carry the Spire of the Drowned Lich into the Drowned Lich's wave and it knows it: it moves 1.15× faster, and the Spire's chill gets through its water shield as 0.5 of a frost stack a blow (3 freeze it, as Ice Shards do).

Corpses

The body of a fallen ordinary enemy lies where it fell for 25 s (it used to vanish after 4 s), fading over 1.5 s; no more than 12 lie at once. A fireball that flies over one burns it away (0.9 s); the Drowned Lich (its drown summon) raises the nearest bodies within 30 m as its thralls, where they lie, and calls the rest in a ring as before.

The Nemesis

An ordinary enemy that kills the player survives the fall as the nemesis, with a generated name, a violet mark and an affix. It returns 1 wave later (on the first ordinary wave), stronger for every time it has killed the player; killing it pays 25 bone marks and a sword or shield one tier up from what the player carries (never above rank 3, Epic). One at a time; saved with the run. A boss, a champion or a thrall never becomes one.

Strength by kills (vigil.json nemesis.strength, on top of the wave's toughness and its affix)
Times it has killed the playerHealthSpeedDamage
1×1.8×1.1×1.25
2×2.3×1.15×1.4
3×2.8×1.2×1.55
4×3.3×1.25×1.7

Elemental reactions

Reactions (spells.json reactions)
ReactionSpellOn an enemy that isWhat happens
Shatterlightningchilled (an Ice Shard slowed it)×1.8 damage, the chill ends, staggered 1 s
Chainlightningsoaked (the Lich's tide washed over it, 8 s)jumps to the nearest 3 enemies within 6 m for 60% of the blow
Slideicecharging (a Hound in its rush)the charge breaks, it slides 4 m on, staggered 1.2 s

Elite affixes

From wave 3, an ordinary enemy of an ordinary wave may spawn as an elite with one affix: 5% at wave 3, 1% more each wave, never above 30%. A ring of the affix's colour shows it.

Affixes (vigil.json affixes.list)
AffixWeightHealthSpeedIts blowsTakesMarksDrops
Warded3×1.5×1×1×0.7+3Lesser Mana Crystal
Frenzied3×1.2×1.3×1×1+3Minor Health Draught
Brutal2×1.3×1×1.6×1+4Minor Health Draught, Lesser Mana Crystal
Gilded1×1.4×1.1×1×1+12Cache of Rune Bombs, Minor Health Draught

Quarter events

On every ordinary wave one quarter of the maze (north, east, south, west) awakens, never the one that woke last: its crossroads runes and sigils burn ×2.2 brighter, 50% of the wave's enemies are placed in it (cells too far to arrive in the wave's window are not used), and 2 extra items (Minor Health Draught 3, Lesser Mana Crystal 3, Cache of Rune Bombs 2, by weight) lie in its dead ends. A boss or champion wave has none.

Wave mutators

From wave 3, an ordinary wave (a boss or champion fights alone and never has one) may roll a mutator: 15% at wave 3, 1.5% more each wave (26% at wave 10), never above 45%. It is drawn by weight, never the one the wave before had, announced by a banner with its name and what it does as the wave starts, kept as a small tag on screen while the wave lasts, and over when the wave is cleared or the player falls. The roll is worked out from one number the run draws when it begins (saved with it) and the wave's number, so the same wave has the same mutator after a fall or a Continue, and a save from before them has none. The effects are plain numbers read by the game's generic rules; no system knows a mutator by name.

Mutators (vigil.json mutators.list)
MutatorWeightShare of rollsWhat the banner saysIn numbers
The Quickened Dead320%The dead move faster: zombies and skeletons most of allspeed ×1.1; Zombie speed ×1.6 on top; Skeleton speed ×1.3 on top
The Draughts Run Dry213%No health draughts lie in the maze this waveno health items laid (floor, elites, quarter dead ends)
The Creeping Fog320%A fog closes in: you see no further than fifteen metresfog: 95% of the view hidden at 15 m (density 0.115 against the maze's 0.008), closing in over 2.5 s
The Hardened Dead213%The dead are hardier: 40% more healthhealth ×1.4
A Great Horde213%A great horde comes: half as many again23 enemies instead of 15 at wave 7 (×1.5)
The Few and the Fell213%Fewer come, and they are far harder to killhealth ×1.6; 9 enemies instead of 15 at wave 7 (×0.6)
Moonlit Plenty17%The moon is kind: more draughts and crystals lie in the maze2 more Minor Health Draught on the floor; 3 more Lesser Mana Crystal on the floor

Cursed relics

Strong items with a real drawback, and always the player's choice: an item with damned: true in items.json is never taken by walking over it. Look at it (within 2.8 m, so its plate is up) and press X. Its plate says what it gives and what it costs, in the Damned colour #E0409A with the tag DAMNED, and that it is bound for the run: it cannot be put down (a drop key would make the curse a switch to flip whenever it bites), up to 2 at a time, and nothing is replaced or destroyed when the slots are full. A fall keeps them like the rest of the gear; a new game starts without any. They are laid, never given: a wave from wave 6 lays one on the floor (10%, 1% more each wave, never above 25%), a vault's loot may hold one (50%), a boss may leave one beside its reward (30%); only one the player does not carry, and only while a slot is free. Switched off with relics.enabled (no relic is laid, the use key does nothing, a saved one is ignored).

Relics (items.json, damned: true; the words come from the numbers through vigil.json relics.words)
RelicGivesCostsWhen the curse bitesProp (halo size)
Widow's BrandSword blows and shield bashes hit 50% harderHealing draughts restore nothingThe draught heals nothing: Widow's Brand has drunk it firstdrawn from shapes; Legendary-sized ring
Cinder CodexSpells hit 60% harderMana crystals restore nothingThe crystal is only ash: Cinder Codex burns it before it can feed youdrawn from shapes; Legendary-sized ring
Gorged Reliquary+40 maximum healthStamina recovers 50% sloweralways on while it is carried: the HUD marks the relicdrawn from shapes; Epic-sized ring
Spurs of the Pale RiderSprinting is faster: +30% of walking speed
A dash is ready 50% sooner
Every blow you take hurts 40% morealways on while it is carried: the HUD marks the relicdrawn from shapes; Epic-sized ring
Tallyman's LedgerEvery kill pays 100% more bone marks
1 more draught and 1 more crystal lie in the maze each wave
The dead move 20% fasteralways on while it is carried: the HUD marks the relicdrawn from shapes; Rare-sized ring
Crown of the Hungry DeadEvery kill heals 6 health
Wounds close by themselves, 1.5 a second
-30 maximum healthalways on while it is carried: the HUD marks the relicdrawn from shapes; Epic-sized ring
Ember CrownSpells hit 40% harderHealing draughts restore 50% lessalways on while it is carried: the HUD marks the relicdrawn from shapes; Mythic / Relic-sized ring

The effects are the passives' own numbers (EFFECT_KEYS: a key ending in Mult is multiplied in, any other is added) folded into the same table, so a relic and a passive that act on the same thing multiply (the Widow's Brand's ×1.5 and Crimson Fury's ×1.15 are ×1.725) and nothing is capped. A maximum-health change is made once, when the relic is taken. The relics are in the codex like any item (the card has the same lines, no prompt); the Nemesis's gift and every boss list never name one.

The active slot

One item rides on a key of its own, V, with a cooldown, apart from the Rune Bombs on G. It is an item of kind active in items.json with an action block; the game knows 4 kinds of action (stagger, reveal, phase, subjugate), each implemented once and read from the numbers, so no system knows an item by name. One slot, one cooldown: carrying a second item means swapping, and a swap does not give a fresh cooldown. Walking over one takes it when the slot is empty; with the slot full it stays lying and the use key (X, looking at it within 2.8 m) swaps it for the one carried, which is laid where the new one lay: nothing is destroyed (until a fall: the item laid down is loose in the maze like any floor loot and goes with the wave). A fall keeps the item like the rest of the gear, and the cooldown is clear when you stand up again (it is not saved). The key does nothing while a choice of passive is open, on your knees, in a finisher or with nothing in the slot; a refusal says how long is left. They are laid, never given: a wave from wave 4 may lay one on the floor (8%, 1% more each wave, never above 16%) and a vault's loot may hold one (50%); never the one carried, and a boss's drop lists are untouched. Switched off with actives.enabled.

Active items (items.json kind active; the lines are made from the numbers through vigil.json actives.words)
ItemActionWhat it doesCooldown
Horn of the Shaken Dead RarestaggerStaggers every ordinary enemy within 9 m for 3 s
A champion reels for 1.2 s
A boss is not moved
28 s
Lantern of Revealing RarerevealEvery Shade within 40 m is seen for 8 s, as by a lit torch30 s
Veilstep Sigil EpicphaseSteps 5 m the way you look, through a thin wall if one is in the way
Nothing hurts you for 0.35 s
Never ends inside a wall, a gate or a sealed vault: with no room to land it fails
14 s
Collar of Subjugation EpicsubjugateBinds the ordinary enemy under the crosshair, within 3 m, to fight beside you until it dies
It keeps within 4.5 m of you, and goes for the nearest enemy within 14 m
A boss, a champion, an elite, a thrall or a nemesis cannot be bound; a refused use costs nothing
When it falls the collar lies where it fell: take it up to use it again
45 s

The step (phase) walks the line the player looks along in 0.25 m steps and lands on the farthest place of it that is at least 1.5 m away and where the body fits: inside the maze, touching no wall, pillar, choke stub or portcullis, clear of other bodies and not in a vault that is still sealed. It may pass through at most 1.2 m of wall on the way, so a maze wall can be crossed but not a thick mass. A wall straight ahead sends the player to the first free floor behind it; at the edge of the maze or with no room to land, the step fails (the cooldown is not spent). The horn staggers a champion for less and a boss not at all (a staggered enemy wears the execution mark). The lantern uses the Shade's own reveal, the one a lit torch and the Veil-Piercing Lens use.

Boss fights in the ruins

On a boss or champion wave the fighter stands in the middle of the ruins from the start of the wave instead of walking in from a far cell, holding, while the spire and beam turn red. It holds until the player comes within 14 m, hits it, or 40 s have passed; then it fights as usual. The alarm lasts until it falls. (The collapsing floor and the flooding arena are not built.)

The Bell of Challenge

A bell stands in the middle of the maze from the start of the wave before a boss or champion wave until that wave starts. X within 2.2 m rings it, up to 3 times; each ring adds its row to the next fighter and gives 1 more drop. It costs nothing: it is a choice to risk the fight.

Rings (vigil.json challenge.rings)
RingHealthSpeedComes with it
1×1.3×12 Skeleton
2×1.3×1.15nothing
3×1.4×12 Shade

Room templates and spawning rules

Room templates and the rules the planner follows (src/util/layout.js planLayout; vigil.json layout)
TemplateShapeHow manyWhereWhat it is for
Courtyard3×3 cells round the start with every inner wall down; the Tree of Life stands at the exact middle (two trunks with a walkable gap between them), the five maidens on a ring under it, the five tombstones on a wider ring, the bell and the start in the room that is left1opened first, so nothing else is placed in it or in the cells touching it; its outer walls keep every opening the maze gave themthe middle of the maze: the hub that grows with every maiden, and the stones of the fallen
Wide hall2×2, 2×3, 3×2 cells (either way round); the inner walls come down, a 0.9 m pillar stands at every inner corner, a brazier in two corner cells3at least 4 cells from the start (measured to the hall's middle), one cell from the border, never touching another featurea room to fight in with cover: the enemies reach you from several sides
Overgrown ruins3×3 cells open; a sunken ring, rubble, four broken columns of different heights, moss, a 9 m spire with a green beam taller than the walls1at least 7 cells from the startthe landmark: seen over the walls, marked on the minimap from the start
Choke pointa stub of wall (0.9 m thick) each side of a straight corridor: a gap of 2.9 m in the 6 m openingup to 12straight corridor cells at least 3 cells from the start, 3+ cells apart, never in a halla gate: the walls, the sight lines and bodies see it, the flow field does not need to
Moon Fountaina dead-end cell with a basin, a spout orb and a floor ring1a dead end 5+ cells from the start, 5+ from another point of interest, from the farther half by walking distancea full heal, once, when needed
Shrine of blessinga dead-end cell with an altar and a floating moon crystal1same rules as the fountaina 90 s boost
Shrine of Triala dead-end cell with an iron brazier on a plinth and a red flame1same rules as the fountain; used on a keya pack of 3+ after 1.4 s; 35 bone marks and Minor Health Draught and Lesser Mana Crystal if it is won
Gambler's Wella dead-end cell with a stone well of green water and a turning gold coin1same rules as the fountain; used on a key20 bone marks (+10 each time, 3 times) for a 60% chance of a gift
Blood Basina dead-end cell with a shallow basin of dark blood, glowing like a slow heart1same rules as the fountain; used on a key30 health for 45 bone marks, 3 times; never the last point
Sealed treasure vaulta dead-end cell whose way in is walled up, with a glowing runed seal and two chests1a dead end 8+ cells from the start, far by walkingloot and wardens, behind a Rune Bomb
Crossroadsa cell with three or four ways out: a floor rune ring, a sigil on a wall, and a torchevery one (59 in this maze; 14 torches at most)3+ openings, outside halls and points of interesta landmark per quarter of the maze, so the player can tell where they are

Rules that hold for every seed (the smoke test checks them over 40 mazes): nothing overlaps; nothing is close to the start; everything that is not a sealed vault can still be walked to from the start; a vault is closed (no flow field reaches it, nothing spawns in it) until its seal breaks and is reachable once it has; a choke never jams a boss.

Landmarks

Wayfinding: the four quarters

Every crossroads gets the same three things, in the colour of the quarter of the maze it lies in (north, east, south or west of the middle, the diagonals splitting them). After a short while the colour alone says where you are.

The four quarters of the maze, seen from the middle (the diagonals split them): each has its own colour and glyph (vigil.json layout.crossroads.colors; src/scenes/LevelDecor.js)
QuarterColourSigil
North #ffb347sun
East #3fd0c9waves
South #a56bffstar
West #ff4f5ecrescent

What the shrines and the vault do

The blessing (vigil.json pois.shrine.blessing.effects)
EffectValueIn play
attackMult×1.2sword, shield bash, Moon Wave and spells hit harder
staminaRegenMult×1.5stamina recovers quicker
sprintDrainMult×0.7a sprint costs less
manaRegenMult×1.5mana recovers quicker
the seal of the vault, from three metres
the seal of the vault, from three metres

Update 26 Oct 2026Model Polish Logs

A log of the three model fixes of the update: what was wrong, the numbers before and after (the "now" column is read from src/data/enemies.json) and pictures from the model lab (lab.html) with the real rigs and clips.

Demon: the armour was blown out

The rebuilt Demon's single material arrived with the file's defaults: the colour map doubled as an emissive map at full strength, so her gold armour was lit by the scene and by its own texture, and came out a flat pale yellow with no relief and a hot, chalky highlight. The surface is now set when the model is built (src/util/materials.js setSurface, new brightness knob; src/prefabs/enemy.js applies an enemy's material). The values were chosen by trying candidates live in the lab: A (emissive 0.25) and C (0.2, more metal) beside the original; the game uses A with a little more self-light (0.3) because the maze is darker than the lab.

The Demon's surface (enemies.json demon.material, applied by util/materials.js setSurface when the model is built)
KnobBeforeAfterWhat it does
emissive10.3the share of the colour map still added as light of its own. The Meshy file ships with its colour map also as an emissive map at full strength, so the armour was lit twice (by the scene and by its own texture)
metalness0.3 (the file's 1, clamped by buildEnemyModel)0.25polished, not a mirror
roughness10.55a soft highlight instead of a chalky one
specular1 (the file asks for 2)0.45the strength of the sheen
brightness10.95a factor on the colour map itself: takes the top off a gold the light already blows out
before: gold lit twice, no relief
before: gold lit twice, no relief
trial A: emissive 0.25, metalness 0.2, roughness 0.6: the embossing and a warm sheen
trial A: emissive 0.25, metalness 0.2, roughness 0.6: the embossing and a warm sheen
trial C: emissive 0.2, metalness 0.45, roughness 0.42: more metal, darker
trial C: emissive 0.2, metalness 0.45, roughness 0.42: more metal, darker

The hurt flash, the telegraph glow and the freeze tint are emissive colours; the base emissive is captured after this look is applied, so they still work (the flash is max(base, flash)).

Shield Skeleton: the mace crosses the fist

In every pose the mace's shaft ran along the forearm beside the hand instead of crossing the fist. Its socket was re-fitted (below); the shield's grip, which was nearly right, was centred. The shield's unguarded and broken poses, the guard overlay on the left arm and every clip are unchanged.

idle: the mace lies along the forearm
Before: idle: the mace lies along the forearm
idle: the shaft crosses the palm
After: idle: the shaft crosses the palm
the slam: the hand under the shaft
Before: the slam: the hand under the shaft
the slam: the fist round the shaft, head forward
After: the slam: the fist round the shaft, head forward
walking (the walk clip, 0.35 s in)
Before: walking (the walk clip, 0.35 s in)
the same frame
After: the same frame
the attack clip, 1.35 s in
Before: the attack clip, 1.35 s in
the same moment: mace and shield sit on the hands
After: the same moment: mace and shield sit on the hands

Skeleton Archer: the bow in the palm

At rest the bow hung behind an open hand at the side. Its rest grip now puts the riser in the left palm, with the limbs leaning forward; the draw pose (the bow upright at the end of the extended arm, the string towards the archer) is exactly what it was.

idle: the bow floats behind the hand
Before: idle: the bow floats behind the hand
idle: the riser in the palm
After: idle: the riser in the palm
walking
Before: walking
walking
After: walking
the draw (halfway)
Before: the draw (halfway)
the draw: identical, by construction
After: the draw: identical, by construction

Sockets and how they were found

Bone sockets (enemies.json attachments: position in metres in the bone's own axes, rotation in degrees XYZ; read live for "now")
PropBoneWas: position · rotationNow: position · rotation
Shield Skeleton: maceRightHand[-0.003, -0.147, -0.135] · [-144.9, 75.1, 5.7][-0.047, -0.018, -0.171] · [-151.3, 77.5, 34.5]
Shield Skeleton: round shieldLeftHand[0.102, 0.059, 0.011] · [-72.5, 27.1, -32.1][0.079, 0.112, 0.002] · [-68.9, 33.1, -33.9]
Skeleton Archer: bow, at restLeftHand[0.041, -0.016, -0.023] · [48.4, 79, 120.6][0.03, 0.09, 0.074] · [40.5, 80.8, 132.3]
Skeleton Archer: bow, draw state (a delta on the rest frame)same[0, 0, 0] · [-8.1, -39.1, 98.6][-0.111, 0.092, 0.01] · [-13.5, -38.4, 93.6]
How the grips were worked out (the model lab: lab.fit and lab.focus, measured on the real rig)
ThingRule
The handthe skeletons have no finger bones: the prop is rigid on the wrist, so a grip is one transform; the palm centre is 0.07 m on from the wrist along the forearm (elbow to wrist)
The macehead at the top of the model, pommel at the bottom, 0.60 m long. Gripped 0.12 m above the pommel; the shaft pitched forward and up (axis 0.12, 0.62, 0.78 in the body's frame in the idle pose, about 127° to the hanging forearm) so it crosses the fist. It had run parallel to the forearm (about 0°), beside the hand
The round shielda disc in the XY plane with the boss on +Z and a vertical handle on the back at z ≈ -0.07: the handle goes in the fist, the face points forward in the raised guard. The old fit was already close; this one centres the handle in the palm
The bowlimbs along Y, string on +X, the riser (the grip) at x ≈ -0.095, the arrow flies towards -X. At rest the riser is in the palm and the limbs lean forward by 12°
The draw posea state is a delta on the rest frame, so moving the rest would have moved the draw. The new delta is rest⁻¹ × (old rest × old delta): the drawn bow ends exactly where it was

Update 1 Nov 2026The Final Vigil

The run has an end. The fifth boss, Forge Golem (wave 50), holds the Crimson Elf and drops The Keepers' Songbook, the song of the Vigil written down. The last fight, Hollow King (wave 60, once), is an exam of the five fires; when he falls the Vigil is kept: the five maidens sing the whole song, and the game offers to go on.

60the last fight, once
43passives in the pool
5capstones the book gives
134 sthe ending
56beats in it

The order of the fights

The fighter of every tenth wave (util/schedule.js, vigil.json waves): the five go round, the king comes once
WaveFighterTimeHealth
10Bone Colossusfirst2,400
20Drowned Lichfirst3,200
30Veiled Matronfirst3,400
40Ember Tyrantfirst2,600
50Forge Golemfirst3,400
60Hollow King the last fightfirst6,500
70Bone Colossusrepeat 14,800
80Drowned Lichrepeat 14,800
90Veiled Matronrepeat 15,440
100Ember Tyrantrepeat 14,160
110Forge Golemrepeat 15,440
120Bone Colossusrepeat 27,200
130Drowned Lichrepeat 26,400
140Veiled Matronrepeat 27,480
150Ember Tyrantrepeat 25,720
160Forge Golemrepeat 27,480

The king is never repeated within a Vigil (a prestige begins a new one, and he comes again): after wave 60 the five go round again, each tougher by its own hpScalePerRepeat. The Iron Knight keeps the other fifth waves and frees no maiden.

The Songbook, the verses and the capstones

The five verses (vigil.json song.verses): sung in the last fight as each pool breaks and, whole, in the ending; 12.8 s each, a line every 2.6 s
VerseSung byWords
● The HearthThe Crimson ElfWe banked the hearth when the first night fell,
and kept it small, that it might last.
A fire shut in must still draw breath:
give it a spark while its door stands open.
● The LampThe Golden ElfWe hung the lamps along the long watch,
each one a promise that she would come.
Light is answered by light: when the hand is raised,
send it a spark, and the hand lets go.
● The VeilThe Shadow ElfWe shut our eyes at the turn of the night
and trusted what we could not see.
Light one small flame in the dark's deep room,
and what hides there must show its face.
● The FrostThe Silver Frost ElfWe drew the water from the deepest well,
and the cold kept every ember honest.
Three times the frost, and the proud thing stills;
a fire laid on the ice will wake it.
● The MirrorThe Emerald ElfWe hung a mirror where the moon would come
that she might see how bright she was.
What is thrown at you, hold up and send home:
it was meant for another, and it will find him.
The five capstones: a fifth passive in each maiden’s branch, offered only once the Songbook is carried (progression.json, requires "songbook")
PassiveHer branchWhat it does
Hearth-SongThe Crimson ElfA fireball bursts into three embers where it lands; each burns on for 40% of the blow.
Lamp-SongThe Golden ElfA Healing Draught drunk under a third of your health restores double, and blows do half as much for 3 seconds.
Frost-SongThe Silver Frost ElfAn Ice Shard freezes what it hits outright for 1.5 seconds (a foe once every 6 s); a boss takes a stack and a half.
Veil-SongThe Shadow ElfAfter a dash the dark takes you for 1.5 seconds: the dead lose you and bolts in the air miss. Ready every 8 seconds.
Mirror-SongThe Emerald ElfWhatever shield you raise throws bolts back; a mirror shield does it half again as hard.

The last fight

Hollow King has 6,500 health in 5 pools (phases at 80%, 60%, 40%, 20%), and a different fire opens him in each, in the order of the maidens’ ring. At each pool’s edge the maiden of the next fire sings her verse while he kneels 7 s and cannot be hurt; with the book she mends 15% of the player’s health and 25% of their mana. The full tables are in Phase 3.

The ending

The ending, 134 s in all (vigil.json ending, util/ending.js): 56 beats in 9 shots
ShotWhenCameraWhat happens
fall0–4 sthe player’s own eyethe song drops to its drone
crown4–10 sthe wide posehis crown flies to the tree
turn10–22 sthe wide pose, a slow push-inthe song rises, all five layers, calm; a maiden turns and steps in
tree22–34 sthe rising posethe tree flares and the stones glow; the sky turns full; his stone rises and both his stanzas are cut; a shaft of moonlight; the Ember Crown may be laid at the tree
curtsy34–40 sthe player posethe five bow to the player
song40–104 sorbits the ring, 40° (8.5 m out)a verse is sung
last104–116 sorbits the ring, 6° (8.5 m out)a maiden’s last words
ascent116–128 sholdsthe screen goes dark
end128–134 sholds–

Rekindling (prestige in the code): the Vigil begun again

Players see it as Rekindle; the code and the save keep the name prestige. The end card’s Rekindle the fire (and the pause card, once the Vigil has been kept and gone on) starts a new Vigil from wave 1: level 1, no passives, the worn sword, every maiden held again, every boss to be fought again, the Golem’s book and the King at wave 60 once more, with the ending. It asks twice, because it ends the run. Kept: the codex, the stanzas on the stones, the Iron Knight’s tally, the bone marks, the settings and the flag that the Vigil was kept. Each prestige makes the dead 15% tougher in health and in blows (added, not compounded, and it stops growing at prestige 10; the number goes on counting), and the player keeps one small gift: 5% more health and stamina for each, up to 5 times (+25%). The prestige is the profile’s own number (the-last-fire.prestige in the browser’s storage) and a save records the one its Vigil began at.

The five fires on the level crest show it: a flame for each prestige, up to 5, in the maidens’ colours in the ring’s order (crimson, golden, silver, shadow, emerald); from prestige 6 the whole ring burns through the five colours and the Roman numeral sits under the crest. The prestige is also said on the title’s Continue line, on the Fallen screen, on the end card and in the credits’ Kept by you.