dcl-npc-toolkit 1.0.10-20230523134956.commit-0a9ee1c → 1.0.10-20230523140244.commit-fbf44ee

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/README.md CHANGED
@@ -1,1098 +1,1950 @@
1
1
 
2
2
 
3
3
 
4
+
5
+
4
6
  # NPC-library
5
7
 
6
8
 
7
9
 
10
+
11
+
8
12
  A collection of tools for creating Non-Player-Characters (NPCs). These are capable of having conversations with the player, and play different animations.
9
13
 
10
14
 
11
15
 
16
+
17
+
12
18
  Capabilities of the NPCs in this library:
13
19
 
14
20
 
15
21
 
22
+
23
+
16
24
  - Start a conversation when clicked or when walking near
17
25
 
26
+
27
+
18
28
  - Trigger any action when clicked or when walking near
19
29
 
30
+
31
+
20
32
  - Trigger any action when the player walks away
21
33
 
34
+
35
+
22
36
  - Turn around slowly to always face the player
23
37
 
38
+
39
+
24
40
  - Play an animation in the NPC 3d model, optionally returning to loop the idle animation afterwards
25
41
 
26
42
 
27
43
 
44
+
45
+
28
46
  The dialog messages can also require that the player chooses options, and any action can be triggered when the player picks an option or advances past a message.
29
47
 
30
48
 
31
49
 
50
+
51
+
32
52
  To use NPCs in your scene:
33
53
 
34
54
 
35
55
 
56
+
57
+
36
58
  1. Install the library as an npm bundle. Run this command in your scene's project folder:
37
59
 
38
60
 
39
61
 
62
+
63
+
40
64
  ```
41
65
 
66
+
67
+
42
68
  npm i dcl-npc-toolkit -B
43
69
 
70
+
71
+
44
72
  ```
45
73
 
74
+
75
+
46
76
  2. Install the dependent sdk utils library as an npm bundle. Run this command in your scene's project folder:
47
77
 
48
78
 
49
79
 
80
+
81
+
50
82
  ```
51
83
 
84
+
85
+
52
86
  npm i @dcl-sdk/utils -B
53
87
 
88
+
89
+
54
90
  ```
91
+
55
92
 
56
93
 
57
94
  3. Run `dcl start` or `dcl build` so the dependencies are correctly installed.
58
95
 
59
96
 
60
97
 
98
+
99
+
61
100
  4. Import the library into the scene's script. Add this line at the start of your `game.ts` file, or any other TypeScript files that require it:
62
101
 
63
102
 
64
103
 
104
+
105
+
65
106
  ```ts
66
107
 
108
+
109
+
67
110
  import * as npc from 'dcl-npc-toolkit'
68
111
 
112
+
113
+
69
114
  ```
70
115
 
71
116
 
72
117
 
118
+
119
+
73
120
  5. In your TypeScript file, call the `create` function passing it a `TransformType` and a `NPCData` object. The `NPCData` object requires a minimum of a `NPCType` and a function to trigger when the NPC is activated:
74
121
 
75
122
 
76
123
 
124
+
125
+
77
126
  ```ts
78
127
 
128
+
129
+
79
130
  export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
80
131
 
132
+
133
+
81
134
  //NPC Data Object
82
135
 
136
+
137
+
83
138
  {
84
139
 
140
+
141
+
85
142
  type: npc.NPCType.CUSTOM,
86
143
 
144
+
145
+
87
146
  model: 'models/npc.glb',
88
147
 
148
+
149
+
89
150
  onActivate:()=>{console.log('npc activated');}
90
151
 
152
+
153
+
91
154
  }
92
155
 
156
+
157
+
93
158
  )
94
159
 
160
+
161
+
95
162
  ```
96
163
 
97
164
 
98
165
 
166
+
167
+
99
168
  5. Write a dialog script for your character, preferably on a separate file, making it of type `Dialog[]`.
100
169
 
101
170
 
102
171
 
172
+
173
+
103
174
  ```ts
104
175
 
176
+
177
+
105
178
  import { Dialog } from 'dcl-npc-toolkit'
106
179
 
107
180
 
108
181
 
182
+
183
+
109
184
  export let ILoveCats: Dialog[] = [
110
185
 
186
+
187
+
111
188
  {
112
189
 
190
+
191
+
113
192
  text: `I really lo-ove cats`,
114
193
 
194
+
195
+
115
196
  isEndOfDialog: true
116
197
 
198
+
199
+
117
200
  }
118
201
 
202
+
203
+
119
204
  ]
120
205
 
206
+
207
+
121
208
  ```
122
209
 
123
210
 
124
211
 
212
+
213
+
125
214
  ## NPC Default Behavior
126
215
 
127
216
 
128
217
 
218
+
219
+
129
220
  NPCs at the very least must have:
130
221
 
131
222
 
132
223
 
224
+
225
+
133
226
  - `position`: (_TransformType_) Must include position, rotation and scale.
134
227
 
228
+
229
+
135
230
  - `NPCData`: (_Data Object_) with a minimum of two variables
136
231
 
232
+
233
+
137
234
  - `type`: (_NPCType_) you have the choice to use a custom GLB object or an `AvatarShape` for your npc
138
235
 
236
+
237
+
139
238
  - `NPCType.CUSTOM`
140
239
 
240
+
241
+
141
242
  - `NPCType.AVATAR`
142
243
 
244
+
245
+
143
246
  - `onActivate()`: (_()=> void_) A function to call when the NPC is activated.
144
247
 
145
248
 
146
249
 
250
+
251
+
147
252
  *if you decide to use a `NPCType.CUSTOM` GLB model for your avatar, you must pass in a model object inside the `NPCData`*
148
253
 
254
+
255
+
149
256
  - `model`: (_string_) The path to a 3D model
150
257
 
151
258
 
152
259
 
260
+
261
+
153
262
  ```ts
154
263
 
264
+
265
+
155
266
  export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
156
267
 
268
+
269
+
157
270
  //NPC Data Object
158
271
 
272
+
273
+
159
274
  {
160
275
 
276
+
277
+
161
278
  type: npc.NPCType.CUSTOM,
162
279
 
280
+
281
+
163
282
  model: 'models/npc.glb',
164
283
 
284
+
285
+
165
286
  onActivate:()=>{console.log('npc activated');}
166
287
 
288
+
289
+
167
290
  }
168
291
 
292
+
293
+
169
294
  )
170
295
 
296
+
297
+
171
298
  ```
172
299
 
173
300
 
174
301
 
302
+
303
+
175
304
  With this default configuration, the NPC behaves in the following way:
176
305
 
177
306
 
178
307
 
308
+
309
+
179
310
  - The `onActivate()` function is called when pressing E on the NPC, and when the player walks near at a distance of 6 meters.
180
311
 
312
+
313
+
181
314
  - Once activated, there's a cooldown period of 5 seconds, that prevents the NPC to be activated again.
182
315
 
