@novely/core 0.4.4 → 0.6.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 -12
- package/dist/index.global.js +108 -66
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +89 -48
- package/dist/index.js.map +1 -1
- package/package.json +61 -61
package/dist/index.d.ts
CHANGED
|
@@ -19,11 +19,11 @@ type Path = PathItem[];
|
|
|
19
19
|
type State = Record<string, any>;
|
|
20
20
|
type Data = Record<string, any>;
|
|
21
21
|
type SaveDate = number;
|
|
22
|
-
type SaveType =
|
|
22
|
+
type SaveType = 'manual' | 'auto';
|
|
23
23
|
type SaveMeta = [SaveDate, SaveType];
|
|
24
24
|
type Save = [Path, State, SaveMeta];
|
|
25
25
|
type Lang = string;
|
|
26
|
-
type TypewriterSpeed =
|
|
26
|
+
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & {});
|
|
27
27
|
type StorageMeta = [Lang, TypewriterSpeed];
|
|
28
28
|
type Migration = (save: unknown) => unknown;
|
|
29
29
|
type StorageData = {
|
|
@@ -37,7 +37,7 @@ type Stack = {
|
|
|
37
37
|
push(value: Save): void;
|
|
38
38
|
clear(): void;
|
|
39
39
|
};
|
|
40
|
-
type NovelyScreen =
|
|
40
|
+
type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
41
41
|
/**
|
|
42
42
|
* @see https://pendletonjones.com/deep-partial
|
|
43
43
|
*/
|
|
@@ -45,9 +45,9 @@ 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
47
|
|
|
48
|
-
type ValidAction = ['choice', [number]] | ['clear', []] | ['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'] | ValidAction[];
|
|
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'] | ValidAction[];
|
|
49
49
|
type Story = Record<string, ValidAction[]>;
|
|
50
|
-
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string>;
|
|
50
|
+
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string | (() => string)>;
|
|
51
51
|
type FunctionableValue<T> = T | (() => T);
|
|
52
52
|
type CustomHandlerGetResultDataFunction = {
|
|
53
53
|
(data?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -76,6 +76,7 @@ type CustomHandler = CustomHandlerFunction & {
|
|
|
76
76
|
callOnlyLatest?: boolean;
|
|
77
77
|
requireUserAction?: boolean;
|
|
78
78
|
skipClearOnGoingBack?: boolean;
|
|
79
|
+
id?: string | symbol;
|
|
79
80
|
};
|
|
80
81
|
interface ActionInputOnInputMeta {
|
|
81
82
|
/**
|
|
@@ -104,7 +105,7 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
|
|
|
104
105
|
(...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
|
|
105
106
|
(question: Unwrappable, ...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
|
|
106
107
|
};
|
|
107
|
-
clear: () => ValidAction;
|
|
108
|
+
clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>) => ValidAction;
|
|
108
109
|
condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
|
|
109
110
|
exit: () => ValidAction;
|
|
110
111
|
dialog: {
|
|
@@ -149,7 +150,7 @@ interface CharacterHandle {
|
|
|
149
150
|
withEmotion: (emotion: string) => () => void;
|
|
150
151
|
append: (className?: string, style?: string, restoring?: boolean) => void;
|
|
151
152
|
remove: (className?: string, style?: string, duration?: number) => (resolve: () => void, restoring: boolean) => void;
|
|
152
|
-
emotions: Record<string, HTMLImageElement | Record<
|
|
153
|
+
emotions: Record<string, HTMLImageElement | Record<'head' | 'left' | 'right', HTMLImageElement>>;
|
|
153
154
|
}
|
|
154
155
|
interface AudioHandle {
|
|
155
156
|
element: HTMLAudioElement;
|
|
@@ -159,7 +160,7 @@ interface AudioHandle {
|
|
|
159
160
|
}
|
|
160
161
|
interface RendererStore {
|
|
161
162
|
characters: Record<string, CharacterHandle>;
|
|
162
|
-
audio: Partial<Record<
|
|
163
|
+
audio: Partial<Record<'music', AudioHandle>>;
|
|
163
164
|
}
|
|
164
165
|
type Renderer = {
|
|
165
166
|
character: (character: string) => CharacterHandle;
|
|
@@ -168,7 +169,7 @@ type Renderer = {
|
|
|
168
169
|
choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[]) => (resolve: (selected: number) => void) => void;
|
|
169
170
|
input: (question: string, onInput: Parameters<DefaultActionProxyProvider['input']>[1], setup?: Parameters<DefaultActionProxyProvider['input']>[2]) => (resolve: () => void) => void;
|
|
170
171
|
music: (source: string, method: keyof RendererStore['audio']) => AudioHandle;
|
|
171
|
-
clear: (goingBack: boolean) => (resolve: () => void) => void;
|
|
172
|
+
clear: (goingBack: boolean, keep: Set<keyof DefaultActionProxyProvider>, keepCharacters: Set<string>) => (resolve: () => void) => void;
|
|
172
173
|
custom: (fn: Parameters<DefaultActionProxyProvider['custom']>[0], goingBack: boolean, push: () => void) => Thenable<void>;
|
|
173
174
|
text: (str: string, resolve: () => void) => void;
|
|
174
175
|
store: RendererStore;
|
|
@@ -176,7 +177,7 @@ type Renderer = {
|
|
|
176
177
|
/**
|
|
177
178
|
* Показывает экран, скрывает другие
|
|
178
179
|
*/
|
|
179
|
-
showScreen(name:
|
|
180
|
+
showScreen(name: 'mainmenu' | 'game' | 'saves' | 'settings' | 'loading'): void;
|
|
180
181
|
};
|
|
181
182
|
};
|
|
182
183
|
type RendererInit = {
|
|
@@ -254,8 +255,25 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
|
|
|
254
255
|
* Migration from old saves to newer
|
|
255
256
|
*/
|
|
256
257
|
migrations?: Migration[];
|
|
258
|
+
/**
|
|
259
|
+
* For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage
|
|
260
|
+
* @default 799
|
|
261
|
+
*/
|
|
262
|
+
throttleTimeout?: number;
|
|
263
|
+
/**
|
|
264
|
+
* Custom language detector
|
|
265
|
+
* @param languages Supported languages aka `languages: []` in the config
|
|
266
|
+
* @example ```ts
|
|
267
|
+
* novely({
|
|
268
|
+
* getLanguage(languages) {
|
|
269
|
+
* return sdk.environment.i18n.lang // i.e. custom language from some sdk
|
|
270
|
+
* }
|
|
271
|
+
* })
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
getLanguage?: (languages: string[]) => string;
|
|
257
275
|
}
|
|
258
|
-
declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends _novely_t9n.T9N<Languages, string>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, t9n, languages, state: defaultState, data: defaultData, autosaves, migrations }: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {
|
|
276
|
+
declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends _novely_t9n.T9N<Languages, string>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, t9n, languages, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage }: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {
|
|
259
277
|
/**
|
|
260
278
|
* Function to set story
|
|
261
279
|
*/
|
|
@@ -281,7 +299,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
281
299
|
/**
|
|
282
300
|
* Unwraps translatable content to a string value
|
|
283
301
|
*/
|
|
284
|
-
unwrap(content:
|
|
302
|
+
unwrap(content: Unwrappable | Record<Languages, string>): string;
|
|
285
303
|
/**
|
|
286
304
|
* Function that is used for translation
|
|
287
305
|
*/
|
package/dist/index.global.js
CHANGED
|
@@ -159,6 +159,9 @@ var Novely = (() => {
|
|
|
159
159
|
var isFunction = (val) => {
|
|
160
160
|
return typeof val === "function";
|
|
161
161
|
};
|
|
162
|
+
var isPromise = (val) => {
|
|
163
|
+
return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
|
|
164
|
+
};
|
|
162
165
|
var isEmpty = (val) => {
|
|
163
166
|
return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
|
|
164
167
|
};
|
|
@@ -270,34 +273,30 @@ var Novely = (() => {
|
|
|
270
273
|
}
|
|
271
274
|
|
|
272
275
|
// src/constants.ts
|
|
273
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set([
|
|
274
|
-
|
|
275
|
-
"choice",
|
|
276
|
-
"input",
|
|
277
|
-
"vibrate",
|
|
278
|
-
"text"
|
|
279
|
-
]);
|
|
276
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
277
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
280
278
|
|
|
281
279
|
// ../t9n/dist/index.js
|
|
282
|
-
var
|
|
280
|
+
var d = (e, o) => {
|
|
283
281
|
let r = [];
|
|
284
|
-
for (let a of
|
|
285
|
-
if (!
|
|
282
|
+
for (let a of o) {
|
|
283
|
+
if (!e)
|
|
286
284
|
break;
|
|
287
|
-
let [
|
|
288
|
-
r.push(
|
|
285
|
+
let [t, i] = e.split(a, 2);
|
|
286
|
+
r.push(t), e = i;
|
|
289
287
|
}
|
|
290
|
-
return r.push(
|
|
288
|
+
return r.push(e), r;
|
|
291
289
|
};
|
|
292
|
-
var
|
|
293
|
-
var
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
290
|
+
var m = /{{(.*?)}}/g;
|
|
291
|
+
var l = (e) => Array.isArray(e) ? e.map((o) => l(o)).join("<br>") : typeof e == "function" ? l(e()) : e;
|
|
292
|
+
var T = (e, o, r, a, t) => l(e).replace(m, (i, s, n) => {
|
|
293
|
+
i = 0, n = o;
|
|
294
|
+
let [c, g, u] = d(s.trim(), ["@", "%"]), S = c.split(".");
|
|
295
|
+
for (; n && i < S.length; )
|
|
296
|
+
n = n[S[i++]];
|
|
297
|
+
g && r && n && t && (n = r[g][t.select(n)]);
|
|
298
|
+
let p = a && u && a[u];
|
|
299
|
+
return p && (n = p(n)), n ?? "";
|
|
301
300
|
});
|
|
302
301
|
|
|
303
302
|
// src/novely.ts
|
|
@@ -312,7 +311,9 @@ var Novely = (() => {
|
|
|
312
311
|
state: defaultState,
|
|
313
312
|
data: defaultData,
|
|
314
313
|
autosaves = true,
|
|
315
|
-
migrations = []
|
|
314
|
+
migrations = [],
|
|
315
|
+
throttleTimeout = 799,
|
|
316
|
+
getLanguage: getLanguage2 = getLanguage
|
|
316
317
|
}) => {
|
|
317
318
|
let story;
|
|
318
319
|
let times = /* @__PURE__ */ new Set();
|
|
@@ -322,17 +323,19 @@ var Novely = (() => {
|
|
|
322
323
|
return times.add(value), value;
|
|
323
324
|
};
|
|
324
325
|
const withStory = (s) => {
|
|
325
|
-
story = Object.fromEntries(
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
326
|
+
story = Object.fromEntries(
|
|
327
|
+
Object.entries(s).map(([name, items]) => {
|
|
328
|
+
const flat = (item) => {
|
|
329
|
+
return item.flatMap((data2) => {
|
|
330
|
+
const type = data2[0];
|
|
331
|
+
if (Array.isArray(type))
|
|
332
|
+
return flat(data2);
|
|
333
|
+
return [data2];
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
return [name, flat(items)];
|
|
337
|
+
})
|
|
338
|
+
);
|
|
336
339
|
if (initialScreen !== "game")
|
|
337
340
|
renderer.ui.showScreen(initialScreen);
|
|
338
341
|
};
|
|
@@ -351,7 +354,14 @@ var Novely = (() => {
|
|
|
351
354
|
stack.value[1] = val;
|
|
352
355
|
}
|
|
353
356
|
const getDefaultSave = (state2 = {}) => {
|
|
354
|
-
return [
|
|
357
|
+
return [
|
|
358
|
+
[
|
|
359
|
+
[null, "start"],
|
|
360
|
+
[null, 0]
|
|
361
|
+
],
|
|
362
|
+
state2,
|
|
363
|
+
[intime(Date.now()), "auto"]
|
|
364
|
+
];
|
|
355
365
|
};
|
|
356
366
|
const createStack = (current, stack2 = [current]) => {
|
|
357
367
|
return {
|
|
@@ -376,7 +386,7 @@ var Novely = (() => {
|
|
|
376
386
|
const initialData = {
|
|
377
387
|
saves: [],
|
|
378
388
|
data: klona(defaultData),
|
|
379
|
-
meta: [
|
|
389
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
380
390
|
};
|
|
381
391
|
const $ = store(initialData);
|
|
382
392
|
let initialDataLoaded = false;
|
|
@@ -384,14 +394,14 @@ var Novely = (() => {
|
|
|
384
394
|
if (initialDataLoaded)
|
|
385
395
|
storage.set(value);
|
|
386
396
|
};
|
|
387
|
-
const throttledOnStorageDataChange = throttle(onStorageDataChange,
|
|
397
|
+
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
388
398
|
$.subscribe(throttledOnStorageDataChange);
|
|
389
399
|
const getStoredData = () => {
|
|
390
400
|
storage.get().then((stored) => {
|
|
391
401
|
for (const migration of migrations) {
|
|
392
402
|
stored = migration(stored);
|
|
393
403
|
}
|
|
394
|
-
stored.meta[0] ||=
|
|
404
|
+
stored.meta[0] ||= getLanguage2(languages);
|
|
395
405
|
stored.meta[1] ||= getTypewriterSpeed();
|
|
396
406
|
if (isEmpty(stored.data)) {
|
|
397
407
|
stored.data = defaultData;
|
|
@@ -451,12 +461,14 @@ var Novely = (() => {
|
|
|
451
461
|
return;
|
|
452
462
|
let latest = save2 ? save2 : $.get().saves.at(-1);
|
|
453
463
|
if (!latest) {
|
|
454
|
-
$.update(() => ({
|
|
464
|
+
$.update(() => ({
|
|
465
|
+
saves: [initial],
|
|
466
|
+
data: klona(defaultData),
|
|
467
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
468
|
+
}));
|
|
455
469
|
latest = klona(initial);
|
|
456
470
|
}
|
|
457
471
|
restoring = true, stack.value = latest;
|
|
458
|
-
renderer.ui.showScreen("game");
|
|
459
|
-
match("clear", [goingBack]);
|
|
460
472
|
let current = story;
|
|
461
473
|
let index = 0;
|
|
462
474
|
const max = stack.value[0].reduce((acc, [type, val]) => {
|
|
@@ -465,22 +477,30 @@ var Novely = (() => {
|
|
|
465
477
|
return acc;
|
|
466
478
|
}, 0);
|
|
467
479
|
const queue = [];
|
|
480
|
+
const keep = /* @__PURE__ */ new Set();
|
|
481
|
+
const characters2 = /* @__PURE__ */ new Set();
|
|
468
482
|
for (const [type, val] of stack.value[0]) {
|
|
469
483
|
if (type === null) {
|
|
470
484
|
if (isString(val)) {
|
|
471
485
|
current = current[val];
|
|
472
486
|
} else if (isNumber(val)) {
|
|
473
487
|
index++;
|
|
474
|
-
for (let i = 0; i
|
|
488
|
+
for (let i = 0; i <= val; i++) {
|
|
475
489
|
const [action2, ...meta] = current[i];
|
|
490
|
+
const push2 = () => {
|
|
491
|
+
keep.add(action2);
|
|
492
|
+
queue.push([action2, meta]);
|
|
493
|
+
};
|
|
494
|
+
if (action2 === "showCharacter")
|
|
495
|
+
characters2.add(meta[0]);
|
|
476
496
|
if (SKIPPED_DURING_RESTORE.has(action2) || isUserRequiredAction(action2, meta)) {
|
|
477
497
|
if (index === max && i === val) {
|
|
478
|
-
|
|
498
|
+
push2();
|
|
479
499
|
} else {
|
|
480
500
|
continue;
|
|
481
501
|
}
|
|
482
502
|
}
|
|
483
|
-
|
|
503
|
+
push2();
|
|
484
504
|
}
|
|
485
505
|
current = current[val];
|
|
486
506
|
}
|
|
@@ -490,21 +510,33 @@ var Novely = (() => {
|
|
|
490
510
|
current = current[2][val];
|
|
491
511
|
}
|
|
492
512
|
}
|
|
493
|
-
|
|
513
|
+
queue.forEach((value, index2) => {
|
|
514
|
+
value.push(index2);
|
|
515
|
+
});
|
|
516
|
+
const indexedQueue = queue;
|
|
517
|
+
renderer.ui.showScreen("game");
|
|
518
|
+
match("clear", [keep, characters2]);
|
|
519
|
+
const next2 = (i) => indexedQueue.slice(i + 1);
|
|
494
520
|
for await (const [action2, meta, i] of indexedQueue) {
|
|
495
521
|
if (action2 === "function" || action2 === "custom") {
|
|
496
522
|
if (action2 === "custom" && meta[0].callOnlyLatest) {
|
|
497
|
-
const
|
|
498
|
-
|
|
523
|
+
const notLatest = next2(i).some(([_action, _meta]) => {
|
|
524
|
+
if (!_meta || !meta)
|
|
525
|
+
return false;
|
|
526
|
+
const c0 = _meta[0];
|
|
527
|
+
const c1 = meta[0];
|
|
528
|
+
const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
|
|
529
|
+
return isIdenticalID || str(c0) === str(c1);
|
|
530
|
+
});
|
|
499
531
|
if (notLatest)
|
|
500
532
|
continue;
|
|
501
533
|
}
|
|
502
534
|
const result = match(action2, meta);
|
|
503
|
-
if (result
|
|
535
|
+
if (isPromise(result)) {
|
|
504
536
|
await result;
|
|
537
|
+
}
|
|
505
538
|
} else if (action2 === "showCharacter") {
|
|
506
|
-
const
|
|
507
|
-
const skip = next2.some(([_action, _meta]) => {
|
|
539
|
+
const skip = next2(i).some(([_action, _meta]) => {
|
|
508
540
|
if (!_meta || !meta)
|
|
509
541
|
return false;
|
|
510
542
|
const hidden = _action === "hideCharacter" && _meta[0] === meta[0];
|
|
@@ -514,9 +546,8 @@ var Novely = (() => {
|
|
|
514
546
|
if (skip)
|
|
515
547
|
continue;
|
|
516
548
|
match(action2, meta);
|
|
517
|
-
} else if (action2 === "showBackground") {
|
|
518
|
-
const
|
|
519
|
-
const notLatest = next2.some(([_action]) => action2 === _action);
|
|
549
|
+
} else if (action2 === "showBackground" || action2 === "animateCharacter") {
|
|
550
|
+
const notLatest = next2(i).some(([_action]) => action2 === _action);
|
|
520
551
|
if (notLatest)
|
|
521
552
|
continue;
|
|
522
553
|
match(action2, meta);
|
|
@@ -599,9 +630,9 @@ var Novely = (() => {
|
|
|
599
630
|
},
|
|
600
631
|
dialog([character, content, emotion]) {
|
|
601
632
|
const name = (() => {
|
|
602
|
-
const
|
|
633
|
+
const c = character, cs = characters;
|
|
603
634
|
const lang = $.get().meta[0];
|
|
604
|
-
return
|
|
635
|
+
return c ? c in cs ? typeof cs[c].name === "string" ? cs[c].name : cs[c].name[lang] : c : "";
|
|
605
636
|
})();
|
|
606
637
|
renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);
|
|
607
638
|
},
|
|
@@ -620,18 +651,27 @@ var Novely = (() => {
|
|
|
620
651
|
const unwrapped = choices.map(([content, action2, visible]) => {
|
|
621
652
|
return [unwrap(content), action2, visible];
|
|
622
653
|
});
|
|
623
|
-
renderer.choices(
|
|
654
|
+
renderer.choices(
|
|
655
|
+
unwrap(question),
|
|
656
|
+
unwrapped
|
|
657
|
+
)((selected) => {
|
|
624
658
|
enmemory();
|
|
625
|
-
|
|
659
|
+
const offset = isWithoutQuestion ? 0 : 1;
|
|
660
|
+
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
661
|
+
render();
|
|
662
|
+
interactivity(true);
|
|
626
663
|
});
|
|
627
664
|
},
|
|
628
665
|
jump([scene]) {
|
|
629
|
-
stack.value[0] = [
|
|
666
|
+
stack.value[0] = [
|
|
667
|
+
[null, scene],
|
|
668
|
+
[null, -1]
|
|
669
|
+
];
|
|
630
670
|
match("clear", []);
|
|
631
671
|
},
|
|
632
|
-
clear() {
|
|
672
|
+
clear([keep, characters2]) {
|
|
633
673
|
vibrate(0);
|
|
634
|
-
renderer.clear(goingBack)(push);
|
|
674
|
+
renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
|
|
635
675
|
},
|
|
636
676
|
condition([condition]) {
|
|
637
677
|
const value = condition();
|
|
@@ -682,9 +722,7 @@ var Novely = (() => {
|
|
|
682
722
|
clearTimeout(timeoutId);
|
|
683
723
|
});
|
|
684
724
|
};
|
|
685
|
-
handler
|
|
686
|
-
return renderer.custom(handler, goingBack, () => {
|
|
687
|
-
}), push();
|
|
725
|
+
match("custom", [handler]);
|
|
688
726
|
},
|
|
689
727
|
text(text) {
|
|
690
728
|
renderer.text(text.map((content) => unwrap(content)).join(" "), forward);
|
|
@@ -738,10 +776,14 @@ var Novely = (() => {
|
|
|
738
776
|
interacted = value;
|
|
739
777
|
};
|
|
740
778
|
const unwrap = (content, global = false) => {
|
|
741
|
-
const {
|
|
779
|
+
const {
|
|
780
|
+
data: data2,
|
|
781
|
+
meta: [lang]
|
|
782
|
+
} = $.get();
|
|
742
783
|
const obj = global ? data2 : state();
|
|
743
|
-
const
|
|
744
|
-
|
|
784
|
+
const cnt = isFunction(content) ? content(lang, obj) : typeof content === "string" ? content : content[lang];
|
|
785
|
+
const str2 = isFunction(cnt) ? cnt() : cnt;
|
|
786
|
+
return T(str2, obj);
|
|
745
787
|
};
|
|
746
788
|
function data(value) {
|
|
747
789
|
if (!value)
|