@patterkit/runtime 0.21.0 → 0.23.0
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/CHANGELOG.md +25 -0
- package/README.md +9 -2
- package/dist/index.cjs +133 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +111 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,13 @@ import { ScalarValue } from '@wildwinter/expr';
|
|
|
2
2
|
import { ScopeRegistry, PropertyBag, ScopeDeclaration, LogMount, ScopeResolver, PropertyRow } from '@wildwinter/scoperegistry';
|
|
3
3
|
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
4
4
|
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, SaveGameV2, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
5
|
-
export { Bundle, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
5
|
+
export { Bundle, DEFAULT_PAD_AFTER, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
6
|
+
|
|
7
|
+
/** A beat's own `padAfter` (when it sets one) and its resolved one (always). */
|
|
8
|
+
interface BeatPad {
|
|
9
|
+
own?: number;
|
|
10
|
+
resolved: number;
|
|
11
|
+
}
|
|
6
12
|
|
|
7
13
|
type SelectableNode = CompiledGroup | CompiledSnippet;
|
|
8
14
|
|
|
@@ -14,12 +20,16 @@ type StepResult = {
|
|
|
14
20
|
character?: string;
|
|
15
21
|
characterName?: string;
|
|
16
22
|
direction?: string;
|
|
23
|
+
qualifier?: string;
|
|
24
|
+
qualifierName?: string;
|
|
25
|
+
padAfter: number;
|
|
17
26
|
gameData?: GameData;
|
|
18
27
|
tags?: string[];
|
|
19
28
|
} | {
|
|
20
29
|
type: "text";
|
|
21
30
|
id: string;
|
|
22
31
|
text: string;
|
|
32
|
+
padAfter: number;
|
|
23
33
|
gameData?: GameData;
|
|
24
34
|
tags?: string[];
|
|
25
35
|
} | {
|
|
@@ -44,6 +54,15 @@ interface BeatInfo {
|
|
|
44
54
|
characterName?: string;
|
|
45
55
|
/** Performance direction (line only). */
|
|
46
56
|
direction?: string;
|
|
57
|
+
/** Speaker qualifier `gameId` (line only), e.g. `vo`. */
|
|
58
|
+
qualifier?: string;
|
|
59
|
+
/** The qualifier's shown name (source locale), e.g. `V.O.`. */
|
|
60
|
+
qualifierName?: string;
|
|
61
|
+
/** The pause after this beat, in seconds, resolved from its own value and the defaults above it (line and
|
|
62
|
+
* text only; see line padding). What a delivered step carries. */
|
|
63
|
+
padAfter?: number;
|
|
64
|
+
/** The beat's own `padAfter`, when it sets one (line and text only). */
|
|
65
|
+
ownPadAfter?: number;
|
|
47
66
|
/** Source text, un-interpolated (line / text). Omitted for gameEvent and IDs-only bundles. */
|
|
48
67
|
text?: string;
|
|
49
68
|
/** Author gameData overrides on this beat (raw, as the step carries them). Omitted when empty. */
|
|
@@ -111,6 +130,12 @@ interface ChoicePrompt {
|
|
|
111
130
|
/** The speaker's resolved player-facing name (locale-aware; absent when the character has none). */
|
|
112
131
|
characterName?: string;
|
|
113
132
|
direction?: string;
|
|
133
|
+
/** The speaker qualifier's `gameId` (`vo`), and its resolved shown name (locale-aware). */
|
|
134
|
+
qualifier?: string;
|
|
135
|
+
qualifierName?: string;
|
|
136
|
+
/** The prompt's resolved pause, in seconds: when it is spoken (by `replayPromptOnChoose`, or by a game that
|
|
137
|
+
* voices it), the wait before the reply, negative to cut in on the question (line padding). */
|
|
138
|
+
padAfter: number;
|
|
114
139
|
}
|
|
115
140
|
/** A single option of a pending `choice` group. */
|
|
116
141
|
interface ChoiceOption {
|
|
@@ -352,6 +377,8 @@ interface FlowHost {
|
|
|
352
377
|
defaultStrings: Record<string, string>;
|
|
353
378
|
/** Cast canonical name -> authoring `displayName` (the unlocalised fallback when no loc string exists). */
|
|
354
379
|
castDisplay: Map<string, string>;
|
|
380
|
+
/** Speaker qualifier gameId -> authored name (the unlocalised fallback when no loc string exists). */
|
|
381
|
+
qualifierDisplay: Map<string, string>;
|
|
355
382
|
nodeIndex: Map<string, SelectableNode>;
|
|
356
383
|
blockIndex: Map<string, {
|
|
357
384
|
sceneId: string;
|
|
@@ -363,6 +390,8 @@ interface FlowHost {
|
|
|
363
390
|
blockGameIdToId: Map<string, Map<string, string>>;
|
|
364
391
|
/** Author tags (#215): node id -> accumulated tags (own + every ancestor's, deduped). Built once. */
|
|
365
392
|
tagIndex: Map<string, string[]>;
|
|
393
|
+
/** Every line and text beat's resolved pause (line padding), precomputed per bundle (pads.ts). */
|
|
394
|
+
padIndex: Map<string, BeatPad>;
|
|
366
395
|
/** The game's one registry: `@patter` (the SHARED globals), host scopes, every instance bag. */
|
|
367
396
|
registry: ScopeRegistry;
|
|
368
397
|
/** True when the engine made the registry (a standalone game): `saveGame()` then carries its values. */
|
|
@@ -994,6 +1023,16 @@ declare class Flow {
|
|
|
994
1023
|
* locale, else the authoring `displayName`. Undefined when the character has no display name at all
|
|
995
1024
|
* (the host falls back to the `character` token itself). */
|
|
996
1025
|
private resolveCharacterName;
|
|
1026
|
+
/** The resolved pause of the beat an option shows as its prompt (its authored prompt, else its first content
|
|
1027
|
+
* line), for a saved option that predates prompts carrying one. */
|
|
1028
|
+
private promptPadOf;
|
|
1029
|
+
/** A line or text beat's resolved pause (line padding): its own `padAfter`, else the nearest default above
|
|
1030
|
+
* it, else the project's, else the built-in one; clamped to zero on a snippet's last line. */
|
|
1031
|
+
private padOf;
|
|
1032
|
+
/** A speaker qualifier's shown name, resolved as a character's is: the `qualifier:<gameId>` string in the
|
|
1033
|
+
* active locale, else the default locale, else the authored name. Undefined in IDs-only mode (the game
|
|
1034
|
+
* maps the `qualifier` gameId itself). */
|
|
1035
|
+
private resolveQualifierName;
|
|
997
1036
|
/** Split a ref into scope + name. Tokens: `@scene`, registered tokens, else `@patter` (incl. bare `@name`). */
|
|
998
1037
|
private splitRef;
|
|
999
1038
|
/** A fresh, unregistered bag for the NOT-shared `@patter` globals (the shared ones live on the host). */
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { ScalarValue } from '@wildwinter/expr';
|
|
|
2
2
|
import { ScopeRegistry, PropertyBag, ScopeDeclaration, LogMount, ScopeResolver, PropertyRow } from '@wildwinter/scoperegistry';
|
|
3
3
|
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
4
4
|
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, SaveGameV2, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
5
|
-
export { Bundle, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
5
|
+
export { Bundle, DEFAULT_PAD_AFTER, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
6
|
+
|
|
7
|
+
/** A beat's own `padAfter` (when it sets one) and its resolved one (always). */
|
|
8
|
+
interface BeatPad {
|
|
9
|
+
own?: number;
|
|
10
|
+
resolved: number;
|
|
11
|
+
}
|
|
6
12
|
|
|
7
13
|
type SelectableNode = CompiledGroup | CompiledSnippet;
|
|
8
14
|
|
|
@@ -14,12 +20,16 @@ type StepResult = {
|
|
|
14
20
|
character?: string;
|
|
15
21
|
characterName?: string;
|
|
16
22
|
direction?: string;
|
|
23
|
+
qualifier?: string;
|
|
24
|
+
qualifierName?: string;
|
|
25
|
+
padAfter: number;
|
|
17
26
|
gameData?: GameData;
|
|
18
27
|
tags?: string[];
|
|
19
28
|
} | {
|
|
20
29
|
type: "text";
|
|
21
30
|
id: string;
|
|
22
31
|
text: string;
|
|
32
|
+
padAfter: number;
|
|
23
33
|
gameData?: GameData;
|
|
24
34
|
tags?: string[];
|
|
25
35
|
} | {
|
|
@@ -44,6 +54,15 @@ interface BeatInfo {
|
|
|
44
54
|
characterName?: string;
|
|
45
55
|
/** Performance direction (line only). */
|
|
46
56
|
direction?: string;
|
|
57
|
+
/** Speaker qualifier `gameId` (line only), e.g. `vo`. */
|
|
58
|
+
qualifier?: string;
|
|
59
|
+
/** The qualifier's shown name (source locale), e.g. `V.O.`. */
|
|
60
|
+
qualifierName?: string;
|
|
61
|
+
/** The pause after this beat, in seconds, resolved from its own value and the defaults above it (line and
|
|
62
|
+
* text only; see line padding). What a delivered step carries. */
|
|
63
|
+
padAfter?: number;
|
|
64
|
+
/** The beat's own `padAfter`, when it sets one (line and text only). */
|
|
65
|
+
ownPadAfter?: number;
|
|
47
66
|
/** Source text, un-interpolated (line / text). Omitted for gameEvent and IDs-only bundles. */
|
|
48
67
|
text?: string;
|
|
49
68
|
/** Author gameData overrides on this beat (raw, as the step carries them). Omitted when empty. */
|
|
@@ -111,6 +130,12 @@ interface ChoicePrompt {
|
|
|
111
130
|
/** The speaker's resolved player-facing name (locale-aware; absent when the character has none). */
|
|
112
131
|
characterName?: string;
|
|
113
132
|
direction?: string;
|
|
133
|
+
/** The speaker qualifier's `gameId` (`vo`), and its resolved shown name (locale-aware). */
|
|
134
|
+
qualifier?: string;
|
|
135
|
+
qualifierName?: string;
|
|
136
|
+
/** The prompt's resolved pause, in seconds: when it is spoken (by `replayPromptOnChoose`, or by a game that
|
|
137
|
+
* voices it), the wait before the reply, negative to cut in on the question (line padding). */
|
|
138
|
+
padAfter: number;
|
|
114
139
|
}
|
|
115
140
|
/** A single option of a pending `choice` group. */
|
|
116
141
|
interface ChoiceOption {
|
|
@@ -352,6 +377,8 @@ interface FlowHost {
|
|
|
352
377
|
defaultStrings: Record<string, string>;
|
|
353
378
|
/** Cast canonical name -> authoring `displayName` (the unlocalised fallback when no loc string exists). */
|
|
354
379
|
castDisplay: Map<string, string>;
|
|
380
|
+
/** Speaker qualifier gameId -> authored name (the unlocalised fallback when no loc string exists). */
|
|
381
|
+
qualifierDisplay: Map<string, string>;
|
|
355
382
|
nodeIndex: Map<string, SelectableNode>;
|
|
356
383
|
blockIndex: Map<string, {
|
|
357
384
|
sceneId: string;
|
|
@@ -363,6 +390,8 @@ interface FlowHost {
|
|
|
363
390
|
blockGameIdToId: Map<string, Map<string, string>>;
|
|
364
391
|
/** Author tags (#215): node id -> accumulated tags (own + every ancestor's, deduped). Built once. */
|
|
365
392
|
tagIndex: Map<string, string[]>;
|
|
393
|
+
/** Every line and text beat's resolved pause (line padding), precomputed per bundle (pads.ts). */
|
|
394
|
+
padIndex: Map<string, BeatPad>;
|
|
366
395
|
/** The game's one registry: `@patter` (the SHARED globals), host scopes, every instance bag. */
|
|
367
396
|
registry: ScopeRegistry;
|
|
368
397
|
/** True when the engine made the registry (a standalone game): `saveGame()` then carries its values. */
|
|
@@ -994,6 +1023,16 @@ declare class Flow {
|
|
|
994
1023
|
* locale, else the authoring `displayName`. Undefined when the character has no display name at all
|
|
995
1024
|
* (the host falls back to the `character` token itself). */
|
|
996
1025
|
private resolveCharacterName;
|
|
1026
|
+
/** The resolved pause of the beat an option shows as its prompt (its authored prompt, else its first content
|
|
1027
|
+
* line), for a saved option that predates prompts carrying one. */
|
|
1028
|
+
private promptPadOf;
|
|
1029
|
+
/** A line or text beat's resolved pause (line padding): its own `padAfter`, else the nearest default above
|
|
1030
|
+
* it, else the project's, else the built-in one; clamped to zero on a snippet's last line. */
|
|
1031
|
+
private padOf;
|
|
1032
|
+
/** A speaker qualifier's shown name, resolved as a character's is: the `qualifier:<gameId>` string in the
|
|
1033
|
+
* active locale, else the default locale, else the authored name. Undefined in IDs-only mode (the game
|
|
1034
|
+
* maps the `qualifier` gameId itself). */
|
|
1035
|
+
private resolveQualifierName;
|
|
997
1036
|
/** Split a ref into scope + name. Tokens: `@scene`, registered tokens, else `@patter` (incl. bare `@name`). */
|
|
998
1037
|
private splitRef;
|
|
999
1038
|
/** A fresh, unregistered bag for the NOT-shared `@patter` globals (the shared ones live on the host). */
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { matchedSpecificity as scoreSpecificity } from "@wildwinter/expr-specifi
|
|
|
4
4
|
import { ScopeRegistry } from "@wildwinter/scoperegistry";
|
|
5
5
|
import { defaultFor, PropertyBag } from "@wildwinter/scoperegistry";
|
|
6
6
|
import { patterDialect, interpolate, splitRef, stripCaptions } from "@patterkit/dialect";
|
|
7
|
-
import { walkNodes, effectiveGameId, castStringKey, DEFAULT_CAPTION_DELIMITERS, DEFAULT_CAPTION_CHARACTER } from "@patterkit/model";
|
|
7
|
+
import { walkNodes, effectiveGameId, castStringKey, qualifierStringKey, DEFAULT_PAD_AFTER as DEFAULT_PAD_AFTER2, DEFAULT_CAPTION_DELIMITERS, DEFAULT_CAPTION_CHARACTER } from "@patterkit/model";
|
|
8
8
|
|
|
9
9
|
// src/tags.ts
|
|
10
10
|
function dedupe(tags) {
|
|
@@ -40,6 +40,45 @@ function buildTagIndex(bundle) {
|
|
|
40
40
|
return index;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// src/pads.ts
|
|
44
|
+
import { DEFAULT_PAD_AFTER } from "@patterkit/model";
|
|
45
|
+
var spoken = (b) => b.kind === "line" || b.kind === "text";
|
|
46
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
47
|
+
function buildPadIndex(bundle) {
|
|
48
|
+
const index = /* @__PURE__ */ new Map();
|
|
49
|
+
const set = (beat, inherited, clamp) => {
|
|
50
|
+
const own = beat.kind === "gameEvent" ? void 0 : num(beat.padAfter);
|
|
51
|
+
let resolved = own ?? inherited;
|
|
52
|
+
if (clamp && resolved < 0) resolved = 0;
|
|
53
|
+
index.set(beat.id, own !== void 0 ? { own, resolved } : { resolved });
|
|
54
|
+
};
|
|
55
|
+
const visit = (node, inherited) => {
|
|
56
|
+
const def = num(node.padAfterDefault) ?? inherited;
|
|
57
|
+
if (node.type === "group") {
|
|
58
|
+
if (node.prompt) set(node.prompt, def, false);
|
|
59
|
+
for (const child of node.children) visit(child, def);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const beats = node.beats ?? [];
|
|
63
|
+
let last = -1;
|
|
64
|
+
beats.forEach((b, i) => {
|
|
65
|
+
if (spoken(b)) last = i;
|
|
66
|
+
});
|
|
67
|
+
beats.forEach((b, i) => {
|
|
68
|
+
if (spoken(b)) set(b, def, i === last);
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
const projectDefault = num(bundle.padAfterDefault) ?? DEFAULT_PAD_AFTER;
|
|
72
|
+
for (const scene of Object.values(bundle.scenes)) {
|
|
73
|
+
const sceneDefault = num(scene.padAfterDefault) ?? projectDefault;
|
|
74
|
+
for (const block of scene.blocks) {
|
|
75
|
+
const blockDefault = num(block.padAfterDefault) ?? sceneDefault;
|
|
76
|
+
for (const child of block.children) visit(child, blockDefault);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return index;
|
|
80
|
+
}
|
|
81
|
+
|
|
43
82
|
// src/engine.ts
|
|
44
83
|
import { SAVE_VERSION } from "@patterkit/model";
|
|
45
84
|
var astCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -52,6 +91,15 @@ function tagIndexFor(bundle) {
|
|
|
52
91
|
}
|
|
53
92
|
return index;
|
|
54
93
|
}
|
|
94
|
+
var padIndexCache = /* @__PURE__ */ new WeakMap();
|
|
95
|
+
function padIndexFor(bundle) {
|
|
96
|
+
let index = padIndexCache.get(bundle);
|
|
97
|
+
if (!index) {
|
|
98
|
+
index = buildPadIndex(bundle);
|
|
99
|
+
padIndexCache.set(bundle, index);
|
|
100
|
+
}
|
|
101
|
+
return index;
|
|
102
|
+
}
|
|
55
103
|
function tagsOf(host, id) {
|
|
56
104
|
return host.tagIndex.get(id)?.slice();
|
|
57
105
|
}
|
|
@@ -117,6 +165,8 @@ var Engine = class _Engine {
|
|
|
117
165
|
}
|
|
118
166
|
const castDisplay = /* @__PURE__ */ new Map();
|
|
119
167
|
for (const c of bundle.cast ?? []) if (c.displayName) castDisplay.set(c.name, c.displayName);
|
|
168
|
+
const qualifierDisplay = /* @__PURE__ */ new Map();
|
|
169
|
+
for (const q of bundle.qualifiers ?? []) if (q?.gameId) qualifierDisplay.set(q.gameId, q.name);
|
|
120
170
|
this.defaultSeed = (options.seed ?? 2654435769) >>> 0;
|
|
121
171
|
const nodeIndex = /* @__PURE__ */ new Map();
|
|
122
172
|
const blockIndex = /* @__PURE__ */ new Map();
|
|
@@ -177,6 +227,7 @@ var Engine = class _Engine {
|
|
|
177
227
|
strings,
|
|
178
228
|
defaultStrings,
|
|
179
229
|
castDisplay,
|
|
230
|
+
qualifierDisplay,
|
|
180
231
|
nodeIndex,
|
|
181
232
|
blockIndex,
|
|
182
233
|
blockById,
|
|
@@ -184,6 +235,7 @@ var Engine = class _Engine {
|
|
|
184
235
|
blockGameIdToId: this.blockGameIdToId,
|
|
185
236
|
// same instances the engine resolves with
|
|
186
237
|
tagIndex: tagIndexFor(bundle),
|
|
238
|
+
padIndex: padIndexFor(bundle),
|
|
187
239
|
registry,
|
|
188
240
|
ownsRegistry,
|
|
189
241
|
patterBag,
|
|
@@ -581,8 +633,16 @@ var Engine = class _Engine {
|
|
|
581
633
|
if (name !== void 0) info.characterName = name;
|
|
582
634
|
}
|
|
583
635
|
if (beat.direction !== void 0) info.direction = beat.direction;
|
|
636
|
+
if (beat.qualifier !== void 0) {
|
|
637
|
+
info.qualifier = beat.qualifier;
|
|
638
|
+
const name = this.host.defaultStrings[qualifierStringKey(beat.qualifier)] ?? this.host.qualifierDisplay.get(beat.qualifier);
|
|
639
|
+
if (name !== void 0) info.qualifierName = name;
|
|
640
|
+
}
|
|
584
641
|
}
|
|
585
642
|
if (beat.kind === "line" || beat.kind === "text") {
|
|
643
|
+
const pad = this.host.padIndex.get(beat.id);
|
|
644
|
+
info.padAfter = pad?.resolved ?? DEFAULT_PAD_AFTER2;
|
|
645
|
+
if (pad?.own !== void 0) info.ownPadAfter = pad.own;
|
|
586
646
|
const source = this.host.defaultStrings[beat.id];
|
|
587
647
|
if (source !== void 0) info.text = source;
|
|
588
648
|
}
|
|
@@ -1376,7 +1436,8 @@ var Flow = class {
|
|
|
1376
1436
|
const node = this.host.nodeIndex.get(o.id);
|
|
1377
1437
|
if (!node) continue;
|
|
1378
1438
|
byId.set(o.id, node);
|
|
1379
|
-
|
|
1439
|
+
const { prompt: saved, ...rest } = o;
|
|
1440
|
+
options.push({ ...rest, ...saved ? { prompt: { ...saved, padAfter: saved.padAfter ?? this.promptPadOf(node) } } : {} });
|
|
1380
1441
|
}
|
|
1381
1442
|
if (options.length > 0) this.pendingChoice = { groupId: c.pendingChoice.groupId, options, byId };
|
|
1382
1443
|
}
|
|
@@ -1385,7 +1446,7 @@ var Flow = class {
|
|
|
1385
1446
|
if (this.pendingPromptOwnerId) {
|
|
1386
1447
|
const owner = this.host.nodeIndex.get(this.pendingPromptOwnerId);
|
|
1387
1448
|
const beat = owner ? this.authoredPromptOf(owner) : void 0;
|
|
1388
|
-
if (beat) this.pendingPrompt = { beat, ...c.pendingPrompt ? { shown: { ...c.pendingPrompt } } : {} };
|
|
1449
|
+
if (beat) this.pendingPrompt = { beat, ...c.pendingPrompt ? { shown: { ...c.pendingPrompt, padAfter: c.pendingPrompt.padAfter ?? this.padOf(beat.id) } } : {} };
|
|
1389
1450
|
else this.pendingPromptOwnerId = null;
|
|
1390
1451
|
}
|
|
1391
1452
|
}
|
|
@@ -1755,7 +1816,7 @@ var Flow = class {
|
|
|
1755
1816
|
case "gameEvent":
|
|
1756
1817
|
return { type: "gameEvent", id: beat.id, gameData: beat.gameData, ...withTags };
|
|
1757
1818
|
case "text":
|
|
1758
|
-
return { type: "text", id: beat.id, text: this.interpolate(this.resolveString(beat.id)), gameData: beat.gameData, ...withTags };
|
|
1819
|
+
return { type: "text", id: beat.id, text: this.interpolate(this.resolveString(beat.id)), padAfter: this.padOf(beat.id), gameData: beat.gameData, ...withTags };
|
|
1759
1820
|
case "line": {
|
|
1760
1821
|
const raw = this.resolveString(beat.id);
|
|
1761
1822
|
const off = !this.host.captionsOn;
|
|
@@ -1769,6 +1830,10 @@ var Flow = class {
|
|
|
1769
1830
|
character: silent ? void 0 : beat.character,
|
|
1770
1831
|
characterName: silent ? void 0 : this.resolveCharacterName(beat.character),
|
|
1771
1832
|
direction: silent ? void 0 : beat.direction,
|
|
1833
|
+
qualifier: silent ? void 0 : beat.qualifier,
|
|
1834
|
+
qualifierName: silent ? void 0 : this.resolveQualifierName(beat.qualifier),
|
|
1835
|
+
padAfter: this.padOf(beat.id),
|
|
1836
|
+
// a silent line still fires, so it still carries its pause
|
|
1772
1837
|
gameData: beat.gameData,
|
|
1773
1838
|
...withTags
|
|
1774
1839
|
};
|
|
@@ -1807,7 +1872,17 @@ var Flow = class {
|
|
|
1807
1872
|
const beat = this.promptBeatOf(node);
|
|
1808
1873
|
if (!beat) return void 0;
|
|
1809
1874
|
const text = this.interpolate(this.resolveString(beat.id));
|
|
1810
|
-
|
|
1875
|
+
const padAfter = this.padOf(beat.id);
|
|
1876
|
+
return beat.kind === "line" ? {
|
|
1877
|
+
kind: "line",
|
|
1878
|
+
text: this.captionLine(text),
|
|
1879
|
+
character: beat.character,
|
|
1880
|
+
characterName: this.resolveCharacterName(beat.character),
|
|
1881
|
+
direction: beat.direction,
|
|
1882
|
+
qualifier: beat.qualifier,
|
|
1883
|
+
qualifierName: this.resolveQualifierName(beat.qualifier),
|
|
1884
|
+
padAfter
|
|
1885
|
+
} : { kind: "text", text, padAfter };
|
|
1811
1886
|
}
|
|
1812
1887
|
/** An option's AUTHORED prompt beat: an Option group's own `prompt`. The only prompt a replay speaks. */
|
|
1813
1888
|
authoredPromptOf(node) {
|
|
@@ -1818,7 +1893,7 @@ var Flow = class {
|
|
|
1818
1893
|
promptResult(beat, shown) {
|
|
1819
1894
|
const tags = tagsOf(this.host, beat.id);
|
|
1820
1895
|
const withTags = tags && tags.length ? { tags } : {};
|
|
1821
|
-
if (shown.kind === "text") return { type: "text", id: beat.id, text: shown.text, gameData: beat.gameData, ...withTags };
|
|
1896
|
+
if (shown.kind === "text") return { type: "text", id: beat.id, text: shown.text, padAfter: this.padOf(beat.id), gameData: beat.gameData, ...withTags };
|
|
1822
1897
|
return {
|
|
1823
1898
|
type: "line",
|
|
1824
1899
|
id: beat.id,
|
|
@@ -1826,6 +1901,9 @@ var Flow = class {
|
|
|
1826
1901
|
character: shown.character,
|
|
1827
1902
|
characterName: shown.characterName,
|
|
1828
1903
|
direction: shown.direction,
|
|
1904
|
+
qualifier: shown.qualifier,
|
|
1905
|
+
qualifierName: shown.qualifierName,
|
|
1906
|
+
padAfter: this.padOf(beat.id),
|
|
1829
1907
|
gameData: beat.gameData,
|
|
1830
1908
|
...withTags
|
|
1831
1909
|
};
|
|
@@ -1862,6 +1940,26 @@ var Flow = class {
|
|
|
1862
1940
|
const key = castStringKey(character);
|
|
1863
1941
|
return this.host.strings[key] ?? this.host.defaultStrings[key] ?? this.host.castDisplay.get(character);
|
|
1864
1942
|
}
|
|
1943
|
+
/** The resolved pause of the beat an option shows as its prompt (its authored prompt, else its first content
|
|
1944
|
+
* line), for a saved option that predates prompts carrying one. */
|
|
1945
|
+
promptPadOf(node) {
|
|
1946
|
+
const beat = this.promptBeatOf(node);
|
|
1947
|
+
return beat ? this.padOf(beat.id) : DEFAULT_PAD_AFTER2;
|
|
1948
|
+
}
|
|
1949
|
+
/** A line or text beat's resolved pause (line padding): its own `padAfter`, else the nearest default above
|
|
1950
|
+
* it, else the project's, else the built-in one; clamped to zero on a snippet's last line. */
|
|
1951
|
+
padOf(beatId) {
|
|
1952
|
+
return this.host.padIndex.get(beatId)?.resolved ?? DEFAULT_PAD_AFTER2;
|
|
1953
|
+
}
|
|
1954
|
+
/** A speaker qualifier's shown name, resolved as a character's is: the `qualifier:<gameId>` string in the
|
|
1955
|
+
* active locale, else the default locale, else the authored name. Undefined in IDs-only mode (the game
|
|
1956
|
+
* maps the `qualifier` gameId itself). */
|
|
1957
|
+
resolveQualifierName(qualifier) {
|
|
1958
|
+
if (qualifier === void 0) return void 0;
|
|
1959
|
+
if (this.host.emitIds) return void 0;
|
|
1960
|
+
const key = qualifierStringKey(qualifier);
|
|
1961
|
+
return this.host.strings[key] ?? this.host.defaultStrings[key] ?? this.host.qualifierDisplay.get(qualifier);
|
|
1962
|
+
}
|
|
1865
1963
|
/** Split a ref into scope + name. Tokens: `@scene`, registered tokens, else `@patter` (incl. bare `@name`). */
|
|
1866
1964
|
splitRef(ref) {
|
|
1867
1965
|
return splitHostRef(this.host, ref);
|
|
@@ -1958,6 +2056,9 @@ function savedPrompt(p) {
|
|
|
1958
2056
|
if (p.character !== void 0) out.character = p.character;
|
|
1959
2057
|
if (p.characterName !== void 0) out.characterName = p.characterName;
|
|
1960
2058
|
if (p.direction !== void 0) out.direction = p.direction;
|
|
2059
|
+
if (p.qualifier !== void 0) out.qualifier = p.qualifier;
|
|
2060
|
+
if (p.qualifierName !== void 0) out.qualifierName = p.qualifierName;
|
|
2061
|
+
if (typeof p.padAfter === "number") out.padAfter = p.padAfter;
|
|
1961
2062
|
return out;
|
|
1962
2063
|
}
|
|
1963
2064
|
function serialiseSelectors(map) {
|
|
@@ -2048,6 +2149,9 @@ function truthy(v) {
|
|
|
2048
2149
|
return v.length > 0;
|
|
2049
2150
|
}
|
|
2050
2151
|
|
|
2152
|
+
// src/index.ts
|
|
2153
|
+
import { DEFAULT_PAD_AFTER as DEFAULT_PAD_AFTER3 } from "@patterkit/model";
|
|
2154
|
+
|
|
2051
2155
|
// src/describe.ts
|
|
2052
2156
|
import { effectiveGameId as effectiveGameId2 } from "@patterkit/model";
|
|
2053
2157
|
var isShared = (d, scopeDefault) => d.shared ?? scopeDefault;
|
|
@@ -2170,6 +2274,7 @@ function effectiveGameData(fields, node) {
|
|
|
2170
2274
|
}
|
|
2171
2275
|
export {
|
|
2172
2276
|
Checkpoint,
|
|
2277
|
+
DEFAULT_PAD_AFTER3 as DEFAULT_PAD_AFTER,
|
|
2173
2278
|
Engine,
|
|
2174
2279
|
Flow,
|
|
2175
2280
|
buildTagIndex,
|