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