@scrthq/runlog 0.0.42 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runlog.js +93 -11
- package/package.json +1 -1
package/dist/runlog.js
CHANGED
|
@@ -26448,13 +26448,15 @@ var Action = external_exports.lazy(
|
|
|
26448
26448
|
do: external_exports.literal("modCounter").describe("Adjust a counter."),
|
|
26449
26449
|
counter: Id.describe("Id of the counter to change."),
|
|
26450
26450
|
by: external_exports.number().int().optional().describe("Amount to add; negative subtracts."),
|
|
26451
|
-
set: external_exports.number().int().optional().describe("Absolute value to set, overriding `by`.")
|
|
26451
|
+
set: external_exports.number().int().optional().describe("Absolute value to set, overriding `by`."),
|
|
26452
|
+
setFrom: external_exports.string().min(1).optional().describe("Set it to a value bound earlier \u2014 a roll's total or a prompt's answer \u2014 by name. Overrides `by` and `set`.")
|
|
26452
26453
|
}).strict().describe("Adjust a counter."),
|
|
26453
26454
|
external_exports.object({
|
|
26454
26455
|
do: external_exports.literal("modResource").describe("Adjust a resource."),
|
|
26455
26456
|
resource: Id.describe("Id of the resource to change."),
|
|
26456
26457
|
by: external_exports.number().int().optional().describe("Amount to add; negative spends."),
|
|
26457
|
-
set: external_exports.number().int().optional().describe("Absolute value to set, overriding `by`.")
|
|
26458
|
+
set: external_exports.number().int().optional().describe("Absolute value to set, overriding `by`."),
|
|
26459
|
+
setFrom: external_exports.string().min(1).optional().describe("Set it to a value bound earlier \u2014 a roll's total or a prompt's answer \u2014 by name. Overrides `by` and `set`.")
|
|
26458
26460
|
}).strict().describe("Adjust a resource, clamped to its declared min and max."),
|
|
26459
26461
|
external_exports.object({
|
|
26460
26462
|
do: external_exports.literal("grantCard").describe("Draw cards into the player's hand."),
|
|
@@ -26520,7 +26522,10 @@ var EntryBase = {
|
|
|
26520
26522
|
grants: external_exports.array(Id).optional().describe(
|
|
26521
26523
|
"States applied to the relevant subject on resolution. Shorthand for an applyState trigger."
|
|
26522
26524
|
),
|
|
26523
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Free tags, for cross-referencing and for filtering results out in some modes.")
|
|
26525
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Free tags, for cross-referencing and for filtering results out in some modes."),
|
|
26526
|
+
points: external_exports.number().int().min(0).optional().describe(
|
|
26527
|
+
"What a contestant earns for completing this result in a moderated mode. A result with points is a challenge the moderator can award; one without is an effect that lands on everyone."
|
|
26528
|
+
)
|
|
26524
26529
|
};
|
|
26525
26530
|
var LookupEntry = external_exports.object({
|
|
26526
26531
|
...EntryBase,
|
|
@@ -26640,7 +26645,8 @@ var Capability = external_exports.enum([
|
|
|
26640
26645
|
"journal",
|
|
26641
26646
|
"bandsResolution",
|
|
26642
26647
|
"opposedResolution",
|
|
26643
|
-
"keyedResolution"
|
|
26648
|
+
"keyedResolution",
|
|
26649
|
+
"moderated"
|
|
26644
26650
|
]).describe("An engine feature this pack needs in order to play correctly.");
|
|
26645
26651
|
var Vocabulary = external_exports.object({
|
|
26646
26652
|
run: external_exports.object({
|
|
@@ -26665,7 +26671,10 @@ var StateDef = external_exports.object({
|
|
|
26665
26671
|
short: external_exports.string().max(8).optional().describe(
|
|
26666
26672
|
"Compact form for embedding in the name of the thing itself \u2014 a file, a layer, a DAW track. Keep it very short, e.g. VF."
|
|
26667
26673
|
),
|
|
26668
|
-
scope: external_exports.enum(["subject", "run"]).default("subject").describe(
|
|
26674
|
+
scope: external_exports.enum(["subject", "run", "contestant"]).default("subject").describe(
|
|
26675
|
+
"Whether this attaches to one subject, to the whole run, or \u2014 in moderated play \u2014 to one contestant on the roster, marked by the moderator: spared from a curse, disqualified, and so on."
|
|
26676
|
+
),
|
|
26677
|
+
until: external_exports.enum(["unitEnd"]).optional().describe("When the state lifts by itself. `unitEnd`: it is taken off everything it is on when the unit closes \u2014 a curse for this region, a cure for this region."),
|
|
26669
26678
|
semantics: external_exports.array(
|
|
26670
26679
|
external_exports.enum(["blocksEdit", "makesUntargetable", "excludesFromResult", "locksValue", "removesFromPlay"])
|
|
26671
26680
|
).optional().describe(
|
|
@@ -26855,6 +26864,16 @@ var Mode = external_exports.object({
|
|
|
26855
26864
|
).optional().describe(
|
|
26856
26865
|
"Per-unit overrides, for modes with a fixed shape \u2014 'unit three always suffers a consequence', and the like."
|
|
26857
26866
|
),
|
|
26867
|
+
moderated: external_exports.object({
|
|
26868
|
+
contestants: external_exports.object({
|
|
26869
|
+
min: external_exports.number().int().min(1).default(2).describe("Fewest contestants."),
|
|
26870
|
+
max: external_exports.number().int().min(1).default(10).describe("Most contestants.")
|
|
26871
|
+
}).strict().default({ min: 2, max: 10 }).describe("How many people race. The moderator is not one of them."),
|
|
26872
|
+
award: external_exports.enum(["first", "everyone"]).default("first").describe("Whether only the first to finish a challenge scores it, or everyone who finishes does."),
|
|
26873
|
+
firstBonus: external_exports.number().int().min(0).default(0).describe("Extra points for finishing first, on top of the result's own. Meaningful with `everyone`.")
|
|
26874
|
+
}).strict().optional().describe(
|
|
26875
|
+
"Moderated play: one person runs the game on the device, a roster of named contestants races every drawn result, and the moderator awards points. Results with `points` are the challenges; everything else lands on everyone."
|
|
26876
|
+
),
|
|
26858
26877
|
notes: external_exports.array(external_exports.string()).optional().describe("Reminders shown to the player in this mode.")
|
|
26859
26878
|
}).strict().describe(
|
|
26860
26879
|
"A set of deltas over the base ruleset. Keeping modes as deltas rather than separate rulesets is what stops them drifting apart as the pack evolves."
|
|
@@ -27245,6 +27264,7 @@ function lintPack(pack) {
|
|
|
27245
27264
|
let usesResources = resourceIds.size > 0;
|
|
27246
27265
|
let usesTimers = false;
|
|
27247
27266
|
let usesResolveTarget = false;
|
|
27267
|
+
const movedCounters = /* @__PURE__ */ new Set();
|
|
27248
27268
|
for (const site of collectActionSites(pack)) {
|
|
27249
27269
|
walkActions(site.actions, (a) => {
|
|
27250
27270
|
switch (a.do) {
|
|
@@ -27263,6 +27283,7 @@ function lintPack(pack) {
|
|
|
27263
27283
|
if (!counterIds.has(a.counter)) {
|
|
27264
27284
|
d.push(err("ref/unknown-counter", site.path, `references unknown counter ${a.counter}`));
|
|
27265
27285
|
}
|
|
27286
|
+
movedCounters.add(a.counter);
|
|
27266
27287
|
break;
|
|
27267
27288
|
case "modResource":
|
|
27268
27289
|
if (!resourceIds.has(a.resource)) {
|
|
@@ -27371,6 +27392,7 @@ function lintPack(pack) {
|
|
|
27371
27392
|
if (typeof item !== "string" && item.tally && !counterIds.has(item.tally)) {
|
|
27372
27393
|
d.push(err("ref/unknown-counter", `${path}.${field}[${ii}]`, `tallies unknown counter ${item.tally}`));
|
|
27373
27394
|
}
|
|
27395
|
+
if (typeof item !== "string" && item.tally) movedCounters.add(item.tally);
|
|
27374
27396
|
if (typeof item !== "string" && item.shows && !tableIds.has(item.shows.table)) {
|
|
27375
27397
|
d.push(err("ref/unknown-table", `${path}.${field}[${ii}]`, `shows unknown table ${item.shows.table}`));
|
|
27376
27398
|
}
|
|
@@ -27479,8 +27501,8 @@ function lintPack(pack) {
|
|
|
27479
27501
|
d.push(err("ref/unknown-state", path, `hooks unknown state ${sel.state}`));
|
|
27480
27502
|
}
|
|
27481
27503
|
}
|
|
27482
|
-
if (!counter.incrementOn?.length && !counter.triggers?.length) {
|
|
27483
|
-
d.push(warn("counter/inert", path, "counter has no incrementOn
|
|
27504
|
+
if (!counter.incrementOn?.length && !counter.triggers?.length && !movedCounters.has(counterId)) {
|
|
27505
|
+
d.push(warn("counter/inert", path, "counter has no incrementOn, no triggers, and nothing moves it; it will never change"));
|
|
27484
27506
|
}
|
|
27485
27507
|
}
|
|
27486
27508
|
if (pack.targeting?.strategy === "anchoredOffset") {
|
|
@@ -27555,6 +27577,17 @@ function lintPack(pack) {
|
|
|
27555
27577
|
);
|
|
27556
27578
|
}
|
|
27557
27579
|
};
|
|
27580
|
+
const moderatedModes = Object.values(pack.modes).filter((m) => m.moderated);
|
|
27581
|
+
const scoringEntries = Object.values(pack.tables).some((t) => t.entries.some((e) => (e.points ?? 0) > 0));
|
|
27582
|
+
requireCap("moderated", moderatedModes.length > 0, "has a moderated mode");
|
|
27583
|
+
if (moderatedModes.length > 0 && !scoringEntries) {
|
|
27584
|
+
d.push(warn("mode/nothing-to-award", "modes", "a mode is moderated, but no table entry carries points, so there is nothing to award"));
|
|
27585
|
+
}
|
|
27586
|
+
for (const [modeId, m] of Object.entries(pack.modes)) {
|
|
27587
|
+
if (m.moderated && m.moderated.contestants.max < m.moderated.contestants.min) {
|
|
27588
|
+
d.push(err("mode/contestant-range", `modes.${modeId}.moderated.contestants`, `max (${m.moderated.contestants.max}) is below min (${m.moderated.contestants.min})`));
|
|
27589
|
+
}
|
|
27590
|
+
}
|
|
27558
27591
|
requireCap("decks", usesDecks, "uses decks");
|
|
27559
27592
|
requireCap("resources", usesResources, "uses resources");
|
|
27560
27593
|
requireCap("counters", counterIds.size > 0, "declares counters");
|
|
@@ -27613,7 +27646,8 @@ var IMPLEMENTED_CAPABILITIES = [
|
|
|
27613
27646
|
"journal",
|
|
27614
27647
|
"bandsResolution",
|
|
27615
27648
|
"opposedResolution",
|
|
27616
|
-
"keyedResolution"
|
|
27649
|
+
"keyedResolution",
|
|
27650
|
+
"moderated"
|
|
27617
27651
|
];
|
|
27618
27652
|
function parsePack(input2) {
|
|
27619
27653
|
if (typeof input2 !== "object" || input2 === null) {
|
|
@@ -28106,6 +28140,11 @@ function modeLength(pack, mode) {
|
|
|
28106
28140
|
return `as many ${n.units} as you like${max ? `, up to ${max}` : ""}`;
|
|
28107
28141
|
}
|
|
28108
28142
|
function modePlayers(mode) {
|
|
28143
|
+
const m = mode.moderated;
|
|
28144
|
+
if (m) {
|
|
28145
|
+
const n = m.contestants.min === m.contestants.max ? `${m.contestants.min}` : `${m.contestants.min}\u2013${m.contestants.max}`;
|
|
28146
|
+
return `moderated, ${n} contestants, ${m.award === "everyone" ? "everyone who finishes scores" : "first to finish scores"}${m.firstBonus ? ` (+${m.firstBonus} for first)` : ""}`;
|
|
28147
|
+
}
|
|
28109
28148
|
const p = mode.players;
|
|
28110
28149
|
if (!p || p.min <= 1 && p.max <= 1) return "solo";
|
|
28111
28150
|
return p.min === p.max ? `${p.min} players` : `${p.min}\u2013${p.max} players`;
|
|
@@ -28294,7 +28333,8 @@ function tableRows(pack, table, opts) {
|
|
|
28294
28333
|
if (e.requires?.length) extras.push(`Only if ${conditionsInWords(pack, e.requires)}; otherwise roll again.`);
|
|
28295
28334
|
}
|
|
28296
28335
|
const text = [e.title ? `${e.title}. ` : "", sentence(e.text), ...extras.map((x) => ` ${x}`)].join("");
|
|
28297
|
-
|
|
28336
|
+
const pts = e.points !== void 0 && e.points > 0 ? `${keys[i] ?? ""} \xB7 ${e.points} pt${e.points === 1 ? "" : "s"}` : keys[i] ?? "";
|
|
28337
|
+
return [pts, text];
|
|
28298
28338
|
});
|
|
28299
28339
|
}
|
|
28300
28340
|
function license(pack) {
|
|
@@ -28390,8 +28430,8 @@ function rulebookDoc(pack) {
|
|
|
28390
28430
|
["State", "On", "Means"],
|
|
28391
28431
|
states.map(([, s]) => [
|
|
28392
28432
|
s.short ? `${s.label} (${s.short})` : s.label,
|
|
28393
|
-
s.scope === "run" ? `the ${n.run}` : `a ${n.subject}`,
|
|
28394
|
-
[s.description ?? "", ...(s.semantics ?? []).map(semanticInWords), s.group ? `Replaces any other \u201C${s.group}\u201D state.` : ""].filter(Boolean).join(" ")
|
|
28433
|
+
s.scope === "run" ? `the ${n.run}` : s.scope === "contestant" ? "a contestant" : `a ${n.subject}`,
|
|
28434
|
+
[s.description ?? "", ...(s.semantics ?? []).map(semanticInWords), s.group ? `Replaces any other \u201C${s.group}\u201D state.` : "", s.until === "unitEnd" ? `Lifts when the ${n.unit} closes.` : ""].filter(Boolean).join(" ")
|
|
28395
28435
|
])
|
|
28396
28436
|
);
|
|
28397
28437
|
}
|
|
@@ -28777,6 +28817,8 @@ function initialState(pack, e) {
|
|
|
28777
28817
|
outcomes: [],
|
|
28778
28818
|
obligations: [],
|
|
28779
28819
|
firedOnce: [],
|
|
28820
|
+
contestants: [],
|
|
28821
|
+
awards: [],
|
|
28780
28822
|
ending: null
|
|
28781
28823
|
};
|
|
28782
28824
|
}
|
|
@@ -28951,6 +28993,10 @@ function reduce(pack, log) {
|
|
|
28951
28993
|
for (const subject of state.subjects) {
|
|
28952
28994
|
if (subject.unit === state.unit) subject.finalized = true;
|
|
28953
28995
|
}
|
|
28996
|
+
const lifts = (id) => pack.states?.[id]?.until === "unitEnd";
|
|
28997
|
+
state.runStates = state.runStates.filter((id) => !lifts(id));
|
|
28998
|
+
for (const subject of state.subjects) subject.states = subject.states.filter((id) => !lifts(id));
|
|
28999
|
+
for (const who of state.contestants) who.states = who.states.filter((id) => !lifts(id));
|
|
28954
29000
|
break;
|
|
28955
29001
|
}
|
|
28956
29002
|
case "JournalWritten":
|
|
@@ -28984,6 +29030,42 @@ function reduce(pack, log) {
|
|
|
28984
29030
|
state.status = "ended";
|
|
28985
29031
|
state.ending = event.ending;
|
|
28986
29032
|
break;
|
|
29033
|
+
case "ContestantAdded":
|
|
29034
|
+
if (!state.contestants.some((c) => c.id === event.contestant)) {
|
|
29035
|
+
state.contestants.push({ id: event.contestant, name: event.name, states: [] });
|
|
29036
|
+
}
|
|
29037
|
+
break;
|
|
29038
|
+
case "ContestantRemoved":
|
|
29039
|
+
state.contestants = state.contestants.filter((c) => c.id !== event.contestant);
|
|
29040
|
+
break;
|
|
29041
|
+
case "ContestantStateApplied": {
|
|
29042
|
+
const who = state.contestants.find((c) => c.id === event.contestant);
|
|
29043
|
+
if (!who) break;
|
|
29044
|
+
const group = pack.states?.[event.state]?.group;
|
|
29045
|
+
if (group) who.states = who.states.filter((s) => s === event.state || pack.states?.[s]?.group !== group);
|
|
29046
|
+
if (!who.states.includes(event.state)) who.states.push(event.state);
|
|
29047
|
+
break;
|
|
29048
|
+
}
|
|
29049
|
+
case "ContestantStateRemoved": {
|
|
29050
|
+
const who = state.contestants.find((c) => c.id === event.contestant);
|
|
29051
|
+
if (who) who.states = who.states.filter((s) => s !== event.state);
|
|
29052
|
+
break;
|
|
29053
|
+
}
|
|
29054
|
+
case "Awarded":
|
|
29055
|
+
if (!state.awards.some((a) => a.contestant === event.contestant && a.outcome === event.outcome)) {
|
|
29056
|
+
state.awards.push({
|
|
29057
|
+
contestant: event.contestant,
|
|
29058
|
+
outcome: event.outcome,
|
|
29059
|
+
table: event.table,
|
|
29060
|
+
entryId: event.entryId,
|
|
29061
|
+
points: event.points,
|
|
29062
|
+
at: event.at
|
|
29063
|
+
});
|
|
29064
|
+
}
|
|
29065
|
+
break;
|
|
29066
|
+
case "AwardRevoked":
|
|
29067
|
+
state.awards = state.awards.filter((a) => !(a.contestant === event.contestant && a.outcome === event.outcome));
|
|
29068
|
+
break;
|
|
28987
29069
|
case "Checked": {
|
|
28988
29070
|
const key = `${event.step}|${event.item}`;
|
|
28989
29071
|
if (event.on) {
|