incanto 0.74.0 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/incanto-multiplay.mjs +52 -4
- package/dist/2d.d.ts +83 -7
- package/dist/2d.js +4 -3
- package/dist/3d.d.ts +861 -167
- package/dist/3d.js +6 -6
- package/dist/{agent8-CHTT4unP.js → agent8-B-bh3n0X.js} +1 -1
- package/dist/{audio-player-BOrk4eQx.d.ts → audio-player-BRo2uvG6.d.ts} +23 -2
- package/dist/{behavior-J1cmVah0.d.ts → behavior-B_245qRy.d.ts} +15 -1
- package/dist/{create-game-ssvGvP7W.js → create-game-BMIPKrQW.js} +84 -8
- package/dist/{create-game-BAiA-FjP.js → create-game-Dai5vfVu.js} +80 -11
- package/dist/debug.d.ts +1 -1
- package/dist/{editor-switch-CFU9mCec.d.ts → editor-switch-Bzt0GzVp.d.ts} +13 -3
- package/dist/editor.js +1600 -1529
- package/dist/env.d.ts +1 -1
- package/dist/{environment-presets-BkqlWewf.js → environment-presets-e_9YCnGu.js} +2361 -104
- package/dist/{gameplay-Bxe1sMVT.js → gameplay-Bfff_beb.js} +10919 -6798
- package/dist/gameplay.d.ts +573 -31
- package/dist/gameplay.js +3 -2
- package/dist/index.d.ts +150 -6
- package/dist/index.js +6 -6
- package/dist/{loader-BAeWMYfF.d.ts → loader-CbkVdXL8.d.ts} +2 -2
- package/dist/net.d.ts +2 -2
- package/dist/net.js +2 -2
- package/dist/{physics-2d-C-SfvjzH.js → physics-2d-Tuf5LAyq.js} +250 -31
- package/dist/{physics-3d-rOzeg890.js → physics-3d-C5MOujfQ.js} +673 -51
- package/dist/{picking-BMV34Pjl.js → picking-DIwE48sU.js} +10 -7
- package/dist/{save-slots-CEUGeLuB.js → pose-ByFB_J3O.js} +217 -11
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/{register-DRQyZKGU.js → register-7E3P1gz6.js} +191 -430
- package/dist/{register-CjociOtt.js → register-B768Qedj.js} +596 -2
- package/dist/{replay-B6BbgGM_.js → replay-DrqQ6dZj.js} +133 -18
- package/dist/{replay-wZK5Ok5c.d.ts → replay-W5nCw_cU.d.ts} +21 -2
- package/dist/{rng-Bb-IutXB.d.ts → rng-BsXZg3D6.d.ts} +7 -0
- package/dist/{split-screen-BxZ5rBe7.js → split-screen-B-dIcQsQ.js} +10 -5
- package/dist/{split-screen-D6sx8z3Z.d.ts → split-screen-CiLJf2-C.d.ts} +3 -3
- package/dist/{sprite-animation-Bz3DHD_4.js → sprite-animation-SQa5gIu2.js} +8 -6
- package/dist/{src-CqtvYtSN.js → src-D823V07k.js} +1 -1
- package/dist/{test-CEl0y2Sw.js → test-CVbxnXlv.js} +487 -82
- package/dist/test.d.ts +90 -12
- package/dist/test.js +2 -2
- package/dist/vite.js +34 -5
- package/editor/assets/{agent8-BlzturGi.js → agent8-DA-I5qhv.js} +1 -1
- package/editor/assets/{debug-BMUi8usj.js → debug-99tEPoGm.js} +1 -1
- package/editor/assets/index-Db74LZY-.js +11579 -0
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +1639 -280
- package/skills/incanto-3d-character.md +383 -20
- package/skills/incanto-audio.md +24 -2
- package/skills/incanto-building-2d-games.md +21 -2
- package/skills/incanto-building-3d-games.md +38 -3
- package/skills/incanto-editor.md +29 -8
- package/skills/incanto-environment.md +257 -14
- package/skills/incanto-game-feel.md +60 -1
- package/skills/incanto-gameplay-behaviors.md +668 -20
- package/skills/incanto-hud.md +116 -0
- package/skills/incanto-multiplayer.md +141 -2
- package/skills/incanto-node-reference.md +398 -16
- package/skills/incanto-performance.md +32 -0
- package/skills/incanto-physics-and-input.md +241 -13
- package/skills/incanto-playtesting.md +2 -2
- package/skills/incanto-save-slots.md +61 -2
- package/skills/incanto-scene-json-authoring.md +13 -0
- package/skills/incanto-verifying-your-game.md +86 -3
- package/templates-app/beacon-isle-3d/PROJECT/Status.md +12 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +157 -3
- package/templates-app/molehill-2d/PROJECT/Status.md +7 -0
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/molehill-2d/src/game.scene.json +129 -2
- package/templates-app/platformer-2d/PROJECT/Status.md +7 -0
- package/templates-app/platformer-2d/docs/project-2d-rules.md +3 -2
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/behaviors.ts +40 -26
- package/templates-app/platformer-2d/src/game.scene.json +144 -2
- package/templates-app/platformer-2d/verify.ts +18 -1
- package/templates-app/star-survivor/PROJECT/Status.md +7 -0
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/behaviors.ts +9 -8
- package/templates-app/star-survivor/src/game.scene.json +142 -4
- package/templates-app/star-survivor/verify.ts +13 -0
- package/templates-app/tps-3d/PROJECT/Status.md +6 -0
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/game.scene.json +71 -10
- package/templates-app/village-quest-3d/PROJECT/Status.md +7 -0
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/behaviors.ts +8 -16
- package/templates-app/village-quest-3d/src/grove.scene.json +121 -5
- package/templates-app/village-quest-3d/src/village.scene.json +126 -2
- package/templates-app/village-quest-3d/verify.ts +52 -2
- package/editor/assets/index-CrUCQoaB.js +0 -11046
|
@@ -27,6 +27,7 @@ import { Behavior, findPath, gridFromRows, Timer } from 'incanto';
|
|
|
27
27
|
import { mergeSolidRects, parseCells } from 'incanto/2d';
|
|
28
28
|
import type { Camera3D, CharacterController3D, Node3D, Trail3D } from 'incanto/3d';
|
|
29
29
|
import { MeshInstance3D, Particles3D, StaticBody3D } from 'incanto/3d';
|
|
30
|
+
import type { Health } from 'incanto/gameplay';
|
|
30
31
|
import { goToScene } from 'incanto/gameplay';
|
|
31
32
|
import groveJsonRaw from './grove.scene.json';
|
|
32
33
|
import { quest, resetQuest } from './quest';
|
|
@@ -558,19 +559,13 @@ export class SwordStrike extends Behavior {
|
|
|
558
559
|
if (!wolf.tree) return; // already gone
|
|
559
560
|
const at = (wolf as unknown as Positioned).position;
|
|
560
561
|
(this.player.getNode('HitSfx') as AudioPlayer).play();
|
|
561
|
-
// two hits per wolf: the first FLINCHES it
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
const len = Math.hypot(dx, dz) || 1;
|
|
569
|
-
(wolf as unknown as Positioned).position = [
|
|
570
|
-
(at[0] ?? 0) + (dx / len) * 1.2,
|
|
571
|
-
at[1] ?? 0.45,
|
|
572
|
-
(at[2] ?? 0) + (dz / len) * 1.2,
|
|
573
|
-
];
|
|
562
|
+
// two hits per wolf (`Vitals` is a `Health` of 2): the first FLINCHES it —
|
|
563
|
+
// `knockback` shoves it along the strike and `staggerSeconds` holds its
|
|
564
|
+
// PathFollow — and the second fells it. The blow's direction is the hit's
|
|
565
|
+
// source: the player's position.
|
|
566
|
+
const vitals = wolf.getNode('Vitals').behavior as Health;
|
|
567
|
+
vitals.damage(1, this.player.position);
|
|
568
|
+
if (!vitals.isDead) {
|
|
574
569
|
(wolf.getNodeOrNull('GrowlSfx') as AudioPlayer | null)?.play();
|
|
575
570
|
flashWolf(wolf);
|
|
576
571
|
return;
|
|
@@ -591,9 +586,6 @@ export class SwordStrike extends Behavior {
|
|
|
591
586
|
}
|
|
592
587
|
}
|
|
593
588
|
|
|
594
|
-
/** Strike bookkeeping: hits per wolf (module-scope — survives behavior instances). */
|
|
595
|
-
const wolfHits = new WeakMap<Node, number>();
|
|
596
|
-
|
|
597
589
|
/**
|
|
598
590
|
* Red hurt-flash on every mesh of the wolf, reverted a beat later.
|
|
599
591
|
*
|
|
@@ -228,6 +228,15 @@
|
|
|
228
228
|
},
|
|
229
229
|
"uid": "n_7pidlrhnsw3irdcq"
|
|
230
230
|
},
|
|
231
|
+
{
|
|
232
|
+
"name": "Vitals",
|
|
233
|
+
"type": "Node",
|
|
234
|
+
"script": {
|
|
235
|
+
"name": "Health",
|
|
236
|
+
"props": { "max": 2, "knockback": 3, "staggerSeconds": 0.35 }
|
|
237
|
+
},
|
|
238
|
+
"uid": "n_3a3vhg3kjbt8z3gy"
|
|
239
|
+
},
|
|
231
240
|
{
|
|
232
241
|
"name": "Fang",
|
|
233
242
|
"type": "Area3D",
|
|
@@ -327,6 +336,15 @@
|
|
|
327
336
|
},
|
|
328
337
|
"uid": "n_b41lz424hn6e1jh1"
|
|
329
338
|
},
|
|
339
|
+
{
|
|
340
|
+
"name": "Vitals",
|
|
341
|
+
"type": "Node",
|
|
342
|
+
"script": {
|
|
343
|
+
"name": "Health",
|
|
344
|
+
"props": { "max": 2, "knockback": 3, "staggerSeconds": 0.35 }
|
|
345
|
+
},
|
|
346
|
+
"uid": "n_8btt3s1ekwpzz16r"
|
|
347
|
+
},
|
|
330
348
|
{
|
|
331
349
|
"name": "Fang",
|
|
332
350
|
"type": "Area3D",
|
|
@@ -426,6 +444,15 @@
|
|
|
426
444
|
},
|
|
427
445
|
"uid": "n_2ph84bwixda1kbuf"
|
|
428
446
|
},
|
|
447
|
+
{
|
|
448
|
+
"name": "Vitals",
|
|
449
|
+
"type": "Node",
|
|
450
|
+
"script": {
|
|
451
|
+
"name": "Health",
|
|
452
|
+
"props": { "max": 2, "knockback": 3, "staggerSeconds": 0.35 }
|
|
453
|
+
},
|
|
454
|
+
"uid": "n_astg45lvndezejsw"
|
|
455
|
+
},
|
|
429
456
|
{
|
|
430
457
|
"name": "Fang",
|
|
431
458
|
"type": "Area3D",
|
|
@@ -664,13 +691,77 @@
|
|
|
664
691
|
"uid": "n_ucyuyojea32g6zm4"
|
|
665
692
|
},
|
|
666
693
|
{
|
|
667
|
-
"name": "
|
|
668
|
-
"type": "
|
|
669
|
-
"
|
|
670
|
-
"
|
|
694
|
+
"name": "Resume",
|
|
695
|
+
"type": "UiButton",
|
|
696
|
+
"uid": "n_ibf6agaxzcxjhcmg",
|
|
697
|
+
"props": { "text": "RESUME", "size": 18 }
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
"name": "PauseOptions",
|
|
701
|
+
"type": "UiButton",
|
|
702
|
+
"uid": "n_kdecsevdetjk0q1i",
|
|
703
|
+
"props": { "text": "OPTIONS", "size": 16 }
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
"name": "Restart",
|
|
707
|
+
"type": "UiButton",
|
|
708
|
+
"uid": "n_vaxmkxrqot30vd7u",
|
|
709
|
+
"props": { "text": "START OVER", "size": 16 }
|
|
671
710
|
}
|
|
672
711
|
],
|
|
673
712
|
"uid": "n_5wfhk1dbgyv25gxl"
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
"name": "Options",
|
|
716
|
+
"type": "UiPanel",
|
|
717
|
+
"uid": "n_p9poexefeps6a5ti",
|
|
718
|
+
"props": {
|
|
719
|
+
"anchor": "center",
|
|
720
|
+
"layout": "column",
|
|
721
|
+
"gap": 10,
|
|
722
|
+
"padding": 22,
|
|
723
|
+
"visible": false,
|
|
724
|
+
"background": "rgba(10,14,22,0.92)",
|
|
725
|
+
"radius": 12
|
|
726
|
+
},
|
|
727
|
+
"children": [
|
|
728
|
+
{
|
|
729
|
+
"name": "OptionsTitle",
|
|
730
|
+
"type": "UiText",
|
|
731
|
+
"uid": "n_iewdvemq5y7qda2b",
|
|
732
|
+
"props": { "text": "OPTIONS", "size": 24 }
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"name": "Master",
|
|
736
|
+
"type": "UiVolumeSlider",
|
|
737
|
+
"uid": "n_ycigwyt5cj3bjz3a",
|
|
738
|
+
"props": { "label": "master", "bus": "master", "width": 260 }
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
"name": "Sfx",
|
|
742
|
+
"type": "UiVolumeSlider",
|
|
743
|
+
"uid": "n_6mnynp8ycxxalwbi",
|
|
744
|
+
"props": { "label": "effects", "bus": "sfx", "width": 260 }
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
"name": "Mute",
|
|
748
|
+
"type": "UiMuteToggle",
|
|
749
|
+
"uid": "n_g2ckhuighfpqsz03",
|
|
750
|
+
"props": { "label": "mute everything" }
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
"name": "Quality",
|
|
754
|
+
"type": "UiQualitySelect",
|
|
755
|
+
"uid": "n_owxh3r8ktaohote2",
|
|
756
|
+
"props": { "label": "quality" }
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
"name": "Back",
|
|
760
|
+
"type": "UiButton",
|
|
761
|
+
"uid": "n_g7ugvwf2z03wjf2r",
|
|
762
|
+
"props": { "text": "BACK", "size": 16 }
|
|
763
|
+
}
|
|
764
|
+
]
|
|
674
765
|
}
|
|
675
766
|
],
|
|
676
767
|
"uid": "n_wwhwnwye7olskfer"
|
|
@@ -680,6 +771,31 @@
|
|
|
680
771
|
},
|
|
681
772
|
"connections": [
|
|
682
773
|
{ "signal": "triggerEnter", "from": "ReturnPortal", "to": "/root", "handler": "onPortalEnter" },
|
|
683
|
-
{ "signal": "died", "from": "Player", "to": "/root", "handler": "onPlayerDown" }
|
|
774
|
+
{ "signal": "died", "from": "Player", "to": "/root", "handler": "onPlayerDown" },
|
|
775
|
+
{
|
|
776
|
+
"from": "/root/HUD/PauseMenu/Resume",
|
|
777
|
+
"signal": "pressed",
|
|
778
|
+
"to": "/root/Flow",
|
|
779
|
+
"handler": "resume"
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
"from": "/root/HUD/PauseMenu/PauseOptions",
|
|
783
|
+
"signal": "pressed",
|
|
784
|
+
"to": "/root/Flow",
|
|
785
|
+
"handler": "screen",
|
|
786
|
+
"args": ["/root/HUD/Options"]
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
"from": "/root/HUD/PauseMenu/Restart",
|
|
790
|
+
"signal": "pressed",
|
|
791
|
+
"to": "/root/Flow",
|
|
792
|
+
"handler": "restart"
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"from": "/root/HUD/Options/Back",
|
|
796
|
+
"signal": "pressed",
|
|
797
|
+
"to": "/root/Flow",
|
|
798
|
+
"handler": "back"
|
|
799
|
+
}
|
|
684
800
|
]
|
|
685
801
|
}
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"sprint": { "type": "button", "keys": ["ShiftLeft", "ShiftRight"] },
|
|
48
48
|
"interact": { "type": "button", "keys": ["KeyE"] },
|
|
49
49
|
"attack": { "type": "button", "keys": ["Mouse0", "KeyF"] },
|
|
50
|
-
"restart": { "type": "button", "keys": ["KeyR"] }
|
|
50
|
+
"restart": { "type": "button", "keys": ["KeyR"] },
|
|
51
|
+
"pause": { "type": "button", "keys": ["Escape"] }
|
|
51
52
|
},
|
|
52
53
|
"assets": {
|
|
53
54
|
"characters/base": {
|
|
@@ -3092,9 +3093,107 @@
|
|
|
3092
3093
|
"type": "UiLanguageSelect",
|
|
3093
3094
|
"uid": "n_4m6tsfl0og3ekii3",
|
|
3094
3095
|
"props": { "label": "@t:settings.language", "anchor": "topRight" }
|
|
3096
|
+
},
|
|
3097
|
+
{
|
|
3098
|
+
"name": "PauseMenu",
|
|
3099
|
+
"type": "UiPanel",
|
|
3100
|
+
"uid": "n_2qwqjqh4quth7e2n",
|
|
3101
|
+
"props": {
|
|
3102
|
+
"anchor": "center",
|
|
3103
|
+
"layout": "column",
|
|
3104
|
+
"gap": 12,
|
|
3105
|
+
"padding": 22,
|
|
3106
|
+
"visible": false,
|
|
3107
|
+
"background": "rgba(10,14,22,0.92)",
|
|
3108
|
+
"radius": 12
|
|
3109
|
+
},
|
|
3110
|
+
"children": [
|
|
3111
|
+
{
|
|
3112
|
+
"name": "PausedTitle",
|
|
3113
|
+
"type": "UiText",
|
|
3114
|
+
"uid": "n_txt30ax88omwicjs",
|
|
3115
|
+
"props": { "text": "PAUSED", "size": 26 }
|
|
3116
|
+
},
|
|
3117
|
+
{
|
|
3118
|
+
"name": "Resume",
|
|
3119
|
+
"type": "UiButton",
|
|
3120
|
+
"uid": "n_jo0ovhcin79mtfel",
|
|
3121
|
+
"props": { "text": "RESUME", "size": 18 }
|
|
3122
|
+
},
|
|
3123
|
+
{
|
|
3124
|
+
"name": "PauseOptions",
|
|
3125
|
+
"type": "UiButton",
|
|
3126
|
+
"uid": "n_gu9f3scxx3ey6zoc",
|
|
3127
|
+
"props": { "text": "OPTIONS", "size": 16 }
|
|
3128
|
+
},
|
|
3129
|
+
{
|
|
3130
|
+
"name": "Restart",
|
|
3131
|
+
"type": "UiButton",
|
|
3132
|
+
"uid": "n_v1jdh9w3njlqtc4u",
|
|
3133
|
+
"props": { "text": "START OVER", "size": 16 }
|
|
3134
|
+
}
|
|
3135
|
+
]
|
|
3136
|
+
},
|
|
3137
|
+
{
|
|
3138
|
+
"name": "Options",
|
|
3139
|
+
"type": "UiPanel",
|
|
3140
|
+
"uid": "n_kq3hlan3nrz5keog",
|
|
3141
|
+
"props": {
|
|
3142
|
+
"anchor": "center",
|
|
3143
|
+
"layout": "column",
|
|
3144
|
+
"gap": 10,
|
|
3145
|
+
"padding": 22,
|
|
3146
|
+
"visible": false,
|
|
3147
|
+
"background": "rgba(10,14,22,0.92)",
|
|
3148
|
+
"radius": 12
|
|
3149
|
+
},
|
|
3150
|
+
"children": [
|
|
3151
|
+
{
|
|
3152
|
+
"name": "OptionsTitle",
|
|
3153
|
+
"type": "UiText",
|
|
3154
|
+
"uid": "n_i0a6qykgauqump71",
|
|
3155
|
+
"props": { "text": "OPTIONS", "size": 24 }
|
|
3156
|
+
},
|
|
3157
|
+
{
|
|
3158
|
+
"name": "Master",
|
|
3159
|
+
"type": "UiVolumeSlider",
|
|
3160
|
+
"uid": "n_n5h7cfsjsych63ix",
|
|
3161
|
+
"props": { "label": "master", "bus": "master", "width": 260 }
|
|
3162
|
+
},
|
|
3163
|
+
{
|
|
3164
|
+
"name": "Sfx",
|
|
3165
|
+
"type": "UiVolumeSlider",
|
|
3166
|
+
"uid": "n_a37vbt17sodktb1h",
|
|
3167
|
+
"props": { "label": "effects", "bus": "sfx", "width": 260 }
|
|
3168
|
+
},
|
|
3169
|
+
{
|
|
3170
|
+
"name": "Mute",
|
|
3171
|
+
"type": "UiMuteToggle",
|
|
3172
|
+
"uid": "n_wxmwd9gbf16mia7v",
|
|
3173
|
+
"props": { "label": "mute everything" }
|
|
3174
|
+
},
|
|
3175
|
+
{
|
|
3176
|
+
"name": "Quality",
|
|
3177
|
+
"type": "UiQualitySelect",
|
|
3178
|
+
"uid": "n_g9f4iazzwcqxlykd",
|
|
3179
|
+
"props": { "label": "quality" }
|
|
3180
|
+
},
|
|
3181
|
+
{
|
|
3182
|
+
"name": "Back",
|
|
3183
|
+
"type": "UiButton",
|
|
3184
|
+
"uid": "n_6vkdb2onbyjrwakr",
|
|
3185
|
+
"props": { "text": "BACK", "size": 16 }
|
|
3186
|
+
}
|
|
3187
|
+
]
|
|
3095
3188
|
}
|
|
3096
3189
|
],
|
|
3097
3190
|
"uid": "n_6u92lb0drej635s9"
|
|
3191
|
+
},
|
|
3192
|
+
{
|
|
3193
|
+
"name": "Flow",
|
|
3194
|
+
"type": "Node",
|
|
3195
|
+
"uid": "n_y2pc0uwbjnsx2ppe",
|
|
3196
|
+
"script": { "name": "GameFlow" }
|
|
3098
3197
|
}
|
|
3099
3198
|
],
|
|
3100
3199
|
"uid": "n_2a2pghqmq92ko29c"
|
|
@@ -3102,6 +3201,31 @@
|
|
|
3102
3201
|
"connections": [
|
|
3103
3202
|
{ "signal": "interacted", "from": "Elder", "to": "/root", "handler": "onTalk" },
|
|
3104
3203
|
{ "signal": "triggerEnter", "from": "GroveGate", "to": "/root", "handler": "onGateEnter" },
|
|
3105
|
-
{ "signal": "pressed", "from": "HUD/RestartBtn", "to": "/root", "handler": "onRestart" }
|
|
3204
|
+
{ "signal": "pressed", "from": "HUD/RestartBtn", "to": "/root", "handler": "onRestart" },
|
|
3205
|
+
{
|
|
3206
|
+
"from": "/root/HUD/PauseMenu/Resume",
|
|
3207
|
+
"signal": "pressed",
|
|
3208
|
+
"to": "/root/Flow",
|
|
3209
|
+
"handler": "resume"
|
|
3210
|
+
},
|
|
3211
|
+
{
|
|
3212
|
+
"from": "/root/HUD/PauseMenu/PauseOptions",
|
|
3213
|
+
"signal": "pressed",
|
|
3214
|
+
"to": "/root/Flow",
|
|
3215
|
+
"handler": "screen",
|
|
3216
|
+
"args": ["/root/HUD/Options"]
|
|
3217
|
+
},
|
|
3218
|
+
{
|
|
3219
|
+
"from": "/root/HUD/PauseMenu/Restart",
|
|
3220
|
+
"signal": "pressed",
|
|
3221
|
+
"to": "/root/Flow",
|
|
3222
|
+
"handler": "restart"
|
|
3223
|
+
},
|
|
3224
|
+
{
|
|
3225
|
+
"from": "/root/HUD/Options/Back",
|
|
3226
|
+
"signal": "pressed",
|
|
3227
|
+
"to": "/root/Flow",
|
|
3228
|
+
"handler": "back"
|
|
3229
|
+
}
|
|
3106
3230
|
]
|
|
3107
3231
|
}
|
|
@@ -117,6 +117,8 @@ const ok = (label: string, cond: boolean): void => {
|
|
|
117
117
|
let sceneName = (): string => 'unset';
|
|
118
118
|
let wolvesWalked = false;
|
|
119
119
|
|
|
120
|
+
let wolfKnock = 0; // metres the first strike shoved the wolf along the blow (Health.knockback)
|
|
121
|
+
let wolfHeld = -1; // metres it walked in the 8 frames AFTER that — its PathFollow is held
|
|
120
122
|
const result = await runScript(villageJson, {
|
|
121
123
|
durationMs: 60000,
|
|
122
124
|
seed: 7,
|
|
@@ -222,7 +224,8 @@ const ok = (label: string, cond: boolean): void => {
|
|
|
222
224
|
const root = engine.scene?.tree.root;
|
|
223
225
|
if (!root) throw new Error('no scene');
|
|
224
226
|
const player = root.getNode('Player') as unknown as Vec;
|
|
225
|
-
// wolves take TWO strikes now (first = flinch knockback
|
|
227
|
+
// wolves take TWO strikes now (first = flinch: `Health.knockback` shoves
|
|
228
|
+
// it along the blow and `staggerSeconds` holds its PathFollow)
|
|
226
229
|
for (let round = 0; round < 6; round++) {
|
|
227
230
|
const wolves = engine.scene?.tree.getNodesInGroup('wolf') ?? [];
|
|
228
231
|
const target = wolves[0] as unknown as Vec | undefined;
|
|
@@ -233,10 +236,49 @@ const ok = (label: string, cond: boolean): void => {
|
|
|
233
236
|
(target.position[2] ?? 0) + 0.8,
|
|
234
237
|
];
|
|
235
238
|
engine.step();
|
|
239
|
+
let hitAt = -1;
|
|
240
|
+
let hitPos: number[] = [];
|
|
241
|
+
let cur = 0;
|
|
242
|
+
if (round === 0) {
|
|
243
|
+
const vitals = (
|
|
244
|
+
target as unknown as { getNode(p: string): { behavior: unknown } }
|
|
245
|
+
).getNode('Vitals').behavior as {
|
|
246
|
+
on(s: string, f: () => void): void;
|
|
247
|
+
};
|
|
248
|
+
vitals.on('damaged', () => {
|
|
249
|
+
hitAt = cur;
|
|
250
|
+
hitPos = [...target.position];
|
|
251
|
+
});
|
|
252
|
+
}
|
|
236
253
|
engine.input.pressAction('attack');
|
|
237
254
|
engine.step();
|
|
238
255
|
engine.input.releaseAction('attack');
|
|
239
|
-
|
|
256
|
+
let held: number[] = [];
|
|
257
|
+
for (let i = 0; i < (round === 0 ? 60 : 40); i++) {
|
|
258
|
+
cur = i;
|
|
259
|
+
engine.step();
|
|
260
|
+
if (round === 0 && hitAt >= 0) {
|
|
261
|
+
const away = [
|
|
262
|
+
(target.position[0] ?? 0) - (player.position[0] ?? 0),
|
|
263
|
+
(target.position[2] ?? 0) - (player.position[2] ?? 0),
|
|
264
|
+
];
|
|
265
|
+
const len = Math.hypot(away[0] ?? 0, away[1] ?? 0) || 1;
|
|
266
|
+
const moved = [
|
|
267
|
+
(target.position[0] ?? 0) - (hitPos[0] ?? 0),
|
|
268
|
+
(target.position[2] ?? 0) - (hitPos[2] ?? 0),
|
|
269
|
+
];
|
|
270
|
+
if (i === hitAt + 9) {
|
|
271
|
+
wolfKnock =
|
|
272
|
+
((moved[0] ?? 0) * (away[0] ?? 0) + (moved[1] ?? 0) * (away[1] ?? 0)) / len;
|
|
273
|
+
held = [...target.position];
|
|
274
|
+
}
|
|
275
|
+
if (i === hitAt + 17)
|
|
276
|
+
wolfHeld = Math.hypot(
|
|
277
|
+
(target.position[0] ?? 0) - (held[0] ?? 0),
|
|
278
|
+
(target.position[2] ?? 0) - (held[2] ?? 0),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
240
282
|
}
|
|
241
283
|
const left = engine.scene?.tree.getNodesInGroup('wolf').length ?? -1;
|
|
242
284
|
if (left !== 0) throw new Error(`${left} wolves survived`);
|
|
@@ -276,6 +318,14 @@ const ok = (label: string, cond: boolean): void => {
|
|
|
276
318
|
});
|
|
277
319
|
|
|
278
320
|
ok('QUEST: full loop (dialogue → grove → wolves → report back)', result.ok);
|
|
321
|
+
ok(
|
|
322
|
+
`QUEST: the first strike MOVED the wolf ${wolfKnock.toFixed(2)} m along the blow (Health.knockback)`,
|
|
323
|
+
wolfKnock > 0.12,
|
|
324
|
+
);
|
|
325
|
+
ok(
|
|
326
|
+
`QUEST: …and HELD it: ${wolfHeld.toFixed(2)} m walked in the 8 frames after (PathFollow staggered; free = 0.32 m)`,
|
|
327
|
+
wolfHeld >= 0 && wolfHeld < 0.05,
|
|
328
|
+
);
|
|
279
329
|
for (const f of result.failures) console.error(` ${f.label}: ${f.message}`);
|
|
280
330
|
}
|
|
281
331
|
|