incanto 0.48.0 → 0.49.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-model.mjs +13 -1
- package/bin/incanto-playtest.mjs +7 -0
- package/bin/incanto-verify.mjs +10 -2
- package/dist/2d.d.ts +21 -12
- package/dist/2d.js +57 -3
- package/dist/3d.d.ts +38 -1
- package/dist/3d.js +114 -4
- package/dist/{create-game-CniOiWzN.js → create-game-BgV6UbVA.js} +5 -5
- package/dist/{create-game-akjPkFv5.js → create-game-DFBjMetZ.js} +5 -5
- package/dist/{duplicate-CRtihGmC.js → duplicate-CI9WF_bg.js} +1 -1
- package/dist/{environment-presets-D1b0ydTS.js → environment-presets-CZOH5TY5.js} +15 -20
- package/dist/{gameplay-BQOeAid6.js → gameplay-02Btmmjn.js} +80 -9
- package/dist/gameplay.d.ts +17 -0
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +7 -7
- package/dist/{loader-r49nDwB4.js → loader-DwazzlQb.js} +36 -6
- package/dist/net.js +3 -3
- package/dist/{physics-2d-BmgXBNDB.js → physics-2d-vyCBfACH.js} +3 -3
- package/dist/{physics-3d-CSoGjM8P.js → physics-3d-DpRqw8Mz.js} +4 -4
- package/dist/react.js +1 -1
- package/dist/{register-R2JTnIMw.js → register-BNPZYJmd.js} +23 -22
- package/dist/{register-D651it1J.js → register-CB11yp21.js} +2 -2
- package/dist/{register-BSXV8T9F.js → register-uvaZj1KX.js} +62 -2
- package/dist/{replay-DilbZgQI.js → replay-C0XJIsO7.js} +1 -1
- package/dist/sprite-animation-CMr6f1K2.d.ts +44 -0
- package/dist/{particle-sim-Bw7hB93B.js → sprite-animation-D_p28jwU.js} +63 -1
- package/dist/{src-Bl1Kire1.js → src-DF4gCsqO.js} +1 -1
- package/dist/{test-E4-otKqK.js → test-DRna_BQU.js} +210 -30
- package/dist/test.d.ts +38 -6
- package/dist/test.js +2 -2
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-_007gPF8.js → agent8-DCW4TgDt.js} +1 -1
- package/editor/assets/{debug-0DI_MJaq.js → debug-RC6qts6S.js} +1 -1
- package/editor/assets/{index-B-6eYZEi.js → index-5dEIhvsf.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +10 -3
- package/skills/incanto-3d-character.md +13 -2
- package/skills/incanto-3d-models.md +40 -0
- package/skills/incanto-assets.md +15 -0
- package/skills/incanto-building-2d-games.md +57 -5
- package/skills/incanto-building-3d-games.md +7 -0
- package/skills/incanto-gameplay-behaviors.md +18 -1
- package/skills/incanto-hud.md +39 -0
- package/skills/incanto-node-reference.md +5 -3
- package/skills/incanto-physics-and-input.md +1 -1
- package/skills/incanto-playtesting.md +9 -2
- package/skills/incanto-verifying-your-game.md +14 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { f as Node, h as effectiveOrder, n as loadScene, w as registerBehavior, y as Behavior } from "./loader-
|
|
1
|
+
import { f as Node, h as effectiveOrder, n as loadScene, w as registerBehavior, y as Behavior } from "./loader-DwazzlQb.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
4
|
-
import { t as duplicateNode } from "./duplicate-
|
|
4
|
+
import { t as duplicateNode } from "./duplicate-CI9WF_bg.js";
|
|
5
5
|
import { Color, CubeCamera, DepthTexture, DoubleSide, Euler, FloatType, Frustum, HalfFloatType, LinearMipmapLinearFilter, MathUtils, Matrix4, Mesh, MeshDepthMaterial, Object3D, PerspectiveCamera, Plane, PlaneGeometry, Quaternion, ShaderMaterial, Sphere, Vector2, Vector3, Vector4, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
|
|
6
6
|
//#region src/3d/frustum.ts
|
|
7
7
|
const scratchFrustum = new Frustum();
|
|
@@ -2553,7 +2553,7 @@ var CharacterBody3D = class extends PhysicsBody3D {
|
|
|
2553
2553
|
0,
|
|
2554
2554
|
0
|
|
2555
2555
|
] },
|
|
2556
|
-
|
|
2556
|
+
stickToGround: { default: true },
|
|
2557
2557
|
slopeLimitDeg: { default: 45 }
|
|
2558
2558
|
};
|
|
2559
2559
|
/** m/s, y-up (up = +y). */
|
|
@@ -2562,9 +2562,30 @@ var CharacterBody3D = class extends PhysicsBody3D {
|
|
|
2562
2562
|
0,
|
|
2563
2563
|
0
|
|
2564
2564
|
];
|
|
2565
|
-
|
|
2565
|
+
/**
|
|
2566
|
+
* Hold the capsule against the surface while it moves, so walking down a
|
|
2567
|
+
* slope does not become a series of small falls.
|
|
2568
|
+
*
|
|
2569
|
+
* Named apart from `Node3D.snapToGround` (which PLACES a node on the ground
|
|
2570
|
+
* at load) because sharing the name silently broke both: the boolean shadowed
|
|
2571
|
+
* the placement prop, its `true` default made the placement pass teleport
|
|
2572
|
+
* every character body in a terrain scene, and a lift value was rejected
|
|
2573
|
+
* outright — so the only escape from the teleport also turned this off.
|
|
2574
|
+
*/
|
|
2575
|
+
stickToGround = true;
|
|
2566
2576
|
/** Max climbable slope angle. */
|
|
2567
2577
|
slopeLimitDeg = 45;
|
|
2578
|
+
/**
|
|
2579
|
+
* `snapToGround` on a character body is ambiguous, so it is refused.
|
|
2580
|
+
*
|
|
2581
|
+
* A boolean here used to mean the ground-stick, and as placement it means
|
|
2582
|
+
* "leave y alone" — which is already the default. Rather than pick one and
|
|
2583
|
+
* silently do the other thing to an existing scene, say which prop was meant.
|
|
2584
|
+
*/
|
|
2585
|
+
onReady() {
|
|
2586
|
+
if (typeof this.snapToGround === "boolean") throw new IncantoError("PROP_TYPE_MISMATCH", `'${this.getPath()}' sets snapToGround to a boolean. On a character body that is ambiguous: 'stickToGround' holds the capsule against the surface while it moves (default true), while 'snapToGround' PLACES the node on the ground at load and takes a lift in metres (e.g. 0.8) — omit it to leave y exactly as authored.`, { prop: "snapToGround" });
|
|
2587
|
+
super.onReady();
|
|
2588
|
+
}
|
|
2568
2589
|
/** @internal Updated by Physics3D.moveAndSlide. */
|
|
2569
2590
|
_grounded = false;
|
|
2570
2591
|
moveAndSlide() {
|
|
@@ -4553,7 +4574,8 @@ var Health = class extends Behavior {
|
|
|
4553
4574
|
static signals = [
|
|
4554
4575
|
"damaged",
|
|
4555
4576
|
"healed",
|
|
4556
|
-
"died"
|
|
4577
|
+
"died",
|
|
4578
|
+
"healthChanged"
|
|
4557
4579
|
];
|
|
4558
4580
|
max = 100;
|
|
4559
4581
|
regenPerSec = 0;
|
|
@@ -4602,13 +4624,29 @@ var Health = class extends Behavior {
|
|
|
4602
4624
|
this.setCurrent(0);
|
|
4603
4625
|
this.die();
|
|
4604
4626
|
}
|
|
4627
|
+
/**
|
|
4628
|
+
* The one funnel every change goes through — and therefore the one place a
|
|
4629
|
+
* HUD can be told about.
|
|
4630
|
+
*
|
|
4631
|
+
* `damaged`/`healed` both lead with the DELTA, which is the number a bar must
|
|
4632
|
+
* not show; wire either to `UiBar.setValue` and the bar paints the damage as
|
|
4633
|
+
* the health and looks like it works. Regeneration is worse: it moves
|
|
4634
|
+
* `current` through here and emits NEITHER, so a regen bar sat still while
|
|
4635
|
+
* the character healed. `healthChanged(current, max)` carries the max too, so
|
|
4636
|
+
* a raised ceiling needs no second wire.
|
|
4637
|
+
*
|
|
4638
|
+
* Silent when nothing moved: a bar that repaints on nothing is noise.
|
|
4639
|
+
*/
|
|
4605
4640
|
setCurrent(value) {
|
|
4606
|
-
|
|
4641
|
+
const next = Math.max(0, Math.min(this.max, value));
|
|
4642
|
+
if (next === this.current) return;
|
|
4643
|
+
this.current = next;
|
|
4644
|
+
this.emit("healthChanged", this.current, this.max);
|
|
4607
4645
|
}
|
|
4608
4646
|
die() {
|
|
4609
4647
|
if (this.dead) return;
|
|
4610
4648
|
this.dead = true;
|
|
4611
|
-
this.
|
|
4649
|
+
this.setCurrent(0);
|
|
4612
4650
|
this.emit("died");
|
|
4613
4651
|
if (this.freeOnDeath) this.node.queueFree();
|
|
4614
4652
|
}
|
|
@@ -5675,6 +5713,10 @@ var Patrol = class extends Behavior {
|
|
|
5675
5713
|
* On overlap with a node in `collectorGroup`, emits `collected(value, other)`
|
|
5676
5714
|
* then `queueFree()`s itself. Wire `collected → ScoreKeeper.addScore` (the
|
|
5677
5715
|
* value is the first arg) or `collected → Collector.collect`.
|
|
5716
|
+
*
|
|
5717
|
+
* `other` is the ENTITY, not whichever of its parts touched — see
|
|
5718
|
+
* {@link findCollector}. A player is a body with children (a reach sensor, a
|
|
5719
|
+
* hitbox), and the part that enters first is rarely the part carrying the group.
|
|
5678
5720
|
*/
|
|
5679
5721
|
var Pickup = class extends Behavior {
|
|
5680
5722
|
static props = {
|
|
@@ -5695,12 +5737,41 @@ var Pickup = class extends Behavior {
|
|
|
5695
5737
|
}
|
|
5696
5738
|
tryCollect(other) {
|
|
5697
5739
|
if (this.collectedAlready) return;
|
|
5698
|
-
|
|
5740
|
+
const collector = findCollector(other, this.collectorGroup);
|
|
5741
|
+
if (!collector) return;
|
|
5699
5742
|
this.collectedAlready = true;
|
|
5700
|
-
this.emit("collected", this.value,
|
|
5743
|
+
this.emit("collected", this.value, collector);
|
|
5701
5744
|
this.node.queueFree();
|
|
5702
5745
|
}
|
|
5703
5746
|
};
|
|
5747
|
+
/**
|
|
5748
|
+
* The entity in `group` that this contact belongs to, or null.
|
|
5749
|
+
*
|
|
5750
|
+
* The same search `DamageOnContact` has always used for `Health` — the
|
|
5751
|
+
* contacted node, its descendants, then the ancestor CHAIN — and for the same
|
|
5752
|
+
* reason. An entity is a body with children (a reach sensor, a hitbox, a skin),
|
|
5753
|
+
* the group sits on one node of it, and whichever part happens to touch first
|
|
5754
|
+
* is rarely that node.
|
|
5755
|
+
*
|
|
5756
|
+
* Matching the literal entering node was a silent failure in exactly the shape
|
|
5757
|
+
* the gameplay skill recommends: a player with a `Grab` area collected almost
|
|
5758
|
+
* nothing, because the sensor is wider than the body and entered first. Five
|
|
5759
|
+
* pickups fired `triggerEnter`; one fired `collected`.
|
|
5760
|
+
*
|
|
5761
|
+
* The ancestor climb deliberately does NOT descend into siblings: past a shared
|
|
5762
|
+
* parent every other entity hangs off it too, and a coin would be collected by
|
|
5763
|
+
* a crate standing next to the player.
|
|
5764
|
+
*/
|
|
5765
|
+
function findCollector(node, group) {
|
|
5766
|
+
const queue = [node];
|
|
5767
|
+
while (queue.length > 0) {
|
|
5768
|
+
const n = queue.shift();
|
|
5769
|
+
if (n.isInGroup(group)) return n;
|
|
5770
|
+
queue.push(...n.children);
|
|
5771
|
+
}
|
|
5772
|
+
for (let n = node.parent; n; n = n.parent) if (n.isInGroup(group)) return n;
|
|
5773
|
+
return null;
|
|
5774
|
+
}
|
|
5704
5775
|
//#endregion
|
|
5705
5776
|
//#region src/gameplay/projectile.ts
|
|
5706
5777
|
/**
|
package/dist/gameplay.d.ts
CHANGED
|
@@ -97,6 +97,19 @@ declare class Health extends Behavior {
|
|
|
97
97
|
heal(n: number): void;
|
|
98
98
|
/** Drop to 0 and die immediately (ignores i-frames). */
|
|
99
99
|
kill(): void;
|
|
100
|
+
/**
|
|
101
|
+
* The one funnel every change goes through — and therefore the one place a
|
|
102
|
+
* HUD can be told about.
|
|
103
|
+
*
|
|
104
|
+
* `damaged`/`healed` both lead with the DELTA, which is the number a bar must
|
|
105
|
+
* not show; wire either to `UiBar.setValue` and the bar paints the damage as
|
|
106
|
+
* the health and looks like it works. Regeneration is worse: it moves
|
|
107
|
+
* `current` through here and emits NEITHER, so a regen bar sat still while
|
|
108
|
+
* the character healed. `healthChanged(current, max)` carries the max too, so
|
|
109
|
+
* a raised ceiling needs no second wire.
|
|
110
|
+
*
|
|
111
|
+
* Silent when nothing moved: a bar that repaints on nothing is noise.
|
|
112
|
+
*/
|
|
100
113
|
private setCurrent;
|
|
101
114
|
private die;
|
|
102
115
|
/** Current HP and whether death already fired — `max` comes back from JSON. */
|
|
@@ -318,6 +331,10 @@ declare class Patrol extends Behavior {
|
|
|
318
331
|
* On overlap with a node in `collectorGroup`, emits `collected(value, other)`
|
|
319
332
|
* then `queueFree()`s itself. Wire `collected → ScoreKeeper.addScore` (the
|
|
320
333
|
* value is the first arg) or `collected → Collector.collect`.
|
|
334
|
+
*
|
|
335
|
+
* `other` is the ENTITY, not whichever of its parts touched — see
|
|
336
|
+
* {@link findCollector}. A player is a body with children (a reach sensor, a
|
|
337
|
+
* hitbox), and the part that enters first is rarely the part carrying the group.
|
|
321
338
|
*/
|
|
322
339
|
declare class Pickup extends Behavior {
|
|
323
340
|
static readonly props: PropSchema;
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-
|
|
1
|
+
import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-02Btmmjn.js";
|
|
2
2
|
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { $ as suggestLocale, A as SettingsValues, At as LogLevel, B as captureBehaviors, C as EngineStats, Ct as PlayMusicOptions, Dt as NodeLifecycle, E as DeviceHints, Et as Node, F as BehaviorState, G as OrderGroup, H as SaveStore, I as RestoreReport, J as resolveOrderGroups, K as OrderGroupTable, L as SaveSlot, M as readDeviceHints, Mt as Signal, N as suggestQuality, Nt as SignalListener, O as QualityTier, Ot as SceneTree, P as Scene, Q as T_PREFIX, R as SaveSlots, S as Scheduler, St as MusicTrack, T as RendererStats, Tt as BusName, U as createSaveStore, V as restoreBehaviors, W as ORDER_GROUP_BASE, X as LocaleTables, Y as BASE_LOCALE, Z as Localization, _ as mergeStaticSignals, _t as SfxWave, a as clearBehaviors, at as Voice, b as Engine, bt as MusicBackend, c as registeredBehaviors, ct as ROLLOFF_MODELS, d as PropSchema, dt as Vec3, et as translationKey, f as clearRegistry, ft as spatialGain, g as getNodeType, gt as SfxParams, h as getNodeSignals, ht as SFX_PRESET_NAMES, i as behaviorSignals, it as isAudioContextAvailable, j as qualityEnvironment, jt as LogManager, k as Settings, kt as LogEntry, l as NodeCtor, lt as RolloffModel, m as getNodeSchema, mt as SFX_PRESETS, n as BehaviorCtor, nt as SfxEngine, o as getBehavior, ot as VoicePreset, p as createNode, pt as spatialPan, q as effectiveOrder, r as behaviorSchema, rt as SfxPlayOptions, s as registerBehavior, st as Listener, t as Behavior, tt as InputMap, u as PropDef, ut as SpatialParams, v as registerNode, vt as SynthOptions, w as GameStats, wt as AudioBuses, x as EngineOptions, xt as MusicManager, y as registeredTypes, yt as synthSfx, z as behaviorsWithoutSave } from "./behavior-62q0HWBO.js";
|
|
2
2
|
import { a as Rng, c as JsonValue, d as jsonKind, i as SceneJson, l as jsonClone, n as NodeJson, o as JsonKind, r as SCENE_FORMAT, s as JsonObject, t as ConnectionJson, u as jsonEquals } from "./schema-CFeioQRE.js";
|
|
3
3
|
import { n as loadScene, t as LoadSceneOptions } from "./loader-CeyU_bm1.js";
|
|
4
|
+
import { i as resolveFrames, n as AnimationEntry, r as resolveAnimation, t as AnimationDef } from "./sprite-animation-CMr6f1K2.js";
|
|
4
5
|
import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-BzJ1yxoE.js";
|
|
5
6
|
import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-C49JSNNq.js";
|
|
6
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-CAphXMyM.js";
|
|
@@ -319,10 +320,37 @@ declare class UiText extends HudWidgetBase {
|
|
|
319
320
|
static override readonly typeName: string;
|
|
320
321
|
static override readonly props: PropSchema;
|
|
321
322
|
text: string;
|
|
323
|
+
/**
|
|
324
|
+
* A template with a `{}` slot that `setText` fills — `"Gems {} / 8"`.
|
|
325
|
+
*
|
|
326
|
+
* Empty (the default) means `setText` replaces the whole line. Resolved at
|
|
327
|
+
* PAINT like `text`, so `"@t:hud.gems"` works and changing locale re-reads
|
|
328
|
+
* it: the value lives here, the words live in the strings table.
|
|
329
|
+
*/
|
|
330
|
+
format: string;
|
|
322
331
|
size: number;
|
|
323
332
|
color: string;
|
|
324
333
|
shadow: boolean;
|
|
325
334
|
private last;
|
|
335
|
+
/** null until something has actually set a value — see `shown`. */
|
|
336
|
+
private slot;
|
|
337
|
+
/**
|
|
338
|
+
* Put a signal's value on screen — `scoreChanged → setText`.
|
|
339
|
+
*
|
|
340
|
+
* A `connections[]` handler must be a METHOD and `text` is a property, so the
|
|
341
|
+
* one wire every game needs (score to screen) could not be declared: every
|
|
342
|
+
* HUD began with a behavior whose whole job was one assignment.
|
|
343
|
+
*/
|
|
344
|
+
setText(value: unknown): void;
|
|
345
|
+
/**
|
|
346
|
+
* What it actually paints, after the template and the locale.
|
|
347
|
+
*
|
|
348
|
+
* Before the first value arrives, a formatted widget shows `text` — its
|
|
349
|
+
* authored opening line. Filling the slot with nothing instead would put
|
|
350
|
+
* `"Gems / 8"` on screen for every game's first frame, and a score line
|
|
351
|
+
* that starts blank looks broken rather than empty.
|
|
352
|
+
*/
|
|
353
|
+
get shown(): string;
|
|
326
354
|
protected _build(): HTMLElement;
|
|
327
355
|
protected override _sync(): void;
|
|
328
356
|
}
|
|
@@ -345,6 +373,16 @@ declare class UiBar extends HudWidgetBase {
|
|
|
345
373
|
private lastRatio;
|
|
346
374
|
/** Current fill ratio 0..1 (what the bar shows). */
|
|
347
375
|
get ratio(): number;
|
|
376
|
+
/**
|
|
377
|
+
* Drive the bar from a signal — `healthChanged → setValue`.
|
|
378
|
+
*
|
|
379
|
+
* Takes the max as a second argument because that is the shape the signal
|
|
380
|
+
* already has, so a bar whose ceiling moves (a max-HP upgrade) needs no
|
|
381
|
+
* second wire.
|
|
382
|
+
*/
|
|
383
|
+
setValue(value: number, max?: number): void;
|
|
384
|
+
/** Move the ceiling on its own, leaving the fill where it is. */
|
|
385
|
+
setMax(max: number): void;
|
|
348
386
|
protected _build(): HTMLElement;
|
|
349
387
|
protected override _sync(): void;
|
|
350
388
|
}
|
|
@@ -810,4 +848,4 @@ declare function computeViewport(canvasW: number, canvasH: number, viewport: {
|
|
|
810
848
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
811
849
|
declare const VERSION: string;
|
|
812
850
|
//#endregion
|
|
813
|
-
export { type AssetFailure, AudioBuses, type AudioElementLike, AudioPlayer, BASE_LOCALE, Behavior, type BehaviorCtor, type BehaviorState, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, type DeviceHints, type DriveScript, type DriveStep, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type GroupedLog, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LiveInput, type LiveReport, type LoadSceneOptions, type LocaleTables, Localization, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, type OrderGroupTable, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, type ParsedNodePath, type ParticlePresetValues, ParticleSim, type ParticleSimConfig, type ParticleView, type PathGrid, type PlayMusicOptions, type PreloadResult, type PropDef, type PropSchema, type QualityTier, ROLLOFF_MODELS, type Recorder, type RendererStats, type ReplayEvent, type ReplayJson, type ResolvedRendering, type ResolvedViewport, type RestoreReport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveSlot, SaveSlots, type SaveStore, Scene, type SceneJson, SceneTree, type Scheduler, Settings, type SettingsValues, SfxEngine, type SfxParams, type SfxPlayOptions, type SfxWave, Signal, type SignalListener, type SpatialParams, type SynthOptions, T_PREFIX, Timer, TouchControls, type TouchControlsOptions, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, type Vec3, type ViewportFit, type Voice, type VoicePreset, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
851
|
+
export { type AnimationDef, type AnimationEntry, type AssetFailure, AudioBuses, type AudioElementLike, AudioPlayer, BASE_LOCALE, Behavior, type BehaviorCtor, type BehaviorState, type BusName, CONST_REF_KEY, type ComputedViewport, type ConnectionJson, type CrossfadeGains, type DebugLineSource, type DeviceHints, type DriveScript, type DriveStep, Engine, type EngineOptions, type EngineStats, type FindPathOptions, type GameStats, type GroupedLog, type HudAnchor, HudLayer, IncantoError, type IncantoErrorCode, type IncantoErrorDetails, InputMap, type JsonKind, type JsonObject, type JsonValue, type Listener, type LiveInput, type LiveReport, type LoadSceneOptions, type LocaleTables, Localization, type LogEntry, type LogLevel, LogManager, type MusicBackend, MusicManager, type MusicTrack, Node, type NodeCtor, type NodeJson, type NodeLifecycle, ORDER_GROUP_BASE, type OrderGroup, type OrderGroupTable, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, type ParsedNodePath, type ParticlePresetValues, ParticleSim, type ParticleSimConfig, type ParticleView, type PathGrid, type PlayMusicOptions, type PreloadResult, type PropDef, type PropSchema, type QualityTier, ROLLOFF_MODELS, type Recorder, type RendererStats, type ReplayEvent, type ReplayJson, type ResolvedRendering, type ResolvedViewport, type RestoreReport, Rng, type RolloffModel, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, type SaveSlot, SaveSlots, type SaveStore, Scene, type SceneJson, SceneTree, type Scheduler, Settings, type SettingsValues, SfxEngine, type SfxParams, type SfxPlayOptions, type SfxWave, Signal, type SignalListener, type SpatialParams, type SynthOptions, T_PREFIX, Timer, TouchControls, type TouchControlsOptions, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, type Vec3, type ViewportFit, type Voice, type VoicePreset, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { C as getBehavior, E as Signal, S as clearBehaviors, T as registeredBehaviors, _ as InputMap, a as SCENE_FORMAT, b as behaviorSchema, c as SceneTree, d as resolveConstants, f as Node, g as resolveOrderGroups, h as effectiveOrder, i as serializeNode, l as CONST_REF_KEY, m as ORDER_GROUP_BASE, n as loadScene, o as computeViewport, p as parseNodePath, r as Scene, s as resolveViewport, u as isConstRef, w as registerBehavior, x as behaviorSignals, y as Behavior } from "./loader-
|
|
2
|
-
import { A as T_PREFIX, B as synthSfx, C as behaviorsWithoutSave, D as LogManager, E as createSaveStore, F as ROLLOFF_MODELS, G as AudioBuses, H as WebAudioMusicBackend, I as spatialGain, L as spatialPan, M as translationKey, N as SfxEngine, O as BASE_LOCALE, P as isAudioContextAvailable, R as SFX_PRESETS, S as SaveSlots, T as restoreBehaviors, U as crossfadeGains, V as MusicManager, W as fadeGain, a as UiSlider, b as readDeviceHints, c as UiButton, d as UiBanner, f as UiBar, g as Settings, h as Engine, i as UiSelect, j as suggestLocale, k as Localization, l as UiDialogue, m as AudioPlayer, n as UiImage, o as UiToggle, p as UiText, r as UiPanel, s as Timer, t as registerCoreNodes, u as HudLayer, v as qualityEnvironment, w as captureBehaviors, x as suggestQuality, z as SFX_PRESET_NAMES } from "./register-
|
|
1
|
+
import { C as getBehavior, E as Signal, S as clearBehaviors, T as registeredBehaviors, _ as InputMap, a as SCENE_FORMAT, b as behaviorSchema, c as SceneTree, d as resolveConstants, f as Node, g as resolveOrderGroups, h as effectiveOrder, i as serializeNode, l as CONST_REF_KEY, m as ORDER_GROUP_BASE, n as loadScene, o as computeViewport, p as parseNodePath, r as Scene, s as resolveViewport, u as isConstRef, w as registerBehavior, x as behaviorSignals, y as Behavior } from "./loader-DwazzlQb.js";
|
|
2
|
+
import { A as T_PREFIX, B as synthSfx, C as behaviorsWithoutSave, D as LogManager, E as createSaveStore, F as ROLLOFF_MODELS, G as AudioBuses, H as WebAudioMusicBackend, I as spatialGain, L as spatialPan, M as translationKey, N as SfxEngine, O as BASE_LOCALE, P as isAudioContextAvailable, R as SFX_PRESETS, S as SaveSlots, T as restoreBehaviors, U as crossfadeGains, V as MusicManager, W as fadeGain, a as UiSlider, b as readDeviceHints, c as UiButton, d as UiBanner, f as UiBar, g as Settings, h as Engine, i as UiSelect, j as suggestLocale, k as Localization, l as UiDialogue, m as AudioPlayer, n as UiImage, o as UiToggle, p as UiText, r as UiPanel, s as Timer, t as registerCoreNodes, u as HudLayer, v as qualityEnvironment, w as captureBehaviors, x as suggestQuality, z as SFX_PRESET_NAMES } from "./register-uvaZj1KX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
|
-
import { n as startRecording, r as auditScene, t as replay } from "./replay-
|
|
5
|
+
import { n as startRecording, r as auditScene, t as replay } from "./replay-C0XJIsO7.js";
|
|
6
6
|
import { n as jsonEquals, r as jsonKind, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
7
7
|
import { a as getNodeSignals, c as mergeStaticSignals, i as getNodeSchema, l as registerNode, n as clearRegistry, o as getNodeType, r as createNode, u as registeredTypes } from "./registry-IyWCGe4q.js";
|
|
8
8
|
import { n as logText, r as parseDrive, t as logReport } from "./log-report-lxrQY9cH.js";
|
|
9
9
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
10
|
-
import { i as
|
|
11
|
-
import { a as findPath, i as preloadUrls, n as newUid, o as gridFromRows, r as assetUrls, t as VERSION } from "./src-
|
|
10
|
+
import { a as PARTICLE_PRESETS, i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-D_p28jwU.js";
|
|
11
|
+
import { a as findPath, i as preloadUrls, n as newUid, o as gridFromRows, r as assetUrls, t as VERSION } from "./src-DF4gCsqO.js";
|
|
12
12
|
import { i as resolveRendering, n as attachTouchControls, r as joystickVector, t as TouchControls } from "./touch-BoNg_MnF.js";
|
|
13
|
-
import { t as duplicateNode } from "./duplicate-
|
|
14
|
-
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
13
|
+
import { t as duplicateNode } from "./duplicate-CI9WF_bg.js";
|
|
14
|
+
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiImage, UiPanel, UiSelect, UiSlider, UiText, UiToggle, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, parseDrive, parseNodePath, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRendering, resolveViewport, restoreBehaviors, serializeNode, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
|
@@ -1606,13 +1606,17 @@ function wireConnections(root, connections, declareSignals = false) {
|
|
|
1606
1606
|
const listener = (...args) => {
|
|
1607
1607
|
if (conn.filter && !matchesFilter(args[0], conn.filter)) return;
|
|
1608
1608
|
if (conn.once) fromNode.off(conn.signal, listener);
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1609
|
+
try {
|
|
1610
|
+
const fn = toNode[conn.handler];
|
|
1611
|
+
if (typeof fn === "function") {
|
|
1612
|
+
fn.apply(toNode, args);
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
const bfn = toNode.behavior ? toNode.behavior[conn.handler] : void 0;
|
|
1616
|
+
if (typeof bfn === "function") bfn.apply(toNode.behavior, args);
|
|
1617
|
+
} catch (error) {
|
|
1618
|
+
quarantineWire(fromNode, toNode, conn, listener, error);
|
|
1613
1619
|
}
|
|
1614
|
-
const bfn = toNode.behavior ? toNode.behavior[conn.handler] : void 0;
|
|
1615
|
-
if (typeof bfn === "function") bfn.apply(toNode.behavior, args);
|
|
1616
1620
|
};
|
|
1617
1621
|
try {
|
|
1618
1622
|
fromNode.on(conn.signal, listener);
|
|
@@ -1622,6 +1626,32 @@ function wireConnections(root, connections, declareSignals = false) {
|
|
|
1622
1626
|
}
|
|
1623
1627
|
}
|
|
1624
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* A handler threw. Turn THAT WIRE off, and leave the game running.
|
|
1631
|
+
*
|
|
1632
|
+
* The engine already draws this line for scripts: "a behavior is your code; the
|
|
1633
|
+
* node is the engine's. A typo in the first must not switch off the second, or
|
|
1634
|
+
* breaking a sword script stops the character from walking." A connection is
|
|
1635
|
+
* the same category — authored wiring, not the emitting node's own logic — and
|
|
1636
|
+
* it behaved the opposite way, because the handler runs inside `Signal.emit`
|
|
1637
|
+
* and its exception surfaces in whoever EMITTED. The node quarantine then blames
|
|
1638
|
+
* and skips that node, so a `movementStateChanged → play` wire naming a clip the
|
|
1639
|
+
* sheet does not have switched off the character controller: no animation, and
|
|
1640
|
+
* no movement either.
|
|
1641
|
+
*
|
|
1642
|
+
* Reported ONCE and disconnected, on the same reasoning as the node quarantine:
|
|
1643
|
+
* a handler that throws throws every frame, and sixty identical traces a second
|
|
1644
|
+
* bury the one line that matters.
|
|
1645
|
+
*/
|
|
1646
|
+
function quarantineWire(fromNode, toNode, conn, listener, error) {
|
|
1647
|
+
fromNode.off(conn.signal, listener);
|
|
1648
|
+
const target = toNode.behavior ? `'${conn.handler}' on behavior '${toNode.script?.name}' (${toNode.getPath()})` : `'${conn.handler}' on ${toNode.getPath()}`;
|
|
1649
|
+
const message = `[incanto] connection '${conn.signal}' from ${fromNode.getPath()} → handler ${target} threw — THIS WIRE is now off; the node that emitted the signal, and the rest of the scene, keep running.`;
|
|
1650
|
+
const engine = toNode.tree?.engine ?? fromNode.tree?.engine;
|
|
1651
|
+
engine?.log.error(message, error);
|
|
1652
|
+
engine?._nodeErrored(toNode);
|
|
1653
|
+
console.error(message, error);
|
|
1654
|
+
}
|
|
1625
1655
|
function resolveEndpoint(root, path, conn, side) {
|
|
1626
1656
|
try {
|
|
1627
1657
|
return root.getNode(path);
|
package/dist/net.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as loadScene } from "./loader-
|
|
2
|
-
import { h as Engine } from "./register-
|
|
1
|
+
import { n as loadScene } from "./loader-DwazzlQb.js";
|
|
2
|
+
import { h as Engine } from "./register-uvaZj1KX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
5
5
|
import { n as createAgent8Server } from "./agent8-CvsfVskX.js";
|
|
6
|
-
import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-
|
|
6
|
+
import { i as applySyncPatch, n as NetworkSpawner, r as NetworkManager, t as registerNodesNet } from "./register-CB11yp21.js";
|
|
7
7
|
//#region src/net/loopback.ts
|
|
8
8
|
/**
|
|
9
9
|
* In-memory multiplayer hub implementing the SAME kernel contract as
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { v as diagnose } from "./loader-
|
|
2
|
+
import { v as diagnose } from "./loader-DwazzlQb.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-
|
|
4
|
+
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-BNPZYJmd.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
//#region src/2d/physics/physics-2d.ts
|
|
7
7
|
var physics_2d_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -122,7 +122,7 @@ var Physics2D = class {
|
|
|
122
122
|
moveAndSlide(node) {
|
|
123
123
|
const e = this.ensureEntry(node);
|
|
124
124
|
const vy = node.velocity[1] ?? 0;
|
|
125
|
-
if (node.
|
|
125
|
+
if (node.stickToGround && vy >= 0) this.kcc.enableSnapToGround(.05);
|
|
126
126
|
else this.kcc.disableSnapToGround();
|
|
127
127
|
this.kcc.setMaxSlopeClimbAngle(node.slopeLimitDeg * DEG);
|
|
128
128
|
let carryX = 0;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { v as diagnose } from "./loader-
|
|
2
|
+
import { v as diagnose } from "./loader-DwazzlQb.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-
|
|
4
|
+
import { F as PhysicsBody3D, I as RigidBody3D, N as Area3D, P as CharacterBody3D, R as Node3D, z as validateCollider3D } from "./gameplay-02Btmmjn.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
|
-
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-
|
|
6
|
+
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-CZOH5TY5.js";
|
|
7
7
|
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
8
8
|
//#region src/3d/physics/collider-lines.ts
|
|
9
9
|
/**
|
|
@@ -373,7 +373,7 @@ var Physics3D = class {
|
|
|
373
373
|
const e = this.ensureEntry(node);
|
|
374
374
|
if (!e) return;
|
|
375
375
|
const vy = node.velocity[1] ?? 0;
|
|
376
|
-
if (node.
|
|
376
|
+
if (node.stickToGround && vy <= 0) this.kcc.enableSnapToGround(.1);
|
|
377
377
|
else this.kcc.disableSnapToGround();
|
|
378
378
|
this.kcc.setMaxSlopeClimbAngle(node.slopeLimitDeg * DEG);
|
|
379
379
|
let carryX = 0;
|
package/dist/react.js
CHANGED
|
@@ -156,7 +156,7 @@ function IncantoCanvas(props) {
|
|
|
156
156
|
pointer: latest.pointer,
|
|
157
157
|
...keyboard !== void 0 ? { keyboard } : {}
|
|
158
158
|
};
|
|
159
|
-
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-DFBjMetZ.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-BgV6UbVA.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { f as Node, h as effectiveOrder } from "./loader-
|
|
2
|
-
import { t as registerCoreNodes } from "./register-
|
|
1
|
+
import { f as Node, h as effectiveOrder } from "./loader-DwazzlQb.js";
|
|
2
|
+
import { t as registerCoreNodes } from "./register-uvaZj1KX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { i as getNodeSchema, l as registerNode } from "./registry-IyWCGe4q.js";
|
|
6
|
-
import { i as
|
|
6
|
+
import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-D_p28jwU.js";
|
|
7
7
|
import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry } from "three";
|
|
8
8
|
//#region src/2d/physics/collider-validate.ts
|
|
9
9
|
/**
|
|
@@ -198,13 +198,19 @@ var CharacterBody2D = class extends PhysicsBody2D {
|
|
|
198
198
|
static typeName = "CharacterBody2D";
|
|
199
199
|
static props = {
|
|
200
200
|
velocity: { default: [0, 0] },
|
|
201
|
-
|
|
201
|
+
stickToGround: { default: true },
|
|
202
202
|
slopeLimitDeg: { default: 45 }
|
|
203
203
|
};
|
|
204
|
+
/**
|
|
205
|
+
* Renamed to match the 3D body, where `snapToGround` had to give the name
|
|
206
|
+
* back to `Node3D`'s PLACEMENT prop. 2D has no placement prop, so nothing is
|
|
207
|
+
* ambiguous here and old scenes keep loading unchanged.
|
|
208
|
+
*/
|
|
209
|
+
static propAliases = { snapToGround: "stickToGround" };
|
|
204
210
|
/** px/s, y-down (up = -y). */
|
|
205
211
|
velocity = [0, 0];
|
|
206
212
|
/** Keep contact on slopes/steps while not moving upward. */
|
|
207
|
-
|
|
213
|
+
stickToGround = true;
|
|
208
214
|
/** Max climbable slope angle. */
|
|
209
215
|
slopeLimitDeg = 45;
|
|
210
216
|
/** @internal Updated by Physics2D.moveAndSlide. */
|
|
@@ -402,13 +408,19 @@ var AnimatedSprite2D = class extends Sprite2D {
|
|
|
402
408
|
frameList = [];
|
|
403
409
|
frameIndex = 0;
|
|
404
410
|
frameTime = 0;
|
|
411
|
+
currentDef = null;
|
|
405
412
|
ownTexture = null;
|
|
406
413
|
loadedSheetRef = "";
|
|
414
|
+
/**
|
|
415
|
+
* `currentAnimation` reports the clip that is RUNNING, not the name asked
|
|
416
|
+
* for: an alias is a rename, and a state machine that reads back `fall` while
|
|
417
|
+
* the idle frames play is describing something that is not happening.
|
|
418
|
+
*/
|
|
407
419
|
play(name) {
|
|
408
|
-
const def = this.animations
|
|
409
|
-
|
|
410
|
-
this.
|
|
411
|
-
this.frameList = resolveFrames(def.frames,
|
|
420
|
+
const { name: resolved, def } = resolveAnimation(this.animations, name, this.name);
|
|
421
|
+
this.currentAnimation = resolved;
|
|
422
|
+
this.currentDef = def;
|
|
423
|
+
this.frameList = resolveFrames(def.frames, resolved);
|
|
412
424
|
this.frameIndex = 0;
|
|
413
425
|
this.currentFrame = this.frameList[0] ?? 0;
|
|
414
426
|
this.frameTime = 0;
|
|
@@ -418,11 +430,12 @@ var AnimatedSprite2D = class extends Sprite2D {
|
|
|
418
430
|
this.playing = false;
|
|
419
431
|
}
|
|
420
432
|
onReady() {
|
|
433
|
+
validateAnimationAliases(this.animations, this.name);
|
|
421
434
|
if (this.autoplay) this.play(this.autoplay);
|
|
422
435
|
}
|
|
423
436
|
update(dt) {
|
|
424
437
|
if (!this.playing || this.currentAnimation === "") return;
|
|
425
|
-
const def = this.
|
|
438
|
+
const def = this.currentDef;
|
|
426
439
|
if (!def || !Number.isFinite(def.fps) || def.fps <= 0) return;
|
|
427
440
|
const perFrame = 1 / def.fps;
|
|
428
441
|
this.frameTime += dt;
|
|
@@ -462,18 +475,6 @@ var AnimatedSprite2D = class extends Sprite2D {
|
|
|
462
475
|
};
|
|
463
476
|
}
|
|
464
477
|
};
|
|
465
|
-
function resolveFrames(frames, name) {
|
|
466
|
-
if (!Array.isArray(frames) || frames.length === 0) throw new IncantoError("BAD_FORMAT", `Animation '${name}': "frames" must be a non-empty array.`);
|
|
467
|
-
if (frames.length === 2) {
|
|
468
|
-
const [start, end] = frames;
|
|
469
|
-
if (end >= start) {
|
|
470
|
-
const out = [];
|
|
471
|
-
for (let f = start; f <= end; f++) out.push(f);
|
|
472
|
-
return out;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
return [...frames];
|
|
476
|
-
}
|
|
477
478
|
//#endregion
|
|
478
479
|
//#region src/2d/nodes/camera-2d.ts
|
|
479
480
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as Signal, f as Node, t as buildNodeJson } from "./loader-
|
|
2
|
-
import { t as registerCoreNodes } from "./register-
|
|
1
|
+
import { E as Signal, f as Node, t as buildNodeJson } from "./loader-DwazzlQb.js";
|
|
2
|
+
import { t as registerCoreNodes } from "./register-uvaZj1KX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
5
5
|
import { l as registerNode } from "./registry-IyWCGe4q.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as Signal, _ as InputMap, b as behaviorSchema, f as Node, g as resolveOrderGroups, m as ORDER_GROUP_BASE, v as diagnose } from "./loader-
|
|
1
|
+
import { E as Signal, _ as InputMap, b as behaviorSchema, f as Node, g as resolveOrderGroups, m as ORDER_GROUP_BASE, v as diagnose } from "./loader-DwazzlQb.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
3
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
4
4
|
import { l as registerNode } from "./registry-IyWCGe4q.js";
|
|
@@ -2558,28 +2558,73 @@ var UiText = class extends HudWidgetBase {
|
|
|
2558
2558
|
static props = {
|
|
2559
2559
|
...HudWidgetBase.props,
|
|
2560
2560
|
text: { default: "" },
|
|
2561
|
+
format: { default: "" },
|
|
2561
2562
|
size: { default: 16 },
|
|
2562
2563
|
color: { default: "#ffffff" },
|
|
2563
2564
|
shadow: { default: true }
|
|
2564
2565
|
};
|
|
2565
2566
|
text = "";
|
|
2567
|
+
/**
|
|
2568
|
+
* A template with a `{}` slot that `setText` fills — `"Gems {} / 8"`.
|
|
2569
|
+
*
|
|
2570
|
+
* Empty (the default) means `setText` replaces the whole line. Resolved at
|
|
2571
|
+
* PAINT like `text`, so `"@t:hud.gems"` works and changing locale re-reads
|
|
2572
|
+
* it: the value lives here, the words live in the strings table.
|
|
2573
|
+
*/
|
|
2574
|
+
format = "";
|
|
2566
2575
|
size = 16;
|
|
2567
2576
|
color = "#ffffff";
|
|
2568
2577
|
shadow = true;
|
|
2569
2578
|
last = "\0";
|
|
2579
|
+
/** null until something has actually set a value — see `shown`. */
|
|
2580
|
+
slot = null;
|
|
2581
|
+
/**
|
|
2582
|
+
* Put a signal's value on screen — `scoreChanged → setText`.
|
|
2583
|
+
*
|
|
2584
|
+
* A `connections[]` handler must be a METHOD and `text` is a property, so the
|
|
2585
|
+
* one wire every game needs (score to screen) could not be declared: every
|
|
2586
|
+
* HUD began with a behavior whose whole job was one assignment.
|
|
2587
|
+
*/
|
|
2588
|
+
setText(value) {
|
|
2589
|
+
this.slot = String(value ?? "");
|
|
2590
|
+
if (!this.format) this.text = this.slot;
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* What it actually paints, after the template and the locale.
|
|
2594
|
+
*
|
|
2595
|
+
* Before the first value arrives, a formatted widget shows `text` — its
|
|
2596
|
+
* authored opening line. Filling the slot with nothing instead would put
|
|
2597
|
+
* `"Gems / 8"` on screen for every game's first frame, and a score line
|
|
2598
|
+
* that starts blank looks broken rather than empty.
|
|
2599
|
+
*/
|
|
2600
|
+
get shown() {
|
|
2601
|
+
if (this.format && this.slot !== null) return this._t(this.format).replace("{}", this.slot);
|
|
2602
|
+
return this._t(this.text);
|
|
2603
|
+
}
|
|
2570
2604
|
_build() {
|
|
2571
2605
|
const el = document.createElement("div");
|
|
2572
2606
|
el.style.cssText = `font-size:${this.size}px;color:${this.color};${this.shadow ? "text-shadow:0 1px 3px rgba(0,0,0,.7);" : ""}white-space:pre;`;
|
|
2573
2607
|
return el;
|
|
2574
2608
|
}
|
|
2575
2609
|
_sync() {
|
|
2576
|
-
const shown = this.
|
|
2610
|
+
const shown = this.shown;
|
|
2577
2611
|
if (shown !== this.last && this._element) {
|
|
2578
2612
|
this.last = shown;
|
|
2579
2613
|
this._element.textContent = shown;
|
|
2580
2614
|
}
|
|
2581
2615
|
}
|
|
2582
2616
|
};
|
|
2617
|
+
/**
|
|
2618
|
+
* A bar fed the wrong argument shows a plausible wrong number forever.
|
|
2619
|
+
*
|
|
2620
|
+
* The trap is one signal away: `Health.damaged` is `(amount, current)`, so
|
|
2621
|
+
* wiring it to `setValue` paints the DAMAGE as the health and looks like a
|
|
2622
|
+
* working health bar. Say which signal has the shape a bar wants.
|
|
2623
|
+
*/
|
|
2624
|
+
function requireNumber(value, node, method) {
|
|
2625
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2626
|
+
throw new IncantoError("PROP_TYPE_MISMATCH", `UiBar '${node.getPath()}'.${method} needs a number, got ${JSON.stringify(value)}. Check what the wired signal passes FIRST — 'damaged' is (amount, current), 'healthChanged' is (current, max), which is the shape a bar wants.`);
|
|
2627
|
+
}
|
|
2583
2628
|
/** A labeled progress bar (health, stamina, reload, boss HP). */
|
|
2584
2629
|
var UiBar = class extends HudWidgetBase {
|
|
2585
2630
|
static typeName = "UiBar";
|
|
@@ -2612,6 +2657,21 @@ var UiBar = class extends HudWidgetBase {
|
|
|
2612
2657
|
get ratio() {
|
|
2613
2658
|
return this.max > 0 ? Math.min(1, Math.max(0, this.value / this.max)) : 0;
|
|
2614
2659
|
}
|
|
2660
|
+
/**
|
|
2661
|
+
* Drive the bar from a signal — `healthChanged → setValue`.
|
|
2662
|
+
*
|
|
2663
|
+
* Takes the max as a second argument because that is the shape the signal
|
|
2664
|
+
* already has, so a bar whose ceiling moves (a max-HP upgrade) needs no
|
|
2665
|
+
* second wire.
|
|
2666
|
+
*/
|
|
2667
|
+
setValue(value, max) {
|
|
2668
|
+
this.value = requireNumber(value, this, "setValue");
|
|
2669
|
+
if (max !== void 0) this.max = requireNumber(max, this, "setValue");
|
|
2670
|
+
}
|
|
2671
|
+
/** Move the ceiling on its own, leaving the fill where it is. */
|
|
2672
|
+
setMax(max) {
|
|
2673
|
+
this.max = requireNumber(max, this, "setMax");
|
|
2674
|
+
}
|
|
2615
2675
|
_build() {
|
|
2616
2676
|
const wrap = document.createElement("div");
|
|
2617
2677
|
wrap.style.cssText = "display:flex;align-items:center;gap:6px;";
|