Commit Graph

23 Commits

Author SHA1 Message Date
NilsBriggen ca3769eb6b Phase 1: PWA auto-update, player-view map fit fix, encounter picker
- PWA registerType autoUpdate + skipWaiting/clientsClaim/cleanupOutdatedCaches so
  a fresh deploy reaches browsers without a manual hard-reload (the old 'prompt'
  served the stale cached bundle, hiding shipped fixes like the polygon outline).
- MapCanvas: always mount the outer container so the ResizeObserver binds even when
  the map image arrives late over WebSocket — fixes the networked player view
  showing the map at 100% instead of fit ("3x magnified").
- TokenPalette: encounter picker for planned AND active encounters (was active-only),
  with per-encounter "+ All" and counts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 14:26:00 +02:00
NilsBriggen 2879059ba5 P20 fix: crisp device-resolution map rendering + live draw previews
Render the map on a single viewport-sized canvas with a camera transform at
devicePixelRatio (image, fog, drawings, overlay) and draw the grid as crisp 1px
device-space lines — instead of CSS-scaling a natural-resolution bitmap, which
blurred the grid/fog/text at any zoom. Tokens now position in screen space so
their labels stay sharp too. Add live tool feedback via a 'hover' phase: polygon
shows its outline + vertices + rubber-band + fill preview, the brush shows its
footprint, and circle/square AoE preview under the cursor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 12:56:28 +02:00
NilsBriggen c28c29a6c6 P20: map viewport zoom/pan/fit + token placement palette
Render maps at natural resolution inside a CSS-transform world layer (zoom,
pan, fit-to-view) instead of shrinking to maxWidth — large maps are now usable.
Pure viewport math in src/lib/map/viewport.ts (unit-tested). New TokenPalette
places party PCs / active-encounter combatants / blanks in one click with dup
detection; tokens gain optional combatantId (Dexie v9) for live encounter HP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 12:34:00 +02:00
NilsBriggen fb459ad92c Phase 17: map & fog VTT overhaul + player-facing projection
- Pure geometry library src/lib/map/* (grid, distance 5e/pf2e/euclid, AoE
  circle/cone/line/square, polygon rasterize + point-in-polygon, brush, fog set
  algebra, player projection) with unit tests.
- Schema: map tokens gain size/kind/characterId/hp/conditions/gmOnly; maps gain
  drawings/gridUnit(feet)/gridType/fogVersion + point/drawing sub-schemas. Dexie v8
  additive migration; mapsRepo.get + transactional mutate.
- Editor split into a shared MapCanvas renderer + MapEditor tool state machine:
  fog via brush/rectangle/polygon (+ size, reveal-all/hide-all), measurement
  (system-aware distance in feet), AoE templates (circle/cone/line/square preview),
  drawing annotations (freehand/line/arrow/rect/circle/text, GM-only), pings, and
  richer tokens (NxN size, character link with live HP ring, condition dots, edit popover).
- Player-facing projection: toPlayerProjection strips GM-only content; PlayerMapView
  renders it read-only with opaque fog; uiStore.activeMapId + 'Show to players'; the
  player view now shows the live battle map. enemyStatus extracted to
  src/lib/combat/playerProjection.ts (reused, and for Phase 18).

9 geometry unit tests; maps e2e covers upload→token→reveal-all→player projection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:31:26 +02:00
NilsBriggen ffe24495b6 Phase 16: advantage/disadvantage applies to any single die
applyRollMode (src/lib/dice/notation.ts) now rewrites the first single-die term
of any size (d4/d6/d20/...) to 2dN kh1/kl1, not just d20. Multi-die pools (2d6)
and terms with an existing keep/drop (4d6kh3) are left untouched. Dice page copy
updated; unit tests for d4/d6/d8 + skip cases; e2e toggles Advantage and rolls a
d4 → 2d4kh1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:18:57 +02:00
NilsBriggen 04fa90e580 Proper guided character builder + level-up wizard
The bare name/class/level form left new characters as shells (1 HP, all-10
abilities, no proficiencies). Now creation and level-up are guided and auto-populate.

- Hand-authored progression tables (no SRD class/slot data exists on disk):
  src/lib/rules/{dnd5e,pf2e}/progression.ts — core classes' hit die/HP, key
  abilities, save & perception proficiencies, trained-skill counts, caster type;
  5e full/half/pact spell-slot tables, pf2e slot approximation; ASI/boost/skill
  schedules.
- src/lib/rules/progression.ts: getClassDefs/getClassDef, classSkillChoices/Count,
  buildCharacter() (HP from hit die + CON over levels, trained saves/skills, spell
  slots + ability), planLevelUp() (HP gain, new slots, ASI/boost/skill choices),
  applyIncreases/bumpRank. Pure + 12 unit tests.
- Multi-step CreationWizard (Basics → Abilities → Skills → Review) replaces the
  old form; pulls PF2e ancestry HP/speed from the bestiary; review previews HP/AC/
  saves/skills/slots; lands on a ready-to-play sheet.
- LevelUpModal reworked into a guided wizard: auto HP + spell slots, presents the
  level's actual choices (5e ASI/feat, pf2e ability boosts + skill increase) and
  applies them; keeps the strategic build-route advisor.

e2e helper drives the wizard; updated 7 specs to the new flow; new character-wizard
spec asserts a complete level-3 Wizard (HP 17, slots 4xL1 2xL2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:55:48 +02:00
NilsBriggen e39def8f02 Phase 15: level-up strategy advisor + campaign insights
- Level-up build-route advisor (src/features/characters/sheet/LevelUpAdvisor.tsx +
  useLevelUpAdvisor): ~4 system-aware routes plus a custom one; choosing a route
  expands it into concrete next-level steps. AI when configured, deterministic
  fallback (src/lib/assistant/levelup.ts) otherwise. Embedded in the existing
  HP-only LevelUpModal, which stays primary.
- Level-up prompts/schemas added to prompts.ts (buildRoutes/buildSteps), each
  leading with the system constraint + class + next level.
- Campaign Insights section on the Assistant page renders deterministic themes,
  with an optional 'ask the assistant to expand' affordance when AI is on.

levelup + prompt unit tests (4 routes both systems, system vocabulary, custom
route); e2e for the deterministic route→steps flow and the insights section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:23:16 +02:00
NilsBriggen dbbf68752e Phase 14: LLM-grounded encounter-balancing tip
- src/lib/assistant/prompts.ts: balanceSuggestionSchema + buildBalancePrompt
  (system message leads with the grounding constraint; restricts choices to the
  provided compendium candidates).
- useEncounterAdvisor hook: builds context → picks system-correct candidates →
  asks the LLM (when configured) for a structured pick, validates + filters names
  to the candidate set, else falls back to the deterministic buildSuggestedEncounter.
  Apply adds the creatures transactionally via encountersRepo.mutate.
- EncounterTipCard in the combat tracker: leads with the detected difficulty
  tendency (or the current difficulty), offers a one-click grounded suggestion
  (AI or deterministic) with propose→confirm Apply.

prompts unit tests + e2e for both the deterministic apply flow and the AI path
(stubbed provider); the AI test also confirms candidate-grounding (only
shortlisted creatures survive).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:17:23 +02:00
NilsBriggen 7fd5fcd9af Phase 12: LLM provider config + client + CSP
- Bring-your-own-key assistant config in a dedicated persisted store
  (src/stores/assistantStore.ts); partialize drops the key from localStorage
  when 'remember' is off. Key lives in localStorage only, so it's auto-excluded
  from Dexie backups.
- Provider-agnostic LLM client (src/lib/llm) over fetch, no SDK: Anthropic
  Messages + OpenAI-compatible Chat Completions (covers OpenAI/OpenRouter/
  Ollama/LM Studio via custom base URL). Structured JSON output parsed +
  Zod-validated; timeouts; typed error kinds; key never leaked in errors.
- Settings 'Assistant (AI)' section with provider/model/baseUrl/key, remember
  + enabled toggles, and Test connection.
- CSP connect-src widened to any https + localhost for the BYO endpoint.

10 client unit tests; settings e2e asserts config persists and the key is
never present in an exported backup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:04:20 +02:00
NilsBriggen 0930136c46 Phase 11: data-driven Assistant
- Deterministic advisors (src/lib/assistant): party resources (downed/bloodied/
  spent slots/rest nudges), session prep (dangling [[wiki links]], active quests,
  empty journal), live combat hints (turn, downed combatants) — pure + tested
- Data-driven encounter builder: greedily assembles level/CR-appropriate monsters
  to a target difficulty via the Phase-3 budget; one click builds + opens combat
- Assistant page: suggestion cards with one-click actions (goto, long rest,
  create note); wired into routes, dashboard, command palette
- 8 advisor/builder unit tests + assistant e2e

Conversational LLM layer intentionally deferred (no provider/key in this env);
the deterministic advisor is the offline default per the plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 08:06:20 +02:00
NilsBriggen bd6bb240a1 Phase 10: command palette, settings, backup/restore, sample campaign
- Command palette (Ctrl/Cmd+K): fuzzy search over pages + active-campaign
  characters/notes/NPCs/quests + actions; keyboard nav; header ⌘K button
- Settings page: theme, full backup export/import (restore replaces all in one
  transaction), load sample campaign, danger-zone clear-all
- Backup lib (src/lib/io/backup.ts) snapshots every table; sample seeder
  (src/lib/sample.ts) builds a demo campaign
- Header gets ⌘K + settings gear; routes + nav wired

Backup round-trip unit tests + command-palette/settings e2e.
(Deferred from this phase, noted in plan: audio, Discord/Foundry/Roll20, i18n,
push notifications.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 08:00:09 +02:00
NilsBriggen 7100ea8dd4 Phase 9: homebrew content + packs
- Homebrew entity (monster/spell/item/feat/condition) — Dexie v6, repo, hook,
  cascade-deleted with campaign
- Homebrew editor page: per-kind fields + description, create/edit/delete
- Compendium merges campaign homebrew of the matching kind (HB badge, generic
  HomebrewDetail) with the same cross-links (add monster->combat, spell/item->character)
- Content packs: export/import homebrew as JSON (validated, ids reassigned)
- System extensibility documented via the existing RulesSystem registry seam
- Fix: card editors (homebrew/npc/quest/note) debounce-save the FULL snapshot, not
  partial patches — editing two fields fast no longer drops an edit

New homebrew e2e + cascade test coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 07:54:53 +02:00
NilsBriggen 744e91f703 Phase 8: player view (local/projector) + sync seam
- Player View (/play): read-only projector screen — party HP bars + conditions,
  active-encounter initiative with current turn; enemy HP hidden behind a
  Healthy/Bloodied/Down status band; Fullscreen button
- SyncAdapter seam (src/lib/sync): local-first default via Dexie liveQuery;
  documents where a future networked (WebSocket/CRDT) backend plugs in
- Dashboard + routes get a Player View entry
- Robustness: encountersRepo.mutate() does transactional read-modify-write so
  rapid combat mutations can't overwrite each other (old C19 race); tracker uses it

New player-view e2e. Networked multiplayer backend intentionally deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 02:07:27 +02:00
NilsBriggen 1632018ce9 Phase 7: maps & VTT
- BattleMap entity (image dataURL, grid, tokens, fog) — Dexie v5, repo, hook,
  cascade-deleted with campaign
- Maps page: upload image (8MB cap), per-campaign list
- Map editor canvas: grid overlay (toggle + cell size), fog of war (canvas) with
  reveal/hide painting + reveal-all/hide-all, draggable tokens that snap to the
  grid (pointer events, touch+mouse), add/remove tokens; debounced autosave
- Dashboard + routes get a Maps entry

New maps e2e (upload, add token, toggle fog).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 02:01:29 +02:00
NilsBriggen 522ff8abce Phase 6: character creation & level-up
- Ability generation: standard array, point buy (27-pt, validated), 4d6kh3 roll;
  AbilityGenModal with assign-from-pool + steppers (pure abilityGen lib + tests)
- Level-up flow: increment level, HP gain (average or roll hit die + CON)
- Print / save-to-PDF: print button + @media print hides app chrome and roll tray
- Plan: added Phase 11 (data-driven Assistant) to the roadmap

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:56:23 +02:00
NilsBriggen ed3d967526 Phase 5: campaign management & worldbuilding
- New entities (note/npc/quest/calendar): schemas, Dexie v4 tables, repos, hooks;
  campaign cascade-delete now covers them all
- Dashboard hub: campaign stats, navigation cards, party overview, recent rolls;
  opening a campaign lands here
- Notes/Wiki: tags, [[wiki-links]] with click-to-open/create, backlinks panel,
  full-text search, autosave
- NPC manager (role/location/faction/status) and Quest tracker (status +
  objectives checklist + reward)
- In-world Calendar: integer day counter + events (no real Date -> no timezone bug)
- Fix: calendarRepo.get is read-only (creating-on-read crashed inside liveQuery)

8 new unit tests (wikilinks + extended cascade), worldbuilding e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:44:47 +02:00
NilsBriggen 9647e6b3d6 Phase 4: interactive dice & sheet rolling
- Dice notation: exploding (Nd6!) and reroll-below (Nd6r2), capped + tested
- Degrees of success / roll-vs-DC (PF2e ±10 + nat 20/1 steps; 5e crit on nat 20/1)
- Global roll tray (shared store + RollTray in layout) with animated result + degree
- Roll from the character sheet: skills, saves, and attack to-hit/damage are
  clickable and post to the tray + history (rollAndShow/rollCheck helpers)
- Saved roll macros per campaign (persisted) on the Dice page

10 new unit tests (notation explode/reroll, degrees), interactive-dice e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:32:15 +02:00
NilsBriggen 3e5bdc06e2 Phase 3: combat depth
- Condition durations + auto-expiry: timed conditions tick down on the affected
  combatant's turn and drop at 0 (engine tickConditions; UI rounds field + (Nr) chip)
- Initiative: Roll-all (d20 + per-combatant bonus, re-sort anchored) + group/quantity add
- Combat log: per-round event feed (turns, round changes, damage/heal, expiries,
  removals) + in-memory Undo of the last change
- Encounter difficulty budget: 5e XP thresholds + PF2e level budget (pure lib +
  tests); live difficulty/XP-award readout from monster combatants vs the party
- Combatants carry initBonus + cr/level; compendium add-to-combat passes them

18 new unit tests (durations, applyInitiatives, budget), new combat-depth e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:23:13 +02:00
NilsBriggen 379b79e6c4 Phase 2: full compendium across all categories + PF2e data
- Scraped PF2e reference from Archives of Nethys ES into public/data/pf2e/
  (spells, creatures, feats, equipment, weapons, armor, ancestries, heritages,
  backgrounds, archetypes, actions, conditions, deities) via scripts/fetch_pf2e.ts
- Registry-driven compendium: system toggle + per-category nav + generic filters
- 5e expanded: weapons, armor, feats, conditions added alongside spells/monsters/items
- PF2e data served as static assets (fetched, not bundled) for fast native parse
- Cross-links: add spell->spellbook / item->inventory to a campaign character;
  add monster/creature -> open encounter
- Condition tooltips in combat sourced from the conditions glossary
- Tests: registry filter unit tests, compendium e2e (browse + cross-link)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 01:00:40 +02:00
NilsBriggen 0b356adf82 Combat: condition dropdown picker with tag chips
- System-aware condition list (5e PHB / pf2e) in src/lib/rules/conditions.ts
- Dropdown replaces free-text input; non-valued conditions add instantly,
  valued ones (Exhaustion, Frightened N, etc.) show a value field, plus Custom
- Already-applied conditions disabled in the list; chips remain click-to-remove
- New e2e covering preset + valued add and tag removal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 00:44:37 +02:00
NilsBriggen 866f1e1bf1 Fixes + UX: combat HP, char delete, dice animation, compendium filters, import/export
- Combat: relabel HP controls Dmg/Heal, disabled at 0 (were silent no-ops)
- Characters: per-card Delete (confirm) + Export; header Import from JSON
- Dice: tumbling roll animation that settles on the result (a11y-safe)
- Compendium: per-category filters (monster type/CR, spell level/school, item rarity/type) + Clear
- Character import/export to portable JSON (reassigns id, validates on import)
- New: 4 io unit tests, e2e fixes spec (HP damage, delete, CR filter)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 00:40:43 +02:00
NilsBriggen 9ecd817bc6 Phase 1: player character depth
- Inventory + currency + encumbrance vs carrying capacity
- Class resources with correct short/long/daily rest recovery (applyRest)
- Spellcasting: slots (+pact), known/prepared spells, derived DC + attack
- Defenses: 5e death saves/inspiration/exhaustion, pf2e dying/wounded/hero points
- Derived weapon attacks + passive perception via extended RulesSystem
- Dexie v2 migration backfills new fields; debounced save flushes on pagehide
- 9 new unit tests, new character-depth e2e; all green

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 00:30:34 +02:00
NilsBriggen 1a9e5e2c18 Build MVP: campaigns, characters, combat, dice, compendium
- Rules abstraction (5e + pf2e) behind one interface, fully tested
- Pure combat engine: turn-order safe across add/remove/reorder/init-change
- Dexie storage with real cascade deletes + Zod validation on write
- Seedable dice engine with notation parser
- Lazy SRD compendium (code-split), bestiary -> combat
- Strict TS, 54 unit tests, Playwright e2e smoke (all green)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 00:09:42 +02:00