reikhelm/combat/combat-web
Parley Hatch 57dba5e149 feat(combat): order-of-magnitude slowdown — fights now ~20-30s
Fights were ~3-5s; the user wanted 20-30s. Tuned the table (and added one
mechanic) so they land there, re-validated against the sim throughout.

- Engine: a `global_cooldown` (the genre swing timer, §10 "attack delay") — an
  actor can't start a new action until it elapses, so no button-masher can
  out-DPS the intended tempo. Config-driven (`global_cooldown` ticks; 0 = off).
  Actor gains `next_action_at`; engine gates decisions on it.
- Controller: ScriptedPlayer now pressures with its heavy proactively when
  healthy (not only on the exact overrun frame), so the sim measures what a real
  player experiences instead of an unrealistically patient bound.
- Config rebalance: damage cut + flattened, fatigue/regen/recovery co-tuned, and
  the kit made roughly **DPS-neutral** with auto-attack (each ability's cooldown
  matched to auto's damage-per-second). Under the global cooldown that's the key
  insight: abilities win through stagger leverage + timing, not raw throughput —
  otherwise strong abilities trivialize the pace and flat ones aren't worth their
  fill (the guardrail kept inverting until this landed). Auto-attacks (difficulty
  0) also no longer fizzle.
- Front-end: cache-bust the config fetch so edits are always picked up; widened
  the sim's archetype sweep to all six monsters.

Result (sim, skilled play ≈ real play): monster fights 16-38s (centered ~24s);
guardrail steep and green (even-con auto 0% → skill20 2% → skill50 12% →
skill80 44% → skill100 78%); all six monsters winnable. Verified live in-browser:
realistic play lands ~15-30s and a clean mid-fight reads perfectly on the dual bar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 13:34:10 -06:00
..
portraits feat(combat): playable browser front-end + AI monster portraits 2026-06-03 12:46:47 -06:00
game.js feat(combat): order-of-magnitude slowdown — fights now ~20-30s 2026-06-03 13:34:10 -06:00
index.html feat(combat): playable browser front-end + AI monster portraits 2026-06-03 12:46:47 -06:00
README.md feat(combat): playable browser front-end + AI monster portraits 2026-06-03 12:46:47 -06:00
style.css feat(combat): playable browser front-end + AI monster portraits 2026-06-03 12:46:47 -06:00

Vigor — playable combat front-end

A browser battler that drives combat-core (via combat-wasm) in real time: pick a foe, manage your single Vigor pool, and try not to spend your survival. The engine is authoritative and unchanged — this is just a presentation layer and a [HumanController] pushing your intent between ticks.

What's here

  • index.html / style.css / game.js — the UI (torch-lit dark fantasy).
  • portraits/ — AI-generated monster art (Z-Image on the LAN workstation; see ../tools/portraits.py). Committed so the game runs offline.
  • pkg/ — the wasm-bindgen output (gitignored; rebuild with the command below).

Build & play

# 1. Build the wasm bridge into ./pkg  (cargo on PATH; from combat/)
export PATH="$HOME/.cargo/bin:$PATH"
wasm-pack build combat-wasm --dev --target web \
  --out-dir ../combat-web/pkg --out-name combat_wasm

# 2. Serve combat/ as the web root (so the page AND configs/ resolve)
python3 -m http.server 8013 --directory .

# 3. Open the game
open http://127.0.0.1:8013/combat-web/

(Re)generate portraits — needs the LAN ComfyUI / Z-Image server up:

python3 tools/portraits.py --url http://192.168.1.26:8188 --size 768

How to play

  • Click a foe to start. The fight runs in real time (10 ticks/second).
  • Auto-attack is on by default (toggle with the AUTO button or space).
  • Abilities: click a card or press 15. Each shows its fill cost — spending fill lowers your capacity, so a big hit leaves you fragile.
  • Watch the dual bar: bright = current fill, dim = regen headroom, the gold line is your ceiling (cap), and the dark cracked zone on the right is fatigue — ceiling lost for the rest of the fight. When the ceiling collapses to your fill, the next hit overruns you (daze → KO).
  • Second Wind restores ceiling; Guard opens a brief block window. Passive auto-attacking beats the weak foes (Dire Rat, Skeleton); the Golem, Troll, and Wraith want real play — recover, punish when they're spent, don't over-commit.

Difficulty is a table: edit ../configs/default.json (monster stats, ability numbers, the con curve) to taste — the same file the sim tunes against.