narrat 0.8.2 → 0.8.5

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/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- // Version: 0.8.2 - May 14, 2022 12:04:03
1
+ // Version: 0.8.5 - June 4, 2022 20:05:21
2
2
  import 'es6-promise/auto';
3
3
  import { ref, reactive, readonly, defineComponent, openBlock, createElementBlock, normalizeStyle, createElementVNode, createCommentVNode, Fragment, renderList, createBlock, Transition, withCtx, renderSlot, createTextVNode, resolveComponent, toDisplayString, TransitionGroup, createVNode, createApp } from 'vue';
4
4
  import { createLogger, createStore } from 'vuex';
@@ -308,6 +308,22 @@ styleInject(css_248z$2);
308
308
 
309
309
  script$1.render = render$1;
310
310
 
311
+ class Logger {
312
+ debug;
313
+ constructor(debug) {
314
+ this.debug = debug;
315
+ }
316
+ setDebug(debug) {
317
+ this.debug = debug;
318
+ }
319
+ log(...args) {
320
+ if (this.debug) {
321
+ console.log(...args);
322
+ }
323
+ }
324
+ }
325
+ const logger = new Logger(false);
326
+
311
327
  function getPlayTime(startedAt, previousTime) {
312
328
  return Date.now() - startedAt + previousTime;
313
329
  }
