feat: add support for stat templates
Introduces a new `template` stat type that allows for table-based lookups via CSV blocks in markdown files. When a template stat is rolled, it uses a dice expression defined in the template to select an entry, applies a label, and automatically updates associated modifier stats using relative values.
This commit is contained in:
@@ -15,10 +15,14 @@ import {
|
||||
getPathsByExtension,
|
||||
getIndexedData,
|
||||
} from "../../data-loader/file-index";
|
||||
import { parseStatYaml, parseStatCsv } from "../../cli/completions/stat-parser";
|
||||
import type { StatDef } from "../../cli/completions/stat-parser";
|
||||
import {
|
||||
parseStatYaml,
|
||||
parseStatCsv,
|
||||
parseTemplateCsv,
|
||||
} from "../../cli/completions/stat-parser";
|
||||
import type { StatDef, StatTemplate } from "../../cli/completions/stat-parser";
|
||||
|
||||
export type { StatDef };
|
||||
export type { StatDef, StatTemplate };
|
||||
|
||||
// ------------------- Types (mirrors CLI) -------------------
|
||||
|
||||
@@ -47,6 +51,7 @@ export interface JournalCompletions {
|
||||
links: LinkCompletion[];
|
||||
sparkTables: SparkTableCompletion[];
|
||||
stats: StatDef[];
|
||||
statTemplates: StatTemplate[];
|
||||
}
|
||||
|
||||
export type CompletionsState =
|
||||
@@ -73,6 +78,9 @@ async function tryServer(): Promise<JournalCompletions | null> {
|
||||
links: Array.isArray(data.links) ? data.links : [],
|
||||
sparkTables: Array.isArray(data.sparkTables) ? data.sparkTables : [],
|
||||
stats: Array.isArray(data.stats) ? data.stats : [],
|
||||
statTemplates: Array.isArray(data.statTemplates)
|
||||
? data.statTemplates
|
||||
: [],
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
@@ -173,7 +181,24 @@ async function scanClientSide(): Promise<JournalCompletions> {
|
||||
}
|
||||
}
|
||||
|
||||
return { dice, links, sparkTables, stats };
|
||||
// Stat template scan
|
||||
const statTemplates: StatTemplate[] = [];
|
||||
const templateBlockRegex =
|
||||
/```csv\s+role=stat-template\s+file=(\S+)\s*\n([\s\S]*?)```/gi;
|
||||
for (const filePath of paths) {
|
||||
const content = await getIndexedData(filePath);
|
||||
if (!content) continue;
|
||||
|
||||
templateBlockRegex.lastIndex = 0;
|
||||
let tMatch: RegExpExecArray | null;
|
||||
while ((tMatch = templateBlockRegex.exec(content)) !== null) {
|
||||
const name = tMatch[1];
|
||||
const csv = tMatch[2];
|
||||
statTemplates.push(parseTemplateCsv(csv, filePath, name));
|
||||
}
|
||||
}
|
||||
|
||||
return { dice, links, sparkTables, stats, statTemplates };
|
||||
}
|
||||
|
||||
function splitTableRow(line: string): string[] | null {
|
||||
@@ -244,6 +269,12 @@ export function useJournalCompletions(): {
|
||||
}
|
||||
return {
|
||||
state: s,
|
||||
data: { dice: [], links: [], sparkTables: [], stats: [] },
|
||||
data: {
|
||||
dice: [],
|
||||
links: [],
|
||||
sparkTables: [],
|
||||
stats: [],
|
||||
statTemplates: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user