316
+
317
+
183
318
  - After walking away from the NPC, if its dialog window was open it will be closed, and if the NPC was rotating to follow the player it will stop.
184
319
 
320
+
321
+
185
322
  - If the NPC already has an open dialog window, clicking on the NPC won't do anything, to prevent accidentally clicking on it while flipping through the conversation.
186
323
 
324
+
325
+
187
326
  - If the NPC has an animation named 'Idle', it will play it in a loop. If other non-looping animations are played, it will return to looping the 'Idle' animation after the indicated duration.
188
327
 
189
328
 
190
329
 
330
+
331
+
191
332
  Many of these behaviors can be overridden or tweaked with the exposed properties.
192
333
 
193
334
 
335
+ ## SDK7 UI
336
+ With sdk7, there are new ways to implement similar features from sdk6, one of them being the way 2D UI objects get created. To add the NPC dialogs to your sdk7 2D UI:
337
+
338
+ - create a variable to hold *all* of your 2D UI objects
339
+ - import the NPC UI from the library and add the React object to your scene UI tree
340
+ - create a function to be called once to render all of your 2D UI objects
341
+
342
+ ```ts
343
+ import ReactEcs, { Label, ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
344
+ import { NpcUtilsUi } from 'dcl-npc-toolkit'
345
+
346
+ const SceneOwnedUi = () =>
347
+ <UiEntity>
348
+ <NpcUtilsUi />
349
+ { /* rest of user defined UI */ }
350
+ </UiEntity>
351
+
352
+ export function setupUi() {
353
+ ReactEcsRenderer.setUiRenderer(SceneOwnedUi)
354
+ }
355
+ ```
356
+
357
+
194
358
 
195
359
  ## NPC Additional Properties
196
360
 
197
361
 
198
362
 
363
+
364
+
199
365
  To configure other properties of an NPC, add a fourth argument as an `NPCData` object. This object can have the following optional properties:
200
366
 
201
367
 
202
368
 
369
+
370
+
203
371
  - `idleAnim`: _(string)_ Name of the idle animation in the model. This animation is always looped. After playing a non-looping animation it returns to looping this one.
204
372
 
373
+
374
+
205
375
  - `faceUser`: _(boolean)_ Set if the NPC rotates to face the user while active.
206
376
 
377
+
378
+
207
379
  - `dialogSound`: _(string)_ Path to sound file to play once for every entry shown on the UI. If the dialog entry being shown has an `audio` field, the NPC will play the file referenced by the `audio` field instead.
208
380
 
381
+
382
+
209
383
  - `coolDownDuration`: _(number)_ Change the cooldown period for activating the NPC again. The number is in seconds.
210
384
 
385
+
386
+
211
387
  - `hoverText`: _(string)_ Set the UI hover feedback when pointing the cursor at the NPC. _TALK_ by default.
212
388
 
389
+
390
+
213
391
  - `onlyClickTrigger`: _(boolean)_ If true, the NPC can't be activated by walking near. Just by clicking on it or calling its `activate()` function.
214
392
 
393
+
394
+
215
395
  - `onlyETrigger`: _(boolean)_ If true, the NPC can't be activated by walking near. Just by pressing the E key on it or calling its `activate()` function.
216
396
 
397
+
398
+
217
399
  - `onlyExternalTrigger`: _(boolean)_ If true, the NPC can't be activated by clicking, pressing E, or walking near. Just by calling its `activate()` function.
218
400
 
401
+
402
+
219
403
  - `reactDistance`: _(number)_ Radius in meters for the player to activate the NPC or trigger the `onWalkAway()` function when leaving the radius.
220
404
 
405
+
406
+
221
407
  - `continueOnWalkAway`: _(boolean)_ If true,when the player walks out of the `reactDistance` radius, the dialog window stays open and the NPC keeps turning to face the player (if applicable). It doesn't affect the triggering of the `onWalkAway()` function.
222
408
 
409
+
410
+
223
411
  - `onWalkAway`: (_()=> void_) Function to call every time the player walks out of the `reactDistance` radius.
224
412
 
413
+
414
+
225
415
  - `walkingAnim`: _(string)_ Name of the walking animation on the model. This animation is looped when calling the `followPath()` function.
226
416
 
417
+
418
+
227
419
  - `walkingSpeed`: _(number)_ Speed of the NPC when walking. By default _2_.
228
420
 
421
+
422
+
229
423
  - `path`: _(Vector3)_ Default path to walk. If a value is provided for this field on NPC initialization, the NPC will walk over this path in loop from the start.
230
- - `bubbleHeight`: _(number)_ The height at which to display the speech bubble above the head of the NPC.
231
- - `textBubble`: _(boolean)_ If true, NPC starts with a speech bubble object ready to be accessed from the start. Otherwise, they text bubble is only built on the first call to `talkBubble()` on the NPC.
424
+
425
+ - `bubbleHeight`: _(number)_ The height at which to display the speech bubble above the head of the NPC.
426
+
427
+ - `textBubble`: _(boolean)_ If true, NPC starts with a speech bubble object ready to be accessed from the start. Otherwise, they text bubble is only built on the first call to `talkBubble()` on the NPC.
428
+
429
+
232
430
 
233
431
  - `noUI`: _(boolean)_ If true, no UI object is built for UI dialogs for this NPC. This may help optimize the scene if this feature is not used.
234
432
 
235
433
 
236
434
 
435
+
436
+
237
437
  ```ts
238
438
 
439
+
440
+
239
441
  export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
240
442
 
443
+
444
+
241
445
  //NPC Data Object
242
446
 
447
+
448
+
243
449
  {
244
450
 
451
+
452
+
245
453
  type: npc.NPCType.CUSTOM,
246
454
 
455
+
456
+
247
457
  model: 'models/npc.glb',
248
458
 
459
+
460
+
249
461
  onActivate: ()=>{console.log('npc activated');},
250
462
 
463
+
464
+
251
465
  onWalkAway: ()=>{console.log('test on walk away function')},
252
466
 
467
+
468
+
253
469
  faceUser: true,
254
470
 
471
+
472
+
255
473
  reactDistance: 3,
256
474
 
475
+
476
+
257
477
  idleAnim: 'idle1',
258
478
 
479
+
480
+
259
481
  walkingAnim: 'walk1',
260
482
 
483
+
484
+
261
485
  hoverText: 'Activate',
262
486
 
487
+
488
+
263
489
  continueOnWalkAway: true,
264
490
 
491
+
492
+
265
493
  onlyClickTrigger: false,
266
494
 
495
+
496
+
267
497
  onlyExternalTrigger: false
268
498
 
499
+
500
+
269
501
  }
270
502
 
503
+
504
+
271
505
  )
272
506
 
507
+
508
+
273
509
  ```
274
510
 
275
511
 
276
512
 
513
+
514
+
277
515
  ## Get NPC Data
278
516
 
279
517
 
280
518
 
519
+
520
+
281
521
  ```ts
282
522
 
523
+
524
+
283
525
  npc.getData(myNPC)
284
526
 
527
+
528
+
285
529
  ```