@@ -408,7 +424,7 @@ var script$3 = defineComponent({
408
424
  wordCount() {
409
425
  const scripts = Object.values(this.$store.state.machine.script);
410
426
  const count = scripts.reduce((count, script) => {
411
- console.log(count);
427
+ logger.log(count);
412
428
  return count + this.countWordsInScriptBranch(script);
413
429
  }, 0);
414
430
  alert(`You have ${count} words`);
@@ -3863,10 +3879,8 @@ var script$4 = defineComponent({
3863
3879
  },
3864
3880
  methods: {
3865
3881
  changeVolume(event) {
3866
- console.log(event);
3867
3882
  const target = event.target;
3868
3883
  howler.Howler.volume(target.value);
3869
- console.log(target.value);
3870
3884
  },
3871
3885
  toggleMute() {
3872
3886
  if (this.muted) {
@@ -4132,7 +4146,7 @@ const images = {};
4132
4146
  let imagesToLoad = 0;
4133
4147
  let imagesLoaded = 0;
4134
4148
  function loadImages(config) {
4135
- console.log(`Loading images`);
4149
+ logger.log(`Loading images`);
4136
4150
  return new Promise((resolve, reject) => {
4137
4151
  for (const key in config.images) {
4138
4152
  const path = config.images[key];
@@ -4142,19 +4156,19 @@ function loadImages(config) {
4142
4156
  }
4143
4157
  function loadImage(key, path, resolver, rejecter) {
4144
4158
  imagesToLoad++;
4145
- console.log(`Loading image ${key} at ${path}`);
4159
+ logger.log(`Loading image ${key} at ${path}`);
4146
4160
  const image = new Image();
4147
4161
  image.onload = () => {
4148
4162
  imagesLoaded += 1;
4149
4163
  images[key] = image;
4150
- console.log(`Loaded image ${key} successfully`);
4164
+ logger.log(`Loaded image ${key} successfully`);
4151
4165
  if (imagesLoaded >= imagesToLoad) {
4152
- console.log(`All images loaded`);
4166
+ logger.log(`All images loaded`);
4153
4167
  resolver();
4154
4168
  }
4155
4169
  };
4156
4170
  image.onerror = (e) => {
4157
- console.log(`Error loading image ${key}`);
4171
+ console.error(`Error loading image ${key}`);
4158
4172
  rejecter(e);
4159
4173
  };
4160
4174
  image.src = path;
@@ -4163,7 +4177,7 @@ function loadImage(key, path, resolver, rejecter) {
4163
4177
  const audio = {};
4164
4178
  howler.Howler.volume(0.5);
4165
4179
  async function loadAudioAssets(config) {
4166
- console.log(`Loading audio`);
4180
+ logger.log(`Loading audio`);
4167
4181
  const loadingPromises = [];
4168
4182
  for (const key in config.music) {
4169
4183
  // Backward compatibility with old music list
@@ -4193,7 +4207,7 @@ async function loadAudioAssets(config) {
4193
4207
  }
4194
4208
  async function loadAudio(key, config) {
4195
4209
  return new Promise((resolve, reject) => {
4196
- console.log(`Loading audio ${config.src}`);
4210
+ logger.log(`Loading audio ${config.src}`);
4197
4211
  const sound = new howler.Howl({
4198
4212
  ...config,
4199
4213
  });
@@ -4384,7 +4398,6 @@ styleInject(css_248z$9);
4384
4398
 
4385
4399
  script$8.render = render$8;
4386
4400
 
4387
- console.log('hello app');
4388
4401
  var script$9 = defineComponent({
4389
4402
  $refs: {
4390
4403
  dialogContainer: HTMLInputElement,
@@ -4444,7 +4457,6 @@ var script$9 = defineComponent({
4444
4457
  dialogLength(newCount, oldCount) {
4445
4458
  if (this.$refs.dialog) {
4446
4459
  const dialog = this.$refs.dialog;
4447
- console.log('hello dialog');
4448
4460
  dialog.scrollTop = dialog.scrollHeight + 100000;
4449
4461
  }
4450
4462
  },
@@ -4677,8 +4689,8 @@ const _hoisted_4$3 = { key: 2 };
4677
4689
 
4678
4690
  function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4679
4691
  const _component_Hud = resolveComponent("Hud");
4680
- const _component_DialogPicture = resolveComponent("DialogPicture");
4681
4692
  const _component_Menu = resolveComponent("Menu");
4693
+ const _component_DialogPicture = resolveComponent("DialogPicture");
4682
4694
  const _component_DialogBox = resolveComponent("DialogBox");
4683
4695
  const _component_LoadingBar = resolveComponent("LoadingBar");
4684
4696
  const _component_DebugMenu = resolveComponent("DebugMenu");
@@ -4695,6 +4707,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4695
4707
  class: "game",
4696
4708
  style: normalizeStyle(_ctx.gameStyle)
4697
4709
  }, [
4710
+ createVNode(_component_Menu, { class: "menu-toggle" }),
4698
4711
  createVNode(Transition, { name: "fade" }, {
4699
4712
  default: withCtx(() => [
4700
4713
  (_ctx.picture)
@@ -4726,7 +4739,6 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4726
4739
  ref: "dialog",
4727
4740
  style: normalizeStyle(_ctx.dialogStyle)
4728
4741
  }, [
4729
- createVNode(_component_Menu, { class: "menu-toggle" }),
4730
4742
  createVNode(TransitionGroup, {
4731
4743
  name: "list",
4732
4744
  tag: "div",
@@ -4736,7 +4748,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4736
4748
  default: withCtx(() => [
4737
4749
  (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.dialog, (dialog, i) => {
4738
4750
  return (openBlock(), createBlock(_component_DialogBox, {
4739
- key: i,
4751
+ key: dialog.id,
4740
4752
  options: _ctx.getDialogBoxOptions(dialog, i),
4741
4753
  active: _ctx.isDialogActive(i)
4742
4754
  }, null, 8, ["options", "active"]))
@@ -4775,7 +4787,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4775
4787
  ], 4))
4776
4788
  }
4777
4789
 
4778
- var css_248z$a = "#app {\n background-color: black;\n width: 100%;\n height: 100%;\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n color: white;\n box-sizing: border-box;\n overflow: hidden;\n transform-origin: center center;\n}\n\n.game {\n background-color: black;\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.interact-button {\n height: 50px;\n background-color: #72080f;\n border: 1px solid black;\n font-weight: bold;\n font-size: 20px;\n text-align: center;\n flex-grow: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n.interact-button:not(:last-child) {\n margin-right: 10px;\n}\n\n.dialog-container {\n flex-shrink: 2;\n /* padding: 20px; */\n min-height: 100%;\n width: 100%;\n background-color: #171717;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: center;\n overflow-x: hidden;\n}\n\n.dialog {\n overflow-y: auto;\n overflow-x: hidden;\n position: relative;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n}\n\n.dialog::-webkit-scrollbar {\n display: none; /* webkit */\n}\n\n.dialog * {\n overflow-anchor: none;\n}\n\n.background {\n margin: 0;\n}\n\n#background-canvas {\n height: 100%;\n}\n\n.anchor {\n overflow-anchor: auto;\n height: 1px;\n}\n\n.menu-toggle {\n position: absolute;\n bottom: 0;\n left: 0;\n}\r\n";
4790
+ var css_248z$a = "#app {\n background-color: black;\n width: 100%;\n height: 100%;\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n color: white;\n box-sizing: border-box;\n overflow: hidden;\n transform-origin: center center;\n}\n\n.game {\n background-color: black;\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.interact-button {\n height: 50px;\n background-color: #72080f;\n border: 1px solid black;\n font-weight: bold;\n font-size: 20px;\n text-align: center;\n flex-grow: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n.interact-button:not(:last-child) {\n margin-right: 10px;\n}\n\n.dialog-container {\n flex-shrink: 2;\n /* padding: 20px; */\n min-height: 100%;\n width: 100%;\n background-color: #171717;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: center;\n overflow-x: hidden;\n}\n\n.dialog {\n overflow-y: auto;\n overflow-x: hidden;\n position: relative;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n}\n\n.dialog::-webkit-scrollbar {\n display: none; /* webkit */\n}\n\n.dialog * {\n overflow-anchor: none;\n}\n\n.background {\n margin: 0;\n}\n\n#background-canvas {\n height: 100%;\n}\n\n.anchor {\n overflow-anchor: auto;\n height: 1px;\n}\n\n.menu-toggle {\n position: fixed;\n bottom: 0px;\n right: 15%;\n z-index: 108398;\n}\r\n";
4779
4791
  styleInject(css_248z$a);
4780
4792
 
4781
4793
  script$9.render = render$9;
@@ -4824,7 +4836,7 @@ function runSkillCheck(ctx, params) {
4824
4836
  }
4825
4837
  roll += state.skills[params.skill].level * skillChecks.skillMultiplier;
4826
4838
  const skill = skills[params.skill];
4827
- console.log(`roll `, roll, params.value);
4839
+ logger.log(`roll `, roll, params.value);
4828
4840
  if (roll < params.value) {
4829
4841
  success = false;
4830
4842
  }
@@ -4840,7 +4852,7 @@ function runSkillCheck(ctx, params) {
4840
4852
  function runConditionCommand(ctx, command) {
4841
4853
  const options = command.options;
4842
4854
  const result = runCondition(ctx, options.condition);
4843
- console.log(result);
4855
+ logger.log(result);
4844
4856
  if (result) {
4845
4857
  return options.success;
4846
4858
  }
@@ -4911,6 +4923,7 @@ async function runCommand(context, cmd, choices) {
4911
4923
  currentIndex: 0,
4912
4924
  };
4913
4925
  commit('setStack', newStack);
4926
+ await dispatch('saveGame');
4914
4927
  await dispatch('runLine');
4915
4928
  break;
4916
4929
  case 'text':
@@ -4961,7 +4974,6 @@ async function runCommand(context, cmd, choices) {
4961
4974
  commit('clearDialog');
4962
4975
  return dispatch('nextLine');
4963
4976
  case 'set_button':
4964
- console.log(cmd.args);
4965
4977
  commit('changeButton', {
4966
4978
  button: cmd.args[0],
4967
4979
  enabled: cmd.args[1],
@@ -5048,7 +5060,7 @@ async function runCommand(context, cmd, choices) {
5048
5060
  }
5049
5061
  }
5050
5062
  catch (err) {
5051
- console.log(state.machine.stack[state.machine.stack.length - 1].label);
5063
+ logger.log(`Error at: `, state.machine.stack[state.machine.stack.length - 1].label);
5052
5064
  console.error(err);
5053
5065
  error(commit, `Narrat script runtime error at <span class="error-filename">${cmd.fileName}:${cmd.line + 1}</span>
5054
5066
  <b>${err}</b>
@@ -5127,7 +5139,6 @@ async function runChoice(context, cmd) {
5127
5139
  const skill = config.skills[check.skill];
5128
5140
  const level = context.state.skills[check.skill].level;
5129
5141
  const difficultyScore = check.value - level * config.skillChecks.skillMultiplier;
5130
- console.log(`Check `, check, `score `, difficultyScore);
5131
5142
  const skillCheckState = getSkillCheckState(context, choice.skillCheck.id);
5132
5143
  let found = false;
5133
5144
  let i = 0;
@@ -5414,7 +5425,7 @@ function parseRenpyScript(errorHandler, code, fileName) {
5414
5425
  };
5415
5426
  ctx.indentSize = detectIndentation(ctx, code);
5416
5427
  const lines = findRenpyLines(ctx, code);
5417
- console.log(lines);
5428
+ logger.log(lines);
5418
5429
  const script = {};
5419
5430
  for (const line of lines) {
5420
5431
  if (line.code.search(':') === -1) {
@@ -5596,10 +5607,14 @@ function detectIndentation(ctx, script) {
5596
5607
  if (result.length < 2) {
5597
5608
  ctx.error(0, `Can't detect indentation level. Make sure you indent with at least 2 spaces and consistently`);
5598
5609
  }
5599
- console.log(result);
5610
+ logger.log(result);
5600
5611
  return result[1].length;
5601
5612
  }
5602
5613
 
5614
+ function randomId() {
5615
+ return `${Date.now() - Math.floor(Math.random() * 99999999)}`;
5616
+ }
5617
+
5603
5618
  let key = Symbol('Store Injection Key');
5604
5619
  let store;
5605
5620
  function setupStore(options) {
@@ -5610,7 +5625,8 @@ function setupStore(options) {
5610
5625
  }
5611
5626
  // define injection key
5612
5627
  key = Symbol('Store Injection Key');
5613
- console.log('setup store');
5628
+ logger.setDebug(options.debug);
5629
+ logger.log('setup store');
5614
5630
  store = createStore({
5615
5631
  state: {
5616
5632
  machine: {
@@ -5680,7 +5696,7 @@ function setupStore(options) {
5680
5696
  };
5681
5697
  }
5682
5698
  const end = Date.now();
5683
- console.log(`script parsed in ${end - start} ms`);
5699
+ logger.log(`script parsed in ${end - start} ms`);
5684
5700
  commit('setButtons', payload.config.buttons);
5685
5701
  commit('setScript', scripts);
5686
5702
  commit('setupSkills', payload.config.skills);
@@ -5702,7 +5718,6 @@ function setupStore(options) {
5702
5718
  this.dispatch('runLine');
5703
5719
  },
5704
5720
  async runLine(context) {
5705
- await this.dispatch('saveGame');
5706
5721
  await runLine(context);
5707
5722
  },
5708
5723
  nextLine(context) {
@@ -5720,13 +5735,22 @@ function setupStore(options) {
5720
5735
  lastLabel: state.lastLabel,
5721
5736
  skillChecks: state.skillChecks,
5722
5737
  playTime: getPlayTime(state.playTime.start, state.playTime.previousPlaytime),
5738
+ hudStats: state.hudStats,
5739
+ currentScreen: state.currentScreen,
5740
+ audio: {
5741
+ currentMusic: state.audio.currentMusic,
5742
+ },
5723
5743
  };
5724
5744
  localStorage.setItem(SAVE_FILE, JSON.stringify(save));
5725
5745
  },
5726
- loadGame({ commit, dispatch }, saveFile) {
5746
+ loadGame(ctx, saveFile) {
5747
+ const { commit, dispatch } = ctx;
5727
5748
  if (saveFile) {
5728
5749
  const save = JSON.parse(saveFile);
5729
5750
  commit('setLoadedData', save);
5751
+ if (save.audio.currentMusic) {
5752
+ changeMusic(ctx, save.audio.currentMusic);
5753
+ }
5730
5754
  dispatch('runLabel', save.lastLabel);
5731
5755
  }
5732
5756
  },
@@ -5749,6 +5773,9 @@ function setupStore(options) {
5749
5773
  state.lastLabel = save.lastLabel;
5750
5774
  state.skillChecks = save.skillChecks;
5751
5775
  state.playTime.previousPlaytime = save.playTime;
5776
+ state.hudStats = save.hudStats;
5777
+ state.currentScreen = save.currentScreen;
5778
+ state.audio = save.audio;
5752
5779
  },
5753
5780
  reset(state) {
5754
5781
  state.ready = false;
@@ -5801,7 +5828,7 @@ function setupStore(options) {
5801
5828
  state.hudStats[stat] += amount;
5802
5829
  },
5803
5830
  addDialog(state, payload) {
5804
- state.dialog.push(payload.dialog);
5831
+ state.dialog.push({ ...payload.dialog, id: randomId() });
5805
5832
  },
5806
5833
  nextLine(state) {
5807
5834
  state.machine.stack[state.machine.stack.length - 1].currentIndex += 1;
@@ -5818,6 +5845,7 @@ function setupStore(options) {
5818
5845
  },
5819
5846
  setStack(state, newStack) {
5820
5847
  state.machine.stack = [];
5848
+ state.lastLabel = newStack.label;
5821
5849
  state.machine.stack.push(newStack);
5822
5850
  },
5823
5851
  setData(state, { path, value }) {
@@ -5877,7 +5905,7 @@ function setupStore(options) {
5877
5905
  return id;
5878
5906
  },
5879
5907
  deleteNotification(state, id) {
5880
- console.log('delete notif', id);
5908
+ logger.log('delete notif', id);
5881
5909
  delete state.notifications[id];
5882
5910
  },
5883
5911
  },
@@ -5902,7 +5930,7 @@ async function startApp(config, options) {
5902
5930
  mousePos.x = e.clientX;
5903
5931
  mousePos.y = e.clientY;
5904
5932
  });
5905
- console.log('%c Narrat game engine – 0.8.2 - May 14, 2022 12:04:03', 'background: #222; color: #bada55');
5933
+ console.log('%c Narrat game engine – 0.8.5 - June 4, 2022 20:05:21', 'background: #222; color: #bada55');
5906
5934
  const storeSetup = setupStore(options);
5907
5935
  store$1 = storeSetup.store;
5908
5936
  app = createApp(script$9, {
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // Version: 0.8.2 - May 14, 2022 12:04:03
1
+ // Version: 0.8.5 - June 4, 2022 20:05:21
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -312,6 +312,22 @@ styleInject(css_248z$2);
312
312
 
313
313
  script$1.render = render$1;
314
314
 
315
+ class Logger {
316
+ debug;
317
+ constructor(debug) {
318
+ this.debug = debug;
319
+ }
320
+ setDebug(debug) {
321
+ this.debug = debug;
322
+ }
323
+ log(...args) {
324
+ if (this.debug) {
325
+ console.log(...args);
326
+ }
327
+ }
328
+ }
329
+ const logger = new Logger(false);
330
+
315
331
  function getPlayTime(startedAt, previousTime) {
316
332
  return Date.now() - startedAt + previousTime;
317
333
  }
@@ -412,7 +428,7 @@ var script$3 = vue.defineComponent({
412
428
  wordCount() {
413
429
  const scripts = Object.values(this.$store.state.machine.script);
414
430
  const count = scripts.reduce((count, script) => {
415
- console.log(count);
431
+ logger.log(count);
416
432
  return count + this.countWordsInScriptBranch(script);
417
433
  }, 0);
418
434
  alert(`You have ${count} words`);
@@ -3867,10 +3883,8 @@ var script$4 = vue.defineComponent({
3867
3883
  },
3868
3884
  methods: {
3869
3885
  changeVolume(event) {
3870
- console.log(event);
3871
3886
  const target = event.target;
3872
3887
  howler.Howler.volume(target.value);
3873
- console.log(target.value);
3874
3888
  },
3875
3889
  toggleMute() {
3876
3890
  if (this.muted) {
@@ -4136,7 +4150,7 @@ const images = {};
4136
4150
  let imagesToLoad = 0;
4137
4151
  let imagesLoaded = 0;
4138
4152
  function loadImages(config) {
4139
- console.log(`Loading images`);
4153
+ logger.log(`Loading images`);
4140
4154
  return new Promise((resolve, reject) => {
4141
4155
  for (const key in config.images) {
4142
4156
  const path = config.images[key];
@@ -4146,19 +4160,19 @@ function loadImages(config) {
4146
4160
  }
4147
4161
  function loadImage(key, path, resolver, rejecter) {
4148
4162
  imagesToLoad++;
4149
- console.log(`Loading image ${key} at ${path}`);
4163
+ logger.log(`Loading image ${key} at ${path}`);
4150
4164
  const image = new Image();
4151
4165
  image.onload = () => {
4152
4166
  imagesLoaded += 1;
4153
4167
  images[key] = image;
4154
- console.log(`Loaded image ${key} successfully`);
4168
+ logger.log(`Loaded image ${key} successfully`);
4155
4169
  if (imagesLoaded >= imagesToLoad) {
4156
- console.log(`All images loaded`);
4170
+ logger.log(`All images loaded`);
4157
4171
  resolver();
4158
4172
  }
4159
4173
  };
4160
4174
  image.onerror = (e) => {
4161
- console.log(`Error loading image ${key}`);
4175
+ console.error(`Error loading image ${key}`);
4162
4176
  rejecter(e);
4163
4177
  };
4164
4178
  image.src = path;
@@ -4167,7 +4181,7 @@ function loadImage(key, path, resolver, rejecter) {
4167
4181
  const audio = {};
4168
4182
  howler.Howler.volume(0.5);
4169
4183
  async function loadAudioAssets(config) {
4170
- console.log(`Loading audio`);
4184
+ logger.log(`Loading audio`);
4171
4185
  const loadingPromises = [];
4172
4186
  for (const key in config.music) {
4173
4187
  // Backward compatibility with old music list
@@ -4197,7 +4211,7 @@ async function loadAudioAssets(config) {
4197
4211
  }
4198
4212
  async function loadAudio(key, config) {
4199
4213
  return new Promise((resolve, reject) => {
4200
- console.log(`Loading audio ${config.src}`);
4214
+ logger.log(`Loading audio ${config.src}`);
4201
4215
  const sound = new howler.Howl({
4202
4216
  ...config,
4203
4217
  });
@@ -4388,7 +4402,6 @@ styleInject(css_248z$9);
4388
4402
 
4389
4403
  script$8.render = render$8;
4390
4404
 
4391
- console.log('hello app');
4392
4405
  var script$9 = vue.defineComponent({
4393
4406
  $refs: {
4394
4407
  dialogContainer: HTMLInputElement,
@@ -4448,7 +4461,6 @@ var script$9 = vue.defineComponent({
4448
4461
  dialogLength(newCount, oldCount) {
4449
4462
  if (this.$refs.dialog) {
4450
4463
  const dialog = this.$refs.dialog;
4451
- console.log('hello dialog');
4452
4464
  dialog.scrollTop = dialog.scrollHeight + 100000;
4453
4465
  }
4454
4466
  },
@@ -4681,8 +4693,8 @@ const _hoisted_4$3 = { key: 2 };
4681
4693
 
4682
4694
  function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4683
4695
  const _component_Hud = vue.resolveComponent("Hud");
4684
- const _component_DialogPicture = vue.resolveComponent("DialogPicture");
4685
4696
  const _component_Menu = vue.resolveComponent("Menu");
4697
+ const _component_DialogPicture = vue.resolveComponent("DialogPicture");
4686
4698
  const _component_DialogBox = vue.resolveComponent("DialogBox");
4687
4699
  const _component_LoadingBar = vue.resolveComponent("LoadingBar");
4688
4700
  const _component_DebugMenu = vue.resolveComponent("DebugMenu");
@@ -4699,6 +4711,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4699
4711
  class: "game",
4700
4712
  style: vue.normalizeStyle(_ctx.gameStyle)
4701
4713
  }, [
4714
+ vue.createVNode(_component_Menu, { class: "menu-toggle" }),
4702
4715
  vue.createVNode(vue.Transition, { name: "fade" }, {
4703
4716
  default: vue.withCtx(() => [
4704
4717
  (_ctx.picture)
@@ -4730,7 +4743,6 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4730
4743
  ref: "dialog",
4731
4744
  style: vue.normalizeStyle(_ctx.dialogStyle)
4732
4745
  }, [
4733
- vue.createVNode(_component_Menu, { class: "menu-toggle" }),
4734
4746
  vue.createVNode(vue.TransitionGroup, {
4735
4747
  name: "list",
4736
4748
  tag: "div",
@@ -4740,7 +4752,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4740
4752
  default: vue.withCtx(() => [
4741
4753
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.dialog, (dialog, i) => {
4742
4754
  return (vue.openBlock(), vue.createBlock(_component_DialogBox, {
4743
- key: i,
4755
+ key: dialog.id,
4744
4756
  options: _ctx.getDialogBoxOptions(dialog, i),
4745
4757
  active: _ctx.isDialogActive(i)
4746
4758
  }, null, 8, ["options", "active"]))
@@ -4779,7 +4791,7 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
4779
4791
  ], 4))
4780
4792
  }
4781
4793
 
4782
- var css_248z$a = "#app {\n background-color: black;\n width: 100%;\n height: 100%;\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n color: white;\n box-sizing: border-box;\n overflow: hidden;\n transform-origin: center center;\n}\n\n.game {\n background-color: black;\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.interact-button {\n height: 50px;\n background-color: #72080f;\n border: 1px solid black;\n font-weight: bold;\n font-size: 20px;\n text-align: center;\n flex-grow: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n.interact-button:not(:last-child) {\n margin-right: 10px;\n}\n\n.dialog-container {\n flex-shrink: 2;\n /* padding: 20px; */\n min-height: 100%;\n width: 100%;\n background-color: #171717;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: center;\n overflow-x: hidden;\n}\n\n.dialog {\n overflow-y: auto;\n overflow-x: hidden;\n position: relative;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n}\n\n.dialog::-webkit-scrollbar {\n display: none; /* webkit */\n}\n\n.dialog * {\n overflow-anchor: none;\n}\n\n.background {\n margin: 0;\n}\n\n#background-canvas {\n height: 100%;\n}\n\n.anchor {\n overflow-anchor: auto;\n height: 1px;\n}\n\n.menu-toggle {\n position: absolute;\n bottom: 0;\n left: 0;\n}\r\n";
4794
+ var css_248z$a = "#app {\n background-color: black;\n width: 100%;\n height: 100%;\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n color: white;\n box-sizing: border-box;\n overflow: hidden;\n transform-origin: center center;\n}\n\n.game {\n background-color: black;\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.interact-button {\n height: 50px;\n background-color: #72080f;\n border: 1px solid black;\n font-weight: bold;\n font-size: 20px;\n text-align: center;\n flex-grow: 2;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n\n.interact-button:not(:last-child) {\n margin-right: 10px;\n}\n\n.dialog-container {\n flex-shrink: 2;\n /* padding: 20px; */\n min-height: 100%;\n width: 100%;\n background-color: #171717;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n align-items: center;\n overflow-x: hidden;\n}\n\n.dialog {\n overflow-y: auto;\n overflow-x: hidden;\n position: relative;\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n}\n\n.dialog::-webkit-scrollbar {\n display: none; /* webkit */\n}\n\n.dialog * {\n overflow-anchor: none;\n}\n\n.background {\n margin: 0;\n}\n\n#background-canvas {\n height: 100%;\n}\n\n.anchor {\n overflow-anchor: auto;\n height: 1px;\n}\n\n.menu-toggle {\n position: fixed;\n bottom: 0px;\n right: 15%;\n z-index: 108398;\n}\r\n";
4783
4795
  styleInject(css_248z$a);
4784
4796
 
4785
4797
  script$9.render = render$9;
@@ -4828,7 +4840,7 @@ function runSkillCheck(ctx, params) {
4828
4840
  }
4829
4841
  roll += state.skills[params.skill].level * skillChecks.skillMultiplier;
4830
4842
  const skill = skills[params.skill];
4831
- console.log(`roll `, roll, params.value);
4843
+ logger.log(`roll `, roll, params.value);
4832
4844
  if (roll < params.value) {
4833
4845
  success = false;
4834
4846
  }
@@ -4844,7 +4856,7 @@ function runSkillCheck(ctx, params) {
4844
4856
  function runConditionCommand(ctx, command) {
4845
4857
  const options = command.options;
4846
4858
  const result = runCondition(ctx, options.condition);
4847
- console.log(result);
4859
+ logger.log(result);
4848
4860
  if (result) {
4849
4861
  return options.success;
4850
4862
  }
@@ -4915,6 +4927,7 @@ async function runCommand(context, cmd, choices) {
4915
4927
  currentIndex: 0,
4916
4928
  };
4917
4929
  commit('setStack', newStack);
4930
+ await dispatch('saveGame');
4918
4931
  await dispatch('runLine');
4919
4932
  break;
4920
4933
  case 'text':
@@ -4965,7 +4978,6 @@ async function runCommand(context, cmd, choices) {
4965
4978
  commit('clearDialog');
4966
4979
  return dispatch('nextLine');
4967
4980
  case 'set_button':
4968
- console.log(cmd.args);
4969
4981
  commit('changeButton', {
4970
4982
  button: cmd.args[0],
4971
4983
  enabled: cmd.args[1],
@@ -5052,7 +5064,7 @@ async function runCommand(context, cmd, choices) {
5052
5064
  }
5053
5065
  }
5054
5066
  catch (err) {
5055
- console.log(state.machine.stack[state.machine.stack.length - 1].label);
5067
+ logger.log(`Error at: `, state.machine.stack[state.machine.stack.length - 1].label);
5056
5068
  console.error(err);
5057
5069
  error(commit, `Narrat script runtime error at <span class="error-filename">${cmd.fileName}:${cmd.line + 1}</span>
5058
5070
  <b>${err}</b>
@@ -5131,7 +5143,6 @@ async function runChoice(context, cmd) {
5131
5143
  const skill = config.skills[check.skill];
5132
5144
  const level = context.state.skills[check.skill].level;
5133
5145
  const difficultyScore = check.value - level * config.skillChecks.skillMultiplier;
5134
- console.log(`Check `, check, `score `, difficultyScore);
5135
5146
  const skillCheckState = getSkillCheckState(context, choice.skillCheck.id);
5136
5147
  let found = false;
5137
5148
  let i = 0;
@@ -5418,7 +5429,7 @@ function parseRenpyScript(errorHandler, code, fileName) {
5418
5429
  };
5419
5430
  ctx.indentSize = detectIndentation(ctx, code);
5420
5431
  const lines = findRenpyLines(ctx, code);
5421
- console.log(lines);
5432
+ logger.log(lines);
5422
5433
  const script = {};
5423
5434
  for (const line of lines) {
5424
5435
  if (line.code.search(':') === -1) {
@@ -5600,10 +5611,14 @@ function detectIndentation(ctx, script) {
5600
5611
  if (result.length < 2) {
5601
5612
  ctx.error(0, `Can't detect indentation level. Make sure you indent with at least 2 spaces and consistently`);
5602
5613
  }
5603
- console.log(result);
5614
+ logger.log(result);
5604
5615
  return result[1].length;
5605
5616
  }
5606
5617
 
5618
+ function randomId() {
5619
+ return `${Date.now() - Math.floor(Math.random() * 99999999)}`;
5620
+ }
5621
+
5607
5622
  let key = Symbol('Store Injection Key');
5608
5623
  let store;
5609
5624
  function setupStore(options) {
@@ -5614,7 +5629,8 @@ function setupStore(options) {
5614
5629
  }
5615
5630
  // define injection key
5616
5631
  key = Symbol('Store Injection Key');
5617
- console.log('setup store');
5632
+ logger.setDebug(options.debug);
5633
+ logger.log('setup store');
5618
5634
  store = vuex.createStore({
5619
5635
  state: {
5620
5636
  machine: {
@@ -5684,7 +5700,7 @@ function setupStore(options) {
5684
5700
  };
5685
5701
  }
5686
5702
  const end = Date.now();
5687
- console.log(`script parsed in ${end - start} ms`);
5703
+ logger.log(`script parsed in ${end - start} ms`);
5688
5704
  commit('setButtons', payload.config.buttons);
5689
5705
  commit('setScript', scripts);
5690
5706
  commit('setupSkills', payload.config.skills);
@@ -5706,7 +5722,6 @@ function setupStore(options) {
5706
5722
  this.dispatch('runLine');
5707
5723
  },
5708
5724
  async runLine(context) {
5709
- await this.dispatch('saveGame');
5710
5725
  await runLine(context);
5711
5726
  },
5712
5727
  nextLine(context) {
@@ -5724,13 +5739,22 @@ function setupStore(options) {
5724
5739
  lastLabel: state.lastLabel,
5725
5740
  skillChecks: state.skillChecks,
5726
5741
  playTime: getPlayTime(state.playTime.start, state.playTime.previousPlaytime),
5742
+ hudStats: state.hudStats,
5743
+ currentScreen: state.currentScreen,
5744
+ audio: {
5745
+ currentMusic: state.audio.currentMusic,
5746
+ },
5727
5747
  };
5728
5748
  localStorage.setItem(SAVE_FILE, JSON.stringify(save));
5729
5749
  },
5730
- loadGame({ commit, dispatch }, saveFile) {
5750
+ loadGame(ctx, saveFile) {
5751
+ const { commit, dispatch } = ctx;
5731
5752
  if (saveFile) {
5732
5753
  const save = JSON.parse(saveFile);
5733
5754
  commit('setLoadedData', save);
5755
+ if (save.audio.currentMusic) {
5756
+ changeMusic(ctx, save.audio.currentMusic);
5757
+ }
5734
5758
  dispatch('runLabel', save.lastLabel);
5735
5759
  }
5736
5760
  },
@@ -5753,6 +5777,9 @@ function setupStore(options) {
5753
5777
  state.lastLabel = save.lastLabel;
5754
5778
  state.skillChecks = save.skillChecks;
5755
5779
  state.playTime.previousPlaytime = save.playTime;
5780
+ state.hudStats = save.hudStats;
5781
+ state.currentScreen = save.currentScreen;
5782
+ state.audio = save.audio;
5756
5783
  },
5757
5784
  reset(state) {
5758
5785
  state.ready = false;
@@ -5805,7 +5832,7 @@ function setupStore(options) {
5805
5832
  state.hudStats[stat] += amount;
5806
5833
  },
5807
5834
  addDialog(state, payload) {
5808
- state.dialog.push(payload.dialog);
5835
+ state.dialog.push({ ...payload.dialog, id: randomId() });
5809
5836
  },
5810
5837
  nextLine(state) {
5811
5838
  state.machine.stack[state.machine.stack.length - 1].currentIndex += 1;
@@ -5822,6 +5849,7 @@ function setupStore(options) {
5822
5849
  },
5823
5850
  setStack(state, newStack) {
5824
5851
  state.machine.stack = [];
5852
+ state.lastLabel = newStack.label;
5825
5853
  state.machine.stack.push(newStack);
5826
5854
  },
5827
5855
  setData(state, { path, value }) {
@@ -5881,7 +5909,7 @@ function setupStore(options) {
5881
5909
  return id;
5882
5910
  },
5883
5911
  deleteNotification(state, id) {
5884
- console.log('delete notif', id);
5912
+ logger.log('delete notif', id);
5885
5913
  delete state.notifications[id];
5886
5914
  },
5887
5915
  },
@@ -5906,7 +5934,7 @@ async function startApp(config, options) {
5906
5934
  mousePos.x = e.clientX;
5907
5935
  mousePos.y = e.clientY;
5908
5936
  });
5909
- console.log('%c Narrat game engine – 0.8.2 - May 14, 2022 12:04:03', 'background: #222; color: #bada55');
5937
+ console.log('%c Narrat game engine – 0.8.5 - June 4, 2022 20:05:21', 'background: #222; color: #bada55');
5910
5938
  const storeSetup = setupStore(options);
5911
5939
  store$1 = storeSetup.store;
5912
5940
  app = vue.createApp(script$9, {
package/lib/store.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { InjectionKey, State } from 'vue';
2
2
  import { Store } from 'vuex';
3
- import { MachineStack } from './types/vuex';
3
+ import { DialogKey, MachineStack } from './types/vuex';
4
4
  import { AppOptions } from '.';
5
+ export declare type AddDialogParams = Omit<DialogKey, 'id'>;
5
6
  export interface SetupStoreResult {
6
7
  store: Store<State>;
7
8
  key: InjectionKey<Store<State>>;
@@ -1,4 +1,4 @@
1
- import { Config } from "@/types/config";
1
+ import { Config } from '@/types/config';
2
2
  export declare const images: {
3
3
  [key: string]: HTMLImageElement;
4
4
  };
@@ -0,0 +1,8 @@
1
+ declare class Logger {
2
+ debug: boolean;
3
+ constructor(debug: boolean);
4
+ setDebug(debug: boolean): void;
5
+ log(...args: any[]): void;
6
+ }
7
+ export declare const logger: Logger;
8
+ export {};
@@ -0,0 +1 @@
1
+ export declare function randomId(): string;
@@ -1,10 +1,11 @@
1
1
  import { ActionContext, Commit } from 'vuex';
2
2
  import { State } from 'vue';
3
- import { DialogKey, DialogChoice } from '@/types/vuex';
3
+ import { DialogChoice } from '@/types/vuex';
4
+ import { AddDialogParams } from '@/store';
4
5
  export declare function runLine(context: ActionContext<State, State>): Promise<void>;
5
6
  export declare function runCommand(context: ActionContext<State, State>, cmd: Parser.Command, choices?: DialogChoice[]): Promise<any>;
6
7
  export declare function playerAnswered(context: ActionContext<State, State>, choiceIndex: number): Promise<void>;
7
8
  export declare function runChoice(context: ActionContext<State, State>, cmd: Parser.Command): Promise<void>;
8
- export declare function textCommand(commit: Commit, dialog: DialogKey): Promise<void>;
9
+ export declare function textCommand(commit: Commit, dialog: AddDialogParams): Promise<void>;
9
10
  export declare function nextLine(ctx: ActionContext<State, State>): Promise<any>;
10
11
  export declare function finishGame({ commit, state }: ActionContext<State, State>): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "narrat",
3
- "version": "0.8.2",
3
+ "version": "0.8.5",
4
4
  "description": "narrat narrative engine",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.esm.js",