Enemies & Bosses¶
Source: PROJECT_CONTEXT.md §8.3, §8.4, §8.5;
config.jsenemies,enemyScale,melee;game.jsMOB_DEF,MOB_TIER,mkMob,updateMob,isLunger,meleeSequence. Status: ✅ Implemented (low-tier lunge 🅿️ Parked, config-gated)
What it is¶
The AI-mob roster the raider dodges, hunts, or backstabs while looting. Mobs are the PvE threat layer and a loot source — they drop valuable resources on death. They range from cheap tier-1 harassers up to the tier-4 Thornback Brute boss, and they read as creatures of the cute-fantasy Thornwood (spiders, goblins, wardens, a forest brute).
How it works¶
- Roster (
MOB_DEF=CONFIG.enemies), tiered byMOB_TIER: - Tier 1 — harassers: Cave Spider (
spider,web:true), Emberling (emberball, rangedfire, floats), Goblin Scout (goblin), Thorn Hound (hound,pack:true), Bone Thug (skeleton, high HP/atk bruiser). - Tier 2: Forest Warden (
warden, ranged) — also spawned as the Keykeeper variant (game.jsOld Market: renamed,dropsKey=true, +120 HP / +8 atk) that drops the 🔑 vault key on death. - Tier 3 — heavies: Rocketeer (
rocketeer,rocket), Bombardier (bombardier,bomb, lobbed), Stone Sentry (sentinel,stationary:true, long sightvisR 370, slowspeed 18). - Tier 4 — boss: Thornback Brute (
boss,hp 1500, bothmeleeandranged/rocket). - Mob AI (
updateMob) — perceive / suspect / patrol / chase / search: perceivegates detection by sight radius (visR), vision-cone half-angle (visA), and line of sight; a bush shrinks an unaware mob's detect radius (stealth.bushDetectMult).- Gradual detection: cone exposure fills
alertover time —< alertSpotted (0.5)unnoticed,0.5–1suspicious (turns/creeps toward, holds fire),1fully spotted (locks on, mutual fire, rallies the pack viaalertPackTimed). This is the "back off in time" stealth window. - Lose-trail: breaking line of sight decays
alert; ducking into a bush after breaking sight decays it fast (bushBreakDecay). Heavy mobs (tier ≥combat.heavyTier) cling far longer (heavyTenacity) — you escape them by distance/dodging, not by ducking a bush; tier-1 harassers stay shakeable. - Stationary Sentry: tracks while noticing but only opens fire at full alert; otherwise idly sweeps its gaze.
- Front armor + rear weak-point: shots to the front armor cone (
armorFront) are reduced (armorFrontMult), flanksarmorFlankMult, the glowing rear weak-point takes bonus damage (armorRearMult). A chasing mob's facing lags the target (turn rate inupdateMob, melee turn 6 / ranged 3.4) so a circling attacker can reach the rear — and mobs juke side-to-side to defend it. A backstab bypasses armor and the Power check entirely. - Ranged charge wind-up telegraph: ranged mobs fire rarely but hard with a
chargeDurwind-up (per-enemy) — a red telegraph that can be dodge-rolled. - Lunge gap-closer (
isLunger,meleeSequence): melee mobs close a real gap with a telegraphed wind-up (melee.windup) → committed dash (lungeTime/lungeSpeed) → heavy hit (dmgMult). In reach they use quick simple attacks (simpleMult) instead. Currentlymelee.lungeMinTier = 2, so tier-1 melee just walk in (parked: they closed too fast — see §8.7). - Drops: mobs drop valuable resources on death; while in-run inventory is parked, loot spills on the ground (
spillLoot) and auto-vacuums. Tier-1 trash is source-gated to blueprints only (loot.t1Valuables=false).
Tunables¶
enemies (per-mob MOB_DEF — hp · atk · speed · visR · visA · fireRate · projDmg · chargeDur):
| key | name | hp | atk | speed | visR | visA | notes |
|---|---|---|---|---|---|---|---|
spider |
Cave Spider | 90 | 24 | 150 | 205 | 1.8 | melee, web |
emberball |
Emberling | 80 | 14 | 58 | 250 | 2.0 | ranged fire, float, projDmg 26 |
goblin |
Goblin Scout | 86 | 28 | 102 | 205 | 1.5 | melee |
hound |
Thorn Hound | 78 | 36 | 162 | 215 | 1.75 | melee, pack |
skeleton |
Bone Thug | 180 | 50 | 82 | 180 | 1.4 | melee bruiser |
warden |
Forest Warden | 210 | 20 | 76 | 340 | 1.15 | ranged, projDmg 62 — Keykeeper variant |
rocketeer |
Rocketeer | 260 | 90 | 64 | 380 | 1.1 | ranged rocket, projDmg 90 |
bombardier |
Bombardier | 420 | 100 | 50 | 320 | 1.25 | bomb, projDmg 100 |
sentinel |
Stone Sentry | 300 | 40 | 18 | 370 | 1.95 | stationary, long sight |
boss |
Thornback Brute | 1500 | 70 | 70 | 360 | 1.3 | melee + ranged rocket |
enemyScale: enemySpeedMul 1.0 (non-boss speed = player base pace), atkCdMul 1.5 (×on every enemy attack cooldown — attack less often, same per-hit dmg), powerRef 1500, hpPerPow 0.7, dmgPerPow 0.5 (HP/dmg ramp once player out-powers the reference).
melee: lungeRange 140, lungeMinRange 75, windup 0.65, lockLead 0.18, lungeTime 0.30, lungeSpeed 480, recover 0.15, dmgMult 2.0, cd 1.7, simpleMult 0.7, lungeMinTier 2 (1 = every melee lunges).
combat (armor/weak-point): armorFront 0.95, armorRear 2.1, armorFrontMult 0.25, armorRearMult 1.6, armorFlankMult 0.65; mobHpMult 2, mobDmgMult 0.5; heavyTier 3, heavyTenacity 0.35; mobMeleeCd 0.7.
Design intent¶
Serves Pillar 1 (hide-and-kill) and Pillar 2 (route over reflexes): front armor + rear weak-point + juking makes a head-on fight a slow, risky grind, while a stealthy rear approach is an instant assassination (backstab ignores armor and the Power check). Gradual detection and the bush window make "back off before it locks" a real skill. Tiering gives a risk gradient — harassers to skip, heavies to route around, the Brute as a set-piece — and weak-point combat keeps fights about positioning, not aim.
Open questions / deltas¶
- Unity port (§9 #1): the 2.5D iso tilt affects how the rear weak-point and juking read on screen — confirm the look survives a flat-top-down decision.
- Low-tier lunge parked (§8.7):
melee.lungeMinTier=2disables tier-1 gap-close pending a feel pass; flip to1to restore. - Prolonged-but-survivable knobs:
combat.mobHpMult(2) andmobDmgMult(0.5) are the Diablo-direction dials, pending a playtest pass (PROJECT_CONTEXT §8.7 notes these defaulted to1in prose butconfig.jsships 2 / 0.5 — confirm intended values).