On load, each player's character sheet is fetched from /api/players/{name}:
- BS and WS set from tabInfo.characteristics
- Weapon dropdown replaced with only their personal weapons (normalised
from tabInfo.weapons: type→class, ap→pen, default modes by type)
- First weapon pre-selected with all its damage/pen/rof/mode defaults applied
- maxWounds set from tabInfo.wounds; curWounds preserved from localStorage
if the player was already tracking mid-session
Active scene conditions (synced from MissionTab via dw:combat-state) now
apply automatic attack modifiers:
- Pinned: –20 BS
- Stunned: –20 BS/WS
- Knocked Down: –20 BS/WS
- Fatigued: –10 BS/WS
- Grappled: –20 WS, ranged/heavy weapons hidden from weapon dropdown
- Bleeding: banner only (no roll modifier)
Condition banner appears above the roller when any condition is active,
showing each condition label and the net modifier to the attack target.
The status bar target display also shows the condition delta inline.
MissionTab: conditions map now included in dw:combat-state localStorage
write and CustomEvent payload so the Dice Roller receives per-player
condition state in real time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All 11 issues from 4-player simulation of The Hunt for Fabius Bile:
1. Roll feed visible to all players (no GM auth guard)
2. Scene text gated by revealed flag; GM explicit reveal per scene
3. GM can add NPC/enemy entries to initiative tracker
4. Round counter synced to Dice Roller via localStorage + custom event
5. Check reward text hidden until player has rolled
6. Checks assignable to specific player via Scene Secrets ⚙ options
7. Fear test quick-roll panel with WP input appears when fearRating > 0
8. Decision checks show textarea/Declare instead of d100 roll button
9. Fate point re-roll: one per check per scene, resets on scene advance
10. Player poll reduced from 8s to 4s, combined mission + roll feed poll
11. Mission complete banner with scene stats and GM outcome notes field
4 follow-up findings from second simulation run:
- Finding #1: Activate mission now initialises revealed:false on all scenes
so players never see scene text before the GM narrates
- Finding #2: Fear penalty auto-applied to WP display; button shows
effective (penalised) target rather than raw WP input
- Finding #3: RollFeedRow moved outside component to avoid re-mount on
every render; onDelete passed as prop
- Finding #4: Removed duplicate "Open for Players" quick-button from
Scene Checks left panel — Scene Secrets is the sole entry point
New files:
- src/tests/missionPlaythrough.test.js — full GM+4-player simulation
test suite covering all 11 issues and 4 findings (39 test cases)
- src/tests/missionTab.test.js — player/GM view isolation tests
- src/utils/diceRoller.js — shared d100/degrees/clampTarget utilities
- tests/missionRoutes.test.js — backend mission route unit tests
- tests/playerRoutesLogin.test.js — player login route tests
- tests/sessionRoutes.test.js — session validation tests
Note: React unit tests require jsdom; segfaults on ARM64 (Raspberry Pi)
due to a known jsdom/Node 20 incompatibility on aarch64. Tests pass on
x86 CI. Backend integration tests (tests/) run normally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace username text input with dropdown selector for player login
- Fix unescaped apostrophe in MissionSimTab.jsx (Emperor's -> double quotes)
- Fix em-dash encoding issues in MissionSimTab.jsx
- Update player password to 1234 in .env
- Tab navigation wraps on small screens (flex-wrap)
- Smaller padding and font on mobile (px-4, text-xl)
- Responsive main content padding (px-4 sm:px-6)
- Tighter spacing on login row (gap-3, mb-3)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Rename MissionTab to MissionSimTab (combat simulation, GM only)
- New MissionTab shows mission history (all users)
- Mission Sim tab added to GM-only navigation
- MissionSimTab.jsx moved to src/components/
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- MariaDB missions table with scenes JSON
- /api/missions CRUD routes
- MissionTab saves completed missions to DB
- Mission history panel in UI
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New MissionTab component with scene-based combat simulation
- Enemy roster from DeathwatchRoller (12 enemy types)
- Scene progression (4-6 scenes) with threat levels
- Combat log and results tracking
- Added to App.js navigation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove OCR noise, credits, and duplicates from rules-database.json (288→255 rules)
- Add clean_rules.py script for rule cleanup
- Add CLAUDE.md, docs/, and update README with documentation links
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- scripts/generate-weapon-images.js: AI image generation for weapon cards
supporting HuggingFace FLUX.1-schnell, OpenAI DALL-E 3, and Gemini Imagen;
images served from public/weapon-images/ via new static route in server.js
- public/cards.html: load manifest.json and show AI art on weapon cards
- scripts/scrape-rules-from-pdfs.py: PyMuPDF scraper extracting full rule
text from all five rulebook PDFs with bold-span heading detection
- scripts/tag-and-dedup-rules.js: standalone dedup helper (JS-side grouping)
- database/routes/rulesRoutes.js: remove content truncation in search/random,
add admin dedup endpoint (JS-side, fast), fix RulesTab to fetch full content
- src/components/RulesTab.jsx: fetch full rule content on modal open
- public/print.html: expanded quick reference with pre-gen character stat
blocks (Sepheran + Lucian), Astartes traits sheet with correct derived SBs
and TBs, full Critical Hit Tables for all 4 locations × 4 damage types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both open in a new tab (target=_blank) since they are standalone
HTML pages outside the React app.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Art box reduced from 32mm to 26mm height, icon enlarged to 22pt
- Stats font increased from 6pt to 7pt with more line spacing
- Replaced floating source pip with proper footer bar showing
renown requirement (left) and source book (right)
- Footer bar colour-coded by weapon category to match title bar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Poker-card sized (63×88mm) cards matching the physical Deathwatch card format:
- Req cost badge top-left
- Title bar with weapon name
- Dark art box with category icon and class label
- Type line (Weapon – Melee, Weapon – Ranged, Equipment, etc.)
- Stats block (Dmg, Pen, Range, RoF, Clip, Rld, Special, Renown)
- Source abbreviation bottom-right
9 cards per A4 sheet, cut-ready.
Filter by category (Melee/Ranged/Grenade/Armour/Other).
Data loaded live from /api/weapons.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The template had a stale hardcoded <script> tag from a previous build
output, causing react-scripts to inject a second script reference on
every new build. Restored to proper CRA template with %PUBLIC_URL%
placeholders.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a new WeaponsTab component with:
- Filterable table of all 73 weapons from scrape-rulebooks.py
- Filter by category: Ranged, Melee, Grenade, Armour, Other
- Text search across name, damage, special rules, source
- Click-to-expand detail panel with full stats
- Parses both ranged (semicolon-separated) and melee (structured) stat formats
Tab is visible to all users (not GM-restricted).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts from CR, FF, RoB, MoX, HtC:
- 36+ weapons (ranged + melee) from Core Rulebook
- 37 talents, 16 traits, 11 weapon qualities
- 89 psychic powers
- 99+ bestiary entries from Mark of the Xenos
- 1100+ lore/chapter entries across all books
- 123 speciality entries
- Total: 3415 rules, 228 bestiary entries in DB
Uses PyMuPDF (fitz) for text blocks and pdfplumber for table extraction.
PDFs are stored on NFS and not in git.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When DB_PASSWORD is missing on startup, server exits and PM2 was
restarting every ~660ms flooding backend.log with ER_ACCESS_DENIED_ERROR.
Now waits 5s between restarts and caps at 10 attempts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
import-rules.js, import-armour.js, import-all.js were used once during
initial data import and have been superseded by the scripts/ directory.
All hardcoded wrong passwords (dwroller2025).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allow selecting an attacker from the bestiary/enemies list to
automatically populate BS and WS values. This enables using player
characters (added as enemies) as attackers in combat rolls.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Switch from localhost to Synology NAS (192.168.1.113:3307) for
centralized database hosting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace hardcoded DB_PASSWORD 'dwroller2025' with process.env.DB_PASSWORD
- Replace hardcoded GM_SECRET 'bongo' with process.env.GM_SECRET
- Replace hardcoded GM_PASSWORD with process.env.GM_PASSWORD
- Replace hardcoded PLAYER_PASSWORD '1234' with process.env.PLAYER_PASSWORD
- Update .env.example to document required environment variables
- Apply changes to all backend routes, database modules, and React components
- Update test files to use environment variables for credentials
- Ensure .env remains in .gitignore for production safety
This fix addresses critical security vulnerabilities where database
credentials and authentication secrets were exposed in source code.
- Updated RequisitionShop component styles for a cohesive dark theme.
- Enhanced RulesTab component with consistent dark styling and improved button visibility.
- Modified XPBar component to align with new dark theme aesthetics.
- Adjusted global styles in index.css to support the new design.
- Added comprehensive DEVELOPMENT_GUIDE.md for project setup, deployment, and maintenance instructions.
- Create new XPBar component with green progress bar visualization
- Add XPSummary card showing total XP, available XP, and current level
- Integrate XP bar into PlayerTab character sheet display
- Add reference guide showing Deathwatch advancement costs
- Add GM controls for quick XP adjustment (+100, +200, -50 XP buttons)
- Set default XP threshold to 500 (customizable per characteristic)
- Supports tracking both total XP and spent XP separately
This enables faster XP progression visualization for monthly play sessions.
- Add comprehensive PlayerManagement component for GMs
- Add all GM API endpoints for player CRUD operations
- Add comprehensive test suite with 14 tests
- Clean up .gitignore to exclude logs, backups, core dumps
- Update README with setup instructions and documentation
- Add setup.sh script for easy project initialization
This provides a complete GM interface for managing players without
the large files that were blocking the previous push.
- Created a new script `migrate-to-sqlite.js` to migrate data from JSON files into a SQLite database.
- Implemented functions to read JSON files safely and handle errors.
- Established database schema with tables for armour, weapons, bestiary, and rules.
- Added logic to insert data from JSON files into the corresponding database tables.
- Included backup functionality for the existing database before migration.
- Logged import totals and sample data from each table for verification.
- Added a new script `check-shop-stats.js` to fetch and log item statistics from the database.
- Added bestiaryRoutes.js to handle API endpoints for fetching enemies, full bestiary data, and statistics.
- Implemented caching mechanism for bestiary data with a 5-minute expiration.
- Created transformation functions for bestiary entries to standardize data format for the dice roller.
- Added admin-only endpoint to force reload bestiary data with GM authentication.
chore: Create scripts for analyzing and cleaning bestiary data
- Developed analyze-bestiary-quality.js to review data quality and identify duplicates or inconsistencies.
- Implemented clean-bestiary-fields.js to extract and clean specific fields from bestiary entries, reducing text duplication.
- Created clean-corrupted-bestiary.js to remove corrupted entries based on defined patterns.
- Generated a comprehensive database-cleanup-report.md summarizing the cleaning process and results.
build: Add fast build script for streamlined deployment
- Introduced fast-build.sh to facilitate quick builds and PM2 reloads without reinstalling dependencies.
test: Add GM authentication logic test
- Created test-gm-auth.js to verify the correctness of GM authentication logic with various test cases.
- Implemented `upsert-allewis-from-5001.js` to fetch and update Allewis data from API.
- Created `upsert-missing-movement-from-5001.js` to fill missing movement and wounds data from API.
- Developed `upsert-missing-movement-from-pdfs.js` to extract movement and wounds from PDF text.
- Added `upsert-missing-profiles-from-pdfs.js` to fill missing profiles from PDF data.
- Introduced `upsert-missing-wounds-from-pdfs.js` to update wounds data from PDF sources.
- Created `validate-bestiary.js` to validate the structure of the bestiary JSON.
- Updated `BestiaryTab.jsx` component to display bestiary data with improved structure and search functionality.
- Added tests for `BestiaryTab` to ensure proper rendering and functionality.
- Updated package.json scripts to include separate unit and integration tests before building.
- Added a new script `test-build-test` to run tests before and after the build process.
- Introduced a new local CI/CD script for streamlined local development and testing.
- Refactored PlayerTab component to normalize skills data structure and added tooltips for Space Marine and Power Armour abilities.
- Added named export for Tooltip in DeathwatchRoller for reuse in other components.