@novely/core 0.16.0 → 0.18.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 CHANGED
@@ -17,7 +17,8 @@ type SaveMeta = [date: SaveDate, type: SaveType];
17
17
  type Save = [path: Path, state: State, meta: SaveMeta];
18
18
  type Lang = string;
19
19
  type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
20
- type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed];
20
+ type SoundVolume = number;
21
+ type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
21
22
  type Migration = (save: unknown) => unknown;
22
23
  type StorageData = {
23
24
  saves: Save[];
@@ -42,7 +43,7 @@ type CoreData = {
42
43
  dataLoaded: boolean;
43
44
  };
44
45
 
45
- type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, 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[];
46
+ type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['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[];
46
47
  type Story = Record<string, ValidAction[]>;
47
48
  type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
48
49
  type FunctionableValue<T> = T | (() => T);
@@ -115,6 +116,16 @@ type ActionProxyProvider<Characters extends Record<string, Character>, Languages
115
116
  showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
116
117
  playMusic: (audio: string) => ValidAction;
117
118
  stopMusic: (audio: string) => ValidAction;
119
+ playSound: (audio: string, loop?: boolean) => ValidAction;
120
+ stopSound: (audio: string) => ValidAction;
121
+ /**
122
+ * Plays voice
123
+ */
124
+ voice: (voice: string) => ValidAction;
125
+ /**
126
+ * Stops currently playing voice
127
+ */
128
+ stopVoice: () => ValidAction;
118
129
  jump: (scene: string) => ValidAction;
119
130
  showCharacter: {
120
131
  <C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
@@ -166,6 +177,9 @@ declare const RU: {
166
177
  ExitDialogBack: string;
167
178
  OpenMenu: string;
168
179
  CloseMenu: string;
180
+ MusicVolume: string;
181
+ SoundVolume: string;
182
+ VoiceVolume: string;
169
183
  };
170
184
  type BaseTranslationStrings = keyof typeof RU;
171
185
  declare const EN: Record<BaseTranslationStrings, string>;
@@ -192,15 +206,13 @@ interface CharacterHandle {
192
206
  remove: (className?: string, style?: string, duration?: number) => (resolve: () => void, restoring: boolean) => void;
193
207
  emotions: Record<string, HTMLImageElement[]>;
194
208
  }
195
- interface AudioHandle {
196
- element: HTMLAudioElement;
209
+ type AudioHandle = {
197
210
  stop: () => void;
198
211
  pause: () => void;
199
212
  play: () => void;
200
- }
213
+ };
201
214
  interface RendererStore {
202
215
  characters: Record<string, CharacterHandle>;
203
- audio: Partial<Record<'music', AudioHandle>>;
204
216
  }
205
217
  type Renderer = {
206
218
  character: (character: string) => CharacterHandle;
@@ -208,7 +220,24 @@ type Renderer = {
208
220
  dialog: (content: string, name: string, character?: string, emotion?: string) => (resolve: () => void, goingBack: boolean) => void;
209
221
  choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[]) => (resolve: (selected: number) => void) => void;
210
222
  input: (question: string, onInput: Parameters<DefaultActionProxyProvider['input']>[1], setup?: Parameters<DefaultActionProxyProvider['input']>[2]) => (resolve: () => void) => void;
211
- music: (source: string, method: keyof RendererStore['audio']) => AudioHandle;
223
+ audio: {
224
+ voice: (source: string) => void;
225
+ voiceStop: () => void;
226
+ music: (source: string, method: 'music' | 'sound', loop?: boolean) => AudioHandle;
227
+ /**
228
+ * Stop all sounds
229
+ */
230
+ clear: () => void;
231
+ /**
232
+ * Destroy
233
+ */
234
+ destroy: () => void;
235
+ /**
236
+ * Start
237
+ * @todo: more descriptive
238
+ */
239
+ start: () => void;
240
+ };
212
241
  clear: (goingBack: boolean, keep: Set<keyof DefaultActionProxyProvider>, keepCharacters: Set<string>) => (resolve: () => void) => void;
213
242
  custom: (fn: Parameters<DefaultActionProxyProvider['custom']>[0], goingBack: boolean, push: () => void) => Thenable<void>;
214
243
  text: (str: string, resolve: () => void, goingBack: boolean) => void;
@@ -225,6 +254,12 @@ type Renderer = {
225
254
  * @returns Image URL
226
255
  */
227
256
  preloadImage: <T extends string>(image: T) => T;
257
+ /**
258
+ * Function to preload audio
259
+ * @param type kind of audio
260
+ * @param source <url> pointing to the audio
261
+ */
262
+ preloadAudioBlocking: (type: 'music', source: string) => Promise<void>;
228
263
  };
229
264
  store: RendererStore;
230
265
  ui: {
@@ -610,7 +610,7 @@ var Novely = (() => {
610
610
  const initialData = {
611
611
  saves: [],
612
612
  data: klona(defaultData),
613
- meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED]
613
+ meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED, 1, 1, 1]
614
614
  };
615
615
  const coreData = {
616
616
  dataLoaded: false
@@ -637,6 +637,9 @@ var Novely = (() => {
637
637
  } else {
638
638
  stored.meta[0] ||= getLanguageWithoutParameters();
639
639
  }
640
+ stored.meta[2] ??= 1;
641
+ stored.meta[3] ??= 1;
642
+ stored.meta[4] ??= 1;
640
643
  if (isEmpty(stored.data)) {
641
644
  stored.data = defaultData;
642
645
  }
@@ -702,7 +705,7 @@ var Novely = (() => {
702
705
  $.update(() => ({
703
706
  saves: [initial],
704
707
  data: klona(defaultData),
705
- meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED]
708
+ meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED, 1, 1, 1]
706
709
  }));
707
710
  latest = klona(initial);
708
711
  }
@@ -852,6 +855,7 @@ var Novely = (() => {
852
855
  const current = stack.value;
853
856
  stack.clear();
854
857
  renderer.ui.showScreen("mainmenu");
858
+ renderer.audio.destroy();
855
859
  const [time, type] = current[2];
856
860
  if (type === "auto" && interacted <= 1 && times.has(time)) {
857
861
  $.update((prev) => {
@@ -893,11 +897,25 @@ var Novely = (() => {
893
897
  push();
894
898
  },
895
899
  playMusic([source]) {
896
- renderer.music(source, "music").play();
900
+ renderer.audio.music(source, "music", true).play();
897
901
  push();
898
902
  },
899
903
  stopMusic([source]) {
900
- renderer.music(source, "music").stop();
904
+ renderer.audio.music(source, "music").stop();
905
+ push();
906
+ },
907
+ playSound([source, loop]) {
908
+ renderer.audio.music(source, "sound", loop || false).play();
909
+ },
910
+ stopSound([source]) {
911
+ renderer.audio.music(source, "sound").stop();
912
+ },
913
+ voice([source]) {
914
+ renderer.audio.voice(source);
915
+ push();
916
+ },
917
+ stopVoice() {
918
+ renderer.audio.voiceStop();
901
919
  push();
902
920
  },
903
921
  showCharacter([character, emotion, className, style]) {
@@ -980,6 +998,7 @@ var Novely = (() => {
980
998
  clear([keep, characters2]) {
981
999
  renderer.vibrate(0);
982
1000
  renderer.clear(goingBack, keep || EMPTY_SET, characters2 || EMPTY_SET)(push);
1001
+ renderer.audio.clear();
983
1002
  },
984
1003
  condition([condition, variants]) {
985
1004
  if (DEV && Object.values(variants).length === 0) {
@@ -1235,7 +1254,10 @@ var Novely = (() => {
1235
1254
  ExitDialogExit: "\u0412\u044B\u0439\u0442\u0438",
1236
1255
  ExitDialogBack: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u0432 \u0438\u0433\u0440\u0443",
1237
1256
  OpenMenu: "\u041E\u0442\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
1238
- CloseMenu: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E"
1257
+ CloseMenu: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043C\u0435\u043D\u044E",
1258
+ MusicVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u043C\u0443\u0437\u044B\u043A\u0438",
1259
+ SoundVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0437\u0432\u0443\u043A\u043E\u0432",
1260
+ VoiceVolume: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0440\u0435\u0447\u0438"
1239
1261
  };
1240
1262
  var EN = {
1241
1263
  NewGame: "New Game",
@@ -1268,7 +1290,10 @@ var Novely = (() => {
1268
1290
  ExitDialogExit: "Exit",
1269
1291
  ExitDialogBack: "Return to game",
1270
1292
  OpenMenu: "Open menu",
1271
- CloseMenu: "Close menu"
1293
+ CloseMenu: "Close menu",
1294
+ MusicVolume: "Music volume",
1295
+ SoundVolume: "Sound volume",
1296
+ VoiceVolume: "Voice volume"
1272
1297
  };
1273
1298
  var KK = {
1274
1299
  NewGame: "\u0416\u0430\u04A3\u0430 \u043E\u0439\u044B\u043D",
@@ -1301,7 +1326,10 @@ var Novely = (() => {
1301
1326
  ExitDialogExit: "\u0428\u044B\u0493\u0443",
1302
1327
  ExitDialogBack: "\u041E\u0439\u044B\u043D\u0493\u0430 \u043E\u0440\u0430\u043B\u0443",
1303
1328
  OpenMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0430\u0448\u044B\u04A3\u044B\u0437",
1304
- CloseMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0436\u0430\u0431\u0443"
1329
+ CloseMenu: "\u041C\u04D9\u0437\u0456\u0440\u0434\u0456 \u0436\u0430\u0431\u0443",
1330
+ MusicVolume: "\u041C\u0443\u0437\u044B\u043A\u0430\u043D\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
1331
+ SoundVolume: "\u0414\u044B\u0431\u044B\u0441\u0442\u0430\u0440\u0434\u044B\u04A3 \u043A\u04E9\u043B\u0435\u043C\u0456",
1332
+ VoiceVolume: "\u0421\u04E9\u0439\u043B\u0435\u0443 \u043A\u04E9\u043B\u0435\u043C\u0456"
1305
1333
  };
1306
1334
  var JP = {
1307
1335
  NewGame: "\u300C\u65B0\u3057\u3044\u30B2\u30FC\u30E0\u300D",
@@ -1334,7 +1362,10 @@ var Novely = (() => {
1334
1362
  ExitDialogExit: "\u7D42\u4E86",
1335
1363
  ExitDialogBack: "\u30B2\u30FC\u30E0\u306B\u623B\u308B",
1336
1364
  OpenMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u958B\u304F",
1337
- CloseMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
1365
+ CloseMenu: "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B",
1366
+ MusicVolume: "\u97F3\u697D\u306E\u30DC\u30EA\u30E5\u30FC\u30E0",
1367
+ SoundVolume: "\u97F3\u91CF",
1368
+ VoiceVolume: "\u30B9\u30D4\u30FC\u30C1\u306E\u91CF"
1338
1369
  };
1339
1370
  return __toCommonJS(src_exports);
1340
1371
  })();