Cyberpunk red character sheet#61
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan
Pre-merge checklist
Code quality:
Version & Release:
frontend/package.jsonversiondocker-compose.ymlAPP_VERSIONCHANGELOG.mdwith release notesBefore merging to main:
Related issues