286
530
 
287
531
 
288
532
 
533
+
534
+
289
535
  There are several properties you can check on an NPC to know what its current state is:
290
536
 
291
537
 
292
538
 
539
+
540
+
293
541
  - `.state`: An enum value of type `NPCState`. Supported values are `NPCState.STANDING` (default), `NPCState.TALKING`, and `NPCState.FOLLOWPATH`. `TALKING` is applied when the dialog window is opened, and set back to `STANDING` when the window is closed. `FOLLOWPATH` is applied when the NPC starts walking, and set back to `STANDING` when the NPC finishes its path or is stopped.
294
542
 
543
+
544
+
295
545
  - `.introduced`: Boolean, false by default. Set to true if the NPC has spoken to the player at least once in this session.
296
546
 
547
+
548
+
297
549
  - `.visible`: Returns a Boolean, false by default. True if the dialog window for this NPC is currently open.
298
550
 
551
+
552
+
299
553
  - `.inCooldown`: Boolean, false by default. True if the NPC was recently activated and it's now in cooldown. The NPC won't respond to being activated till `inCooldown` is false.
300
554
 
301
555
 
302
556
 
557
+
558
+
303
559
  > TIP: If you want to force an activation of the NPC in spite of the `inCooldown` value, you can force this value to true before activating.
304
560
 
305
561
 
306
562
 
563
+
564
+
307
565
  ## NPC Callable Actions
308
566
 
309
567
 
310
568
 
569
+
570
+
311
571
  An NPC object has several callable functions that come with the class:
312
572
 
313
573
 
314
574
 
575
+
576
+
315
577
  ### Talk
316
578
 
317
579
 
318
580
 
581
+
582
+
319
583
  To start a conversation with the NPC using the dialog UI, call the `talk()` function. The function takes the following **required** parameter:
320
584
 
321
585
 
322
586
 
587
+
588
+
323
589
  - `script`: _(Dialog[])_ This array contains the information to manage the conversation, including events that may be triggered, options to choose, etc.
324
590
 
325
591
 
326
592
 
593
+
594
+
327
595
  It can also take the following optional parameters:
328
596
 
329
597
 
330
598
 
599
+
600
+
331
601
  - `startIndex`: _(number | string)_ The _Dialog_ object from the `script` array to open first. By default this is _0_, the first element of the array. Pass a number to open the entry on a given array position, or pass a string to open the entry with a `name` property matching that string.
332
602
 
603
+
604
+
333
605
  - `duration`: _(number)_ Number of seconds to wait before closing the dialog window. If no value is set, the window is kept open till the player reaches the end of the conversation or something else closes it.
334
606
 
335
607
 
336
608
 
609
+
610
+
337
611
  ```ts
338
612
 
613
+
614
+
339
615
  npc.talk(myNPC,myScript, 0)
340
616
 
617
+
618
+
341
619
  ```
342
620
 
343
621
 
344
622
 
623
+
624
+
345
625
  Learn how to build a script object for NPCs in a section below.
346
626
 
347
627
 
348
628
 
629
+
630
+
349
631
  ### Play Animations
350
632
 
351
633
 
352
634
 
635
+
636
+
353
637
  By default, the NPC will loop an animation named 'Idle', or with a name passed in the `idleAnim` parameter.
354
638
 
355
639
 
356
640
 
641
+
642
+
357
643
  Make the NPC play another animation by calling the `playAnimation()` function. The function takes the following **required** parameter:
358
644
 
359
645
 
360
646
 
647
+
648
+
361
649
  - `animationName`: _(string)_ The name of the animation to play.
362
650
 
363
651
 
364
652
 
653
+
654
+
365
655
  It can also take the following optional parameters:
366
656
 
367
657
 
368
658
 
659
+
660
+
369
661
  - `noLoop`: _(boolean)_ If true, plays the animation just once. Otherwise, the animation is looped.
370
662
 
663
+
664
+
371
665
  - `duration`: _(number)_ Specifies the duration in seconds of the animation. When finished, it returns to playing the idle animation.
372
666
 
373
667
 
374
668
 
669
+
670
+
375
671
  > Note: If `noLoop` is true but no `duration` is set, the model will stay still after playing the animation instead of returning to the idle animation.
376
672
 
377
673
 
378
674
 
675
+
676
+
379
677
  ```ts
380
678
 
679
+
680
+
381
681
  npc.playAnimation(myNPC, `Head_Yes`, true, 2.63)
382
682
 
683
+
684
+
383
685
  ```
384
686
 
385
687
 
386
688
 
689
+
690
+
387
691
  ### Change idle animation
388
692
 
389
693
 
390
694
 
695
+
696
+
391
697
  The NPC's idle animation is looped by default whenever the NPC is not playing any other animations. In some cases you may want to have different idle animations depending on the circumstances, like while in a conversation, or if the NPC changes its general attitude after some event.
392
698
 
393
699
 
394
700
 
701
+
702
+
395
703
  You set the NPC's idle animation when creating the NPC, using the `idleAnim` field. To change this animation at some later time, use `changeIdleAnim()`.
396
704
 
397
705
 
398
706
 
707
+
708
+
399
709
  The `changeIdleAnim()` function takes two arguments:
400
710
 
401
711
 
402
712
 
713
+
714
+
403
715
  - `animation`: The name of the new animation to set as the idle animation
404
716
 
717
+
718
+
405
719
  - `play`: Optionally pass this value as _true_ if you want this new animation to start playing right away.
406
720
 
407
721
 
408
722
 
723
+
724
+
409
725
  ```ts
410
726
 
727
+
728
+
411
729
  npc.changeIdleAnim(myNPC,`AngryIdle`, true)
412
730
 
731
+
732
+
413
733
  ```
414
734
 
415
735
 
416
736
 
737
+
738
+
417
739
  ### Activate
418
740
 
419
741
 
420
742
 
743
+
744
+
421
745
  The `activate()` function can be used to trigger the `onActivate()` function, as an alternative to pressing E or walking near.
422
746
 
423
747
 
424
748
 
749
+
750
+
425
751
  ```ts
426
752
 
753
+
754
+
427
755
  npc.activate(myNPC)
428
756
 
757
+
758
+
429
759
  ```
430
760
 
431
761
 
432
762
 
763
+
764
+
433
765
  The `activate()` function is callable even when in cool down period, and it doesn't start a new cool down period.
434
766
 
435
767
 
436
768
 
769
+
770
+
437
771
  ### Stop Walking
438
772
 
439
773
 
440
774
 
775
+
776
+
441
777
  If the NPC is currently walking, call `stopWalking()` to stop it moving and return to playing its idle animation.
442
778
 
443
779
 
444
780
 
781
+
782
+
445
783
  ```ts
446
784
 
785
+
786
+
447
787
  npc.stopWalking(myNPC)
448
788
 
789
+
790
+
449
791
  ```
450
792
 
451
793
 
