Boss Kind Multipliers
Boss-tier encounters (mini-boss / boss levels) inflate the roster’s base stats so a single BossDef can serve both tiers without duplicating data. The encounter spawner reads a kind: 'mini' | 'boss' argument and applies a fixed HP and damage multiplier to every roster body at spawn time. Depth scaling then layers a per-level ramp on top.
The constants
Defined in data/level-progression.ts:
| Constant | Value |
|---|---|
BOSS_KIND_HP_MULT_MINI | 4.0 |
BOSS_KIND_HP_MULT_BOSS | 8.0 |
BOSS_KIND_DAMAGE_MULT_MINI | 4.0 |
BOSS_KIND_DAMAGE_MULT_BOSS | 8.0 |
Post-v5.162.2 these are the across-the-board 4× buff values — bosses were inflated so they “feel like real walls” rather than slightly chunky mobs. HP and damage move together at the same scale.
Locked ratio: BOSS = 2 × MINI
The boss tier is exactly twice the mini tier on both axes. The header comment on the constants is explicit:
Boss tier doubles mini’s mult so the relative scale (boss = 2× mini) is preserved.
This ratio is the design contract. If the mini constants change, the boss constants must double them — no independent tuning per tier.
Where it fires
spawnBoss(defId, game, world, kind) in engine/boss/encounter.ts picks the base multipliers:
const baseHpMult = kind === 'boss' ? BOSS_KIND_HP_MULT_BOSS : BOSS_KIND_HP_MULT_MINI;
const baseDmgMult = kind === 'boss' ? BOSS_KIND_DAMAGE_MULT_BOSS : BOSS_KIND_DAMAGE_MULT_MINI;The two tiers map to the run sequence (see level-progression):
- mini — level 3 in normal mode, levels 3/6/9 in challenge mode (
mini_bossslots). - boss — level 5 in normal mode, level 10 in challenge mode (
bossslot).
Default is 'mini' if no kind is passed (dev/playground spawns).
Depth scaling layered on top
After the kind multiplier, encounter.ts applies a linear depth ramp based on where the encounter sits in the run:
depthFrac = (currentLevel - 1) / (totalLevels - 1)
depthMult = 1.0 + 0.5 * depthFrac // 1.00 at level 1 → 1.50 at final
hpMult = baseHpMult * depthMult
dmgMult = baseDmgMult * depthMult
totalLevels is 5 in normal mode and 10 in challenge mode (read from RUN_LEVEL_SEQUENCE / CHALLENGE_LEVEL_SEQUENCE), so the ramp stretches to fit the run length and tracks deep-run progression in both modes.
Effective multipliers per run slot
Normal mode (5 levels):
| Level | Kind | Depth frac | Depth mult | HP mult | Damage mult |
|---|---|---|---|---|---|
| 3 | mini_boss | 0.50 | 1.25× | 5.00× | 5.00× |
| 5 | boss | 1.00 | 1.50× | 12.00× | 12.00× |
Challenge mode (10 levels):
| Level | Kind | Depth frac | Depth mult | HP mult | Damage mult |
|---|---|---|---|---|---|
| 3 | mini_boss | 0.22 | 1.11× | 4.44× | 4.44× |
| 6 | mini_boss | 0.56 | 1.28× | 5.11× | 5.11× |
| 9 | mini_boss | 0.89 | 1.44× | 5.78× | 5.78× |
| 10 | boss | 1.00 | 1.50× | 12.00× | 12.00× |
The final boss always sits at 1.50× depth in both modes — same end-state, longer ramp in challenge.
Application to roster bodies
Inside the spawn loop:
- HP —
enemy.hp = entry.hp * hpMult; enemy.hpMax = entry.hp * hpMult. Applied to every roster entry, not just theisBossanchor — shared-health sharers and untargetable carriers also scale. - Damage —
enemy.damageMult = prior * dmgMult. Multiplied into the existingdamageMultexpando so charger / melee / projectile damage paths all read it consistently. Mini-tier-with-no-depth (dmgMult === 1) is a no-op.
The multiplier is baked into the entity at spawn — there’s no per-frame re-application. Affixes and abilities that read enemy.damageMult downstream pick up the scaled value naturally.
Why one BossDef serves both tiers
Boss data files (data/bosses/*) author one roster at base stats. The kind multiplier lets the same def appear as:
- A mini-boss mid-run gate fight (level 3) — moderately tanky, hits hard but survivable.
- A boss final fight (level 5 / 10) — 2× the HP, 2× the damage, the run’s wall.
Without this layer, every boss would need a mini and a boss variant authored separately — twice the data, twice the drift surface. The constant pair keeps that scaling in one place.
Related
level-progression.md— theLevelKindsequence that selects when each tier fires.sealed-arenas.md— the arena that bounds the encounter.- Per-boss authoring lives in
data/bosses/*— see the boss authoring guide.