Skip to content

Cyberpunk red character sheet#61

Merged
over2take merged 19 commits into
mainfrom
Cyberpunk-Red-character-sheet
Jul 14, 2026
Merged

Cyberpunk red character sheet#61
over2take merged 19 commits into
mainfrom
Cyberpunk-Red-character-sheet

Conversation

@over2take

@over2take over2take commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

Test plan

  • Tested locally
  • Tests pass

Pre-merge checklist

Code quality:

  • Code follows project style
  • No breaking changes (or clearly documented)
  • No console errors or warnings

Version & Release:

  • Version bumped? If releasing to users, update:
    • frontend/package.json version
    • docker-compose.yml APP_VERSION
    • CHANGELOG.md with release notes
  • GitHub Actions will auto-tag Docker images with the new version

Before merging to main:

  • All tests passing
  • PR reviewed and approved
  • Branch is up to date with main
  • No merge conflicts

Related issues

Developer and others added 19 commits July 12, 2026 12:35
The setup script and README both create a root .env for docker-compose
variable substitution (includes the DuckDNS token), but only backend/.env
was ignored - the root copy showed up as untracked and could be committed
by accident.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Data:
- character_sheets table (one sheet per player per system; NPC sheets exempt
  via partial unique index) + npc_sheet_links table + saved_maps.npc_links_data
- game_system global setting

Backend:
- routes/sheets.js: admin REST (list, full view, per-field patch) with an
  explicit admin role check (player tokens rejected), public game-system
  endpoint, PUT system emits gameSystemChanged
- sheets/templates.js: server-side public/combat field metadata; the server
  filter is the only privacy gate
- Socket events: requestMySheet (auto-creates blank sheet, carries portrait
  across systems), updateSheetField (identity from socket, never payload),
  requestQuickSheet (public fields only, spectator-allowlisted)

Frontend:
- Template engine (src/sheets/): types, generic template, full Cyberpunk RED
  template (10 stats, 65 skills with derived BASE, armor SP, health, gear)
- SheetRenderer: one renderer for any template (grid/skills/list/notes
  layouts, collapsible sections, current/max pairs)
- CharacterSheetWindow: DraggableWindow with edit-in-place and debounced
  per-field socket saves; re-syncs on admin edits
- CHARACTER_SHEET button in TOKEN_PROTOCOLS sidebar menu
- Admin panel TTRPG_SYSTEM section: system selector + sheet list

Tests: 20 backend (routes, filter, constraints, role rejection) +
14 frontend (registry integrity, renderer, window socket flows)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Identity header block: targeting-bracket portrait frame (initial or
  uploaded image), name + subtitle line, HP bar, at-a-glance chips -
  all template-declared via new SheetHeader metadata
- Bottom tab bar (STATS / SKILLS / GEAR / NOTES) replaces the long
  scroll; sections map to tabs via section.tab
- Stat tiles: label / centered value / roll-affordance strip, number
  input spinners hidden
- Skills rows: proficiency dot + row shading for leveled skills,
  signed BASE with the roll glyph
- "click to roll" hint marks Phase 2 territory

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ?sheet=true renders a dedicated full-browser-tab sheet page (SheetPage)
  instead of the app; reuses SheetRenderer with a 900px column
- Open-in-new-tab button on the sheet window title bar; identity handed
  to the tab via a one-shot localStorage handshake (read then deleted).
  Secure Mode still verifies the player token server-side on identify
- Stat/skill grids use auto-fit columns so nothing overflows the window
  width, and they expand to fill the standalone tab; window widened to 520px

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- The open-in-tab button now uses the win95-close-btn class so it's
  visible against the inverted title bar (matched to the X button)
- Admins were rejected by the standalone tab in Secure Mode: the
  handshake only carried the player token. It now carries the admin
  token too and the sheet page identifies with whichever it has

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drag the bottom-right corner to resize between 360x320 and 520px wide /
92vh tall; content flexes to fill. Width cap stays at the current 520px -
the standalone tab is the big-screen option.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… size