452
794
 
795
+
796
+
453
797
  `stopWalking()` can be called with no parameters, or it can also be called with:
454
798
 
455
799
 
456
800
 
801
+
802
+
457
803
  - `duration`: Seconds to wait before starting to walk again. If not provided, the NPC will stop walking indefinitely.
458
804
 
459
805
 
460
806
 
807
+
808
+
461
809
  > Note: If the NPC is has its dialog window open when the timer for the `duration` ends, the NPC will not return to walking.
462
810
 
463
811
 
464
812
 
813
+
814
+
465
815
  To make the NPC play a different animation from idle when paused, call `playAnimation()` after `stopWalking()`.
466
816
 
467
817
 
468
818
 
819
+
820
+
469
821
  ### Follow Path
470
822
 
471
823
 
472
824
 
825
+
826
+
473
827
  Make an NPC walk following a path of `Vector3` points by calling `followPath()`. While walking, the NPC will play the `walkingAnim` if one was set when defining the NPC. The path can be taken once or on a loop.
474
828
 
475
829
 
476
830
 
831
+
832
+
477
833
  `followPath()` can be called with no parameters if a `path` was already provided in the NPC's initialization or in a previous calling of `followPath()`. If the NPC was previously in the middle of walking a path and was interrupted, calling `followPath()` again with no arguments will return the NPC to that path.
478
834
 
479
835
 
480
836
 
837
+
838
+
481
839
  ```ts
482
840
 
841
+
842
+
483
843
  npc.followPath(myNPC)
484
844
 
845
+
846
+
485
847
  ```
486
848
 
487
849
 
488
850
 
851
+
852
+
489
853
  > Note: If the NPC is initialized with a `path` value, it will start out walking that path in a loop, no need to run `followPath()`.
490
854
 
491
855
 
492
856
 
857
+
858
+
493
859
  `followPath()` has a single optional parameter of type `FollowPathData`. This object may have the following optional fields:
494
860
 
495
861
 
496
862
 
863
+
864
+
497
865
  - path: Array of `Vector3` positions to walk over.
498
866
 
867
+
868
+
499
869
  - speed: Speed to move at while walking this path. If no `speed` or `totalDuration` is provided, it uses the NPC's `walkingSpeed`, which is _2_ by default.
500
870
 
871
+
872
+
501
873
  - totalDuration: The duration in _seconds_ that the whole path should take. The NPC will move at the constant speed required to finish in that time. This value overrides that of the _speed_.
502
874
 
875
+
876
+
503
877
  - loop: _boolean_ If true, the NPC walks in circles over the provided set of points in the path. _false_ by default, unless the NPC is initiated with a `path`, in which case it starts as _true_.
504
878
 
879
+
880
+
505
881
  - curve: _boolean_ If true, the path is traced a single smooth curve that passes over each of the indicated points. The curve is made out of straight-line segments, the path is stored with 4 times as many points as originally defined. _false_ by default.
506
882
 
883
+
884
+
507
885
  - startingPoint: Index position for what point to start from on the path. _0_ by default.
508
886
 
887
+
888
+
509
889
  - onFinishCallback: Function to call when the NPC finished walking over all the points on the path. This is only called when `loop` is _false_.
510
890
 
891
+
892
+
511
893
  - onReachedPointCallback: Function to call once every time the NPC reaches a point in the path.
512
894
 
513
895
 
514
896
 
897
+
898
+
515
899
  ```ts
516
900
 
901
+
902
+
517
903
  export let myNPC = npc.create({position: Vector3.create(8,0,8),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
518
904
 
905
+
906
+
519
907
  //NPC Data Object
520
908
 
909
+
910
+
521
911
  {
522
912
 
913
+
914
+
523
915
  type: npc.NPCType.CUSTOM,
524
916
 
917
+
918
+
525
919
  model: 'models/npc.glb',
526
920
 
921
+
922
+
527
923
  onActivate: ()=>{console.log('npc activated');},
528
924
 
925
+
926
+
529
927
  onWalkAway: ()=>{console.log('test on walk away function')},
530
928
 
929
+
930
+
531
931
  faceUser: true,
532
932
 
933
+
934
+
533
935
  reactDistance: 3,
534
936
 
937
+
938
+
535
939
  idleAnim: 'idle1',
536
940
 
941
+
942
+
537
943
  walkingAnim: 'walk1',
538
944
 
945
+
946
+
539
947
  hoverText: "Activate"
540
948
 
949
+
950
+
541
951
  }
542
952
 
953
+
954
+
543
955
  )
544
956
 
545
957
 
546
958
 
959
+
960
+
547
961
  npc.followPath(myNPC,
548
962
 
963
+
964
+
549
965
  {
550
966
 
967
+
968
+
551
969
  path:path,
552
970
 
971
+
972
+
553
973
  loop:true,
554
974
 
975
+
976
+
555
977
  pathType: npc.NPCPathType.RIGID_PATH,
556
978
 
979
+
980
+
557
981
  onFinishCallback:()=>{console.log('path is done')},
558
982
 
983
+
984
+
559
985
  onReachedPointCallback:()=>{console.log('ending oint')},
560
986
 
987
+
988
+
561
989
  totalDuration: 20
562
990
 
991
+
992
+
563
993
  }
564
994
 
995
+
996
+
565
997
  )
566
998
 
567
999
 
568
1000
 
1001
+
1002
+
569
1003
  ```
570
1004
 
571
1005
 
572
1006
 
1007
+
1008
+
573
1009
  #### NPC Walking Speed
574
1010
 
575
1011
 
576
1012
 
1013
+
1014
+
577
1015
  The following list of factors are used to determine speed in hierarchical order:
578
1016
 
579
1017
 
580
1018
 
1019
+
1020
+
581
1021
  - `totalDuration` parameter set when calling `followPath()` is used over the total distance travelled over the path.
582
1022
 
1023
+
1024
+
583
1025
  - `speed` parameter set when calling `followPath()`
584
1026
 
1027
+
1028
+
585
1029
  - `walkingSpeed` parameter set when initializing NPC
586
1030
 
1031
+
1032
+
587
1033
  - Default value _2_.
588
1034
 
589
1035
 
590
1036
 
1037
+
1038
+
591
1039
  #### Joining the path
592
1040
 
593
1041
 
594
1042
 
1043
+
1044
+
595
1045
  If the NPC's current position when calling `followPath()` doesn't match the first position in the `path` array (or the one that matches the `startingPoint` value), the current position is added to the `path` array. The NPC will start by walking from its current position to the first point provided in the path.
596
1046
 
597
1047
 
598
1048
 
1049
+
1050
+
599
1051
  The `path` can be a single point, and the NPC will then walk a from its current position to that point.
600
1052
 
601
1053
 
602
1054
 
1055
+
1056
+
603
1057
  > Note: If the speed of the NPC is determined by a `totalDuration` value, the segment that the NPC walks to join into the path is counted as part of the full path. If this segment is long, it will increase the NPC walking speed so that the full path lasts as what's indicated by the `totalDuration`.
