incanto 0.69.0 → 0.70.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/_behaviors-loader.mjs +22 -0
- package/bin/_read-json.mjs +28 -0
- package/bin/incanto-assets.mjs +5 -4
- package/bin/incanto-check.mjs +58 -31
- package/bin/incanto-editor.mjs +128 -5
- package/bin/incanto-env.mjs +3 -2
- package/bin/incanto-feel.mjs +24 -13
- package/bin/incanto-frame.mjs +8 -1
- package/bin/incanto-multiplay.mjs +11 -9
- package/bin/incanto-new.mjs +105 -10
- package/bin/incanto-play.mjs +158 -16
- package/bin/incanto-playtest.mjs +66 -23
- package/bin/incanto-skills.mjs +14 -2
- package/bin/incanto-verify.mjs +125 -44
- package/bin/incanto.mjs +3 -2
- package/dist/2d.d.ts +281 -34
- package/dist/2d.js +4 -4
- package/dist/3d.d.ts +157 -9
- package/dist/3d.js +7 -7
- package/dist/{agent8-CvsfVskX.js → agent8-CmNF01gA.js} +61 -8
- package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-DaMxqfNE.d.ts} +2 -2
- package/dist/{behavior-rm8vVzu_.d.ts → behavior-DZExDn9o.d.ts} +744 -46
- package/dist/{create-game-CwxEDlCm.js → create-game-Bwvh6q8A.js} +142 -59
- package/dist/{create-game-CvJ1wSRP.js → create-game-C7ffQWW7.js} +97 -47
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +2 -3
- package/dist/diagnostics-Cu85N3tL.d.ts +12 -0
- package/dist/{editor-switch-CnIOiyNJ.d.ts → editor-switch-CFU9mCec.d.ts} +22 -13
- package/dist/editor.js +1065 -863
- package/dist/env.d.ts +1 -1
- package/dist/env.js +5 -3
- package/dist/{environment-presets-BO-7XoFV.js → environment-presets-D6Q5BxeE.js} +298 -45
- package/dist/{gameplay-D1KixWK8.js → gameplay-BfHkuzVb.js} +809 -211
- package/dist/gameplay.d.ts +187 -7
- package/dist/gameplay.js +1 -1
- package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
- package/dist/index.d.ts +156 -13
- package/dist/index.js +10 -12
- package/dist/json-CfTjpvW8.js +67 -0
- package/dist/{loader-DadV2QCT.d.ts → loader-Cff09LMm.d.ts} +2 -2
- package/dist/net.d.ts +27 -3
- package/dist/net.js +2 -2
- package/dist/{noise-CGUMx44x.js → noise-D3nPpmFg.js} +1 -1
- package/dist/{physics-2d-CF5yyjbj.js → physics-2d-CE0Qvy3V.js} +136 -11
- package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CpH-2gn5.js} +104 -23
- package/dist/{teardown-CMqFVxO9.js → picking-CQJ_PJKh.js} +103 -12
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{register-mmfugpaQ.js → register-6DYnKZcy.js} +546 -817
- package/dist/{register-DbVArsns.js → register-Bkk0wSDB.js} +332 -23
- package/dist/{replay-BEHLDcQV.js → replay-DjAkAzMq.js} +224 -14
- package/dist/{replay-BQfkX4x7.d.ts → replay-Dmw-PKQu.d.ts} +20 -3
- package/dist/{schema-B6ugCV1Q.d.ts → rng-Bb-IutXB.d.ts} +38 -21
- package/dist/{rng-DP-SR7eg.js → rng-CDOMybym.js} +22 -0
- package/dist/{loader-DZE7B07H.js → save-slots-BXVg148r.js} +4570 -2322
- package/dist/{split-screen-Cg76MCV5.d.ts → split-screen--k-XpBjr.d.ts} +36 -4
- package/dist/{split-screen-CauMwu6y.js → split-screen-PL78oVXP.js} +159 -26
- package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
- package/dist/{src-CYEu-_S9.js → src-Cxfiv1Hg.js} +2 -17
- package/dist/test-iHYVUcDK.js +4036 -0
- package/dist/test.d.ts +531 -30
- package/dist/test.js +3 -3
- package/dist/touch-BnCyPA0G.js +519 -0
- package/dist/vite.d.ts +20 -37
- package/dist/vite.js +176 -6
- package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
- package/editor/assets/agent8-D0MS174y.js +1 -0
- package/editor/assets/{debug-CMULinBW.js → debug-BnXkKuYu.js} +2 -2
- package/editor/assets/index-CIu3uc3l.js +11046 -0
- package/editor/index.html +1 -1
- package/package.json +4 -14
- package/schemas/scene.schema.json +30 -3
- package/skills/incanto-3d-character.md +14 -1
- package/skills/incanto-3d-models.md +12 -0
- package/skills/incanto-assets.md +9 -1
- package/skills/incanto-audio.md +8 -2
- package/skills/incanto-behaviors-and-scripts.md +83 -6
- package/skills/incanto-building-2d-games.md +77 -8
- package/skills/incanto-building-3d-games.md +58 -4
- package/skills/incanto-editor.md +46 -7
- package/skills/incanto-environment.md +19 -1
- package/skills/incanto-game-feel.md +70 -0
- package/skills/incanto-gameplay-behaviors.md +109 -19
- package/skills/incanto-hud.md +128 -7
- package/skills/incanto-localization.md +13 -5
- package/skills/incanto-multiplayer.md +83 -3
- package/skills/incanto-node-reference.md +222 -58
- package/skills/incanto-performance.md +52 -0
- package/skills/incanto-physics-and-input.md +123 -24
- package/skills/incanto-playtesting.md +78 -2
- package/skills/incanto-save-slots.md +161 -6
- package/skills/incanto-scene-json-authoring.md +69 -12
- package/skills/incanto-verifying-your-game.md +196 -10
- package/skills/incanto-web-integration.md +28 -0
- package/skills/incanto-your-first-game.md +3 -1
- package/templates-app/beacon-isle-3d/generate-world.ts +77 -9
- package/templates-app/beacon-isle-3d/package.json +2 -2
- package/templates-app/beacon-isle-3d/src/behaviors.ts +22 -0
- package/templates-app/beacon-isle-3d/src/game.scene.json +103 -378
- package/templates-app/beacon-isle-3d/src/main.ts +11 -1
- package/templates-app/beacon-isle-3d/tsconfig.json +1 -1
- package/templates-app/beacon-isle-3d/verify.ts +3 -1
- package/templates-app/molehill-2d/.incanto/playtest/lost-seed1.json +4277 -0
- package/templates-app/molehill-2d/PROJECT/Context.md +58 -0
- package/templates-app/molehill-2d/PROJECT/Requirements.md +39 -0
- package/templates-app/molehill-2d/PROJECT/Status.md +27 -0
- package/templates-app/molehill-2d/PROJECT/Structure.md +48 -0
- package/templates-app/molehill-2d/docs/project-2d-rules.md +44 -0
- package/templates-app/molehill-2d/index.html +73 -0
- package/templates-app/molehill-2d/package.json +23 -0
- package/templates-app/molehill-2d/src/behaviors.ts +198 -0
- package/templates-app/molehill-2d/src/game.scene.json +1255 -0
- package/templates-app/molehill-2d/src/main.ts +41 -0
- package/templates-app/molehill-2d/tsconfig.json +13 -0
- package/templates-app/molehill-2d/verify.ts +247 -0
- package/templates-app/molehill-2d/vite.config.ts +12 -0
- package/templates-app/platformer-2d/package.json +2 -2
- package/templates-app/platformer-2d/src/game.scene.json +128 -600
- package/templates-app/platformer-2d/src/main.ts +11 -1
- package/templates-app/platformer-2d/tsconfig.json +1 -1
- package/templates-app/star-survivor/package.json +2 -2
- package/templates-app/star-survivor/src/game.scene.json +41 -195
- package/templates-app/star-survivor/src/main.ts +11 -1
- package/templates-app/star-survivor/tsconfig.json +1 -1
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/package.json +2 -2
- package/templates-app/tps-3d/src/behaviors.ts +19 -1
- package/templates-app/tps-3d/src/game.scene.json +78 -217
- package/templates-app/tps-3d/src/main.ts +13 -2
- package/templates-app/tps-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/.incanto/playtest/swapped-seed1.json +1735 -0
- package/templates-app/village-quest-3d/package.json +2 -2
- package/templates-app/village-quest-3d/src/behaviors.ts +21 -0
- package/templates-app/village-quest-3d/src/grove.scene.json +54 -221
- package/templates-app/village-quest-3d/src/main.ts +11 -1
- package/templates-app/village-quest-3d/src/village.scene.json +199 -838
- package/templates-app/village-quest-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/verify.ts +14 -1
- package/dist/duplicate-Dj4L-5AA.js +0 -22
- package/dist/json-CwwhxQgb.js +0 -36
- package/dist/registry-CF70EArN.js +0 -212
- package/dist/rolldown-runtime-D7D4PA-g.js +0 -13
- package/dist/test-D6ISmuFE.js +0 -2383
- package/dist/touch-DEAmqGdf.js +0 -225
- package/editor/assets/agent8-BDvaZMQJ.js +0 -1
- package/editor/assets/index-CZIRr5EL.js +0 -10958
package/dist/gameplay.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-
|
|
2
|
-
import { c as JsonValue, s as JsonObject } from "./
|
|
1
|
+
import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-DZExDn9o.js";
|
|
2
|
+
import { c as JsonValue, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
3
3
|
|
|
4
4
|
//#region src/gameplay/chase.d.ts
|
|
5
5
|
/**
|
|
@@ -58,6 +58,8 @@ declare class Collector extends Behavior {
|
|
|
58
58
|
/** How many have been picked up so far. */
|
|
59
59
|
override serialize(): JsonValue;
|
|
60
60
|
override deserialize(data: JsonValue): void;
|
|
61
|
+
/** The counter on screen. `collect(0)` used to be the only way to repaint it. */
|
|
62
|
+
override announce(): void;
|
|
61
63
|
}
|
|
62
64
|
//#endregion
|
|
63
65
|
//#region src/gameplay/currency.d.ts
|
|
@@ -85,10 +87,21 @@ declare class Currency extends Behavior {
|
|
|
85
87
|
spend(cost: number): boolean;
|
|
86
88
|
/** Take payment in. */
|
|
87
89
|
earn(gain: number): void;
|
|
90
|
+
/** What has already been complained about, so a loop says it once. */
|
|
91
|
+
private complained;
|
|
92
|
+
/**
|
|
93
|
+
* A zero is ordinary; a NEGATIVE is a caller that flipped a sign.
|
|
94
|
+
*
|
|
95
|
+
* Reported rather than thrown: this is called from game code inside a frame,
|
|
96
|
+
* and a throw here quarantines the node holding the player's money.
|
|
97
|
+
*/
|
|
98
|
+
private refuseNonsense;
|
|
88
99
|
/** Set it outright (a shop that grants, a cheat, a restore). */
|
|
89
100
|
setAmount(next: number): void;
|
|
90
101
|
override serialize(): JsonValue;
|
|
91
102
|
override deserialize(data: JsonValue): void;
|
|
103
|
+
/** The wallet on screen — `setAmount`'s own doc comment already named a restore. */
|
|
104
|
+
override announce(): void;
|
|
92
105
|
}
|
|
93
106
|
//#endregion
|
|
94
107
|
//#region src/gameplay/health.d.ts
|
|
@@ -116,6 +129,7 @@ declare class Health extends Behavior {
|
|
|
116
129
|
regenPerSec: number;
|
|
117
130
|
invulnerableFor: number;
|
|
118
131
|
freeOnDeath: boolean;
|
|
132
|
+
freeParent: boolean;
|
|
119
133
|
/** Current hit points (set to `max` on ready). */
|
|
120
134
|
current: number;
|
|
121
135
|
private invulnTimer;
|
|
@@ -194,6 +208,14 @@ declare class Health extends Behavior {
|
|
|
194
208
|
/** Current HP and whether death already fired — `max` comes back from JSON. */
|
|
195
209
|
override serialize(): JsonValue;
|
|
196
210
|
override deserialize(data: JsonValue): void;
|
|
211
|
+
/**
|
|
212
|
+
* Repaint the bar. Not `died` — a save is being read, nobody just died.
|
|
213
|
+
*
|
|
214
|
+
* This one needed the hook most: `setCurrent` is private AND early-returns
|
|
215
|
+
* when the value is unchanged, so no call a game could make would repaint a
|
|
216
|
+
* restored bar. It read 100 at 38 HP until the next hit teleported it to 37.
|
|
217
|
+
*/
|
|
218
|
+
override announce(): void;
|
|
197
219
|
}
|
|
198
220
|
//#endregion
|
|
199
221
|
//#region src/gameplay/damage-on-contact.d.ts
|
|
@@ -297,6 +319,7 @@ declare class FollowCamera extends Behavior {
|
|
|
297
319
|
offset: number[];
|
|
298
320
|
smoothing: number;
|
|
299
321
|
deadzone: number;
|
|
322
|
+
private shakeRng;
|
|
300
323
|
override onReady(): void;
|
|
301
324
|
private shakeMag;
|
|
302
325
|
private shakeT;
|
|
@@ -321,6 +344,8 @@ declare class Interactable extends Behavior {
|
|
|
321
344
|
action: string;
|
|
322
345
|
range: number;
|
|
323
346
|
actorGroup: string;
|
|
347
|
+
/** Actions already reported missing, so a per-frame read says it once. */
|
|
348
|
+
private readonly reportedActions;
|
|
324
349
|
override update(): void;
|
|
325
350
|
}
|
|
326
351
|
//#endregion
|
|
@@ -466,7 +491,31 @@ declare class Patrol extends Behavior {
|
|
|
466
491
|
* this one is invisible to it.
|
|
467
492
|
*/
|
|
468
493
|
private reportDeadWaypoint;
|
|
469
|
-
/**
|
|
494
|
+
/**
|
|
495
|
+
* Resolve waypoint `i` to a position in the MOVER's frame, reading node paths
|
|
496
|
+
* live.
|
|
497
|
+
*
|
|
498
|
+
* A node-path waypoint used to return the marker's raw `position`, which is
|
|
499
|
+
* parent-relative — and it was then fed to `moveToward(mover.position, …)`,
|
|
500
|
+
* i.e. read in the MOVER's frame. So a walker and its markers under different
|
|
501
|
+
* parents walked a shifted copy of the path, silently, with the marker nodes
|
|
502
|
+
* sitting right there in the scene. Measured on a tower-defence lane
|
|
503
|
+
* organised the ordinary way (markers under `/root/Path`, spawns under a
|
|
504
|
+
* container at [-50, 90]): every creep stacked motionless 90 px below and
|
|
505
|
+
* 72 px short of the keep, `incanto-check` `1/1 scene(s) valid`, zero errors,
|
|
506
|
+
* zero warnings, and the wave could be neither won nor lost.
|
|
507
|
+
*
|
|
508
|
+
* `Chase` has converted through world space since the identical bug was found
|
|
509
|
+
* there ("comparing two nodes' raw `position` only worked while they happened
|
|
510
|
+
* to share a parent"), and a `FollowCamera` aimed at a node uses its world
|
|
511
|
+
* position too. Patrol was the outlier.
|
|
512
|
+
*
|
|
513
|
+
* A LITERAL array stays local, because that is the only frame an author can
|
|
514
|
+
* mean when they type numbers into a behaviour's props.
|
|
515
|
+
*
|
|
516
|
+
* `reportDeadWaypoint` could not see this: it fires when a path resolves to
|
|
517
|
+
* NOTHING, and a path that resolves into the wrong frame resolves fine.
|
|
518
|
+
*/
|
|
470
519
|
private pointAt;
|
|
471
520
|
private advance;
|
|
472
521
|
}
|
|
@@ -508,14 +557,58 @@ declare class Pickup extends Behavior {
|
|
|
508
557
|
* `null` (the engine's "any JSON" escape hatch) and `null` means `'forward'`.
|
|
509
558
|
* `gravity` adds a constant downward (+y, the 2D y-down convention) pull, for
|
|
510
559
|
* lobbed/arcing shots.
|
|
560
|
+
*
|
|
561
|
+
* **Every prop here is live.** `speed` and `direction` re-bake the heading when
|
|
562
|
+
* written, and the heading is resolved on the FIRST STEP rather than at
|
|
563
|
+
* `onReady` — because `onReady` is before the one place a game aims a spawned
|
|
564
|
+
* bullet. `SpawnSource.spawn` ends with `parent.addChild(clone)` and `Spawner`
|
|
565
|
+
* emits `spawned(node)` after that, so a handler that sets a rotation or a
|
|
566
|
+
* direction was always too late. Measured at speed 100 over 60 frames:
|
|
567
|
+
*
|
|
568
|
+
* ```
|
|
569
|
+
* A rotation 0 direction [0,1] -> pos [ 0, 100] authored: obeyed
|
|
570
|
+
* B rotation 90 direction "forward" -> pos [ 0, 100] authored: obeyed
|
|
571
|
+
* C rotation 90 set after addChild -> pos [100, 0] IGNORED
|
|
572
|
+
* D direction [0,1] set after add -> pos [100, 0] IGNORED — and it read
|
|
573
|
+
* back [0,1] while
|
|
574
|
+
* travelling +x
|
|
575
|
+
* ```
|
|
576
|
+
*
|
|
577
|
+
* What is deliberately NOT live is `rotation` after that first step: a
|
|
578
|
+
* projectile that spins for looks would have its spin become its trajectory.
|
|
579
|
+
* Call `aim()` to re-derive from the current rotation on purpose.
|
|
511
580
|
*/
|
|
512
581
|
declare class Projectile extends Behavior {
|
|
513
582
|
static readonly props: PropSchema;
|
|
514
583
|
static readonly signals: readonly string[];
|
|
515
|
-
|
|
516
|
-
|
|
584
|
+
private _speed;
|
|
585
|
+
private _direction;
|
|
517
586
|
gravity: number;
|
|
587
|
+
/** The straight-line part, `direction × speed`. Empty until the first step. */
|
|
518
588
|
private velocity;
|
|
589
|
+
/**
|
|
590
|
+
* The +y accumulated by `gravity`, kept APART from `velocity`.
|
|
591
|
+
*
|
|
592
|
+
* Re-aiming replaces the straight-line part; the fall is a fact about the
|
|
593
|
+
* world, not about the shot, so an arrow re-aimed halfway down keeps falling
|
|
594
|
+
* rather than snapping back to level.
|
|
595
|
+
*/
|
|
596
|
+
private fall;
|
|
597
|
+
/** Units per second along `direction`. Writable at any time. */
|
|
598
|
+
get speed(): number;
|
|
599
|
+
set speed(value: number);
|
|
600
|
+
/** A vector (`[x,y(,z)]`) or `'forward'`. Writable at any time. */
|
|
601
|
+
get direction(): JsonValue;
|
|
602
|
+
set direction(value: JsonValue);
|
|
603
|
+
private get armed();
|
|
604
|
+
/**
|
|
605
|
+
* Re-derive the heading from `direction` (or, for `'forward'`, from the
|
|
606
|
+
* node's CURRENT rotation) and bake it into the velocity.
|
|
607
|
+
*
|
|
608
|
+
* This is what a `spawned(node)` handler calls after turning the clone, and
|
|
609
|
+
* the only way a `'forward'` projectile ever re-reads its rotation.
|
|
610
|
+
*/
|
|
611
|
+
aim(direction?: JsonValue | undefined): void;
|
|
519
612
|
override onReady(): void;
|
|
520
613
|
override update(dt: number): void;
|
|
521
614
|
/** Resolve `direction` to a unit vector, deriving 'forward' from rotation. */
|
|
@@ -642,6 +735,14 @@ declare class ScoreKeeper extends Behavior {
|
|
|
642
735
|
/** The run's progress. `scoreToWin` is balance and comes back from JSON. */
|
|
643
736
|
override serialize(): JsonValue;
|
|
644
737
|
override deserialize(data: JsonValue): void;
|
|
738
|
+
/**
|
|
739
|
+
* The score line and the lives counter. NOT `won`/`lost`.
|
|
740
|
+
*
|
|
741
|
+
* Re-firing those on load is how a Continue lands straight on the game-over
|
|
742
|
+
* screen it was loaded to escape — the flags come back through `hasWon` /
|
|
743
|
+
* `hasLost` and the game reads them, rather than being told again.
|
|
744
|
+
*/
|
|
745
|
+
override announce(): void;
|
|
645
746
|
}
|
|
646
747
|
//#endregion
|
|
647
748
|
//#region src/gameplay/spawner.d.ts
|
|
@@ -679,6 +780,7 @@ declare class Spawner extends Behavior {
|
|
|
679
780
|
get liveCount(): number;
|
|
680
781
|
/** @internal The detached template node (test/debug only). */
|
|
681
782
|
_templateForTest(): Node;
|
|
783
|
+
override onEnterTree(): void;
|
|
682
784
|
override onReady(): void;
|
|
683
785
|
/** Begin (or resume) interval spawning. */
|
|
684
786
|
start(): void;
|
|
@@ -740,9 +842,27 @@ declare class WaveSpawner extends Behavior {
|
|
|
740
842
|
private timer;
|
|
741
843
|
private spawnedThisWave;
|
|
742
844
|
private announced;
|
|
845
|
+
override onEnterTree(): void;
|
|
743
846
|
override onReady(): void;
|
|
744
847
|
/** Start (or restart from) wave 0. */
|
|
745
848
|
start(): void;
|
|
849
|
+
/**
|
|
850
|
+
* Which wave you were on — and nothing else.
|
|
851
|
+
*
|
|
852
|
+
* `behaviorsWithoutSave` is documented as "the list to read before shipping",
|
|
853
|
+
* and nobody had read it against this repo's own examples. Five of them put a
|
|
854
|
+
* `WaveSpawner` at the centre of the game (`fps-3d`, `tps-3d`, `tps-3d-neon`,
|
|
855
|
+
* `tps-3d-ruins`, `dogfight-3d`), and every one of them saved a run on wave 3
|
|
856
|
+
* and continued it on wave 1 — silently, because a save reloads the scene
|
|
857
|
+
* from source and a fresh `onReady` honestly starts at the beginning.
|
|
858
|
+
*
|
|
859
|
+
* The wave RESTARTS rather than resuming mid-spawn, which is the same
|
|
860
|
+
* checkpoint rule the rest of the save system follows: spawned entities are
|
|
861
|
+
* never restored, so resuming "four enemies into wave 3" would mean resuming
|
|
862
|
+
* a wave whose enemies do not exist. `waveStarted` fires again for the HUD.
|
|
863
|
+
*/
|
|
864
|
+
override serialize(): JsonValue;
|
|
865
|
+
override deserialize(data: JsonValue): void;
|
|
746
866
|
override update(dt: number): void;
|
|
747
867
|
private beginWave;
|
|
748
868
|
private prune;
|
|
@@ -834,6 +954,18 @@ declare class DayNight extends Behavior {
|
|
|
834
954
|
private baseAmbient;
|
|
835
955
|
private baseExposure;
|
|
836
956
|
private captured;
|
|
957
|
+
/** Said once: there was no sky to move when this first looked. */
|
|
958
|
+
private reportedNoSky;
|
|
959
|
+
/**
|
|
960
|
+
* What time it is. A save that forgets it returns you at dawn.
|
|
961
|
+
*
|
|
962
|
+
* `startHour` is the scene's opening, not the run's clock: a fresh `onReady`
|
|
963
|
+
* cannot know that this player has been out all night. `paused` goes with it
|
|
964
|
+
* because a game that stops the clock for a cutscene must not resume ticking
|
|
965
|
+
* on load.
|
|
966
|
+
*/
|
|
967
|
+
override serialize(): JsonValue;
|
|
968
|
+
override deserialize(data: JsonValue): void;
|
|
837
969
|
override onReady(): void;
|
|
838
970
|
override update(dt: number): void;
|
|
839
971
|
private applyHour;
|
|
@@ -904,6 +1036,25 @@ type GameFlowState = "playing" | "paused" | "gameover" | "won";
|
|
|
904
1036
|
/**
|
|
905
1037
|
* Swap to another scene behind a black fade (title→game→next level).
|
|
906
1038
|
* Headless (no DOM) the swap is immediate. Restores timeScale to 1.
|
|
1039
|
+
*
|
|
1040
|
+
* ONE AT A TIME. A door is usually a trigger, and a player who walks along a
|
|
1041
|
+
* wall of them fires several inside one fade. Measured on three doorways passed
|
|
1042
|
+
* in about a second:
|
|
1043
|
+
*
|
|
1044
|
+
* ```
|
|
1045
|
+
* setScene calls: 3 | order: ["crypt","garden","forge"]
|
|
1046
|
+
* final scene : forge
|
|
1047
|
+
* ```
|
|
1048
|
+
*
|
|
1049
|
+
* Three complete scenes loaded and the player landed in the third — a level
|
|
1050
|
+
* they never walked to, from a door they never reached. Further calls while a
|
|
1051
|
+
* travel is in flight are IGNORED rather than queued: you already went through
|
|
1052
|
+
* a door, and the second one is the same input arriving twice.
|
|
1053
|
+
*
|
|
1054
|
+
* The outgoing scene also stops while the screen is black. It kept simulating
|
|
1055
|
+
* through the fade, so a player who triggered the door mid-fall died in the
|
|
1056
|
+
* level they were leaving — and the checkpoint that death wrote was for the
|
|
1057
|
+
* level they had left.
|
|
907
1058
|
*/
|
|
908
1059
|
declare function goToScene(engine: Engine, sceneJson: JsonObject, opts?: {
|
|
909
1060
|
fadeSeconds?: number;
|
|
@@ -961,8 +1112,24 @@ declare class GameFlow extends Behavior {
|
|
|
961
1112
|
state: GameFlowState;
|
|
962
1113
|
private frozeScale;
|
|
963
1114
|
override onReady(): void;
|
|
964
|
-
/**
|
|
1115
|
+
/**
|
|
1116
|
+
* The panel follows the state; nothing else may own its visibility.
|
|
1117
|
+
*
|
|
1118
|
+
* …and while it is up, the layer it lives on takes ARROW KEYS AND THE PAD.
|
|
1119
|
+
* `HudLayer.focusNavigation` is off by default and rightly so — a game whose
|
|
1120
|
+
* HUD happens to contain a button must not lose its arrow keys the moment one
|
|
1121
|
+
* exists — and `incanto-hud.md` says "turn it on for the screens that ARE
|
|
1122
|
+
* menus and off again when play resumes". A pause panel IS that screen, and
|
|
1123
|
+
* this is the one place in the engine that knows when it opens and closes, so
|
|
1124
|
+
* every game with a pause menu was writing the same two lines or shipping a
|
|
1125
|
+
* menu no controller could reach.
|
|
1126
|
+
*
|
|
1127
|
+
* The layer's own value is remembered and put back: a game that turned
|
|
1128
|
+
* navigation on for its own reasons keeps it after a pause.
|
|
1129
|
+
*/
|
|
965
1130
|
private syncPausePanel;
|
|
1131
|
+
/** The layer's own `focusNavigation`, while this flow is borrowing it. */
|
|
1132
|
+
private navigationWas;
|
|
966
1133
|
gameOver(text?: string, color?: string): void;
|
|
967
1134
|
win(text?: string, color?: string): void;
|
|
968
1135
|
pause(): void;
|
|
@@ -971,7 +1138,7 @@ declare class GameFlow extends Behavior {
|
|
|
971
1138
|
/** Fade to another scene (next level, back to title). */
|
|
972
1139
|
goToScene(sceneJson: JsonObject, opts?: {
|
|
973
1140
|
fadeSeconds?: number;
|
|
974
|
-
}): void;
|
|
1141
|
+
} | undefined): void;
|
|
975
1142
|
private transition;
|
|
976
1143
|
private freeze;
|
|
977
1144
|
private thaw;
|
|
@@ -1025,6 +1192,19 @@ declare class CameraShake extends Behavior {
|
|
|
1025
1192
|
private t;
|
|
1026
1193
|
private prev;
|
|
1027
1194
|
/**
|
|
1195
|
+
* Decoration draws from its OWN stream — see `effectRng`.
|
|
1196
|
+
*
|
|
1197
|
+
* A shake drew from `engine.rng`, the stream game logic reads and
|
|
1198
|
+
* `captureState` saves, once per axis per RENDERED frame. So the player's
|
|
1199
|
+
* frame rate decided the game's random numbers, and toggling the
|
|
1200
|
+
* `reduceMotion` accessibility switch changed the rolls: a replay recorded at
|
|
1201
|
+
* 60 fps does not reproduce on a laptop that dropped to 30, and two players
|
|
1202
|
+
* with the same seed diverge because one of them was hit. The particle
|
|
1203
|
+
* siblings were moved off `engine.rng` for exactly this; both camera shakes
|
|
1204
|
+
* were left behind.
|
|
1205
|
+
*/
|
|
1206
|
+
private shakeRng;
|
|
1207
|
+
/**
|
|
1028
1208
|
* Start a shake — unless the player asked for no motion.
|
|
1029
1209
|
*
|
|
1030
1210
|
* `settings.reduceMotion` is an accessibility switch, and camera movement the
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as phaseOf, C as restartScene, D as FloatAway, F as Chase, M as Health, N as Currency, O as FaceTarget, P as Collector, S as goToScene, T as FollowCamera, X as localFromWorld, Z as worldPosition, _ as Cooldown, a as Wander, b as Interactable, c as SavePoint, d as Patrol, f as PathFollow, g as CameraShake, h as Lifetime, i as WaveSpawner, j as DamageOnContact, k as DayNight, l as Projectile, m as MoveTo, n as registerGameplayBehaviors, o as Spawner, p as Oscillate, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Pickup, v as hitStop, x as GameFlow, y as screenFlash } from "./gameplay-BfHkuzVb.js";
|
|
2
2
|
export { CameraShake, Chase, Collector, Cooldown, Currency, DamageOnContact, DayNight, FaceTarget, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, localFromWorld, phaseOf, registerGameplayBehaviors, restartScene, screenFlash, worldPosition };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { a as ParticleSimConfig, c as showBootFailure, i as ParticleSim, n as AudioPlayer, o as ParticleView, s as isWebGLAvailable, t as AudioElementLike } from "./audio-player-
|
|
2
|
-
import { $ as T_PREFIX, A as SettingsValues, At as BusName, B as captureBehaviors, C as EngineStats, Ct as sfxDuration, Dt as MusicTrack, E as DeviceHints, Et as MusicManager, F as BehaviorState, Ft as LogLevel, G as ORDER_GROUP_BASE, H as savesWithoutUid, I as RestoreReport, It as LogManager, J as effectiveOrder, K as OrderGroup, L as SaveSlot, Lt as Signal, M as readDeviceHints, Mt as NodeLifecycle, N as suggestQuality, Nt as SceneTree, O as QualityTier, Ot as PlayMusicOptions, P as Scene, Pt as LogEntry, Q as Localization, R as SaveSlots, Rt as SignalListener, S as Scheduler, St as SynthOptions, T as RendererStats, Tt as MusicBackend, U as SaveStore, V as restoreBehaviors, W as createSaveStore, X as BASE_LOCALE, Y as resolveOrderGroups, Z as LocaleTables, _ as mergeStaticSignals, _t as spatialPan, a as clearBehaviors, at as EffectLog, b as Engine, bt as SfxParams, c as registeredBehaviors, ct as isAudioContextAvailable, d as PropSchema, dt as Listener, et as suggestLocale, f as clearRegistry, ft as ROLLOFF_MODELS, g as getNodeType, gt as spatialGain, h as getNodeSignals, ht as Vec3, i as behaviorSignals, it as EffectKind, j as qualityEnvironment, jt as Node, k as Settings, kt as AudioBuses, l as NodeCtor, lt as Voice, m as getNodeSchema, mt as SpatialParams, n as BehaviorCtor, nt as InputMap, o as getBehavior, ot as SfxEngine, p as createNode, pt as RolloffModel, q as OrderGroupTable, r as behaviorSchema, rt as EffectEvent, s as registerBehavior, st as SfxPlayOptions, t as Behavior, tt as translationKey, u as PropDef, ut as VoicePreset, v as registerNode, vt as SFX_PRESETS, w as GameStats, wt as synthSfx, x as EngineOptions, xt as SfxWave, y as registeredTypes, yt as SFX_PRESET_NAMES, z as behaviorsWithoutSave } from "./behavior-
|
|
3
|
-
import { a as
|
|
4
|
-
import { n as loadScene, t as LoadSceneOptions } from "./loader-
|
|
1
|
+
import { a as ParticleSimConfig, c as showBootFailure, i as ParticleSim, n as AudioPlayer, o as ParticleView, s as isWebGLAvailable, t as AudioElementLike } from "./audio-player-DaMxqfNE.js";
|
|
2
|
+
import { $ as T_PREFIX, A as SettingsValues, At as BusName, B as captureBehaviors, C as EngineStats, Ct as sfxDuration, Dt as MusicTrack, E as DeviceHints, Et as MusicManager, F as BehaviorState, Ft as LogLevel, G as ORDER_GROUP_BASE, H as savesWithoutUid, I as RestoreReport, It as LogManager, J as effectiveOrder, K as OrderGroup, L as SaveSlot, Lt as Signal, M as readDeviceHints, Mt as NodeLifecycle, N as suggestQuality, Nt as SceneTree, O as QualityTier, Ot as PlayMusicOptions, P as Scene, Pt as LogEntry, Q as Localization, R as SaveSlots, Rt as SignalListener, S as Scheduler, St as SynthOptions, T as RendererStats, Tt as MusicBackend, U as SaveStore, V as restoreBehaviors, W as createSaveStore, X as BASE_LOCALE, Y as resolveOrderGroups, Z as LocaleTables, _ as mergeStaticSignals, _t as spatialPan, a as clearBehaviors, at as EffectLog, b as Engine, bt as SfxParams, c as registeredBehaviors, ct as isAudioContextAvailable, d as PropSchema, dt as Listener, et as suggestLocale, f as clearRegistry, ft as ROLLOFF_MODELS, g as getNodeType, gt as spatialGain, h as getNodeSignals, ht as Vec3, i as behaviorSignals, it as EffectKind, j as qualityEnvironment, jt as Node, k as Settings, kt as AudioBuses, l as NodeCtor, lt as Voice, m as getNodeSchema, mt as SpatialParams, n as BehaviorCtor, nt as InputMap, o as getBehavior, ot as SfxEngine, p as createNode, pt as RolloffModel, q as OrderGroupTable, r as behaviorSchema, rt as EffectEvent, s as registerBehavior, st as SfxPlayOptions, t as Behavior, tt as translationKey, u as PropDef, ut as VoicePreset, v as registerNode, vt as SFX_PRESETS, w as GameStats, wt as synthSfx, x as EngineOptions, xt as SfxWave, y as registeredTypes, yt as SFX_PRESET_NAMES, z as behaviorsWithoutSave } from "./behavior-DZExDn9o.js";
|
|
3
|
+
import { a as SceneJson, c as JsonValue, d as jsonKind, i as SCENE_FORMAT, l as jsonClone, n as ConnectionJson, o as JsonKind, r as NodeJson, s as JsonObject, t as Rng, u as jsonEquals } from "./rng-Bb-IutXB.js";
|
|
4
|
+
import { n as loadScene, t as LoadSceneOptions } from "./loader-Cff09LMm.js";
|
|
5
5
|
import { i as resolveFrames, n as AnimationEntry, r as resolveAnimation, t as AnimationDef } from "./sprite-animation-CMr6f1K2.js";
|
|
6
6
|
import { i as gridFromRows, n as PathGrid, r as findPath, t as FindPathOptions } from "./pathfinding-_fGrCFmH.js";
|
|
7
|
-
import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-
|
|
7
|
+
import { a as startRecording, c as IncantoErrorDetails, i as replay, l as auditScene, n as ReplayEvent, o as IncantoError, r as ReplayJson, s as IncantoErrorCode, t as Recorder } from "./replay-Dmw-PKQu.js";
|
|
8
8
|
|
|
9
9
|
//#region src/core/audio/crossfade.d.ts
|
|
10
10
|
/**
|
|
@@ -109,6 +109,20 @@ type DriveStep = {
|
|
|
109
109
|
kind: "pointer";
|
|
110
110
|
dx: number;
|
|
111
111
|
dy: number;
|
|
112
|
+
} | {
|
|
113
|
+
kind: "at";
|
|
114
|
+
x: number;
|
|
115
|
+
y: number;
|
|
116
|
+
} | {
|
|
117
|
+
kind: "atNode";
|
|
118
|
+
path: string;
|
|
119
|
+
} | {
|
|
120
|
+
kind: "click";
|
|
121
|
+
button: number;
|
|
122
|
+
} | {
|
|
123
|
+
kind: "mouse";
|
|
124
|
+
button: number;
|
|
125
|
+
down: boolean;
|
|
112
126
|
} | {
|
|
113
127
|
kind: "step";
|
|
114
128
|
ms: number;
|
|
@@ -245,13 +259,26 @@ type RefResult = {
|
|
|
245
259
|
declare function resolveRefInJson(root: RefNode | undefined, owner: readonly number[], value: string): RefResult;
|
|
246
260
|
/** The problem in English, for `incanto-check` and as the editor's base text. */
|
|
247
261
|
declare function describeRefProblem(problem: RefProblem, value: string): string;
|
|
262
|
+
interface RefWarningOptions {
|
|
263
|
+
/**
|
|
264
|
+
* This file is a PREFAB another scene drops in, so a path may legitimately
|
|
265
|
+
* leave it.
|
|
266
|
+
*
|
|
267
|
+
* `/root/Bolts` is the fragment's own root only while the fragment is alone;
|
|
268
|
+
* attached, it resolves. Four such warnings stood forever on four of five
|
|
269
|
+
* files of a real project whose main scene audited clean. The verdict is
|
|
270
|
+
* reworded rather than suppressed: a typo'd path is MOST likely in a file
|
|
271
|
+
* written away from the scene that gives it meaning, so it still gets named.
|
|
272
|
+
*/
|
|
273
|
+
fragment?: boolean;
|
|
274
|
+
}
|
|
248
275
|
/**
|
|
249
276
|
* Scene lints for node-path props that point at nothing.
|
|
250
277
|
*
|
|
251
278
|
* An EMPTY value is not reported: `''` is the default of most of these props and
|
|
252
279
|
* means "not set", which is a choice rather than a typo.
|
|
253
280
|
*/
|
|
254
|
-
declare function nodeRefWarnings(scene: JsonObject): string[];
|
|
281
|
+
declare function nodeRefWarnings(scene: JsonObject, opts?: RefWarningOptions): string[];
|
|
255
282
|
//#endregion
|
|
256
283
|
//#region src/core/nodes/hud.d.ts
|
|
257
284
|
/**
|
|
@@ -305,6 +332,22 @@ declare class HudLayer extends Node {
|
|
|
305
332
|
override onExitTree(): void;
|
|
306
333
|
override update(): void;
|
|
307
334
|
/**
|
|
335
|
+
* Is this the layer the keyboard is talking to?
|
|
336
|
+
*
|
|
337
|
+
* Keyboard focus is singular by nature — a browser has ONE focused element —
|
|
338
|
+
* and `focusNavigation` is per LAYER, so a game with a HUD and a modal that
|
|
339
|
+
* armed both had a single Enter activate the focused widget in EACH: the
|
|
340
|
+
* pause menu's RESUME and whatever the screen underneath happened to have
|
|
341
|
+
* focused, which is "the modal does not block the screen behind it" arriving
|
|
342
|
+
* through the keyboard.
|
|
343
|
+
*
|
|
344
|
+
* The TOPMOST armed layer wins — last in document order, which is the one
|
|
345
|
+
* drawn on top, and the one a modal is. A hidden layer is not armed at all: a
|
|
346
|
+
* closed menu must not eat the key from the HUD it covers. With one layer,
|
|
347
|
+
* which is the usual case, this is always true.
|
|
348
|
+
*/
|
|
349
|
+
private ownsFocus;
|
|
350
|
+
/**
|
|
308
351
|
* Arrow keys / d-pad move the focus, Enter / A activates it.
|
|
309
352
|
*
|
|
310
353
|
* Off by default: a game whose HUD has a button must not lose its arrow keys
|
|
@@ -361,6 +404,19 @@ declare abstract class HudWidgetBase extends Node {
|
|
|
361
404
|
* A or an arrow ON this widget means. Default: nothing.
|
|
362
405
|
*/
|
|
363
406
|
_activate(_dir: number): void;
|
|
407
|
+
/**
|
|
408
|
+
* @internal What a MOUSE CLICK on this widget does. Defaults to `_activate`.
|
|
409
|
+
*
|
|
410
|
+
* For a button, a toggle and a select the two are the same thing, which is
|
|
411
|
+
* why one entry point served both for a while. For `UiDialogue` they are
|
|
412
|
+
* not: Enter on a waiting choice ANSWERS it, and a click on the box does
|
|
413
|
+
* not — `advance()` returns early while `current.choices` is set, with the
|
|
414
|
+
* comment "must pick — clicks don't skip choices".
|
|
415
|
+
*
|
|
416
|
+
* A harness whose `click:` answered the question would pass a test the real
|
|
417
|
+
* game fails, which is the one thing the ladder must not do.
|
|
418
|
+
*/
|
|
419
|
+
_click(): void;
|
|
364
420
|
/** @internal Draw the focus ring. Overridable if a widget wants its own. */
|
|
365
421
|
_paintFocus(): void;
|
|
366
422
|
/** @internal */
|
|
@@ -379,6 +435,27 @@ declare abstract class HudWidgetBase extends Node {
|
|
|
379
435
|
*/
|
|
380
436
|
_mountWidget(): void;
|
|
381
437
|
/**
|
|
438
|
+
* The gesture, without a pointer — the `press()` of drag and drop.
|
|
439
|
+
*
|
|
440
|
+
* All four signals lived on `_wireDrag`, which is wired to a DOM element and
|
|
441
|
+
* therefore does not exist headless. So the one screen the HUD skill says
|
|
442
|
+
* needs more than a click — an inventory — was the one screen no harness
|
|
443
|
+
* could drive: `dragStarted`, `droppedOn`, `dropped` and `dragCancelled`
|
|
444
|
+
* were unreachable from `runScript`, `incanto-playtest` and every check in
|
|
445
|
+
* the ladder, and a game that moves items between slots could only be tested
|
|
446
|
+
* by hand in a browser.
|
|
447
|
+
*
|
|
448
|
+
* Same rules as the pointer path, so a test that passes here is a test about
|
|
449
|
+
* the game: a non-`draggable` source does nothing, a target that is not a
|
|
450
|
+
* `dropTarget` CANCELS, and dropping a thing back where it came from — on
|
|
451
|
+
* itself, or on the slot it is already in — is not a move.
|
|
452
|
+
*
|
|
453
|
+
* Returns whether the drop was taken.
|
|
454
|
+
*/
|
|
455
|
+
dropOnto(target: HudWidgetBase | null): boolean;
|
|
456
|
+
/** The slot this widget is sitting in, if any — its origin for a drop. */
|
|
457
|
+
private dropTargetAbove;
|
|
458
|
+
/**
|
|
382
459
|
* Drag and drop, on the DOM the engine already builds.
|
|
383
460
|
*
|
|
384
461
|
* An inventory is the one screen where "click it" is not enough, and every
|
|
@@ -409,6 +486,12 @@ declare abstract class HudWidgetBase extends Node {
|
|
|
409
486
|
* did nothing at all, forever.
|
|
410
487
|
*/
|
|
411
488
|
private _followAnchor;
|
|
489
|
+
/**
|
|
490
|
+
* Follow the engine, and let a change made HERE reach it — with or without a
|
|
491
|
+
* DOM element. No element access allowed: this is the half that runs
|
|
492
|
+
* headless.
|
|
493
|
+
*/
|
|
494
|
+
protected _pull(): void;
|
|
412
495
|
protected _sync(): void;
|
|
413
496
|
/**
|
|
414
497
|
* Resolve a text prop through the engine's locale.
|
|
@@ -487,6 +570,20 @@ declare class UiText extends HudWidgetBase {
|
|
|
487
570
|
* authored opening line. Filling the slot with nothing instead would put
|
|
488
571
|
* `"Gems / 8"` on screen for every game's first frame, and a score line
|
|
489
572
|
* that starts blank looks broken rather than empty.
|
|
573
|
+
*
|
|
574
|
+
* Unless there IS no opening line. `format` alone painted `""`:
|
|
575
|
+
*
|
|
576
|
+
* ```
|
|
577
|
+
* format = 'Gems {} / 8'
|
|
578
|
+
* shown before setText "" <- nothing on screen
|
|
579
|
+
* shown after setText "Gems 3 / 8"
|
|
580
|
+
* ```
|
|
581
|
+
*
|
|
582
|
+
* and the signals a HUD is wired to — `scoreChanged`, `healthChanged` — only
|
|
583
|
+
* fire on CHANGE, so the row stays invisible through the whole opening of the
|
|
584
|
+
* game and forever if the value never moves. An empty slot in a visible
|
|
585
|
+
* template is the lesser of those two: it shows the author what they
|
|
586
|
+
* declared, where they declared it.
|
|
490
587
|
*/
|
|
491
588
|
get shown(): string;
|
|
492
589
|
override _paintedText(): string | undefined;
|
|
@@ -522,7 +619,7 @@ declare class UiBar extends HudWidgetBase {
|
|
|
522
619
|
* already has, so a bar whose ceiling moves (a max-HP upgrade) needs no
|
|
523
620
|
* second wire.
|
|
524
621
|
*/
|
|
525
|
-
setValue(value: number, max?: number): void;
|
|
622
|
+
setValue(value: number, max?: number | undefined): void;
|
|
526
623
|
/** Move the ceiling on its own, leaving the fill where it is. */
|
|
527
624
|
setMax(max: number): void;
|
|
528
625
|
protected _build(): HTMLElement;
|
|
@@ -554,7 +651,7 @@ declare class UiBanner extends HudWidgetBase {
|
|
|
554
651
|
show(text: string, opts?: {
|
|
555
652
|
color?: string;
|
|
556
653
|
seconds?: number;
|
|
557
|
-
}): void;
|
|
654
|
+
} | undefined): void;
|
|
558
655
|
/** Drop everything (scene transitions). */
|
|
559
656
|
clear(): void;
|
|
560
657
|
protected _build(): HTMLElement;
|
|
@@ -626,7 +723,7 @@ declare class UiDialogue extends HudWidgetBase {
|
|
|
626
723
|
/** What the box currently shows (grows while typing) — test-friendly. */
|
|
627
724
|
get showing(): string;
|
|
628
725
|
/** Queue a line; optional `choices` renders buttons after the line types out. */
|
|
629
|
-
say(speaker: string, text: string, choices?: string[]): void;
|
|
726
|
+
say(speaker: string, text: string, choices?: string[] | undefined): void;
|
|
630
727
|
/**
|
|
631
728
|
* A dialogue takes focus while it is up.
|
|
632
729
|
*
|
|
@@ -647,6 +744,14 @@ declare class UiDialogue extends HudWidgetBase {
|
|
|
647
744
|
* `dir` is 0 for "activate" and ±1 for a nudge, the same shape `UiSelect`
|
|
648
745
|
* uses — so one key layout drives a menu, a slider and a conversation.
|
|
649
746
|
*/
|
|
747
|
+
/**
|
|
748
|
+
* A click on the BOX is `advance()`, which refuses to skip a choice.
|
|
749
|
+
*
|
|
750
|
+
* The DOM handler is `box.addEventListener('click', () => this.advance())`
|
|
751
|
+
* and `advance` returns early while `current.choices` is set. Enter is a
|
|
752
|
+
* different verb — it answers — so a harness clicking the box must not.
|
|
753
|
+
*/
|
|
754
|
+
override _click(): void;
|
|
650
755
|
override _activate(dir: number): void;
|
|
651
756
|
/** Show which option the keyboard is on — a ring nobody can see is not one. */
|
|
652
757
|
private paintCursor;
|
|
@@ -776,6 +881,16 @@ declare class Timer extends Node {
|
|
|
776
881
|
private remaining;
|
|
777
882
|
start(time?: number): void;
|
|
778
883
|
stop(): void;
|
|
884
|
+
/**
|
|
885
|
+
* Scene-load validation: a period of zero is a timer that never fires.
|
|
886
|
+
*
|
|
887
|
+
* `update` guards it — a non-positive period "would spin forever on any dt",
|
|
888
|
+
* so it calls `stop()` — and the guard is right. Being SILENT about it is
|
|
889
|
+
* what a load error is for: a scene asking for a tick every zero seconds got
|
|
890
|
+
* no ticks and no word said. The runtime guard stays, for code that zeroes
|
|
891
|
+
* the period from a handler.
|
|
892
|
+
*/
|
|
893
|
+
static validateJson(node: Node): void;
|
|
779
894
|
override onReady(): void;
|
|
780
895
|
override update(dt: number): void;
|
|
781
896
|
}
|
|
@@ -890,6 +1005,22 @@ declare class UiSelect extends HudWidgetBase {
|
|
|
890
1005
|
options: string;
|
|
891
1006
|
value: string;
|
|
892
1007
|
override focusable: boolean;
|
|
1008
|
+
/** The options, as the list of values it actually offers. */
|
|
1009
|
+
private choices;
|
|
1010
|
+
/**
|
|
1011
|
+
* A value the list cannot show is a setting the game and the screen disagree
|
|
1012
|
+
* about.
|
|
1013
|
+
*
|
|
1014
|
+
* The browser cannot select an option that does not exist, so it shows the
|
|
1015
|
+
* FIRST one — while `node.value` keeps answering with what it was given, and
|
|
1016
|
+
* `changed` only fires when a person moves it, so nothing ever reconciles
|
|
1017
|
+
* them. That is the shape a saved setting has after a patch removes a quality
|
|
1018
|
+
* tier, and it is silent for the rest of the session.
|
|
1019
|
+
*
|
|
1020
|
+
* A hard error at LOAD, like every other enum in this engine. An empty value
|
|
1021
|
+
* is "nothing chosen yet", which is a choice.
|
|
1022
|
+
*/
|
|
1023
|
+
static validateJson(node: Node): void;
|
|
893
1024
|
/** Left/right (and confirm) walk the list — a select has no other gesture. */
|
|
894
1025
|
override _activate(dir: number): void;
|
|
895
1026
|
private select;
|
|
@@ -909,7 +1040,18 @@ declare class UiSelect extends HudWidgetBase {
|
|
|
909
1040
|
*/
|
|
910
1041
|
protected _optionLabel(value: string): string;
|
|
911
1042
|
private fillOptions;
|
|
1043
|
+
/** What was already reported, so a stuck value is said once and not per frame. */
|
|
1044
|
+
private complainedAbout;
|
|
1045
|
+
/**
|
|
1046
|
+
* The runtime half of `validateJson`.
|
|
1047
|
+
*
|
|
1048
|
+
* A behaviour may legitimately write the value first and widen `options`
|
|
1049
|
+
* after — so this reports rather than refuses, and goes quiet again when the
|
|
1050
|
+
* list catches up.
|
|
1051
|
+
*/
|
|
1052
|
+
private reportMismatch;
|
|
912
1053
|
protected override _sync(): void;
|
|
1054
|
+
protected override _pull(): void;
|
|
913
1055
|
}
|
|
914
1056
|
/**
|
|
915
1057
|
* The language picker, done — because every game needs the same one.
|
|
@@ -935,7 +1077,7 @@ declare class UiLanguageSelect extends UiSelect {
|
|
|
935
1077
|
override label: string;
|
|
936
1078
|
/** Last locale we PUSHED into `value`, to tell an engine change from a player one. */
|
|
937
1079
|
private lastLocale;
|
|
938
|
-
protected override
|
|
1080
|
+
protected override _pull(): void;
|
|
939
1081
|
protected override _optionLabel(value: string): string;
|
|
940
1082
|
}
|
|
941
1083
|
/**
|
|
@@ -967,6 +1109,7 @@ declare abstract class UiSettingSelect extends UiSelect {
|
|
|
967
1109
|
* `settings.quality.high` is worse than one reading `High`. English is the
|
|
968
1110
|
* base language and the fallback, always.
|
|
969
1111
|
*/
|
|
1112
|
+
protected override _pull(): void;
|
|
970
1113
|
protected override _sync(): void;
|
|
971
1114
|
}
|
|
972
1115
|
/**
|
|
@@ -1062,7 +1205,7 @@ declare class UiVolumeSlider extends UiSlider {
|
|
|
1062
1205
|
/** Last value we PUSHED in, to tell an engine-side change from a player drag. */
|
|
1063
1206
|
private lastPushed;
|
|
1064
1207
|
protected override _labelText(): string;
|
|
1065
|
-
protected override
|
|
1208
|
+
protected override _pull(): void;
|
|
1066
1209
|
}
|
|
1067
1210
|
/**
|
|
1068
1211
|
* The mute switch.
|
|
@@ -1079,7 +1222,7 @@ declare class UiMuteToggle extends UiToggle {
|
|
|
1079
1222
|
static override readonly props: PropSchema;
|
|
1080
1223
|
private lastPushed;
|
|
1081
1224
|
protected override _labelText(): string;
|
|
1082
|
-
protected override
|
|
1225
|
+
protected override _pull(): void;
|
|
1083
1226
|
}
|
|
1084
1227
|
//#endregion
|
|
1085
1228
|
//#region src/core/noise.d.ts
|
|
@@ -1208,7 +1351,7 @@ declare function resolveConstants<T extends JsonValue | undefined>(value: T, con
|
|
|
1208
1351
|
* duplicating a uid'd template can never mint colliding ids. Names ARE
|
|
1209
1352
|
* kept — rename clones you need to look up individually.
|
|
1210
1353
|
*/
|
|
1211
|
-
declare function duplicateNode(node: Node): Node;
|
|
1354
|
+
declare function duplicateNode(node: Node, opts?: LoadSceneOptions): Node;
|
|
1212
1355
|
//#endregion
|
|
1213
1356
|
//#region src/core/scene/serializer.d.ts
|
|
1214
1357
|
/**
|