- .win95-content's CSS max-height:300px was capping the sheet content,
  leaving dead space under the tab bar - override it and let the
  renderer flex to fill
- ⧉ button glyph sized down to match the close button

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Linked fields live in their owning system and are overlaid onto sheet
data at read time - never stored in the sheet JSON, so one source of
truth. HP bar mirrors the token (click opens HIT_POINTS); cash mirrors
the bank balance, read-only (click opens BANK). Sheets re-fetch on
sheetUpdated / bankUpdate, and a pending-edit guard keeps re-fetches
from stomping fields mid-typing. Redundant HP tile removed from the
CP:R HEALTH section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Untouched sheets read as all zeroes. Focusing a number field selects
its content so typing replaces the 0 rather than appending to it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Clicking a stat tile or skill BASE rolls it. The client sends only
{ fieldId }; the server resolves the formula from its own roll map
against the STORED sheet values, rolls, and broadcasts through the
existing dice pipeline (tray/scoreboard/history unchanged). Shapes:
sum and CP:R explode10 (nat 10 adds a d10, nat 1 subtracts one, never
chains); pool reserved for SR6/CY_BORG. A drift test cross-checks
frontend template formulas against the server roll map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s last roll

In-app, a sheet roll pops the dice tray so the result is visible.
The standalone tab has no tray, so it shows the latest roll inline
under the header instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templates can set a per-field hint (tooltip). Current/max pairs show
a CUR / MAX micro-label so the two numbers are self-explanatory.
CP:R hints added for LUCK, EMP, Humanity, wound thresholds, and SP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templates declare tokenDefense { editOnToken, label, note }. Generic
keeps the melee/ranged AC editor; Cyberpunk RED hides it (armor SP
lives on the character sheet, combat-private) and the token menu
button jumps to the sheet. Attack banners label the to-hit number
with the system term (AC vs DV). App tracks the active system via
/api/sheets/system + the gameSystemChanged socket event.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Quick-sheet card (public fields + portrait) on clicking another player's rhombus
- Portrait upload with SHA-256 hash deduplication; shown on sheet header
- NPC sheet library: create/folder/attach-to-token, admin-only REST routes
- GENERATE_SHEET socket event seeds an NPC sheet from token name/HP
- LUCK pips in sheet header: click to spend, admin RESET button restores to max
- 25 new tests across backend NPC routes, portrait upload, QuickSheetCard, NpcLibrary, and LUCK pip rendering

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full CP:R implementation on the template-driven sheet engine:
- Server-authoritative combat: single ATTACK button, weapon rows, to-hit
  vs DV, aimed shots, SP soak + ablation, shield breakdown, critical
  injuries (+5 direct, GM rolls table), damage write-through to token HP
- Death saves (escalating penalty, nat-10 fails), Seriously Wounded -2 /
  Mortally Wounded -4 auto-applied, armor penalty on REF/DEX checks
- LUCK: arm pips before a roll for a flat bonus (server-capped and
  decremented); fumble-shield + bonus-negates-nat-1 behind a house-rule
  toggle; RESET_ALL_LUCK admin action
- House rules panel (staged APPLY/REVERT): melee DV take-10, LUCK
  fumble negation; live via settingsUpdated
- NPC library: folders + MOVE, ATTACH to token, OPEN sheet editor,
  linked-token HP mirroring; tiered generation (MOOK..ELITE) seeding
  stats/skills/armor/weapons and token HP/DV (melee DV from sheet)
- Modular sheet import: fillable-PDF form extraction, JSON, stat-block
  text; per-system alias mapping with preview
- Humanity -> EMP derived fields; CUR<=MAX clamping; placeholders;
  OPEN_SHEET on token windows (player own, admin all); DV labels per
  system; CHECK_HEALTH tracks NPC tokens live
- backend: npm run dev (nodemon) to end stale-server restarts

Tests: 377 backend / 574 frontend passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@over2take over2take merged commit de75440 into main Jul 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant