# Status — star-survivor (Incanto)

## Implemented

- **Hollow Horde** — a top-down survivors-like. Full-window canvas + DOM HUD (HP/XP
  bars, level, kills, survive-timer), a LEVEL-UP overlay with 3 upgrade cards, and a
  win/lose banner.
- `game.scene.json`: top-down (`gravity [0,0]`), `move` input, knight/goblin/ghost
  spritesheets, `ScoreKeeper(lives 1)`, a dark arena, the `Player`
  (`CharacterBody2D` + `Survivor`, `Health` on child `Vitals`), two built-in
  `Spawner`s (goblin/ghost, infinite) with hidden templates (`Health` freeOnDeath +
  `Chase` + `EnemyFace` + `DamageOnContact` + `EnemyDrop`), a `Director`, a
  `FollowCamera`, and SFX players.
- Custom `src/behaviors.ts`: `Survivor` (move + auto-attack managed bolts + XP magnet
  + level-up/upgrades + pause via `engine.stop/start` + DOM HUD), `Director`
  (ring-scatter spawns + time escalation), `EnemyDrop`, `EnemyFace`.
- `App.tsx` injects the three sheet urls; `vite.config.ts` aliases `incanto/assets`.

## Works (verified)

- `bun run check` → 1/1 scene valid. `bun run typecheck` / `bun run lint` clean.
- `bun run verify` (headless `runScript`): 7/7 — move walks the player; the
  auto-attack kills a spawned goblin which drops an XP shard + tallies a kill;
  gaining XP raises the level; the survive-timer emits `won`; HP→0 emits `lost`.
- Played in a real browser (Playwright): the horde streams in from all sides as real
  animated **goblin + ghost** sprites; the knight auto-attacks the nearest enemy;
  kills drop cyan XP shards that the magnet vacuums up; LEVEL-UP freezes the world and
  shows 3 random upgrade cards (e.g. +Damage / +Fire rate / +Pierce / +Magnet / +Max
  HP), and picking one applies it + resumes; difficulty escalates. 0 console errors.
- HIT FEEDBACK: every bolt that connects pops an additive impact spark, shoves the
  enemy back (knockback), and PUNCHES its sprite (scale-up + opacity dip via
  EnemyFace on the `damaged` signal); a kill adds a colour POOF burst + SFX. The
  ARENA is an INFINITE grid (`GridFloor`): a camera-following backdrop + grid lines
  snapped to world multiples of `cell`, so it tiles forever with no visible border.

## Not Included (on purpose — and next polish passes)

- Bolts/XP are simple `ColorRect2D`s (swap for sprites/FX if desired); the grid floor
  is procedural (no tile art).
- No weapon VARIETY beyond the straight bolt (the upgrade pool tunes one weapon), no
  boss, no meta-progression, no bundled music (SFX presets only).
- Spawning leans on the built-in `Spawner` + `Director` scatter (the engine's clone
  path is internal). Add enemy types by copying a template + spawner into the
  `Director.spawners` list.

## Pausing

ESC pauses and shows the pause menu; OPTIONS opens the settings over it and
BACK returns to the menu that asked. All of it is `GameFlow` (`pausePanelPath`,
`screen(path)`, `back()`) wired with `connections` — there is no TypeScript for
any screen in this game.
