feat: full character creation, personality traits, and session quality-of-life
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
This commit is contained in:
@@ -107,6 +107,54 @@ function resolveLayer1Links() {
|
||||
}
|
||||
}
|
||||
|
||||
const CULTURE_TABLE_LINKS = [
|
||||
[/primitive/i, 'Primitive Occupation Table (d100)'],
|
||||
[/nomad/i, 'Nomad Occupation Table (d100)'],
|
||||
[/barbarian/i, 'Barbarian Occupation Table (d100)'],
|
||||
[/civilized/i, 'Civilized Occupation Table (d100)'],
|
||||
];
|
||||
|
||||
const OCCUPATION_CRAFTER_LINKS = [
|
||||
['Barbarian Occupation Table (d100)', 'Barbarian Craft Table (d100)'],
|
||||
['Civilized Occupation Table (d100)', 'Urban Crafts Table (d100)'],
|
||||
];
|
||||
|
||||
function resolveCharacterTableLinks() {
|
||||
const sourceFile = 'rq3_character_tables.md';
|
||||
|
||||
// Culture Table → Occupation Tables
|
||||
const cultureTable = dbApi.tables.findTableByHeading(sourceFile, 'Culture Table (d8)');
|
||||
if (cultureTable) {
|
||||
const rows = dbApi.tables.getRowsForTable(cultureTable.id);
|
||||
for (const row of rows) {
|
||||
const text = row.cells[0] || '';
|
||||
const match = CULTURE_TABLE_LINKS.find(([pattern]) => pattern.test(text));
|
||||
if (!match) continue;
|
||||
const [, targetHeading] = match;
|
||||
const target = dbApi.tables.findTableByHeading(sourceFile, targetHeading);
|
||||
if (!target) { console.warn(`Culture link target not found: "${targetHeading}"`); continue; }
|
||||
dbApi.tables.insertLink({ table_id: cultureTable.id, row_id: row.id, target_table_id: target.id });
|
||||
stats.links++;
|
||||
}
|
||||
} else {
|
||||
console.warn('Could not find Culture Table for link resolution');
|
||||
}
|
||||
|
||||
// Occupation Tables → Craft Sub-tables (Crafter rows)
|
||||
for (const [occHeading, craftHeading] of OCCUPATION_CRAFTER_LINKS) {
|
||||
const occTable = dbApi.tables.findTableByHeading(sourceFile, occHeading);
|
||||
const craftTable = dbApi.tables.findTableByHeading(sourceFile, craftHeading);
|
||||
if (!occTable || !craftTable) continue;
|
||||
const rows = dbApi.tables.getRowsForTable(occTable.id);
|
||||
for (const row of rows) {
|
||||
if (/^crafter$/i.test((row.cells[0] || '').trim())) {
|
||||
dbApi.tables.insertLink({ table_id: occTable.id, row_id: row.id, target_table_id: craftTable.id });
|
||||
stats.links++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
dbApi.tables.clearImported();
|
||||
|
||||
@@ -116,6 +164,7 @@ function main() {
|
||||
}
|
||||
|
||||
resolveLayer1Links();
|
||||
resolveCharacterTableLinks();
|
||||
|
||||
console.log('---');
|
||||
console.log(`Files: ${stats.files}`);
|
||||
|
||||
Reference in New Issue
Block a user