@novely/core 0.10.0 → 0.12.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/dist/index.d.ts +30 -15
- package/dist/index.global.js +153 -62
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +153 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,17 +14,17 @@ type Character<LanguageKeys extends string = string> = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type Thenable<T> = T | Promise<T>;
|
|
17
|
-
type PathItem = [null, number | string] | ['choice'
|
|
17
|
+
type PathItem = [null, number | string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
|
|
18
18
|
type Path = PathItem[];
|
|
19
19
|
type State = Record<string, any>;
|
|
20
20
|
type Data = Record<string, any>;
|
|
21
21
|
type SaveDate = number;
|
|
22
22
|
type SaveType = 'manual' | 'auto';
|
|
23
|
-
type SaveMeta = [SaveDate, SaveType];
|
|
24
|
-
type Save = [Path, State, SaveMeta];
|
|
23
|
+
type SaveMeta = [date: SaveDate, type: SaveType];
|
|
24
|
+
type Save = [path: Path, state: State, meta: SaveMeta];
|
|
25
25
|
type Lang = string;
|
|
26
26
|
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
|
|
27
|
-
type StorageMeta = [Lang, TypewriterSpeed];
|
|
27
|
+
type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed];
|
|
28
28
|
type Migration = (save: unknown) => unknown;
|
|
29
29
|
type StorageData = {
|
|
30
30
|
saves: Save[];
|
|
@@ -44,8 +44,12 @@ type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
|
44
44
|
type DeepPartial<T> = unknown extends T ? T : T extends object ? {
|
|
45
45
|
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
|
|
46
46
|
} : T;
|
|
47
|
+
type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
|
|
48
|
+
type CoreData = {
|
|
49
|
+
dataLoaded: boolean;
|
|
50
|
+
};
|
|
47
51
|
|
|
48
|
-
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit'] | ['preload', [string]] | ValidAction[];
|
|
52
|
+
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
|
|
49
53
|
type Story = Record<string, ValidAction[]>;
|
|
50
54
|
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string | (() => string)>;
|
|
51
55
|
type FunctionableValue<T> = T | (() => T);
|
|
@@ -100,6 +104,7 @@ interface ActionInputOnInputMeta {
|
|
|
100
104
|
value: string;
|
|
101
105
|
}
|
|
102
106
|
type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
|
|
107
|
+
type BackgroundImage = Partial<Record<"portrait" | "landscape" | "all", string>> & Record<(string), string>;
|
|
103
108
|
type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
104
109
|
choice: {
|
|
105
110
|
(...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
|
|
@@ -114,19 +119,15 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
|
114
119
|
(person: string, content: Unwrappable, emotion?: undefined): ValidAction;
|
|
115
120
|
};
|
|
116
121
|
end: () => ValidAction;
|
|
117
|
-
showBackground: (background: string) => ValidAction;
|
|
122
|
+
showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
|
|
118
123
|
playMusic: (audio: string) => ValidAction;
|
|
119
124
|
stopMusic: (audio: string) => ValidAction;
|
|
120
125
|
jump: (scene: string) => ValidAction;
|
|
121
126
|
showCharacter: {
|
|
122
127
|
<C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
|
|
123
128
|
};
|
|
124
|
-
hideCharacter:
|
|
125
|
-
|
|
126
|
-
};
|
|
127
|
-
animateCharacter: {
|
|
128
|
-
<C extends keyof Characters>(character: C, timeout: number, ...classes: string[]): ValidAction;
|
|
129
|
-
};
|
|
129
|
+
hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
|
|
130
|
+
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
130
131
|
wait: (time: FunctionableValue<number>) => ValidAction;
|
|
131
132
|
function: (fn: (restoring: boolean, goingBack: boolean) => Thenable<void>) => ValidAction;
|
|
132
133
|
input: (question: Unwrappable, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
|
|
@@ -135,6 +136,7 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
|
135
136
|
next: () => ValidAction;
|
|
136
137
|
text: (...text: Unwrappable[]) => ValidAction;
|
|
137
138
|
preload: (source: string) => ValidAction;
|
|
139
|
+
block: (scene: string) => ValidAction;
|
|
138
140
|
};
|
|
139
141
|
type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>>;
|
|
140
142
|
type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
|
|
@@ -165,7 +167,7 @@ interface RendererStore {
|
|
|
165
167
|
}
|
|
166
168
|
type Renderer = {
|
|
167
169
|
character: (character: string) => CharacterHandle;
|
|
168
|
-
background: (background: string) => void;
|
|
170
|
+
background: (background: string | BackgroundImage) => void;
|
|
169
171
|
dialog: (content: string, name: string, character?: string, emotion?: string) => (resolve: () => void, goingBack: boolean) => void;
|
|
170
172
|
choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[]) => (resolve: (selected: number) => void) => void;
|
|
171
173
|
input: (question: string, onInput: Parameters<DefaultActionProxyProvider['input']>[1], setup?: Parameters<DefaultActionProxyProvider['input']>[2]) => (resolve: () => void) => void;
|
|
@@ -176,13 +178,22 @@ type Renderer = {
|
|
|
176
178
|
store: RendererStore;
|
|
177
179
|
ui: {
|
|
178
180
|
/**
|
|
179
|
-
*
|
|
181
|
+
* Shows the screen
|
|
180
182
|
*/
|
|
181
183
|
showScreen(name: 'mainmenu' | 'game' | 'saves' | 'settings' | 'loading'): void;
|
|
182
184
|
/**
|
|
183
185
|
* Shows prompt to exit
|
|
184
186
|
*/
|
|
185
187
|
showExitPrompt(): void;
|
|
188
|
+
/**
|
|
189
|
+
* Render the game
|
|
190
|
+
*/
|
|
191
|
+
start(): {
|
|
192
|
+
/**
|
|
193
|
+
* Unmount
|
|
194
|
+
*/
|
|
195
|
+
unmount(): void;
|
|
196
|
+
};
|
|
186
197
|
};
|
|
187
198
|
};
|
|
188
199
|
type RendererInit = {
|
|
@@ -203,6 +214,10 @@ type RendererInit = {
|
|
|
203
214
|
* Store that tracks data updates
|
|
204
215
|
*/
|
|
205
216
|
$: Stored<StorageData>;
|
|
217
|
+
/**
|
|
218
|
+
* Store that used to communicate between renderer and core
|
|
219
|
+
*/
|
|
220
|
+
$$: Stored<CoreData>;
|
|
206
221
|
};
|
|
207
222
|
|
|
208
223
|
interface LocalStorageStorageSettings {
|
|
@@ -328,4 +343,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
328
343
|
t: Inter["t"];
|
|
329
344
|
};
|
|
330
345
|
|
|
331
|
-
export { ActionProxyProvider, AudioHandle, Character, CharacterHandle, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, DefaultActionProxyProvider, Emotions, FunctionableValue, GetActionParameters, Lang, NovelyScreen, Path, Renderer, RendererInit, RendererStore, Storage, StorageData, StorageMeta, Stored, Story, Thenable, TypewriterSpeed, Unwrappable, ValidAction, localStorageStorage, novely };
|
|
346
|
+
export { ActionProxyProvider, AudioHandle, Character, CharacterHandle, CoreData, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, DefaultActionProxyProvider, Emotions, FunctionableValue, GetActionParameters, Lang, NovelyScreen, Path, Renderer, RendererInit, RendererStore, Storage, StorageData, StorageMeta, Stored, Story, Thenable, TypewriterSpeed, Unwrappable, ValidAction, localStorageStorage, novely };
|
package/dist/index.global.js
CHANGED
|
@@ -141,6 +141,13 @@ var Novely = (() => {
|
|
|
141
141
|
novely: () => novely
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
+
// src/constants.ts
|
|
145
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
146
|
+
var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
|
|
147
|
+
var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
|
|
148
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
149
|
+
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
150
|
+
|
|
144
151
|
// src/utils.ts
|
|
145
152
|
var matchAction = (values) => {
|
|
146
153
|
return (action, props) => {
|
|
@@ -213,8 +220,8 @@ var Novely = (() => {
|
|
|
213
220
|
}
|
|
214
221
|
};
|
|
215
222
|
var findLastIndex = (array, fn) => {
|
|
216
|
-
for (let i = array.length - 1; i
|
|
217
|
-
if (fn(array[i])) {
|
|
223
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
224
|
+
if (fn(array[i], array[i + 1])) {
|
|
218
225
|
return i;
|
|
219
226
|
}
|
|
220
227
|
}
|
|
@@ -242,6 +249,24 @@ var Novely = (() => {
|
|
|
242
249
|
});
|
|
243
250
|
return { resolve, reject, promise };
|
|
244
251
|
};
|
|
252
|
+
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
253
|
+
const index = findLastIndex(path, ([_name, _value], next) => {
|
|
254
|
+
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
255
|
+
});
|
|
256
|
+
return path[index];
|
|
257
|
+
};
|
|
258
|
+
var isBlockStatement = (statement) => {
|
|
259
|
+
return BLOCK_STATEMENTS.has(statement);
|
|
260
|
+
};
|
|
261
|
+
var isBlockExitStatement = (statement) => {
|
|
262
|
+
return BLOCK_EXIT_STATEMENTS.has(statement);
|
|
263
|
+
};
|
|
264
|
+
var isSkippedDurigRestore = (item) => {
|
|
265
|
+
return SKIPPED_DURING_RESTORE.has(item);
|
|
266
|
+
};
|
|
267
|
+
var isAction = (element) => {
|
|
268
|
+
return Array.isArray(element) && isString(element[0]);
|
|
269
|
+
};
|
|
245
270
|
|
|
246
271
|
// src/global.ts
|
|
247
272
|
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
@@ -298,11 +323,6 @@ var Novely = (() => {
|
|
|
298
323
|
return val;
|
|
299
324
|
}
|
|
300
325
|
|
|
301
|
-
// src/constants.ts
|
|
302
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
303
|
-
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
304
|
-
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
305
|
-
|
|
306
326
|
// ../t9n/dist/index.js
|
|
307
327
|
var g = (e, r) => {
|
|
308
328
|
let o = [];
|
|
@@ -447,41 +467,43 @@ var Novely = (() => {
|
|
|
447
467
|
data: klona(defaultData),
|
|
448
468
|
meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED]
|
|
449
469
|
};
|
|
470
|
+
const coreData = {
|
|
471
|
+
dataLoaded: false
|
|
472
|
+
};
|
|
450
473
|
const $ = store(initialData);
|
|
451
|
-
|
|
474
|
+
const $$ = store(coreData);
|
|
452
475
|
const onStorageDataChange = (value) => {
|
|
453
|
-
if (
|
|
476
|
+
if ($$.get().dataLoaded)
|
|
454
477
|
storage.set(value);
|
|
455
478
|
};
|
|
456
479
|
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
457
480
|
$.subscribe(throttledOnStorageDataChange);
|
|
458
|
-
const getStoredData = () => {
|
|
459
|
-
storage.get()
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
});
|
|
481
|
+
const getStoredData = async () => {
|
|
482
|
+
let stored = await storage.get();
|
|
483
|
+
for (const migration of migrations) {
|
|
484
|
+
stored = migration(stored);
|
|
485
|
+
}
|
|
486
|
+
stored.meta[1] ||= DEFAULT_TYPEWRITER_SPEED;
|
|
487
|
+
if (overrideLanguage) {
|
|
488
|
+
stored.meta[0] = getLanguageWithoutParameters();
|
|
489
|
+
} else {
|
|
490
|
+
stored.meta[0] ||= getLanguageWithoutParameters();
|
|
491
|
+
}
|
|
492
|
+
if (isEmpty(stored.data)) {
|
|
493
|
+
stored.data = defaultData;
|
|
494
|
+
}
|
|
495
|
+
$$.update((prev) => (prev.dataLoaded = true, prev));
|
|
496
|
+
$.update(() => stored);
|
|
497
|
+
if (initialScreen === "game") {
|
|
498
|
+
await assetsLoaded.promise;
|
|
499
|
+
restore();
|
|
500
|
+
}
|
|
479
501
|
};
|
|
480
502
|
storageDelay.then(getStoredData);
|
|
481
503
|
const initial = getDefaultSave(klona(defaultState));
|
|
482
504
|
const stack = createStack(initial);
|
|
483
505
|
const save = (override = false, type = override ? "auto" : "manual") => {
|
|
484
|
-
if (
|
|
506
|
+
if (!$$.get().dataLoaded)
|
|
485
507
|
return;
|
|
486
508
|
if (!autosaves && type === "auto")
|
|
487
509
|
return;
|
|
@@ -504,7 +526,7 @@ var Novely = (() => {
|
|
|
504
526
|
});
|
|
505
527
|
};
|
|
506
528
|
const newGame = () => {
|
|
507
|
-
if (
|
|
529
|
+
if (!$$.get().dataLoaded)
|
|
508
530
|
return;
|
|
509
531
|
const save2 = getDefaultSave(klona(defaultState));
|
|
510
532
|
if (autosaves) {
|
|
@@ -522,7 +544,7 @@ var Novely = (() => {
|
|
|
522
544
|
let goingBack = false;
|
|
523
545
|
let interacted = 0;
|
|
524
546
|
const restore = async (save2) => {
|
|
525
|
-
if (
|
|
547
|
+
if (!$$.get().dataLoaded)
|
|
526
548
|
return;
|
|
527
549
|
let latest = save2 || $.get().saves.at(-1);
|
|
528
550
|
if (!latest) {
|
|
@@ -534,31 +556,46 @@ var Novely = (() => {
|
|
|
534
556
|
latest = klona(initial);
|
|
535
557
|
}
|
|
536
558
|
restoring = true, stack.value = latest;
|
|
559
|
+
const path = stack.value[0];
|
|
537
560
|
let current = story;
|
|
561
|
+
let precurrent;
|
|
562
|
+
let ignoreNested = false;
|
|
538
563
|
let index = 0;
|
|
539
564
|
const max = stack.value[0].reduce((acc, [type, val]) => {
|
|
540
|
-
if (isNull(type) && isNumber(val))
|
|
565
|
+
if (isNull(type) && isNumber(val)) {
|
|
541
566
|
return acc + 1;
|
|
567
|
+
}
|
|
542
568
|
return acc;
|
|
543
569
|
}, 0);
|
|
544
570
|
const queue = [];
|
|
545
571
|
const keep = /* @__PURE__ */ new Set();
|
|
546
572
|
const characters2 = /* @__PURE__ */ new Set();
|
|
547
|
-
|
|
573
|
+
const blocks = [];
|
|
574
|
+
for (const [type, val] of path) {
|
|
548
575
|
if (type === null) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
} else if (isNumber(val)) {
|
|
576
|
+
precurrent = current;
|
|
577
|
+
if (isNumber(val)) {
|
|
552
578
|
index++;
|
|
553
|
-
|
|
554
|
-
|
|
579
|
+
let startIndex = 0;
|
|
580
|
+
if (ignoreNested) {
|
|
581
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, index), "block");
|
|
582
|
+
if (prev) {
|
|
583
|
+
startIndex = prev[1];
|
|
584
|
+
ignoreNested = false;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
for (let i = startIndex; i <= val; i++) {
|
|
588
|
+
const item = current[i];
|
|
589
|
+
if (!isAction(item))
|
|
590
|
+
continue;
|
|
591
|
+
const [action2, ...meta] = item;
|
|
555
592
|
const push2 = () => {
|
|
556
593
|
keep.add(action2);
|
|
557
594
|
queue.push([action2, meta]);
|
|
558
595
|
};
|
|
559
596
|
if (action2 === "showCharacter")
|
|
560
597
|
characters2.add(meta[0]);
|
|
561
|
-
if (
|
|
598
|
+
if (isSkippedDurigRestore(action2) || isUserRequiredAction(action2, meta)) {
|
|
562
599
|
if (index === max && i === val) {
|
|
563
600
|
push2();
|
|
564
601
|
} else {
|
|
@@ -567,12 +604,20 @@ var Novely = (() => {
|
|
|
567
604
|
}
|
|
568
605
|
push2();
|
|
569
606
|
}
|
|
570
|
-
current = current[val];
|
|
571
607
|
}
|
|
608
|
+
current = current[val];
|
|
572
609
|
} else if (type === "choice") {
|
|
610
|
+
blocks.push(precurrent = current);
|
|
573
611
|
current = current[val + 1][1];
|
|
574
612
|
} else if (type === "condition") {
|
|
613
|
+
blocks.push(precurrent = current);
|
|
575
614
|
current = current[2][val];
|
|
615
|
+
} else if (type === "block") {
|
|
616
|
+
blocks.push(precurrent);
|
|
617
|
+
current = story[val];
|
|
618
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
619
|
+
current = blocks.pop();
|
|
620
|
+
ignoreNested = true;
|
|
576
621
|
}
|
|
577
622
|
}
|
|
578
623
|
renderer.ui.showScreen("game");
|
|
@@ -587,7 +632,8 @@ var Novely = (() => {
|
|
|
587
632
|
const c0 = _meta[0];
|
|
588
633
|
const c1 = meta[0];
|
|
589
634
|
const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
|
|
590
|
-
|
|
635
|
+
const isIdenticalByReference = c0 === c1;
|
|
636
|
+
return isIdenticalID || isIdenticalByReference || str(c0) === str(c1);
|
|
591
637
|
});
|
|
592
638
|
if (notLatest)
|
|
593
639
|
continue;
|
|
@@ -618,15 +664,25 @@ var Novely = (() => {
|
|
|
618
664
|
}
|
|
619
665
|
restoring = goingBack = false, render();
|
|
620
666
|
};
|
|
621
|
-
const refer = () => {
|
|
667
|
+
const refer = (path = stack.value[0]) => {
|
|
622
668
|
let current = story;
|
|
623
|
-
|
|
669
|
+
let precurrent = story;
|
|
670
|
+
const blocks = [];
|
|
671
|
+
for (const [type, val] of path) {
|
|
624
672
|
if (type === null) {
|
|
673
|
+
precurrent = current;
|
|
625
674
|
current = current[val];
|
|
626
675
|
} else if (type === "choice") {
|
|
676
|
+
blocks.push(precurrent = current);
|
|
627
677
|
current = current[val + 1][1];
|
|
628
678
|
} else if (type === "condition") {
|
|
679
|
+
blocks.push(precurrent = current);
|
|
629
680
|
current = current[2][val];
|
|
681
|
+
} else if (type === "block") {
|
|
682
|
+
blocks.push(precurrent);
|
|
683
|
+
current = story[val];
|
|
684
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
685
|
+
current = blocks.pop();
|
|
630
686
|
}
|
|
631
687
|
}
|
|
632
688
|
return current;
|
|
@@ -663,8 +719,10 @@ var Novely = (() => {
|
|
|
663
719
|
stack,
|
|
664
720
|
languages,
|
|
665
721
|
t: t9n.i,
|
|
666
|
-
|
|
722
|
+
$,
|
|
723
|
+
$$
|
|
667
724
|
});
|
|
725
|
+
renderer.ui.start();
|
|
668
726
|
const match = matchAction({
|
|
669
727
|
wait([time]) {
|
|
670
728
|
if (!restoring)
|
|
@@ -749,9 +807,13 @@ var Novely = (() => {
|
|
|
749
807
|
renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
|
|
750
808
|
},
|
|
751
809
|
condition([condition]) {
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
810
|
+
if (!restoring) {
|
|
811
|
+
stack.value[0].push(
|
|
812
|
+
["condition", String(condition())],
|
|
813
|
+
[null, 0]
|
|
814
|
+
);
|
|
815
|
+
render();
|
|
816
|
+
}
|
|
755
817
|
},
|
|
756
818
|
end() {
|
|
757
819
|
match("clear", []);
|
|
@@ -803,24 +865,55 @@ var Novely = (() => {
|
|
|
803
865
|
renderer.text(text.map((content) => unwrap(content)).join(" "), forward, goingBack);
|
|
804
866
|
},
|
|
805
867
|
exit() {
|
|
868
|
+
if (restoring)
|
|
869
|
+
return;
|
|
806
870
|
const path = stack.value[0];
|
|
807
|
-
|
|
871
|
+
const last = path.at(-1);
|
|
872
|
+
const ignore = [];
|
|
873
|
+
if (!isAction(refer(path))) {
|
|
874
|
+
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
875
|
+
last[1]--;
|
|
876
|
+
} else {
|
|
877
|
+
path.pop();
|
|
878
|
+
}
|
|
879
|
+
}
|
|
808
880
|
for (let i = path.length - 1; i > 0; i--) {
|
|
809
|
-
|
|
881
|
+
const [name] = path[i];
|
|
882
|
+
if (isBlockExitStatement(name)) {
|
|
883
|
+
ignore.push(name);
|
|
884
|
+
}
|
|
885
|
+
if (!isBlockStatement(name))
|
|
886
|
+
continue;
|
|
887
|
+
if (ignore.at(-1)?.startsWith(name)) {
|
|
888
|
+
ignore.pop();
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
path.push([`${name}:exit`]);
|
|
892
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, i + 1), name);
|
|
893
|
+
if (prev)
|
|
894
|
+
path.push([null, prev[1] + 1]);
|
|
895
|
+
if (!isAction(refer(path))) {
|
|
896
|
+
path.pop();
|
|
810
897
|
continue;
|
|
811
|
-
|
|
812
|
-
stack.value[0] = path.slice(0, i);
|
|
813
|
-
next();
|
|
898
|
+
}
|
|
814
899
|
break;
|
|
815
900
|
}
|
|
816
|
-
|
|
817
|
-
render();
|
|
901
|
+
render();
|
|
818
902
|
},
|
|
819
903
|
preload([source]) {
|
|
820
904
|
if (!PRELOADED_ASSETS.has(source) && !goingBack && !restoring) {
|
|
821
905
|
PRELOADED_ASSETS.add(document.createElement("img").src = source);
|
|
822
906
|
}
|
|
823
907
|
push();
|
|
908
|
+
},
|
|
909
|
+
block([scene]) {
|
|
910
|
+
if (!restoring) {
|
|
911
|
+
stack.value[0].push(
|
|
912
|
+
["block", scene],
|
|
913
|
+
[null, 0]
|
|
914
|
+
);
|
|
915
|
+
render();
|
|
916
|
+
}
|
|
824
917
|
}
|
|
825
918
|
});
|
|
826
919
|
const enmemory = () => {
|
|
@@ -834,13 +927,11 @@ var Novely = (() => {
|
|
|
834
927
|
const next = () => {
|
|
835
928
|
const path = stack.value[0];
|
|
836
929
|
const last = path.at(-1);
|
|
837
|
-
if (
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
return;
|
|
930
|
+
if (last && isNull(last[0]) && isNumber(last[1])) {
|
|
931
|
+
last[1]++;
|
|
932
|
+
} else {
|
|
933
|
+
path.push([null, 0]);
|
|
842
934
|
}
|
|
843
|
-
path.push([null, 0]);
|
|
844
935
|
};
|
|
845
936
|
const render = () => {
|
|
846
937
|
const referred = refer();
|