main
Character creation: - Full RQ3 Previous Experience wizard (4-step: identity, characteristics, culture/occupation/skills, review+save) with all 29 occupations across 4 cultures; skills computed as base + category modifier + years × multiplier - Character sheet expanded to show culture, occupation, derived stats (HP/FP/MP/ DB/SR), all 7 skill category modifier badges, computed skill percentages grouped by category, weapon attack/parry %, hit locations with armour AP - Location/destination tracker on character sheet (auto-saves on blur) - parry_percent stored on combatant_weapons Personality traits: - 24 predefined traits (Brave, Greedy, Cautious, etc.) each rated 0-100% - Trait → action bias map drives scene choice weighting - rollPersonalityAction() rolls d100 per trait, sums biases, returns suggestion - Trait editor (pill UI) on both character sheet and NPC view - Adventure tab: Roll Personality button fires traits, highlights suggested choice Tables and data: - Import RQ3 character creation tables (Culture d8, Occupation d100 ×4, Craft sub-tables, Language Proficiency, Dropped Oil Lamp, Aging, Armor Points) - Cross-table links: Culture → Occupation, Barbarian/Civilized Crafter → Craft - Fix rollOnTable to use actual dice notation instead of flat random row index - Remove unused resolveHeadInjury function Session tools: - Clear All button wipes all session data (characters, NPCs, enemies, combat, adventure, log) while keeping tables and spell mappings - PATCH /api/characters/:id/traits and /api/npcs/:id/traits endpoints - GET /api/rules/personality-traits reference endpoint - POST /api/adventure/personality-roll endpoint
RQ3 Story Tool
A solo web app for narrative-driven play using RuneQuest 3rd Edition rules with a custom fiction layer.
Setup
npm install
The first time you run the app, the SQLite database is created automatically at data/story-tool.db from db.js's schema.
Importing the table files
tables/*.md are converted into the database once, then the database is authoritative (the .md files can be deleted afterward):
npm run import-tables
Re-running this command wipes and rebuilds the imported table tree, NPC-field detection, and the Norse Layer 1→2 table links - safe to re-run any time the .md files change.
Run
npm start
Then open http://localhost:3000.
Project layout
db.js- SQLite schema and all query helpers (npcs, enemies, log, combat state, imported tables, spell mappings).rq3.js- the RuneQuest 3rd Edition rules engine. Pure functions only, no DB/HTTP dependencies.server.js- Express routes. All state changes go through/api/*and are logged.lib/markdownTableParser.js- parses the heading/table structure out oftables/*.md.scripts/import-tables.js- one-time markdown → SQLite conversion (see above).public/- the frontend (index.html,app.js,style.css). Plain JS, no framework, no rules logic - everything goes through the API.
Notes
- The fiction layer (NPC names, encounter flavor text, custom spell names) lives entirely in the database (originally seeded from
tables/*.md) and never touches the RQ3 rules engine inrq3.js. - Spell name → mechanic mappings are managed via
/api/spell-mappingsrather than markdown, since the table content has already moved into the database. - Closing the tab while there are unexported changes triggers an export reminder; data is also safely persisted in SQLite regardless.
Languages
JavaScript
96.7%
CSS
2.6%
HTML
0.7%