604
1058
 
605
1059
 
606
1060
 
1061
+
1062
+
607
1063
  In this example the NPC is far away from the start of the path. It will first walk from _10, 0, 10_ to _2, 0, 2_ and then continue the path.
608
1064
 
609
1065
 
610
1066
 
1067
+
1068
+
611
1069
  ```ts
612
1070
 
1071
+
1072
+
613
1073
  export let myNPC = npc.create({position: Vector3.create(10,0,10),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
614
1074
 
1075
+
1076
+
615
1077
  //NPC Data Object
616
1078
 
1079
+
1080
+
617
1081
  {
618
1082
 
1083
+
1084
+
619
1085
  type: npc.NPCType.CUSTOM,
620
1086
 
1087
+
1088
+
621
1089
  model: 'models/npc.glb',
622
1090
 
1091
+
1092
+
623
1093
  onActivate: ()=>{console.log('npc activated');},
624
1094
 
1095
+
1096
+
625
1097
  }
626
1098
 
1099
+
1100
+
627
1101
  )
628
1102
 
1103
+
1104
+
629
1105
  npc.followPath(myNPC,
630
1106
 
1107
+
1108
+
631
1109
  {
632
1110
 
1111
+
1112
+
633
1113
  path: [new Vector3(2, 0, 2), new Vector3(4, 0, 4), new Vector3(6, 0, 6)]
634
1114
 
1115
+
1116
+
635
1117
  })
636
1118
 
1119
+
1120
+
637
1121
  ```
638
1122
 
639
1123
 
640
1124
 
1125
+
1126
+
641
1127
  #### Example Interrupting the NPC
642
1128
 
643
1129
 
644
1130
 
1131
+
1132
+
645
1133
  In the following example, an NPC starts roaming walking over a path, pausing on every point to call out for its lost kitten. If the player activates the NPC (by pressing E on it or walking near it) the NPC stops, and turns to face the player and talk. When the conversation is over, the NPC returns to walking its path from where it left off.
646
1134
 
647
1135
 
648
1136
 
1137
+
1138
+
649
1139
  ```ts
650
1140
 
1141
+
1142
+
651
1143
  export let myNPC = npc.create({position: Vector3.create(10,0,10),rotation:Quaternion.Zero(), scale: Vector3.create(1,1,1)},
652
1144
 
1145
+
1146
+
653
1147
  //NPC Data Object
654
1148
 
1149
+
1150
+
655
1151
  {
656
1152
 
1153
+
1154
+
657
1155
  type: npc.NPCType.CUSTOM,
658
1156
 
1157
+
1158
+
659
1159
  model: 'models/npc.glb',
660
1160
 
1161
+
1162
+
661
1163
  onActivate: ()=>{
662
1164
 
1165
+
1166
+
663
1167
  npc.stopWalking(myNPC);
664
1168
 
1169
+
1170
+
665
1171
  npc.talk(myNPC, lostCat, 0)
666
1172
 
1173
+
1174
+
667
1175
  console.log('npc activated');
668
1176
 
1177
+
1178
+
669
1179
  },
670
1180
 
1181
+
1182
+
671
1183
  walkingAnim: 'walk1',
672
1184
 
1185
+
1186
+
673
1187
  faceUser:true
674
1188
 
1189
+
1190
+
675
1191
  }
676
1192
 
1193
+
1194
+
677
1195
  )
678
1196
 
679
1197
 
680
1198
 
1199
+
1200
+
681
1201
  npc.followPath(myNPC,
682
1202
 
1203
+
1204
+
683
1205
  {
684
1206
 
1207
+
1208
+
685
1209
  path: [new Vector3(4, 0, 30), new Vector3(6, 0, 29), new Vector3(15, 0, 25)],
686
1210
 
1211
+
1212
+
687
1213
  loop: true,
688
1214
 
1215
+
1216
+
689
1217
  onReachedPointCallback: () => {
690
1218
 
1219
+
1220
+
691
1221
  npc.stopWalking(myNPC, 3)
692
1222
 
1223
+
1224
+
693
1225
  npc.playAnimation(myNPC, `Cocky`, true, 2.93)
694
1226
 
1227
+
1228
+
695
1229
  }
696
1230
 
1231
+
1232
+
697
1233
  })
698
1234
 
699
1235
 
700
1236
 
1237
+
1238
+
701
1239
  export let lostCat: Dialog[] = [
702
1240
 
1241
+
1242
+
703
1243
  {
704
1244
 
1245
+
1246
+
705
1247
  text: `I lost my cat, I'm going crazy here`
706
1248
 
1249
+
1250
+
707
1251
  },
708
1252
 
1253
+
1254
+
709
1255
  {
710
1256
 
1257
+
1258
+
711
1259
  text: `Have you seen it anywhere?`
712
1260
 
1261
+
1262
+
713
1263
  },
714
1264
 
1265
+
1266
+
715
1267
  {
716
1268
 
1269
+
1270
+
717
1271
  text: `Ok, I'm gonna go back to looking for it`,
718
1272
 
1273
+
1274
+
719
1275
  triggeredByNext: () => {
720
1276
 
1277
+
1278
+
721
1279
  npc.followPath(myNPC)
722
1280
 
1281
+
1282
+
723
1283
  },
724
1284
 
1285
+
1286
+
725
1287
  isEndOfDialog: true
726
1288
 
1289
+
1290
+
727
1291
  }
728
1292
 
1293
+
1294
+
729
1295
  ]
730
1296
 
1297
+
1298
+
731
1299
  ```
732
1300
 
733
1301
 
734
1302
 
1303
+
1304
+
735
1305
  ### End interaction
736
1306
 
737
1307
 
738
1308
 
1309
+
1310
+
739
1311
  The `endInteraction()` function can be used to abruptly end interactions with the NPC.
740
1312
 
741
1313
 
742
1314
 
1315
+
1316
+
743
1317
  If applicable, it closes the dialog UI, hides speech bubbles, and makes the NPC stop rotating to face the player.
744
1318
 
745
1319
 
746
1320
 
1321
+
1322
+
747
1323
  ```ts
748
1324
 
1325
+
1326
+
749
1327
  npc.endInteraction(myNPC)
750
1328
 
