incanto 0.69.0 → 0.71.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 +121 -102
- package/bin/incanto.mjs +3 -2
- package/dist/2d.d.ts +296 -34
- package/dist/2d.js +4 -4
- package/dist/3d.d.ts +157 -9
- package/dist/3d.js +8 -8
- package/dist/{agent8-CvsfVskX.js → agent8-Cfmd3ar_.js} +61 -8
- package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-L8yccdMP.d.ts} +2 -2
- package/dist/{behavior-rm8vVzu_.d.ts → behavior-Dcz0fr1S.d.ts} +755 -46
- package/dist/{create-game-CwxEDlCm.js → create-game-CH4kt78v.js} +143 -60
- package/dist/{create-game-CvJ1wSRP.js → create-game-LCHBLfA4.js} +98 -48
- 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 +1088 -882
- package/dist/env.d.ts +1 -1
- package/dist/env.js +5 -3
- package/dist/{environment-presets-BO-7XoFV.js → environment-presets-99BzP_L-.js} +298 -45
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-D1KixWK8.js → gameplay-CNULJvwh.js} +914 -214
- package/dist/gameplay.d.ts +254 -10
- package/dist/gameplay.js +2 -2
- package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
- package/dist/index.d.ts +179 -13
- package/dist/index.js +10 -12
- package/dist/json-CfTjpvW8.js +67 -0
- package/dist/{loader-DadV2QCT.d.ts → loader-8-IHvbKD.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-FhrXUc6B.js} +136 -11
- package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CFEGxBXZ.js} +104 -23
- package/dist/{teardown-CMqFVxO9.js → picking-DVo7fI13.js} +104 -13
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{register-DbVArsns.js → register-BYQCBySi.js} +429 -28
- package/dist/{register-mmfugpaQ.js → register-DuVdzxbq.js} +594 -831
- package/dist/{replay-BEHLDcQV.js → replay-DEvp3kyV.js} +224 -14
- package/dist/{replay-BQfkX4x7.d.ts → replay-F7IZHdFR.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-Bvuh2p_r.js} +4619 -2318
- package/dist/{split-screen-Cg76MCV5.d.ts → split-screen-CIYf1zSf.d.ts} +36 -4
- package/dist/{split-screen-CauMwu6y.js → split-screen-eULetcg-.js} +159 -26
- package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
- package/dist/{src-CYEu-_S9.js → src-_jk0qLsS.js} +2 -17
- package/dist/test-CmN54kWv.js +4264 -0
- package/dist/test.d.ts +639 -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 +177 -7
- package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
- package/editor/assets/agent8-yLIEYHbd.js +1 -0
- package/editor/assets/{debug-CMULinBW.js → debug-u31w_yhq.js} +2 -2
- package/editor/assets/index-DK9xMGpW.js +11046 -0
- package/editor/index.html +1 -1
- package/package.json +4 -14
- package/schemas/scene.schema.json +34 -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 +105 -7
- package/skills/incanto-building-2d-games.md +97 -10
- 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 +172 -20
- package/skills/incanto-hud.md +142 -7
- package/skills/incanto-localization.md +13 -5
- package/skills/incanto-multiplayer.md +83 -3
- package/skills/incanto-node-reference.md +239 -59
- package/skills/incanto-performance.md +52 -0
- package/skills/incanto-physics-and-input.md +123 -24
- package/skills/incanto-playtesting.md +112 -2
- package/skills/incanto-save-slots.md +217 -7
- package/skills/incanto-scene-json-authoring.md +69 -12
- package/skills/incanto-verifying-your-game.md +207 -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 +143 -600
- 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 +1205 -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 +178 -986
- 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 +43 -216
- 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 +66 -263
- 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 +42 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +68 -306
- package/templates-app/village-quest-3d/src/main.ts +11 -1
- package/templates-app/village-quest-3d/src/village.scene.json +202 -863
- 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-Dcz0fr1S.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;
|
|
@@ -724,8 +826,9 @@ declare class Wander extends Behavior {
|
|
|
724
826
|
* every `interval` seconds, then waits until they're ALL cleared (freed) before
|
|
725
827
|
* starting the next wave.
|
|
726
828
|
*
|
|
727
|
-
* Signals: `
|
|
728
|
-
* its last instance frees, `allCleared` after
|
|
829
|
+
* Signals: `spawned(node)` per clone, `waveStarted(i)` when a wave begins
|
|
830
|
+
* spawning, `waveCleared(i)` when its last instance frees, `allCleared` after
|
|
831
|
+
* the final wave clears.
|
|
729
832
|
*/
|
|
730
833
|
declare class WaveSpawner extends Behavior {
|
|
731
834
|
static readonly props: PropSchema;
|
|
@@ -740,9 +843,27 @@ declare class WaveSpawner extends Behavior {
|
|
|
740
843
|
private timer;
|
|
741
844
|
private spawnedThisWave;
|
|
742
845
|
private announced;
|
|
846
|
+
override onEnterTree(): void;
|
|
743
847
|
override onReady(): void;
|
|
744
848
|
/** Start (or restart from) wave 0. */
|
|
745
849
|
start(): void;
|
|
850
|
+
/**
|
|
851
|
+
* Which wave you were on — and nothing else.
|
|
852
|
+
*
|
|
853
|
+
* `behaviorsWithoutSave` is documented as "the list to read before shipping",
|
|
854
|
+
* and nobody had read it against this repo's own examples. Five of them put a
|
|
855
|
+
* `WaveSpawner` at the centre of the game (`fps-3d`, `tps-3d`, `tps-3d-neon`,
|
|
856
|
+
* `tps-3d-ruins`, `dogfight-3d`), and every one of them saved a run on wave 3
|
|
857
|
+
* and continued it on wave 1 — silently, because a save reloads the scene
|
|
858
|
+
* from source and a fresh `onReady` honestly starts at the beginning.
|
|
859
|
+
*
|
|
860
|
+
* The wave RESTARTS rather than resuming mid-spawn, which is the same
|
|
861
|
+
* checkpoint rule the rest of the save system follows: spawned entities are
|
|
862
|
+
* never restored, so resuming "four enemies into wave 3" would mean resuming
|
|
863
|
+
* a wave whose enemies do not exist. `waveStarted` fires again for the HUD.
|
|
864
|
+
*/
|
|
865
|
+
override serialize(): JsonValue;
|
|
866
|
+
override deserialize(data: JsonValue): void;
|
|
746
867
|
override update(dt: number): void;
|
|
747
868
|
private beginWave;
|
|
748
869
|
private prune;
|
|
@@ -834,6 +955,18 @@ declare class DayNight extends Behavior {
|
|
|
834
955
|
private baseAmbient;
|
|
835
956
|
private baseExposure;
|
|
836
957
|
private captured;
|
|
958
|
+
/** Said once: there was no sky to move when this first looked. */
|
|
959
|
+
private reportedNoSky;
|
|
960
|
+
/**
|
|
961
|
+
* What time it is. A save that forgets it returns you at dawn.
|
|
962
|
+
*
|
|
963
|
+
* `startHour` is the scene's opening, not the run's clock: a fresh `onReady`
|
|
964
|
+
* cannot know that this player has been out all night. `paused` goes with it
|
|
965
|
+
* because a game that stops the clock for a cutscene must not resume ticking
|
|
966
|
+
* on load.
|
|
967
|
+
*/
|
|
968
|
+
override serialize(): JsonValue;
|
|
969
|
+
override deserialize(data: JsonValue): void;
|
|
837
970
|
override onReady(): void;
|
|
838
971
|
override update(dt: number): void;
|
|
839
972
|
private applyHour;
|
|
@@ -904,6 +1037,25 @@ type GameFlowState = "playing" | "paused" | "gameover" | "won";
|
|
|
904
1037
|
/**
|
|
905
1038
|
* Swap to another scene behind a black fade (title→game→next level).
|
|
906
1039
|
* Headless (no DOM) the swap is immediate. Restores timeScale to 1.
|
|
1040
|
+
*
|
|
1041
|
+
* ONE AT A TIME. A door is usually a trigger, and a player who walks along a
|
|
1042
|
+
* wall of them fires several inside one fade. Measured on three doorways passed
|
|
1043
|
+
* in about a second:
|
|
1044
|
+
*
|
|
1045
|
+
* ```
|
|
1046
|
+
* setScene calls: 3 | order: ["crypt","garden","forge"]
|
|
1047
|
+
* final scene : forge
|
|
1048
|
+
* ```
|
|
1049
|
+
*
|
|
1050
|
+
* Three complete scenes loaded and the player landed in the third — a level
|
|
1051
|
+
* they never walked to, from a door they never reached. Further calls while a
|
|
1052
|
+
* travel is in flight are IGNORED rather than queued: you already went through
|
|
1053
|
+
* a door, and the second one is the same input arriving twice.
|
|
1054
|
+
*
|
|
1055
|
+
* The outgoing scene also stops while the screen is black. It kept simulating
|
|
1056
|
+
* through the fade, so a player who triggered the door mid-fall died in the
|
|
1057
|
+
* level they were leaving — and the checkpoint that death wrote was for the
|
|
1058
|
+
* level they had left.
|
|
907
1059
|
*/
|
|
908
1060
|
declare function goToScene(engine: Engine, sceneJson: JsonObject, opts?: {
|
|
909
1061
|
fadeSeconds?: number;
|
|
@@ -961,8 +1113,24 @@ declare class GameFlow extends Behavior {
|
|
|
961
1113
|
state: GameFlowState;
|
|
962
1114
|
private frozeScale;
|
|
963
1115
|
override onReady(): void;
|
|
964
|
-
/**
|
|
1116
|
+
/**
|
|
1117
|
+
* The panel follows the state; nothing else may own its visibility.
|
|
1118
|
+
*
|
|
1119
|
+
* …and while it is up, the layer it lives on takes ARROW KEYS AND THE PAD.
|
|
1120
|
+
* `HudLayer.focusNavigation` is off by default and rightly so — a game whose
|
|
1121
|
+
* HUD happens to contain a button must not lose its arrow keys the moment one
|
|
1122
|
+
* exists — and `incanto-hud.md` says "turn it on for the screens that ARE
|
|
1123
|
+
* menus and off again when play resumes". A pause panel IS that screen, and
|
|
1124
|
+
* this is the one place in the engine that knows when it opens and closes, so
|
|
1125
|
+
* every game with a pause menu was writing the same two lines or shipping a
|
|
1126
|
+
* menu no controller could reach.
|
|
1127
|
+
*
|
|
1128
|
+
* The layer's own value is remembered and put back: a game that turned
|
|
1129
|
+
* navigation on for its own reasons keeps it after a pause.
|
|
1130
|
+
*/
|
|
965
1131
|
private syncPausePanel;
|
|
1132
|
+
/** The layer's own `focusNavigation`, while this flow is borrowing it. */
|
|
1133
|
+
private navigationWas;
|
|
966
1134
|
gameOver(text?: string, color?: string): void;
|
|
967
1135
|
win(text?: string, color?: string): void;
|
|
968
1136
|
pause(): void;
|
|
@@ -971,7 +1139,7 @@ declare class GameFlow extends Behavior {
|
|
|
971
1139
|
/** Fade to another scene (next level, back to title). */
|
|
972
1140
|
goToScene(sceneJson: JsonObject, opts?: {
|
|
973
1141
|
fadeSeconds?: number;
|
|
974
|
-
}): void;
|
|
1142
|
+
} | undefined): void;
|
|
975
1143
|
private transition;
|
|
976
1144
|
private freeze;
|
|
977
1145
|
private thaw;
|
|
@@ -1025,6 +1193,19 @@ declare class CameraShake extends Behavior {
|
|
|
1025
1193
|
private t;
|
|
1026
1194
|
private prev;
|
|
1027
1195
|
/**
|
|
1196
|
+
* Decoration draws from its OWN stream — see `effectRng`.
|
|
1197
|
+
*
|
|
1198
|
+
* A shake drew from `engine.rng`, the stream game logic reads and
|
|
1199
|
+
* `captureState` saves, once per axis per RENDERED frame. So the player's
|
|
1200
|
+
* frame rate decided the game's random numbers, and toggling the
|
|
1201
|
+
* `reduceMotion` accessibility switch changed the rolls: a replay recorded at
|
|
1202
|
+
* 60 fps does not reproduce on a laptop that dropped to 30, and two players
|
|
1203
|
+
* with the same seed diverge because one of them was hit. The particle
|
|
1204
|
+
* siblings were moved off `engine.rng` for exactly this; both camera shakes
|
|
1205
|
+
* were left behind.
|
|
1206
|
+
*/
|
|
1207
|
+
private shakeRng;
|
|
1208
|
+
/**
|
|
1028
1209
|
* Start a shake — unless the player asked for no motion.
|
|
1029
1210
|
*
|
|
1030
1211
|
* `settings.reduceMotion` is an accessibility switch, and camera movement the
|
|
@@ -1085,6 +1266,69 @@ declare class PathFollow extends Behavior {
|
|
|
1085
1266
|
override update(dt: number): void;
|
|
1086
1267
|
}
|
|
1087
1268
|
//#endregion
|
|
1269
|
+
//#region src/gameplay/prefab-shelf.d.ts
|
|
1270
|
+
/**
|
|
1271
|
+
* A shelf of templates the GAME clones itself — towers, bolts, damage numbers.
|
|
1272
|
+
*
|
|
1273
|
+
* `Spawner` detaches its one prefab at enter, so a spawned enemy's whole
|
|
1274
|
+
* subtree is live and nobody has to think about it. A game that clones on its
|
|
1275
|
+
* own terms — a tower the player places, a bolt that tower fires — has no
|
|
1276
|
+
* spawner, so its templates sat in the tree as LIVE nodes: their behaviours
|
|
1277
|
+
* ticked, their turrets shot, and `visible: false` hid a node without switching
|
|
1278
|
+
* it off. The documented answer was to author every template `"enabled": false`
|
|
1279
|
+
* and wake the clone with `clone.behavior?.enable()`.
|
|
1280
|
+
*
|
|
1281
|
+
* That wakes ONE node, and the same docs teach that a node carries one
|
|
1282
|
+
* behaviour — so a prefab's parts live on children, and every one of those
|
|
1283
|
+
* stays asleep, silently and for good, because `enabled` is a pause switch that
|
|
1284
|
+
* never complains. Measured on a shipped tower defense: the bolt's
|
|
1285
|
+
* `Projectile` was woken and its sibling `Lifetime` was not, so every bolt that
|
|
1286
|
+
* MISSED flew forever — five still in the tree at 69 seconds, in a game that
|
|
1287
|
+
* passed its harness, its audit and every rung of the ladder.
|
|
1288
|
+
*
|
|
1289
|
+
* ```json
|
|
1290
|
+
* { "name": "Prefabs", "type": "Node2D", "script": { "name": "PrefabShelf" },
|
|
1291
|
+
* "children": [ { "name": "Tower", "type": "Node2D", "children": [] } ] }
|
|
1292
|
+
* ```
|
|
1293
|
+
* ```ts
|
|
1294
|
+
* const shelf = this.node.getNode('/Game/Prefabs').behavior as PrefabShelf;
|
|
1295
|
+
* const tower = shelf.make('Tower'); // detached, like `duplicateNode`
|
|
1296
|
+
* tower.position = at; // set it up BEFORE it readies
|
|
1297
|
+
* this.node.getNode('/Game/Towers').addChild(tower);
|
|
1298
|
+
* ```
|
|
1299
|
+
*
|
|
1300
|
+
* The children never ENTER the tree, so nothing has to be asleep, nothing has
|
|
1301
|
+
* to be hidden, and `make()` hands back a clone that is awake all the way down.
|
|
1302
|
+
*/
|
|
1303
|
+
declare class PrefabShelf extends Behavior {
|
|
1304
|
+
static readonly props: PropSchema;
|
|
1305
|
+
static readonly signals: readonly string[];
|
|
1306
|
+
prefabs: string;
|
|
1307
|
+
/** Templates, in the order they were authored. */
|
|
1308
|
+
private readonly held;
|
|
1309
|
+
override onEnterTree(): void;
|
|
1310
|
+
/** A shelf attached at runtime never saw `onEnterTree`; idempotent. */
|
|
1311
|
+
override onReady(): void;
|
|
1312
|
+
private claim;
|
|
1313
|
+
/** What this shelf holds, in authored order. */
|
|
1314
|
+
names(): string[];
|
|
1315
|
+
/**
|
|
1316
|
+
* A live clone of one template, DETACHED — `addChild` it yourself.
|
|
1317
|
+
*
|
|
1318
|
+
* Detached for the same reason `duplicateNode` is, and it is not a
|
|
1319
|
+
* formality: `onReady` fires on attach, and a behaviour that reads its node
|
|
1320
|
+
* there (`FloatAway` banks its starting position) would bank the wrong one.
|
|
1321
|
+
* Set the clone up, then attach it.
|
|
1322
|
+
*
|
|
1323
|
+
* The clone is VISIBLE even if the template was authored hidden (a scene
|
|
1324
|
+
* migrating off the old `visible: false` shelf keeps working), and every
|
|
1325
|
+
* behaviour in it is however it was authored: awake unless the template
|
|
1326
|
+
* itself asks to sleep, which is now only ever a state machine's own doing.
|
|
1327
|
+
*/
|
|
1328
|
+
make(name: string): Node;
|
|
1329
|
+
private childNames;
|
|
1330
|
+
}
|
|
1331
|
+
//#endregion
|
|
1088
1332
|
//#region src/gameplay/spatial.d.ts
|
|
1089
1333
|
/**
|
|
1090
1334
|
* A node's position with every spatial ancestor's added in.
|
|
@@ -1131,4 +1375,4 @@ declare function registerGameplayBehaviors(opts?: {
|
|
|
1131
1375
|
replace?: boolean;
|
|
1132
1376
|
}): void;
|
|
1133
1377
|
//#endregion
|
|
1134
|
-
export { CameraShake, Chase, Collector, Cooldown, Currency, DamageOnContact, DayNight, type DayPhase, FaceTarget, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, type GameFlowState, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, localFromWorld, phaseOf, registerGameplayBehaviors, restartScene, screenFlash, worldPosition };
|
|
1378
|
+
export { CameraShake, Chase, Collector, Cooldown, Currency, DamageOnContact, DayNight, type DayPhase, FaceTarget, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, type GameFlowState, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, PrefabShelf, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, localFromWorld, phaseOf, registerGameplayBehaviors, restartScene, screenFlash, worldPosition };
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
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 };
|
|
1
|
+
import { A as DayNight, C as goToScene, E as FollowCamera, F as Collector, I as Chase, M as DamageOnContact, N as Health, O as FloatAway, P as Currency, Q as worldPosition, S as GameFlow, Z as localFromWorld, _ as CameraShake, a as Wander, b as screenFlash, c as SavePoint, d as Pickup, f as Patrol, g as Lifetime, h as MoveTo, i as WaveSpawner, j as phaseOf, k as FaceTarget, l as Projectile, m as Oscillate, n as registerGameplayBehaviors, o as Spawner, p as PathFollow, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as PrefabShelf, v as Cooldown, w as restartScene, x as Interactable, y as hitStop } from "./gameplay-CNULJvwh.js";
|
|
2
|
+
export { CameraShake, Chase, Collector, Cooldown, Currency, DamageOnContact, DayNight, FaceTarget, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, PrefabShelf, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, localFromWorld, phaseOf, registerGameplayBehaviors, restartScene, screenFlash, worldPosition };
|