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,7 +15,13 @@ import { actionPrefill, setActionPrefill } from "../stores/reveal";
|
||||
import { useJournalCompletions, ensureCompletions } from "./completions";
|
||||
import { resolveRollPayload } from "./types/roll";
|
||||
import { resolveSparkPayload } from "./types/spark";
|
||||
import { resolveStatRoll, canModifyStat, fullKey } from "./stat-helpers";
|
||||
import {
|
||||
resolveStatRoll,
|
||||
resolveTemplateSet,
|
||||
canModifyStat,
|
||||
fullKey,
|
||||
findStatDef,
|
||||
} from "./stat-helpers";
|
||||
import { parseInput } from "./command-parser";
|
||||
import type { CompletionItem } from "./command-parser";
|
||||
import { buildCompletions } from "./command-completions";
|
||||
@@ -152,17 +158,35 @@ export const JournalInput: Component = () => {
|
||||
comp.data.stats,
|
||||
stream.stats,
|
||||
stream.myName,
|
||||
comp.data.statTemplates,
|
||||
);
|
||||
if (resolved.error) {
|
||||
setError(resolved.error);
|
||||
} else {
|
||||
// Send the primary stat value
|
||||
const result = sendMessage("stat", {
|
||||
action: "set",
|
||||
key: resolved.fullKey,
|
||||
value: resolved.value,
|
||||
});
|
||||
const r = unwrap(result);
|
||||
finish(r.ok, r.err);
|
||||
if (!r.ok) {
|
||||
finish(false, r.err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send any modifier overrides from template
|
||||
if (resolved.modifiers) {
|
||||
for (const [mk, mv] of Object.entries(resolved.modifiers)) {
|
||||
sendMessage("stat", {
|
||||
action: "set",
|
||||
key: mk,
|
||||
value: mv,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
finish(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -186,7 +210,32 @@ export const JournalInput: Component = () => {
|
||||
value: p.value,
|
||||
});
|
||||
const r = unwrap(result);
|
||||
finish(r.ok, r.err);
|
||||
if (!r.ok) {
|
||||
finish(false, r.err);
|
||||
return;
|
||||
}
|
||||
|
||||
// If setting a template-type stat, apply its modifier overrides
|
||||
if (p.action === "set" && p.value) {
|
||||
const def = findStatDef(fk, comp.data.stats, stream.myName);
|
||||
if (def) {
|
||||
const modifiers = resolveTemplateSet(
|
||||
def,
|
||||
p.value,
|
||||
comp.data.stats,
|
||||
stream.stats,
|
||||
stream.myName,
|
||||
comp.data.statTemplates,
|
||||
);
|
||||
if (modifiers) {
|
||||
for (const [mk, mv] of Object.entries(modifiers)) {
|
||||
sendMessage("stat", { action: "set", key: mk, value: mv });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish(true);
|
||||
}
|
||||
|
||||
/** Resolve a bare or full key to the actual runtime key. */
|
||||
|
||||
Reference in New Issue
Block a user