1329
+
1330
+
751
1331
  ```
752
1332
 
753
1333
 
754
1334
 
1335
+
1336
+
755
1337
  As an alternative, you can call the `handleWalkAway()` function, which has the same effects (as long as `continueOnWalkAway` isn't set to true), but also triggers the `onWalkAway()` function.
756
1338
 
757
1339
 
758
1340
 
1341
+
1342
+
759
1343
  ## NPC Dialog Window
760
1344
 
761
1345
 
762
1346
 
1347
+
1348
+
763
1349
  You can display an interactive dialog window to simulate a conversation with a non-player character (NPC).
764
1350
 
765
1351
 
766
1352
 
1353
+
1354
+
767
1355
  The conversation is based on a script in JSON format. The script can include questions that can take you forward or backward, or end the conversation.
768
1356
 
769
1357
 
770
1358
 
1359
+
1360
+
771
1361
  <img src="screenshots/NPC1.png" width="500">
772
1362
 
773
1363
 
774
1364
 
1365
+
1366
+
775
1367
  ### The NPC script
776
1368
 
777
1369
 
778
1370
 
1371
+
1372
+
779
1373
  Each entry on the script must include at least a `text` field, but can include several more fields to further customize it.
780
1374
 
781
1375
 
782
1376
 
1377
+
1378
+
783
1379
  Below is a minimal dialog.
784
1380
 
785
1381
 
786
1382
 
1383
+
1384
+
787
1385
  ```ts
788
1386
 
1387
+
1388
+
789
1389
  export let NPCTalk: Dialog[] = [
790
1390
 
1391
+
1392
+
791
1393
  {
792
1394
 
1395
+
1396
+
793
1397
  text: 'Hi there'
794
1398
 
1399
+
1400
+
795
1401
  },
796
1402
 
1403
+
1404
+
797
1405
  {
798
1406
 
1407
+
1408
+
799
1409
  text: 'It sure is nice talking to you'
800
1410
 
1411
+
1412
+
801
1413
  },
802
1414
 
1415
+
1416
+
803
1417
  {
804
1418
 
1419
+
1420
+
805
1421
  text: 'I must go, my planet needs me',
806
1422
 
1423
+
1424
+
807
1425
  isEndOfDialog: true
808
1426
 
1427
+
1428
+
809
1429
  }
810
1430
 
1431
+
1432
+
811
1433
  ]
812
1434
 
1435
+
1436
+
813
1437
  ```
814
1438
 
815
1439
 
816
1440
 
1441
+
1442
+
817
1443
  The player advances through each entry by clicking the mouse button. Once the last is reached, clicking again closes the window, as it's marked as `isEndOfDialog`.
818
1444
 
819
1445
 
820
1446
 
1447
+
1448
+
821
1449
  The script must adhere to the following schema:
822
1450
 
823
1451
 
824
1452
 
1453
+
1454
+
825
1455
  ```ts
826
1456
 
1457
+
1458
+
827
1459
  class Dialog {
828
1460
 
1461
+
1462
+
829
1463
  text: string
830
1464
 
1465
+
1466
+
831
1467
  fontSize?: number
832
1468
 
1469
+
1470
+
833
1471
  typeSpeed?: number
834
1472
 
1473
+
1474
+
835
1475
  isEndOfDialog?: boolean
836
1476
 
1477
+
1478
+
837
1479
  isQuestion?:boolean
838
1480
 
1481
+
1482
+
839
1483
  buttons?: ButtonData[]
840
1484
 
1485
+
1486
+
841
1487
  audio?: string
842
1488
 
1489
+
1490
+
843
1491
  triggeredByNext?: () => void
844
1492
 
1493
+
1494
+
845
1495
  }
846
1496
 
1497
+
1498
+
847
1499
  ```
848
1500
 
849
1501
 
850
1502
 
1503
+
1504
+
851
1505
  > Note: A `Dialog` object can be used as an input both for the `talk()` function (that is displayed in the UI), and the `talkBubble()` function (that is displayed in a floating bubble over the NPC). Properties marked with `*` are only applicable to UI dialogs.
852
1506
 
853
1507
 
1508
+
854
1509
 
855
1510
 
856
1511
  You can set the following fields to change the appearance of a dialog:
857
1512
 
858
1513
 
859
1514
 
1515
+
1516
+
860
1517
  - `text`: The dialog text
861
1518
 
1519
+
1520
+
862
1521
  - `fontSize`: Size of the text
863
1522
 
864
1523
 
865
1524
 
1525
+
1526
+
866
1527
  Other fields:
867
1528
 
1529
+
1530
+
868
1531
  - `buttons *`: An array of buttons to use in a question entry, covered in the next section.
869
1532
 
1533
+
1534
+
870
1535
  - `audio`: String with the path to an audio file to play once when this dialog is shown on the UI.
871
1536
 
1537
+
1538
+
872
1539
  - `typeSpeed`: The text appears one character at a time, simulating typing. Players can click to skip the animation. Tune the speed of this typing (30 by default) to go slower or faster. Set to _-1_ to skip the animation.
873
1540
 
874
1541
 
875
1542
 
1543
+
1544
+
876
1545
  #### Questions and conversation trees
877
1546
 
878
1547
 
879
1548
 
1549
+
1550
+
880
1551
  The script can include questions that prompt the player to pick between two or up to four options. These questions can branch the conversation out and trigger other actions in the scene.
881
1552
 
882
1553
 
883
1554
 
1555
+
1556
+
884
1557
  <img src="screenshots/NPC2.png" width="500">
885
1558
 
886
1559
 
887
1560
 
1561
+
1562
+
888
1563
  > Note: Questions are only used by UI dialogs. If used in a speech bubble, questions will be displayed as regular entries with no buttons or options.
889
1564
 
890
1565
 
891
1566
 
1567
+
1568
+
892
1569
  To make an entry a question, set the `isQuestion` field to _true_. This displays a set of buttons rather than the click icon. It also disables the click to advance to the next entry.
893
1570
 
894
1571
 
895
1572
 
1573
+
1574
+
896
1575
  The `buttons` property of an entry contains an array of `ButtonData` objects, each one of these defines one button.
897
1576
 
898
1577
 
899
1578
 
1579
+
1580
+
900
1581
  When on a question entry, you must provide at least the following for each button:
901
1582
 
902
1583
 
903
1584
 
1585
+
1586
+
904
1587
  - `label`: _(string)_ The label to show on the button.
905
1588
 
1589
+
1590
+
906
1591
  - `goToDialog`: _(number | string)_ The index or name of the next dialog entry to display when activated.
907
1592
 
908
1593
 
909
1594
 
1595
+
1596
+
910
1597
  > TIP: It's always better to refer to an entry by name, since the array index might shift if you add more entries and it can get hard to keep track of these references.
911
1598
 
912
1599
 
913
1600
 
1601
+
1602
+
914
1603
  You can also set the following:
915
1604
 
916
1605
 
917
1606
 
1607
+
1608
+
918
1609
  - `triggeredActions`: _( () => void )_ An additional function to run whenever the button is activated
919
1610
 
1611
+
1612
+
920
1613
  - `fontSize`: _(number)_ Font size of the text
921
1614
 
1615
+
1616
+
922
1617
  - `offsetX`: _(number)_ Offset of the label on the X axis, relative to its normal position.
923
1618
 
1619
+
1620
+
924
1621
  - `offsetY`: _(number)_ Offset of the label on the Y axis, relative to its normal position.
925
1622
 
926
1623
 
927
1624
 
1625
+
1626
+
928
1627
  All buttons can be clicked to activate them. Additionally, the first button in the array can be activated by pressing the _E_ key. The second button in the array can be activated by pressing the _F_ key,
929
1628
 
930
1629
 
931
1630
 
1631
+
1632
+
932
1633
  <img src="screenshots/NPC3.png" width="500">
933
1634
 
934
1635
 
935
1636
 
1637
+
1638
+
936
1639
  ```ts
