narrat 1.2.1 → 1.3.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/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- // Version: 1.2.1 - June 25, 2022 14:20:12
1
+ // Version: 1.3.0 - June 25, 2022 18:05:43
2
2
  import 'es6-promise/auto';
3
3
  import { ref, reactive, readonly, defineComponent, openBlock, createElementBlock, normalizeStyle, createElementVNode, createCommentVNode, Fragment, renderList, normalizeClass, createBlock, Transition, withCtx, renderSlot, createTextVNode, computed, resolveComponent, withDirectives, vModelText, toDisplayString, TransitionGroup, createVNode, createApp } from 'vue';
4
4
  import { defineStore, mapState, createPinia } from 'pinia';
@@ -3560,32 +3560,178 @@ function randomId() {
3560
3560
  return `${Date.now() - Math.floor(Math.random() * 99999999)}`;
3561
3561
  }
3562
3562
 
3563
- // Create a pinia store named dialog with a state using the type DialogState, with actions addDialog and clearDialog
3564
- const useDialogStore = defineStore('dialog', {
3563
+ // Generate a pinia store named notifications with a state using the type NotificationsState, and save type NotificationsSave, with actions:
3564
+ // addNotification(text: string): Adds a new notification to the state, and deletes it after a timeout
3565
+ // deleteNotification(id: string): Deletes a notification from the state
3566
+ const useNotifications = defineStore('notifications', {
3567
+ state: () => ({ notifications: {} }),
3568
+ actions: {
3569
+ async addNotification(text) {
3570
+ const id = `${Date.now()}-${Math.random() * 10000}`;
3571
+ this.notifications[id] = {
3572
+ text,
3573
+ };
3574
+ if (getConfig().notifications.alsoPrintInDialogue) {
3575
+ writeText(`[NOTIFICATION] ${text}`);
3576
+ }
3577
+ await timeout(getConfig().notifications.timeOnScreen * 1000);
3578
+ this.deleteNotification(id);
3579
+ },
3580
+ deleteNotification(id) {
3581
+ delete this.notifications[id];
3582
+ },
3583
+ },
3584
+ });
3585
+
3586
+ // create a pinia store named inventory with a state containing items and actions to add and delete items
3587
+ // create a pinia store named inventory with a state of type ItemState and actions to add and delete items. Adding items should increase the amount of any existing item that matches the id.
3588
+ const useInventory = defineStore('inventory', {
3565
3589
  state: () => ({
3566
- dialog: [],
3590
+ items: {},
3567
3591
  }),
3568
3592
  actions: {
3569
3593
  generateSaveData() {
3570
3594
  return {
3571
- dialog: this.dialog,
3595
+ items: this.items,
3572
3596
  };
3573
3597
  },
3574
- loadSaveData(data) {
3575
- this.dialog = data.dialog;
3598
+ loadSaveData(save) {
3599
+ this.items = { ...this.items, ...save.items };
3576
3600
  },
3577
- addDialog(dialog) {
3578
- this.dialog.push({
3579
- ...dialog,
3580
- interactive: dialog.interactive ?? false,
3581
- id: randomId(),
3601
+ setupItems(items) {
3602
+ Object.keys(items).forEach((key) => {
3603
+ this.items[key] = {
3604
+ amount: 0,
3605
+ id: key,
3606
+ };
3582
3607
  });
3583
3608
  },
3584
- clearDialog() {
3585
- this.dialog.splice(0, this.dialog.length);
3609
+ getExistingItem(id) {
3610
+ return this.items[id];
3586
3611
  },
3587
- reset() {
3588
- this.dialog = [];
3612
+ getItemAmount(id) {
3613
+ return this.getExistingItem(id)?.amount || 0;
3614
+ },
3615
+ add(item) {
3616
+ const existingItem = this.getExistingItem(item.id);
3617
+ if (existingItem) {
3618
+ existingItem.amount += item.amount;
3619
+ }
3620
+ else {
3621
+ this.items[item.id] = { ...item };
3622
+ }
3623
+ useNotifications().addNotification(`Received item: ${getItemConfig(item.id).name} x ${item.amount}`);
3624
+ },
3625
+ remove(item) {
3626
+ const existingItem = this.getExistingItem(item.id);
3627
+ if (existingItem) {
3628
+ existingItem.amount -= item.amount;
3629
+ useNotifications().addNotification(`Lost item: ${getItemConfig(item.id).name} x ${item.amount}`);
3630
+ if (existingItem.amount <= 0) {
3631
+ this.deleteItem(item.id);
3632
+ }
3633
+ }
3634
+ },
3635
+ deleteItem(id) {
3636
+ const existingItem = this.getExistingItem(id);
3637
+ if (existingItem) {
3638
+ this.items[id].amount = 0;
3639
+ }
3640
+ },
3641
+ },
3642
+ });
3643
+
3644
+ const everyObject = (object, predicate) => {
3645
+ for (const key in object) {
3646
+ if (!predicate(object[key])) {
3647
+ return false;
3648
+ }
3649
+ }
3650
+ return true;
3651
+ };
3652
+ const filterObject = (object, predicate) => {
3653
+ const result = {};
3654
+ for (const key in object) {
3655
+ if (predicate(object[key])) {
3656
+ result[key] = object[key];
3657
+ }
3658
+ }
3659
+ return result;
3660
+ };
3661
+
3662
+ const useQuests = defineStore('quests', {
3663
+ state: () => ({
3664
+ quests: {},
3665
+ }),
3666
+ actions: {
3667
+ getQuest(questId) {
3668
+ const quest = this.quests[questId];
3669
+ if (quest) {
3670
+ return quest;
3671
+ }
3672
+ error(`Quest ${questId} doesn't exist!`);
3673
+ },
3674
+ getObjective(quest, objectiveId) {
3675
+ const questObjective = this.getQuest(quest).objectives[objectiveId];
3676
+ if (questObjective) {
3677
+ return questObjective;
3678
+ }
3679
+ error(`Objective ${objectiveId} doesn't exist in quest ${quest}!`);
3680
+ },
3681
+ setupQuests(quests) {
3682
+ // iterate through quests to generate quest states to add to this.quests object
3683
+ for (const key of Object.keys(quests)) {
3684
+ const data = quests[key];
3685
+ this.quests[key] = {
3686
+ id: key,
3687
+ state: 'hidden',
3688
+ objectives: {},
3689
+ };
3690
+ // iterate through data.objectives to populate the objectives array of this.quests[key]
3691
+ for (const objectiveKey of Object.keys(data.objectives)) {
3692
+ const objective = data.objectives[objectiveKey];
3693
+ this.quests[key].objectives[objectiveKey] = {
3694
+ id: objectiveKey,
3695
+ state: objective.hidden ? 'hidden' : 'unlocked',
3696
+ };
3697
+ }
3698
+ }
3699
+ },
3700
+ startQuest(questId) {
3701
+ this.getQuest(questId).state = 'unlocked';
3702
+ useNotifications().addNotification(`Started quest: ${getQuestConfig(questId).title}`);
3703
+ },
3704
+ startObjective(questId, objectiveId) {
3705
+ this.getObjective(questId, objectiveId).state = 'unlocked';
3706
+ useNotifications().addNotification(`New quest objective: ${getObjectiveConfig(questId, objectiveId).description}`);
3707
+ },
3708
+ completeObjective(questId, objectiveId) {
3709
+ this.getObjective(questId, objectiveId).state = 'completed';
3710
+ useNotifications().addNotification(`Objective completed!`);
3711
+ },
3712
+ completeQuest(questId, ending) {
3713
+ this.getQuest(questId).state = 'completed';
3714
+ if (ending) {
3715
+ this.getQuest(questId).ending = ending;
3716
+ }
3717
+ useNotifications().addNotification(`Quest completed: ${getQuestConfig(questId).title}`);
3718
+ },
3719
+ isQuestCompleted(questId) {
3720
+ const quest = this.getQuest(questId);
3721
+ return everyObject(quest.objectives, (objective) => objective.state === 'completed');
3722
+ },
3723
+ removeQuest(id) {
3724
+ delete this.quests[id];
3725
+ },
3726
+ generateSaveData() {
3727
+ return {
3728
+ quests: {
3729
+ ...this.quests,
3730
+ },
3731
+ };
3732
+ },
3733
+ loadSaveData(data) {
3734
+ this.quests = data.quests;
3589
3735
  },
3590
3736
  },
3591
3737
  });
@@ -3722,122 +3868,6 @@ var deepmerge_1 = deepmerge;
3722
3868
 
3723
3869
  var cjs = deepmerge_1;
3724
3870
 
3725
- // Create a pinia store named hud with a state using the type HudState, and save type HudSave, with actions:
3726
- // setupHudStats(stats: { [key: string]: HudStatConfig }): Iterates the stats argument to add new stats to the state
3727
- // setStat(stat: string, value: number): Sets the value of a stat
3728
- // addStat(stat: string, value: number): Adds a value to a stat
3729
- // generateSaveData(): Function that generates a HudSave object from the data in the state
3730
- // loadSaveData(data: HudSave): Function that loads the data into the state
3731
- const useHud = defineStore('hud', {
3732
- state: () => ({
3733
- hudStats: {},
3734
- }),
3735
- actions: {
3736
- setupHudStats(stats) {
3737
- for (const stat in stats) {
3738
- this.hudStats[stat] = {
3739
- value: stats[stat].startingValue,
3740
- };
3741
- }
3742
- },
3743
- setStat(stat, value) {
3744
- this.hudStats[stat].value = value;
3745
- },
3746
- addStat(stat, value) {
3747
- this.hudStats[stat].value += value;
3748
- },
3749
- generateSaveData() {
3750
- return {
3751
- hudStats: this.hudStats,
3752
- };
3753
- },
3754
- loadSaveData(data) {
3755
- this.hudStats = cjs(this.hudStats, data.hudStats);
3756
- },
3757
- },
3758
- });
3759
-
3760
- // Generate a pinia store named notifications with a state using the type NotificationsState, and save type NotificationsSave, with actions:
3761
- // addNotification(text: string): Adds a new notification to the state, and deletes it after a timeout
3762
- // deleteNotification(id: string): Deletes a notification from the state
3763
- const useNotifications = defineStore('notifications', {
3764
- state: () => ({ notifications: {} }),
3765
- actions: {
3766
- async addNotification(text) {
3767
- const id = `${Date.now()}-${Math.random() * 10000}`;
3768
- this.notifications[id] = {
3769
- text,
3770
- };
3771
- if (getConfig().notifications.alsoPrintInDialogue) {
3772
- writeText(`[NOTIFICATION] ${text}`);
3773
- }
3774
- await timeout(getConfig().notifications.timeOnScreen * 1000);
3775
- this.deleteNotification(id);
3776
- },
3777
- deleteNotification(id) {
3778
- delete this.notifications[id];
3779
- },
3780
- },
3781
- });
3782
-
3783
- // create a pinia store named inventory with a state containing items and actions to add and delete items
3784
- // create a pinia store named inventory with a state of type ItemState and actions to add and delete items. Adding items should increase the amount of any existing item that matches the id.
3785
- const useInventory = defineStore('inventory', {
3786
- state: () => ({
3787
- items: {},
3788
- }),
3789
- actions: {
3790
- generateSaveData() {
3791
- return {
3792
- items: this.items,
3793
- };
3794
- },
3795
- loadSaveData(save) {
3796
- this.items = { ...this.items, ...save.items };
3797
- },
3798
- setupItems(items) {
3799
- Object.keys(items).forEach((key) => {
3800
- this.items[key] = {
3801
- amount: 0,
3802
- id: key,
3803
- };
3804
- });
3805
- },
3806
- getExistingItem(id) {
3807
- return this.items[id];
3808
- },
3809
- getItemAmount(id) {
3810
- return this.getExistingItem(id)?.amount || 0;
3811
- },
3812
- add(item) {
3813
- const existingItem = this.getExistingItem(item.id);
3814
- if (existingItem) {
3815
- existingItem.amount += item.amount;
3816
- }
3817
- else {
3818
- this.items[item.id] = { ...item };
3819
- }
3820
- useNotifications().addNotification(`Received item: ${getItemConfig(item.id).name} x ${item.amount}`);
3821
- },
3822
- remove(item) {
3823
- const existingItem = this.getExistingItem(item.id);
3824
- if (existingItem) {
3825
- existingItem.amount -= item.amount;
3826
- useNotifications().addNotification(`Lost item: ${getItemConfig(item.id).name} x ${item.amount}`);
3827
- if (existingItem.amount <= 0) {
3828
- this.deleteItem(item.id);
3829
- }
3830
- }
3831
- },
3832
- deleteItem(id) {
3833
- const existingItem = this.getExistingItem(id);
3834
- if (existingItem) {
3835
- this.items[id].amount = 0;
3836
- }
3837
- },
3838
- },
3839
- });
3840
-
3841
3871
  // Create a pinia store named skills with a state using the type Skills, with actions:
3842
3872
  // setupSkillCheck(skillCheck: SkillCheckState, id: string)
3843
3873
  // passSkillCheck(skillCheckId: string)
@@ -3885,6 +3915,9 @@ const useSkills = defineStore('skills', {
3885
3915
  },
3886
3916
  addXp(skill, xp) {
3887
3917
  const skillData = this.skills[skill];
3918
+ if (!skillData) {
3919
+ error(`Skill ${skill} doesn't exist`);
3920
+ }
3888
3921
  skillData.xp += xp;
3889
3922
  if (skillData.xp >= getConfig().skillOptions.xpPerLevel) {
3890
3923
  skillData.xp = 0;
@@ -3925,101 +3958,6 @@ function getFile(url) {
3925
3958
  });
3926
3959
  }
3927
3960
 
3928
- const everyObject = (object, predicate) => {
3929
- for (const key in object) {
3930
- if (!predicate(object[key])) {
3931
- return false;
3932
- }
3933
- }
3934
- return true;
3935
- };
3936
- const filterObject = (object, predicate) => {
3937
- const result = {};
3938
- for (const key in object) {
3939
- if (predicate(object[key])) {
3940
- result[key] = object[key];
3941
- }
3942
- }
3943
- return result;
3944
- };
3945
-
3946
- const useQuests = defineStore('quests', {
3947
- state: () => ({
3948
- quests: {},
3949
- }),
3950
- actions: {
3951
- getQuest(questId) {
3952
- const quest = this.quests[questId];
3953
- if (quest) {
3954
- return quest;
3955
- }
3956
- error(`Quest ${questId} doesn't exist!`);
3957
- },
3958
- getObjective(quest, objectiveId) {
3959
- const questObjective = this.getQuest(quest).objectives[objectiveId];
3960
- if (questObjective) {
3961
- return questObjective;
3962
- }
3963
- error(`Objective ${objectiveId} doesn't exist in quest ${quest}!`);
3964
- },
3965
- setupQuests(quests) {
3966
- // iterate through quests to generate quest states to add to this.quests object
3967
- for (const key of Object.keys(quests)) {
3968
- const data = quests[key];
3969
- this.quests[key] = {
3970
- id: key,
3971
- state: 'hidden',
3972
- objectives: {},
3973
- };
3974
- // iterate through data.objectives to populate the objectives array of this.quests[key]
3975
- for (const objectiveKey of Object.keys(data.objectives)) {
3976
- const objective = data.objectives[objectiveKey];
3977
- this.quests[key].objectives[objectiveKey] = {
3978
- id: objectiveKey,
3979
- state: objective.hidden ? 'hidden' : 'unlocked',
3980
- };
3981
- }
3982
- }
3983
- },
3984
- startQuest(questId) {
3985
- this.getQuest(questId).state = 'unlocked';
3986
- useNotifications().addNotification(`Started quest: ${getQuestConfig(questId).title}`);
3987
- },
3988
- startObjective(questId, objectiveId) {
3989
- this.getObjective(questId, objectiveId).state = 'unlocked';
3990
- useNotifications().addNotification(`New quest objective: ${getObjectiveConfig(questId, objectiveId).description}`);
3991
- },
3992
- completeObjective(questId, objectiveId) {
3993
- this.getObjective(questId, objectiveId).state = 'completed';
3994
- useNotifications().addNotification(`Objective completed!`);
3995
- },
3996
- completeQuest(questId, ending) {
3997
- this.getQuest(questId).state = 'completed';
3998
- if (ending) {
3999
- this.getQuest(questId).ending = ending;
4000
- }
4001
- useNotifications().addNotification(`Quest completed: ${getQuestConfig(questId).title}`);
4002
- },
4003
- isQuestCompleted(questId) {
4004
- const quest = this.getQuest(questId);
4005
- return everyObject(quest.objectives, (objective) => objective.state === 'completed');
4006
- },
4007
- removeQuest(id) {
4008
- delete this.quests[id];
4009
- },
4010
- generateSaveData() {
4011
- return {
4012
- quests: {
4013
- ...this.quests,
4014
- },
4015
- };
4016
- },
4017
- loadSaveData(data) {
4018
- this.quests = data.quests;
4019
- },
4020
- },
4021
- });
4022
-
4023
3961
  // Create a pinia store named screens with a state using the type ScreenState, with actions:
4024
3962
  // setScreen(screen: string): Sets the current screen to the given screen
4025
3963
  // setButtons(buttons: { [key: string]: ButtonConfig }): Adds buttons to the buttons state by using the values in the buttons config object
@@ -4311,6 +4249,7 @@ const useVM = defineStore('vm', {
4311
4249
  data: {},
4312
4250
  lastLabel: 'main',
4313
4251
  script: {},
4252
+ labelStack: ['main'],
4314
4253
  }),
4315
4254
  actions: {
4316
4255
  generateSaveData() {
@@ -4427,6 +4366,19 @@ const useVM = defineStore('vm', {
4427
4366
  const cmd = this.currentLine;
4428
4367
  await runCommand(cmd);
4429
4368
  },
4369
+ async runLabelFunction(label) {
4370
+ const branch = this.script[label];
4371
+ if (!branch) {
4372
+ console.error(`Label ${branch} doesn't exist`);
4373
+ }
4374
+ const stack = {
4375
+ currentIndex: 0,
4376
+ branch: branch,
4377
+ label,
4378
+ };
4379
+ this.addStack(stack);
4380
+ await this.runLine();
4381
+ },
4430
4382
  runLabel(label) {
4431
4383
  const branch = this.script[label];
4432
4384
  if (!branch) {
@@ -4455,6 +4407,88 @@ const useVM = defineStore('vm', {
4455
4407
  },
4456
4408
  });
4457
4409
 
4410
+ function processText(text) {
4411
+ const vmStore = useVM();
4412
+ const skillStore = useSkills();
4413
+ return text.replace(/%{[^}]*}/g, (match) => {
4414
+ const key = match.substr(2, match.length - 3);
4415
+ const searchableState = {
4416
+ data: vmStore.data,
4417
+ skills: skillStore.skills,
4418
+ items: useInventory().items,
4419
+ quests: useQuests().quests,
4420
+ };
4421
+ const [obj, newKey] = findDataHelper(searchableState, key);
4422
+ return obj[newKey];
4423
+ });
4424
+ }
4425
+
4426
+ // Create a pinia store named dialog with a state using the type DialogState, with actions addDialog and clearDialog
4427
+ const useDialogStore = defineStore('dialog', {
4428
+ state: () => ({
4429
+ dialog: [],
4430
+ }),
4431
+ actions: {
4432
+ generateSaveData() {
4433
+ return {
4434
+ dialog: this.dialog,
4435
+ };
4436
+ },
4437
+ loadSaveData(data) {
4438
+ this.dialog = data.dialog;
4439
+ },
4440
+ addDialog(dialog) {
4441
+ this.dialog.push({
4442
+ ...dialog,
4443
+ interactive: dialog.interactive ?? false,
4444
+ id: randomId(),
4445
+ text: processText(dialog.text),
4446
+ });
4447
+ },
4448
+ clearDialog() {
4449
+ this.dialog.splice(0, this.dialog.length);
4450
+ },
4451
+ reset() {
4452
+ this.dialog = [];
4453
+ },
4454
+ },
4455
+ });
4456
+
4457
+ // Create a pinia store named hud with a state using the type HudState, and save type HudSave, with actions:
4458
+ // setupHudStats(stats: { [key: string]: HudStatConfig }): Iterates the stats argument to add new stats to the state
4459
+ // setStat(stat: string, value: number): Sets the value of a stat
4460
+ // addStat(stat: string, value: number): Adds a value to a stat
4461
+ // generateSaveData(): Function that generates a HudSave object from the data in the state
4462
+ // loadSaveData(data: HudSave): Function that loads the data into the state
4463
+ const useHud = defineStore('hud', {
4464
+ state: () => ({
4465
+ hudStats: {},
4466
+ }),
4467
+ actions: {
4468
+ setupHudStats(stats) {
4469
+ for (const stat in stats) {
4470
+ this.hudStats[stat] = {
4471
+ value: stats[stat].startingValue,
4472
+ };
4473
+ }
4474
+ },
4475
+ setStat(stat, value) {
4476
+ this.hudStats[stat].value = value;
4477
+ },
4478
+ addStat(stat, value) {
4479
+ this.hudStats[stat].value += value;
4480
+ },
4481
+ generateSaveData() {
4482
+ return {
4483
+ hudStats: this.hudStats,
4484
+ };
4485
+ },
4486
+ loadSaveData(data) {
4487
+ this.hudStats = cjs(this.hudStats, data.hudStats);
4488
+ },
4489
+ },
4490
+ });
4491
+
4458
4492
  function createSkillCheckState() {
4459
4493
  const skillCheck = {
4460
4494
  passed: false,
@@ -7722,22 +7756,6 @@ styleInject(css_248z$8);
7722
7756
 
7723
7757
  script$7.render = render$7;
7724
7758
 
7725
- function processText(text) {
7726
- const vmStore = useVM();
7727
- const skillStore = useSkills();
7728
- return text.replace(/%{[^}]*}/g, (match) => {
7729
- const key = match.substr(2, match.length - 3);
7730
- const searchableState = {
7731
- data: vmStore.data,
7732
- skills: skillStore.skills,
7733
- items: useInventory().items,
7734
- quests: useQuests().quests,
7735
- };
7736
- const [obj, newKey] = findDataHelper(searchableState, key);
7737
- return obj[newKey];
7738
- });
7739
- }
7740
-
7741
7759
  function aspectRatioFit(screenWidth, screenHeight, gameWidth, gameHeight) {
7742
7760
  const widthRatio = screenWidth / gameWidth;
7743
7761
  const heightRatio = screenHeight / gameHeight;
@@ -8719,7 +8737,7 @@ var script$d = defineComponent({
8719
8737
  }
8720
8738
  return {
8721
8739
  title,
8722
- text: processText(dialogKey.text),
8740
+ text: dialogKey.text,
8723
8741
  styleId: dialogKey.speaker,
8724
8742
  choices: dialogKey.choices,
8725
8743
  old: index < this.dialog.length - 1,
@@ -9439,6 +9457,15 @@ const completeQuestPlugin = new CommandPlugin('complete_quest', async (cmd) => {
9439
9457
  return useVM().nextLine();
9440
9458
  }, generateParser('complete_quest'));
9441
9459
 
9460
+ // Write a CommandPlugin for running a label using the runLabelFunction of the useVM store
9461
+ const runLabelPlugin = new CommandPlugin('run_label', async (cmd) => {
9462
+ const label = cmd.args[0];
9463
+ if (!label) {
9464
+ error(`run_label command needs a label to argument run`);
9465
+ }
9466
+ await useVM().runLabelFunction(label);
9467
+ }, generateParser('run_label'));
9468
+
9442
9469
  function registerBaseCommands(vm) {
9443
9470
  vm.addCommand(addItemPlugin);
9444
9471
  vm.addCommand(addLevelPlugin);
@@ -9461,6 +9488,9 @@ function registerBaseCommands(vm) {
9461
9488
  vm.addCommand(talkCommand);
9462
9489
  vm.addCommand(textCommandPlugin);
9463
9490
  vm.addCommand(waitCommand);
9491
+ // functions and labels
9492
+ vm.addCommand(jumpCommand);
9493
+ vm.addCommand(runLabelPlugin);
9464
9494
  // Quests
9465
9495
  vm.addCommand(startQuestPlugin);
9466
9496
  vm.addCommand(startObjectivePlugin);
@@ -9508,7 +9538,7 @@ async function startApp(config, options) {
9508
9538
  });
9509
9539
  registerBaseCommands(vm);
9510
9540
  logManager.setupDebugger(options.debug);
9511
- console.log('%c Narrat game engine – 1.2.1 - June 25, 2022 14:20:12', 'background: #222; color: #bada55');
9541
+ console.log('%c Narrat game engine – 1.3.0 - June 25, 2022 18:05:43', 'background: #222; color: #bada55');
9512
9542
  vm.callHook('onNarratSetup');
9513
9543
  app.mount('#game-holder');
9514
9544
  if (options.debug) {
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // Version: 1.2.1 - June 25, 2022 14:20:12
1
+ // Version: 1.3.0 - June 25, 2022 18:05:43
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -3564,32 +3564,178 @@ function randomId() {
3564
3564
  return `${Date.now() - Math.floor(Math.random() * 99999999)}`;
3565
3565
  }
3566
3566
 
3567
- // Create a pinia store named dialog with a state using the type DialogState, with actions addDialog and clearDialog
3568
- const useDialogStore = pinia.defineStore('dialog', {
3567
+ // Generate a pinia store named notifications with a state using the type NotificationsState, and save type NotificationsSave, with actions:
3568
+ // addNotification(text: string): Adds a new notification to the state, and deletes it after a timeout
3569
+ // deleteNotification(id: string): Deletes a notification from the state
3570
+ const useNotifications = pinia.defineStore('notifications', {
3571
+ state: () => ({ notifications: {} }),
3572
+ actions: {
3573
+ async addNotification(text) {
3574
+ const id = `${Date.now()}-${Math.random() * 10000}`;
3575
+ this.notifications[id] = {
3576
+ text,
3577
+ };
3578
+ if (getConfig().notifications.alsoPrintInDialogue) {
3579
+ writeText(`[NOTIFICATION] ${text}`);
3580
+ }
3581
+ await timeout(getConfig().notifications.timeOnScreen * 1000);
3582
+ this.deleteNotification(id);
3583
+ },
3584
+ deleteNotification(id) {
3585
+ delete this.notifications[id];
3586
+ },
3587
+ },
3588
+ });
3589
+
3590
+ // create a pinia store named inventory with a state containing items and actions to add and delete items
3591
+ // create a pinia store named inventory with a state of type ItemState and actions to add and delete items. Adding items should increase the amount of any existing item that matches the id.
3592
+ const useInventory = pinia.defineStore('inventory', {
3569
3593
  state: () => ({
3570
- dialog: [],
3594
+ items: {},
3571
3595
  }),
3572
3596
  actions: {
3573
3597
  generateSaveData() {
3574
3598
  return {
3575
- dialog: this.dialog,
3599
+ items: this.items,
3576
3600
  };
3577
3601
  },
3578
- loadSaveData(data) {
3579
- this.dialog = data.dialog;
3602
+ loadSaveData(save) {
3603
+ this.items = { ...this.items, ...save.items };
3580
3604
  },
3581
- addDialog(dialog) {
3582
- this.dialog.push({
3583
- ...dialog,
3584
- interactive: dialog.interactive ?? false,
3585
- id: randomId(),
3605
+ setupItems(items) {
3606
+ Object.keys(items).forEach((key) => {
3607
+ this.items[key] = {
3608
+ amount: 0,
3609
+ id: key,
3610
+ };
3586
3611
  });
3587
3612
  },
3588
- clearDialog() {
3589
- this.dialog.splice(0, this.dialog.length);
3613
+ getExistingItem(id) {
3614
+ return this.items[id];
3590
3615
  },
3591
- reset() {
3592
- this.dialog = [];
3616
+ getItemAmount(id) {
3617
+ return this.getExistingItem(id)?.amount || 0;
3618
+ },
3619
+ add(item) {
3620
+ const existingItem = this.getExistingItem(item.id);
3621
+ if (existingItem) {
3622
+ existingItem.amount += item.amount;
3623
+ }
3624
+ else {
3625
+ this.items[item.id] = { ...item };
3626
+ }
3627
+ useNotifications().addNotification(`Received item: ${getItemConfig(item.id).name} x ${item.amount}`);
3628
+ },
3629
+ remove(item) {
3630
+ const existingItem = this.getExistingItem(item.id);
3631
+ if (existingItem) {
3632
+ existingItem.amount -= item.amount;
3633
+ useNotifications().addNotification(`Lost item: ${getItemConfig(item.id).name} x ${item.amount}`);
3634
+ if (existingItem.amount <= 0) {
3635
+ this.deleteItem(item.id);
3636
+ }
3637
+ }
3638
+ },
3639
+ deleteItem(id) {
3640
+ const existingItem = this.getExistingItem(id);
3641
+ if (existingItem) {
3642
+ this.items[id].amount = 0;
3643
+ }
3644
+ },
3645
+ },
3646
+ });
3647
+
3648
+ const everyObject = (object, predicate) => {
3649
+ for (const key in object) {
3650
+ if (!predicate(object[key])) {
3651
+ return false;
3652
+ }
3653
+ }
3654
+ return true;
3655
+ };
3656
+ const filterObject = (object, predicate) => {
3657
+ const result = {};
3658
+ for (const key in object) {
3659
+ if (predicate(object[key])) {
3660
+ result[key] = object[key];
3661
+ }
3662
+ }
3663
+ return result;
3664
+ };
3665
+
3666
+ const useQuests = pinia.defineStore('quests', {
3667
+ state: () => ({
3668
+ quests: {},
3669
+ }),
3670
+ actions: {
3671
+ getQuest(questId) {
3672
+ const quest = this.quests[questId];
3673
+ if (quest) {
3674
+ return quest;
3675
+ }
3676
+ error(`Quest ${questId} doesn't exist!`);
3677
+ },
3678
+ getObjective(quest, objectiveId) {
3679
+ const questObjective = this.getQuest(quest).objectives[objectiveId];
3680
+ if (questObjective) {
3681
+ return questObjective;
3682
+ }
3683
+ error(`Objective ${objectiveId} doesn't exist in quest ${quest}!`);
3684
+ },
3685
+ setupQuests(quests) {
3686
+ // iterate through quests to generate quest states to add to this.quests object
3687
+ for (const key of Object.keys(quests)) {
3688
+ const data = quests[key];
3689
+ this.quests[key] = {
3690
+ id: key,
3691
+ state: 'hidden',
3692
+ objectives: {},
3693
+ };
3694
+ // iterate through data.objectives to populate the objectives array of this.quests[key]
3695
+ for (const objectiveKey of Object.keys(data.objectives)) {
3696
+ const objective = data.objectives[objectiveKey];
3697
+ this.quests[key].objectives[objectiveKey] = {
3698
+ id: objectiveKey,
3699
+ state: objective.hidden ? 'hidden' : 'unlocked',
3700
+ };
3701
+ }
3702
+ }
3703
+ },
3704
+ startQuest(questId) {
3705
+ this.getQuest(questId).state = 'unlocked';
3706
+ useNotifications().addNotification(`Started quest: ${getQuestConfig(questId).title}`);
3707
+ },
3708
+ startObjective(questId, objectiveId) {
3709
+ this.getObjective(questId, objectiveId).state = 'unlocked';
3710
+ useNotifications().addNotification(`New quest objective: ${getObjectiveConfig(questId, objectiveId).description}`);
3711
+ },
3712
+ completeObjective(questId, objectiveId) {
3713
+ this.getObjective(questId, objectiveId).state = 'completed';
3714
+ useNotifications().addNotification(`Objective completed!`);
3715
+ },
3716
+ completeQuest(questId, ending) {
3717
+ this.getQuest(questId).state = 'completed';
3718
+ if (ending) {
3719
+ this.getQuest(questId).ending = ending;
3720
+ }
3721
+ useNotifications().addNotification(`Quest completed: ${getQuestConfig(questId).title}`);
3722
+ },
3723
+ isQuestCompleted(questId) {
3724
+ const quest = this.getQuest(questId);
3725
+ return everyObject(quest.objectives, (objective) => objective.state === 'completed');
3726
+ },
3727
+ removeQuest(id) {
3728
+ delete this.quests[id];
3729
+ },
3730
+ generateSaveData() {
3731
+ return {
3732
+ quests: {
3733
+ ...this.quests,
3734
+ },
3735
+ };
3736
+ },
3737
+ loadSaveData(data) {
3738
+ this.quests = data.quests;
3593
3739
  },
3594
3740
  },
3595
3741
  });
@@ -3726,122 +3872,6 @@ var deepmerge_1 = deepmerge;
3726
3872
 
3727
3873
  var cjs = deepmerge_1;
3728
3874
 
3729
- // Create a pinia store named hud with a state using the type HudState, and save type HudSave, with actions:
3730
- // setupHudStats(stats: { [key: string]: HudStatConfig }): Iterates the stats argument to add new stats to the state
3731
- // setStat(stat: string, value: number): Sets the value of a stat
3732
- // addStat(stat: string, value: number): Adds a value to a stat
3733
- // generateSaveData(): Function that generates a HudSave object from the data in the state
3734
- // loadSaveData(data: HudSave): Function that loads the data into the state
3735
- const useHud = pinia.defineStore('hud', {
3736
- state: () => ({
3737
- hudStats: {},
3738
- }),
3739
- actions: {
3740
- setupHudStats(stats) {
3741
- for (const stat in stats) {
3742
- this.hudStats[stat] = {
3743
- value: stats[stat].startingValue,
3744
- };
3745
- }
3746
- },
3747
- setStat(stat, value) {
3748
- this.hudStats[stat].value = value;
3749
- },
3750
- addStat(stat, value) {
3751
- this.hudStats[stat].value += value;
3752
- },
3753
- generateSaveData() {
3754
- return {
3755
- hudStats: this.hudStats,
3756
- };
3757
- },
3758
- loadSaveData(data) {
3759
- this.hudStats = cjs(this.hudStats, data.hudStats);
3760
- },
3761
- },
3762
- });
3763
-
3764
- // Generate a pinia store named notifications with a state using the type NotificationsState, and save type NotificationsSave, with actions:
3765
- // addNotification(text: string): Adds a new notification to the state, and deletes it after a timeout
3766
- // deleteNotification(id: string): Deletes a notification from the state
3767
- const useNotifications = pinia.defineStore('notifications', {
3768
- state: () => ({ notifications: {} }),
3769
- actions: {
3770
- async addNotification(text) {
3771
- const id = `${Date.now()}-${Math.random() * 10000}`;
3772
- this.notifications[id] = {
3773
- text,
3774
- };
3775
- if (getConfig().notifications.alsoPrintInDialogue) {
3776
- writeText(`[NOTIFICATION] ${text}`);
3777
- }
3778
- await timeout(getConfig().notifications.timeOnScreen * 1000);
3779
- this.deleteNotification(id);
3780
- },
3781
- deleteNotification(id) {
3782
- delete this.notifications[id];
3783
- },
3784
- },
3785
- });
3786
-
3787
- // create a pinia store named inventory with a state containing items and actions to add and delete items
3788
- // create a pinia store named inventory with a state of type ItemState and actions to add and delete items. Adding items should increase the amount of any existing item that matches the id.
3789
- const useInventory = pinia.defineStore('inventory', {
3790
- state: () => ({
3791
- items: {},
3792
- }),
3793
- actions: {
3794
- generateSaveData() {
3795
- return {
3796
- items: this.items,
3797
- };
3798
- },
3799
- loadSaveData(save) {
3800
- this.items = { ...this.items, ...save.items };
3801
- },
3802
- setupItems(items) {
3803
- Object.keys(items).forEach((key) => {
3804
- this.items[key] = {
3805
- amount: 0,
3806
- id: key,
3807
- };
3808
- });
3809
- },
3810
- getExistingItem(id) {
3811
- return this.items[id];
3812
- },
3813
- getItemAmount(id) {
3814
- return this.getExistingItem(id)?.amount || 0;
3815
- },
3816
- add(item) {
3817
- const existingItem = this.getExistingItem(item.id);
3818
- if (existingItem) {
3819
- existingItem.amount += item.amount;
3820
- }
3821
- else {
3822
- this.items[item.id] = { ...item };
3823
- }
3824
- useNotifications().addNotification(`Received item: ${getItemConfig(item.id).name} x ${item.amount}`);
3825
- },
3826
- remove(item) {
3827
- const existingItem = this.getExistingItem(item.id);
3828
- if (existingItem) {
3829
- existingItem.amount -= item.amount;
3830
- useNotifications().addNotification(`Lost item: ${getItemConfig(item.id).name} x ${item.amount}`);
3831
- if (existingItem.amount <= 0) {
3832
- this.deleteItem(item.id);
3833
- }
3834
- }
3835
- },
3836
- deleteItem(id) {
3837
- const existingItem = this.getExistingItem(id);
3838
- if (existingItem) {
3839
- this.items[id].amount = 0;
3840
- }
3841
- },
3842
- },
3843
- });
3844
-
3845
3875
  // Create a pinia store named skills with a state using the type Skills, with actions:
3846
3876
  // setupSkillCheck(skillCheck: SkillCheckState, id: string)
3847
3877
  // passSkillCheck(skillCheckId: string)
@@ -3889,6 +3919,9 @@ const useSkills = pinia.defineStore('skills', {
3889
3919
  },
3890
3920
  addXp(skill, xp) {
3891
3921
  const skillData = this.skills[skill];
3922
+ if (!skillData) {
3923
+ error(`Skill ${skill} doesn't exist`);
3924
+ }
3892
3925
  skillData.xp += xp;
3893
3926
  if (skillData.xp >= getConfig().skillOptions.xpPerLevel) {
3894
3927
  skillData.xp = 0;
@@ -3929,101 +3962,6 @@ function getFile(url) {
3929
3962
  });
3930
3963
  }
3931
3964
 
3932
- const everyObject = (object, predicate) => {
3933
- for (const key in object) {
3934
- if (!predicate(object[key])) {
3935
- return false;
3936
- }
3937
- }
3938
- return true;
3939
- };
3940
- const filterObject = (object, predicate) => {
3941
- const result = {};
3942
- for (const key in object) {
3943
- if (predicate(object[key])) {
3944
- result[key] = object[key];
3945
- }
3946
- }
3947
- return result;
3948
- };
3949
-
3950
- const useQuests = pinia.defineStore('quests', {
3951
- state: () => ({
3952
- quests: {},
3953
- }),
3954
- actions: {
3955
- getQuest(questId) {
3956
- const quest = this.quests[questId];
3957
- if (quest) {
3958
- return quest;
3959
- }
3960
- error(`Quest ${questId} doesn't exist!`);
3961
- },
3962
- getObjective(quest, objectiveId) {
3963
- const questObjective = this.getQuest(quest).objectives[objectiveId];
3964
- if (questObjective) {
3965
- return questObjective;
3966
- }
3967
- error(`Objective ${objectiveId} doesn't exist in quest ${quest}!`);
3968
- },
3969
- setupQuests(quests) {
3970
- // iterate through quests to generate quest states to add to this.quests object
3971
- for (const key of Object.keys(quests)) {
3972
- const data = quests[key];
3973
- this.quests[key] = {
3974
- id: key,
3975
- state: 'hidden',
3976
- objectives: {},
3977
- };
3978
- // iterate through data.objectives to populate the objectives array of this.quests[key]
3979
- for (const objectiveKey of Object.keys(data.objectives)) {
3980
- const objective = data.objectives[objectiveKey];
3981
- this.quests[key].objectives[objectiveKey] = {
3982
- id: objectiveKey,
3983
- state: objective.hidden ? 'hidden' : 'unlocked',
3984
- };
3985
- }
3986
- }
3987
- },
3988
- startQuest(questId) {
3989
- this.getQuest(questId).state = 'unlocked';
3990
- useNotifications().addNotification(`Started quest: ${getQuestConfig(questId).title}`);
3991
- },
3992
- startObjective(questId, objectiveId) {
3993
- this.getObjective(questId, objectiveId).state = 'unlocked';
3994
- useNotifications().addNotification(`New quest objective: ${getObjectiveConfig(questId, objectiveId).description}`);
3995
- },
3996
- completeObjective(questId, objectiveId) {
3997
- this.getObjective(questId, objectiveId).state = 'completed';
3998
- useNotifications().addNotification(`Objective completed!`);
3999
- },
4000
- completeQuest(questId, ending) {
4001
- this.getQuest(questId).state = 'completed';
4002
- if (ending) {
4003
- this.getQuest(questId).ending = ending;
4004
- }
4005
- useNotifications().addNotification(`Quest completed: ${getQuestConfig(questId).title}`);
4006
- },
4007
- isQuestCompleted(questId) {
4008
- const quest = this.getQuest(questId);
4009
- return everyObject(quest.objectives, (objective) => objective.state === 'completed');
4010
- },
4011
- removeQuest(id) {
4012
- delete this.quests[id];
4013
- },
4014
- generateSaveData() {
4015
- return {
4016
- quests: {
4017
- ...this.quests,
4018
- },
4019
- };
4020
- },
4021
- loadSaveData(data) {
4022
- this.quests = data.quests;
4023
- },
4024
- },
4025
- });
4026
-
4027
3965
  // Create a pinia store named screens with a state using the type ScreenState, with actions:
4028
3966
  // setScreen(screen: string): Sets the current screen to the given screen
4029
3967
  // setButtons(buttons: { [key: string]: ButtonConfig }): Adds buttons to the buttons state by using the values in the buttons config object
@@ -4315,6 +4253,7 @@ const useVM = pinia.defineStore('vm', {
4315
4253
  data: {},
4316
4254
  lastLabel: 'main',
4317
4255
  script: {},
4256
+ labelStack: ['main'],
4318
4257
  }),
4319
4258
  actions: {
4320
4259
  generateSaveData() {
@@ -4431,6 +4370,19 @@ const useVM = pinia.defineStore('vm', {
4431
4370
  const cmd = this.currentLine;
4432
4371
  await runCommand(cmd);
4433
4372
  },
4373
+ async runLabelFunction(label) {
4374
+ const branch = this.script[label];
4375
+ if (!branch) {
4376
+ console.error(`Label ${branch} doesn't exist`);
4377
+ }
4378
+ const stack = {
4379
+ currentIndex: 0,
4380
+ branch: branch,
4381
+ label,
4382
+ };
4383
+ this.addStack(stack);
4384
+ await this.runLine();
4385
+ },
4434
4386
  runLabel(label) {
4435
4387
  const branch = this.script[label];
4436
4388
  if (!branch) {
@@ -4459,6 +4411,88 @@ const useVM = pinia.defineStore('vm', {
4459
4411
  },
4460
4412
  });
4461
4413
 
4414
+ function processText(text) {
4415
+ const vmStore = useVM();
4416
+ const skillStore = useSkills();
4417
+ return text.replace(/%{[^}]*}/g, (match) => {
4418
+ const key = match.substr(2, match.length - 3);
4419
+ const searchableState = {
4420
+ data: vmStore.data,
4421
+ skills: skillStore.skills,
4422
+ items: useInventory().items,
4423
+ quests: useQuests().quests,
4424
+ };
4425
+ const [obj, newKey] = findDataHelper(searchableState, key);
4426
+ return obj[newKey];
4427
+ });
4428
+ }
4429
+
4430
+ // Create a pinia store named dialog with a state using the type DialogState, with actions addDialog and clearDialog
4431
+ const useDialogStore = pinia.defineStore('dialog', {
4432
+ state: () => ({
4433
+ dialog: [],
4434
+ }),
4435
+ actions: {
4436
+ generateSaveData() {
4437
+ return {
4438
+ dialog: this.dialog,
4439
+ };
4440
+ },
4441
+ loadSaveData(data) {
4442
+ this.dialog = data.dialog;
4443
+ },
4444
+ addDialog(dialog) {
4445
+ this.dialog.push({
4446
+ ...dialog,
4447
+ interactive: dialog.interactive ?? false,
4448
+ id: randomId(),
4449
+ text: processText(dialog.text),
4450
+ });
4451
+ },
4452
+ clearDialog() {
4453
+ this.dialog.splice(0, this.dialog.length);
4454
+ },
4455
+ reset() {
4456
+ this.dialog = [];
4457
+ },
4458
+ },
4459
+ });
4460
+
4461
+ // Create a pinia store named hud with a state using the type HudState, and save type HudSave, with actions:
4462
+ // setupHudStats(stats: { [key: string]: HudStatConfig }): Iterates the stats argument to add new stats to the state
4463
+ // setStat(stat: string, value: number): Sets the value of a stat
4464
+ // addStat(stat: string, value: number): Adds a value to a stat
4465
+ // generateSaveData(): Function that generates a HudSave object from the data in the state
4466
+ // loadSaveData(data: HudSave): Function that loads the data into the state
4467
+ const useHud = pinia.defineStore('hud', {
4468
+ state: () => ({
4469
+ hudStats: {},
4470
+ }),
4471
+ actions: {
4472
+ setupHudStats(stats) {
4473
+ for (const stat in stats) {
4474
+ this.hudStats[stat] = {
4475
+ value: stats[stat].startingValue,
4476
+ };
4477
+ }
4478
+ },
4479
+ setStat(stat, value) {
4480
+ this.hudStats[stat].value = value;
4481
+ },
4482
+ addStat(stat, value) {
4483
+ this.hudStats[stat].value += value;
4484
+ },
4485
+ generateSaveData() {
4486
+ return {
4487
+ hudStats: this.hudStats,
4488
+ };
4489
+ },
4490
+ loadSaveData(data) {
4491
+ this.hudStats = cjs(this.hudStats, data.hudStats);
4492
+ },
4493
+ },
4494
+ });
4495
+
4462
4496
  function createSkillCheckState() {
4463
4497
  const skillCheck = {
4464
4498
  passed: false,
@@ -7726,22 +7760,6 @@ styleInject(css_248z$8);
7726
7760
 
7727
7761
  script$7.render = render$7;
7728
7762
 
7729
- function processText(text) {
7730
- const vmStore = useVM();
7731
- const skillStore = useSkills();
7732
- return text.replace(/%{[^}]*}/g, (match) => {
7733
- const key = match.substr(2, match.length - 3);
7734
- const searchableState = {
7735
- data: vmStore.data,
7736
- skills: skillStore.skills,
7737
- items: useInventory().items,
7738
- quests: useQuests().quests,
7739
- };
7740
- const [obj, newKey] = findDataHelper(searchableState, key);
7741
- return obj[newKey];
7742
- });
7743
- }
7744
-
7745
7763
  function aspectRatioFit(screenWidth, screenHeight, gameWidth, gameHeight) {
7746
7764
  const widthRatio = screenWidth / gameWidth;
7747
7765
  const heightRatio = screenHeight / gameHeight;
@@ -8723,7 +8741,7 @@ var script$d = vue.defineComponent({
8723
8741
  }
8724
8742
  return {
8725
8743
  title,
8726
- text: processText(dialogKey.text),
8744
+ text: dialogKey.text,
8727
8745
  styleId: dialogKey.speaker,
8728
8746
  choices: dialogKey.choices,
8729
8747
  old: index < this.dialog.length - 1,
@@ -9443,6 +9461,15 @@ const completeQuestPlugin = new CommandPlugin('complete_quest', async (cmd) => {
9443
9461
  return useVM().nextLine();
9444
9462
  }, generateParser('complete_quest'));
9445
9463
 
9464
+ // Write a CommandPlugin for running a label using the runLabelFunction of the useVM store
9465
+ const runLabelPlugin = new CommandPlugin('run_label', async (cmd) => {
9466
+ const label = cmd.args[0];
9467
+ if (!label) {
9468
+ error(`run_label command needs a label to argument run`);
9469
+ }
9470
+ await useVM().runLabelFunction(label);
9471
+ }, generateParser('run_label'));
9472
+
9446
9473
  function registerBaseCommands(vm) {
9447
9474
  vm.addCommand(addItemPlugin);
9448
9475
  vm.addCommand(addLevelPlugin);
@@ -9465,6 +9492,9 @@ function registerBaseCommands(vm) {
9465
9492
  vm.addCommand(talkCommand);
9466
9493
  vm.addCommand(textCommandPlugin);
9467
9494
  vm.addCommand(waitCommand);
9495
+ // functions and labels
9496
+ vm.addCommand(jumpCommand);
9497
+ vm.addCommand(runLabelPlugin);
9468
9498
  // Quests
9469
9499
  vm.addCommand(startQuestPlugin);
9470
9500
  vm.addCommand(startObjectivePlugin);
@@ -9512,7 +9542,7 @@ async function startApp(config, options) {
9512
9542
  });
9513
9543
  registerBaseCommands(vm);
9514
9544
  logManager.setupDebugger(options.debug);
9515
- console.log('%c Narrat game engine – 1.2.1 - June 25, 2022 14:20:12', 'background: #222; color: #bada55');
9545
+ console.log('%c Narrat game engine – 1.3.0 - June 25, 2022 18:05:43', 'background: #222; color: #bada55');
9516
9546
  vm.callHook('onNarratSetup');
9517
9547
  app.mount('#game-holder');
9518
9548
  if (options.debug) {
@@ -227,6 +227,7 @@ export declare const useMain: import("pinia").StoreDefinition<"main", MainState,
227
227
  previousStack(): void;
228
228
  finishGame(): void;
229
229
  runLine(): Promise<void>;
230
+ runLabelFunction(label: string): Promise<void>;
230
231
  runLabel(label: string): void;
231
232
  }>;
232
233
  hud: import("pinia").Store<"hud", import("./hud-stats-store").HudState, {}, {
@@ -147,5 +147,6 @@ export declare const useVM: import("pinia").StoreDefinition<"vm", VMState, {
147
147
  previousStack(): void;
148
148
  finishGame(): void;
149
149
  runLine(): Promise<void>;
150
+ runLabelFunction(label: string): Promise<void>;
150
151
  runLabel(label: string): void;
151
152
  }>;
@@ -0,0 +1,2 @@
1
+ import { CommandPlugin } from './command-plugin';
2
+ export declare const runLabelPlugin: CommandPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "narrat",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "narrat narrative engine",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.esm.js",