937
1640
 
1641
+
1642
+
938
1643
  export let GemsMission: Dialog[] = [
939
1644
 
1645
+
1646
+
940
1647
  {
941
1648
 
1649
+
1650
+
942
1651
  text: `Hello stranger`
943
1652
 
1653
+
1654
+
944
1655
  },
945
1656
 
1657
+
1658
+
946
1659
  {
947
1660
 
1661
+
1662
+
948
1663
  text: `Can you help me finding my missing gems?`,
949
1664
 
1665
+
1666
+
950
1667
  isQuestion: true,
951
1668
 
1669
+
1670
+
952
1671
  buttons: [
953
1672
 
1673
+
1674
+
954
1675
  { label: `Yes!`, goToDialog: 2 },
955
1676
 
1677
+
1678
+
956
1679
  { label: `I'm busy`, goToDialog: 4 }
957
1680
 
1681
+
1682
+
958
1683
  ]
959
1684
 
1685
+
1686
+
960
1687
  },
961
1688
 
1689
+
1690
+
962
1691
  {
963
1692
 
1693
+
1694
+
964
1695
  text: `Ok, awesome, thanks!`
965
1696
 
1697
+
1698
+
966
1699
  },
967
1700
 
1701
+
1702
+
968
1703
  {
969
1704
 
1705
+
1706
+
970
1707
  text: `I need you to find 10 gems scattered around this scene, go find them!`,
971
1708
 
1709
+
1710
+
972
1711
  isEndOfDialog: true
973
1712
 
1713
+
1714
+
974
1715
  },
975
1716
 
1717
+
1718
+
976
1719
  {
977
1720
 
1721
+
1722
+
978
1723
  text: `Ok, come back soon`,
979
1724
 
1725
+
1726
+
980
1727
  isEndOfDialog: true
981
1728
 
1729
+
1730
+
982
1731
  }
983
1732
 
1733
+
1734
+
984
1735
  ]
985
1736
 
1737
+
1738
+
986
1739
  ```
987
1740
 
988
1741
 
989
1742
 
1743
+
1744
+
990
1745
  #### Triggering functions from the dialog
991
1746
 
992
1747
 
993
1748
 
1749
+
1750
+
994
1751
  You can run functions that may affect any other part of your scene. These functions get triggered when the player interacts with the dialog window, or when the NPC displays speech bubbles.
995
1752
 
996
1753
 
997
1754
 
1755
+
1756
+
998
1757
  - `triggeredByNext`: Is executed when the player advances to the next dialog on a non-question dialog. The function also gets called if the dialog is the end of the conversation. It also gets called when a speech bubble advances to the next entry.
999
1758
 
1000
1759
 
1001
1760
 
1761
+
1762
+
1002
1763
  - `triggeredActions`: This property is associated to a button and is executed on a question dialog if the player activates the corresponding button. You can have up to 4 different buttons per entry, each with its own actions.
1003
1764
 
1004
1765
 
1005
1766
 
1767
+
1768
+
1006
1769
  ```ts
1007
1770
 
1771
+
1772
+
1008
1773
  export let GemsMission: Dialog[] = [
1009
1774
 
1775
+
1776
+
1010
1777
  {
1011
1778
 
1779
+
1780
+
1012
1781
  text: `Hello stranger`,
1013
1782
 
1783
+
1784
+
1014
1785
  triggeredByNext: () => {
1015
1786
 
1787
+
1788
+
1016
1789
  // NPC plays animation to show a gem
1017
1790
 
1791
+
1792
+
1018
1793
  }
1019
1794
 
1795
+
1796
+
1020
1797
  },
1021
1798
 
1799
+
1800
+
1022
1801
  {
1023
1802
 
1803
+
1804
+
1024
1805
  text: `Can you help me finding my missing gems?`,
1025
1806
 
1807
+
1808
+
1026
1809
  isQuestion: true,
1027
1810
 
1811
+
1812
+
1028
1813
  buttons: [
1029
1814
 
1815
+
1816
+
1030
1817
  {
1031
1818
 
1819
+
1820
+
1032
1821
  label: `Yes!`,
1033
1822
 
1823
+
1824
+
1034
1825
  goToDialog: 2,
1035
1826
 
1827
+
1828
+
1036
1829
  triggeredActions: () => {
1037
1830
 
1831
+
1832
+
1038
1833
  // NPC plays an animation to celebrate
1039
1834
 
1835
+
1836
+
1040
1837
  }
1041
1838
 
1839
+
1840
+
1042
1841
  },
1043
1842
 
1843
+
1844
+
1044
1845
  {
1045
1846
 
1847
+
1848
+
1046
1849
  label: `I'm busy`,
1047
1850
 
1851
+
1852
+
1048
1853
  goToDialog: 4
1049
1854
 
1855
+
1856
+
1050
1857
  triggeredActions: () => {
1051
1858
 
1859
+
1860
+
1052
1861
  // NPC waves goodbye
1053
1862
 
1863
+
1864
+
1054
1865
  }
1055
1866
 
1867
+
1868
+
1056
1869
  },
1057
1870
 
1871
+
1872
+
1058
1873
  ]
1059
1874
 
1875
+
1876
+
1060
1877
  },
1061
1878
 
1879
+
1880
+
1062
1881
  {
1063
1882
 
1883
+
1884
+
1064
1885
  text: `Ok, awesome, thanks!`,
1065
1886
 
1887
+
1888
+
1066
1889
  },
1067
1890
 
1891
+
1892
+
1068
1893
  {
1069
1894
 
1895
+
1896
+
1070
1897
  text: `I need you to find 10 gems scattered around this scene, go find them!`,
1071
1898
 
1899
+
1900
+
1072
1901
  isEndOfDialog: true
1073
1902
 
1903
+
1904
+
1074
1905
  triggeredByNext: () => {
1075
1906
 
1907
+
1908
+
1076
1909
  // Gems are rendered all around the scene
1077
1910
 
1911
+
1912
+
1078
1913
  }
1079
1914
 
1915
+
1916
+
1080
1917
  },
1081
1918
 
1919
+
1920
+
1082
1921
  {
1083
1922
 
1923
+
1924
+
1084
1925
  text: `Ok, come back soon`,
1085
1926
 
1927
+
1928
+
1086
1929
  isEndOfDialog: true
1087
1930
 
1931
+
1932
+
1088
1933
  }
1089
1934
 
1935
+
1936
+
1090
1937
  ]
1091
1938
 
1939
+
1940
+
1092
1941
  ```
1093
1942
 
1094
1943
 
1095
- ## No-NPC Dialogs
1944
+
1945
+ ## No-NPC Dialogs
1946
+
1947
+
1096
1948
 
1097
1949
 
1098
1950
 
@@ -1100,136 +1952,217 @@ You can open a Dialog window that isn't associated with any `NPC` object in the
1100
1952
 
1101
1953
 
1102
1954
 
1955
+
1956
+
1103
1957
  ### The Dialog window
1104
1958
 
1105
1959
 
1106
1960
 
1961
+
1962
+
1107
1963
  To create a new dialog window, call `createDialogWindow()` and store as a variable. This will instantiate the window but keep it hidden until you open it.
1108
1964
 
1965
+
1966
+
1109
1967
  ```ts
1110
1968
 
1969
+
1970
+
1111
1971
  let dialogWindow = npc.createDialogWindow()
1112
1972
 
1973
+
1974
+
1113
1975
  ```
1114
1976
 
1115
-
1977
+
1978
+
1116
1979
  <img src="screenshots/NPC1.png" width="500">
1117
1980
 
1118
-
1981
+
1982
+
1119
1983
  When instantiating a new blank dialog, you can pass the following optional parameters:
1120
1984
 
1985
+
1986
+
1121
1987
 
1122
1988
  - `defaultPortrait`: Sets a default portrait image to use on the left of all dialogs that don't specify an image. If a dialog has no portrait and no default is provided, no image is shown on the left. This field expects a `Portrait` object, that may include the following fields: - `path`: Path to the image file - `xOffset`: Offset on X, relative to the normal position of the portrait. - `yOffset`: Offset on Y, relative to the normal position of the portrait. - `section`: Use only a section of the image file, useful when arranging multiple icons into an image atlas. This field takes an `ImageSection` object, specifying `sourceWidth` and `sourceHeight`, and optionally also `sourceLeft` and `sourceTop`.
1123
1989
 
1990
+
1991
+
1124
1992
  - `useDarkTheme`: Switch the style of the window to the dark theme.
1125
1993
 
1994
+
1995
+
1126
1996
  - `sound`: Path to a sound file that will be played once for every dialog entry shown, as long as the dialog entry doesn't have its own `audio` property.
1127
1997
 
1128
1998
 
1129
1999
 
2000
+
2001
+
1130
2002
  Once you have created a dialog window, you can open a dialog window with the `openDialogWindow()` function.
1131
2003
 
1132
2004
 
1133
2005
 
2006
+
2007
+
1134
2008
  ```ts
1135
2009
 
2010
+
2011
+
1136
2012
  npc.openDialogWindow(dialogWindow, NPCTalk, 0)
1137
2013
 
2014
+
2015
+
1138
2016
  ```
1139
2017
 
1140
2018
 
1141
2019
 
2020
+
2021
+
1142
2022
  When calling this function, you must specify:
1143
2023
 
1144
2024
 
1145
2025
 
2026
+
2027
+
1146
2028
  - `NPCScript`: A JSON object composed of an array of `Dialog` objects, that includes all the dialog tree.
1147
2029
 
1148
2030
 
1149
2031
 
2032
+
2033
+
1150
2034
  A second optional parameter is also available:
1151
2035
 
1152
2036
 
1153
2037
 
2038
+
2039
+
1154
2040
  - `textId`: The index or `name` property of the entry to show first from the script. The first entry is 0.
1155
2041
 
1156
2042
 
1157
2043
 
2044
+
2045
+
1158
2046
  > TIP: It's always better to refer to an entry by name, since the array index might shift if you add more entries and it can get hard to keep track of these references.
1159
2047
 
1160
2048
 
1161
2049
 
2050
+
2051
+
1162
2052
  Close a dialog window at any time by calling the `closeDialogWindow()` function.
1163
2053
 
1164
2054
 
1165
2055
 
2056
+
2057
+
1166
2058
  ```ts
1167
2059
 
2060
+
2061
+
1168
2062
  npc.closeDialogWindow(dialogWindow)
1169
2063
 
2064
+
2065
+
1170
2066
  ```
1171
2067
 
1172
2068
 
1173
2069
 
2070
+
2071
+
1174
2072
  For details on how to construct the dialog tree, see the sections above. The required `NPCScript` by the `DialogWindow` has exactly the same characteristics as the one used on the `NPC` object when calling the `talk()` function.
1175
2073
 
1176
2074
 
1177
2075
 
2076
+
2077
+
1178
2078
  ---
1179
2079
 
2080
+
2081
+
1180
2082
  ## Contribute
1181
2083
 
1182
2084
 
1183
2085
 
2086
+
2087
+
1184
2088
  In order to test changes made to this repository in active scenes, do the following:
1185
2089
 
1186
2090
 
1187
2091
 
2092
+
2093
+
1188
2094
  1. Run `npm run build` for the internal files of the library to be generated
1189
2095
 
2096
+
2097
+
1190
2098
  2. Run `npm run link` on this repository
1191
2099
 
2100
+
2101
+
1192
2102
  3. On a new Decentraland scene, import this library as you normally would and include the tests you need
1193
2103
 
2104
+
2105
+
1194
2106
  4. On the scene directory, run `npm link dcl-npc-toolkit`
1195
2107
 
1196
2108
 
1197
2109
 
2110
+
2111
+
1198
2112
  > Note: When done testing, run `npm unlink` on both folders, so that the scene stops using the local version of the library.
1199
2113
 
1200
2114
 
2115
+
1201
2116
 
1202
2117
 
1203
2118
  ## CI/CD
1204
2119
 
1205
2120
 
1206
2121
 
2122
+
2123
+
1207
2124
  This repository uses `semantic-release` to automatically release new versions of the package to NPM.
1208
2125
 
1209
2126
 
1210
2127
 
2128
+
2129
+
1211
2130
  Use the following convention for commit names:
1212
2131
 
1213
2132
 
1214
2133
 
2134
+
2135
+
1215
2136
  `feat: something`: Minor release, every time you add a feature or enhancement that doesn’t break the api.
1216
2137
 
1217
2138
 
1218
2139
 
2140
+
2141
+
1219
2142
  `fix: something`: Bug fixing / patch
1220
2143
 
1221
2144
 
1222
2145
 
2146
+
2147
+
1223
2148
  `chore: something`: Anything that doesn't require a release to npm, like changing the readme. Updating a dependency is **not** a chore if it fixes a bug or a vulnerability, that's a `fix`.
1224
2149
 
1225
2150
 
1226
2151
 
2152
+
2153
+
1227
2154
  If you break the API of the library, you need to do a major release, and that's done a different way. You need to add a second comment that starts with `BREAKING CHANGE`, like:
1228
2155
 
1229
2156
 
1230
2157
 
2158
+
2159
+
1231
2160
  ```
1232
2161
 
2162
+
2163
+
1233
2164
  commit -m "feat: changed the signature of a method" -m "BREAKING CHANGE: this commit breaks the API, changing foo(arg1) to foo(arg1, arg2)"
1234
2165
 
2166
+
2167
+
1235
2168
  ```