incanto 0.65.0 → 0.66.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/dist/2d.d.ts +38 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +130 -3
- package/dist/3d.js +4 -4
- package/dist/{audio-player-BrEHwbK1.d.ts → audio-player-_UAcHxnC.d.ts} +1 -1
- package/dist/{behavior-CmMuQ6CL.d.ts → behavior-BXNLfIJk.d.ts} +19 -0
- package/dist/{create-game-W2xzTJhs.js → create-game-DYJCIzO0.js} +66 -5
- package/dist/{create-game-DIyh5Zy9.js → create-game-Dd7H4bJV.js} +5 -5
- package/dist/debug.d.ts +1 -1
- package/dist/{environment-presets-BvHs6HEk.js → environment-presets-BlPsEmq6.js} +69 -5
- package/dist/{gameplay-D-H986A4.js → gameplay-D1RADWu3.js} +267 -7
- package/dist/gameplay.d.ts +78 -3
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/{loader-CTB441z4.d.ts → loader-Cga7FVP4.d.ts} +1 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/{physics-2d-CmnunaR2.js → physics-2d-Cji5A6sX.js} +29 -3
- package/dist/{physics-3d-DULB1lD1.js → physics-3d-BkHjwJgI.js} +46 -4
- package/dist/{quiet-rapier-BAJ4K94N.js → quiet-rapier-C6fW4zcW.js} +14 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-CgeR4ckF.js → register-BmuqYTiY.js} +29 -0
- package/dist/{register-DO5_Qp0Q.js → register-D0CxCveZ.js} +37 -3
- package/dist/{replay-CThvwkcQ.d.ts → replay-BHoB6fCU.d.ts} +1 -1
- package/dist/{replay-CEw2xAhG.js → replay-IsZbNu6d.js} +1 -1
- package/dist/{split-screen-gb0c3xdb.js → split-screen-D_i7GRcY.js} +1 -1
- package/dist/{split-screen-DxZzC1nm.d.ts → split-screen-eJUFjhi1.d.ts} +2 -2
- package/dist/{src-DYffzHbd.js → src-BTLbXFPZ.js} +1 -1
- package/dist/{teardown-BordHL9o.js → teardown-byR9USax.js} +1 -1
- package/dist/{test-CXZuXs8k.js → test-DgrD0jHD.js} +11 -11
- package/dist/test.d.ts +4 -4
- package/dist/test.js +2 -2
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-DO5qzIOD.js → agent8-9N-Pd_YS.js} +1 -1
- package/editor/assets/{debug-DntG9CVD.js → debug-CkbJICYp.js} +1 -1
- package/editor/assets/{index-CqEUVaPN.js → index-CeDhIPTC.js} +72 -72
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +19 -0
- package/skills/incanto-gameplay-behaviors.md +85 -6
- package/skills/incanto-node-reference.md +59 -1
- package/skills/incanto-physics-and-input.md +69 -0
- package/skills/incanto-web-integration.md +24 -3
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/coverage.json +0 -9
- package/templates-app/platformer-2d/coverage.json +0 -5
- package/templates-app/star-survivor/coverage.json +0 -5
- package/templates-app/tps-3d/coverage.json +0 -5
- package/templates-app/village-quest-3d/coverage.json +0 -9
|
@@ -2534,6 +2534,36 @@ var StaticBody3D = class extends PhysicsBody3D {
|
|
|
2534
2534
|
/** Sensor volume emitting `triggerEnter(other)` / `triggerExit(other)`. */
|
|
2535
2535
|
var Area3D = class extends PhysicsBody3D {
|
|
2536
2536
|
static typeName = "Area3D";
|
|
2537
|
+
/**
|
|
2538
|
+
* Who is inside RIGHT NOW — the standing answer behind the enter/exit pair.
|
|
2539
|
+
*
|
|
2540
|
+
* Enter and exit tell you about crossings; a pressure plate, a capture point,
|
|
2541
|
+
* a "how many enemies are in the blast" count and a shop trigger all want
|
|
2542
|
+
* OCCUPANCY. Without this every one of them kept a private `Set` fed by the
|
|
2543
|
+
* two signals, and had to guard it, because a body that is teleported or
|
|
2544
|
+
* freed inside a sensor does not reliably announce its exit. Physics already
|
|
2545
|
+
* knows; now it says.
|
|
2546
|
+
*
|
|
2547
|
+
* ```ts
|
|
2548
|
+
* const load = this.area.overlapping()
|
|
2549
|
+
* .reduce((kg, b) => kg + ((b as RigidBody3D).mass ?? 0), 0);
|
|
2550
|
+
* door.open = load >= 60;
|
|
2551
|
+
* ```
|
|
2552
|
+
*
|
|
2553
|
+
* It reports everything the solver says is inside, STATIC WORLD INCLUDED — a
|
|
2554
|
+
* plate laid into the floor genuinely contains the floor. Pass a group to ask
|
|
2555
|
+
* the question you usually mean:
|
|
2556
|
+
*
|
|
2557
|
+
* ```ts
|
|
2558
|
+
* area.overlapping('crate') // only things tagged `crate`
|
|
2559
|
+
* ```
|
|
2560
|
+
*
|
|
2561
|
+
* Empty in a scene with no physics world.
|
|
2562
|
+
*/
|
|
2563
|
+
overlapping(group) {
|
|
2564
|
+
const all = this._physics?.overlapping(this) ?? [];
|
|
2565
|
+
return group === void 0 ? all : all.filter((n) => n.isInGroup(group));
|
|
2566
|
+
}
|
|
2537
2567
|
};
|
|
2538
2568
|
/** Dynamic simulated body. */
|
|
2539
2569
|
var RigidBody3D = class extends PhysicsBody3D {
|
|
@@ -2548,6 +2578,11 @@ var RigidBody3D = class extends PhysicsBody3D {
|
|
|
2548
2578
|
0,
|
|
2549
2579
|
0,
|
|
2550
2580
|
0
|
|
2581
|
+
] },
|
|
2582
|
+
angularVelocity: { default: [
|
|
2583
|
+
0,
|
|
2584
|
+
0,
|
|
2585
|
+
0
|
|
2551
2586
|
] }
|
|
2552
2587
|
};
|
|
2553
2588
|
mass = 1;
|
|
@@ -2561,6 +2596,18 @@ var RigidBody3D = class extends PhysicsBody3D {
|
|
|
2561
2596
|
0,
|
|
2562
2597
|
0
|
|
2563
2598
|
];
|
|
2599
|
+
/**
|
|
2600
|
+
* rad/s about each world axis. Read back every step; write to spin.
|
|
2601
|
+
*
|
|
2602
|
+
* A puzzle builder could neither launch a spinning body nor read how fast a
|
|
2603
|
+
* lever was swinging — only its angle, differenced by hand — because this had
|
|
2604
|
+
* no counterpart to `linearVelocity`. `fixedRotation` pins it at zero.
|
|
2605
|
+
*/
|
|
2606
|
+
angularVelocity = [
|
|
2607
|
+
0,
|
|
2608
|
+
0,
|
|
2609
|
+
0
|
|
2610
|
+
];
|
|
2564
2611
|
/** @internal set by Physics3D */
|
|
2565
2612
|
_physics3d = null;
|
|
2566
2613
|
/** World-space impulse (kg·m/s) — the floating-capsule controller's verb. */
|
|
@@ -4711,7 +4758,7 @@ var Clickable = class extends Behavior {
|
|
|
4711
4758
|
if (this.hovering) this.setHover(false);
|
|
4712
4759
|
return;
|
|
4713
4760
|
}
|
|
4714
|
-
const hit =
|
|
4761
|
+
const hit = engine.pickAt(pointer.x, pointer.y);
|
|
4715
4762
|
const over = hit !== null && this.isSelfOrDescendant(hit) && this.withinRange(hit);
|
|
4716
4763
|
if (over !== this.hovering) this.setHover(over);
|
|
4717
4764
|
if (engine.input.mouseJustPressed(this.button)) this.pressedHere = over;
|
|
@@ -4781,6 +4828,104 @@ group: { default: "player" } };
|
|
|
4781
4828
|
}
|
|
4782
4829
|
};
|
|
4783
4830
|
//#endregion
|
|
4831
|
+
//#region src/gameplay/currency.ts
|
|
4832
|
+
/**
|
|
4833
|
+
* Money. Earn it, spend it, and refuse what you cannot afford.
|
|
4834
|
+
*
|
|
4835
|
+
* `ScoreKeeper` is the closest thing the library had and it is a SCORE: it
|
|
4836
|
+
* counts up, it has no spend, no affordability question, and its counter is
|
|
4837
|
+
* already wired to the win condition. So a tower defense built on 0.65.0 wrote
|
|
4838
|
+
* its own wallet — and so does every shop, every build mode, every upgrade tree
|
|
4839
|
+
* and every economy game.
|
|
4840
|
+
*
|
|
4841
|
+
* `spend` is the whole point: it returns whether it went through, and emits
|
|
4842
|
+
* `refused` when it did not, so "you cannot afford that" is a wire rather than
|
|
4843
|
+
* a comparison every caller repeats and one caller forgets.
|
|
4844
|
+
*/
|
|
4845
|
+
var Currency = class extends Behavior {
|
|
4846
|
+
static props = {
|
|
4847
|
+
/** What you start with. */
|
|
4848
|
+
amount: { default: 0 },
|
|
4849
|
+
/** Ceiling (0 = none). */
|
|
4850
|
+
max: { default: 0 }
|
|
4851
|
+
};
|
|
4852
|
+
static signals = [
|
|
4853
|
+
"changed",
|
|
4854
|
+
"earned",
|
|
4855
|
+
"spent",
|
|
4856
|
+
"refused"
|
|
4857
|
+
];
|
|
4858
|
+
amount = 0;
|
|
4859
|
+
max = 0;
|
|
4860
|
+
/** Can this be paid right now? */
|
|
4861
|
+
canAfford(cost) {
|
|
4862
|
+
return cost <= this.amount;
|
|
4863
|
+
}
|
|
4864
|
+
/** Pay `cost` if it is there. Returns whether it went through. */
|
|
4865
|
+
spend(cost) {
|
|
4866
|
+
if (!this.canAfford(cost)) {
|
|
4867
|
+
this.emit("refused", cost);
|
|
4868
|
+
return false;
|
|
4869
|
+
}
|
|
4870
|
+
this.amount -= cost;
|
|
4871
|
+
this.emit("spent", cost);
|
|
4872
|
+
this.emit("changed", this.amount);
|
|
4873
|
+
return true;
|
|
4874
|
+
}
|
|
4875
|
+
/** Take payment in. */
|
|
4876
|
+
earn(gain) {
|
|
4877
|
+
this.amount = this.max > 0 ? Math.min(this.max, this.amount + gain) : this.amount + gain;
|
|
4878
|
+
this.emit("earned", gain);
|
|
4879
|
+
this.emit("changed", this.amount);
|
|
4880
|
+
}
|
|
4881
|
+
/** Set it outright (a shop that grants, a cheat, a restore). */
|
|
4882
|
+
setAmount(next) {
|
|
4883
|
+
this.amount = this.max > 0 ? Math.min(this.max, next) : next;
|
|
4884
|
+
this.emit("changed", this.amount);
|
|
4885
|
+
}
|
|
4886
|
+
serialize() {
|
|
4887
|
+
return { amount: this.amount };
|
|
4888
|
+
}
|
|
4889
|
+
deserialize(data) {
|
|
4890
|
+
const d = data;
|
|
4891
|
+
if (typeof d.amount === "number") this.amount = d.amount;
|
|
4892
|
+
}
|
|
4893
|
+
};
|
|
4894
|
+
//#endregion
|
|
4895
|
+
//#region src/gameplay/free-target.ts
|
|
4896
|
+
/**
|
|
4897
|
+
* Free the ENTITY a despawning behavior belongs to, not just the node it sits on.
|
|
4898
|
+
*
|
|
4899
|
+
* `Lifetime` and `DamageOnContact` both remove their own node, which is right
|
|
4900
|
+
* when the behavior IS the thing. It is wrong for the composition the docs
|
|
4901
|
+
* teach: a node carries ONE script, so a bullet that both hurts and expires must
|
|
4902
|
+
* put those on CHILD nodes — and then each child quietly removed itself while
|
|
4903
|
+
* the bullet flew on forever, leaking a node per shot.
|
|
4904
|
+
*
|
|
4905
|
+
* `freeParent: true` is the other half. It is the same escape hatch the movement
|
|
4906
|
+
* behaviors call `moveParent`, named the same way for the same reason.
|
|
4907
|
+
*/
|
|
4908
|
+
function freeOwner(behavior, freeParent, who) {
|
|
4909
|
+
if (!freeParent) {
|
|
4910
|
+
behavior.node.queueFree();
|
|
4911
|
+
return;
|
|
4912
|
+
}
|
|
4913
|
+
const parent = behavior.node.parent;
|
|
4914
|
+
if (!parent) {
|
|
4915
|
+
diagnose(behavior.node.tree?.engine ?? null, "error", `[incanto] ${who} on '${behavior.node.getPath()}': "freeParent" is set and this node has no parent to free — it is the scene root. Nothing was removed. Drop the prop, or move this behavior onto a child of the thing you meant to despawn.`);
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
parent.queueFree();
|
|
4919
|
+
}
|
|
4920
|
+
/** The shared prop, so both behaviors declare it identically. */
|
|
4921
|
+
const FREE_PARENT_PROP = {
|
|
4922
|
+
/**
|
|
4923
|
+
* Free this node's PARENT instead of this node — the composition where a
|
|
4924
|
+
* bullet carries `Projectile` and its children carry the damage and the
|
|
4925
|
+
* timer. Without it each child removes only itself and the bullet leaks.
|
|
4926
|
+
*/
|
|
4927
|
+
freeParent: { default: false } };
|
|
4928
|
+
//#endregion
|
|
4784
4929
|
//#region src/gameplay/health.ts
|
|
4785
4930
|
/**
|
|
4786
4931
|
* Hit points with regeneration and post-hit invulnerability (i-frames) —
|
|
@@ -4971,7 +5116,9 @@ function onTriggerEnter(behavior, fn) {
|
|
|
4971
5116
|
* - `repeatEvery` (seconds, 0 = off) re-damages targets that STAY overlapped —
|
|
4972
5117
|
* lava pools, poison clouds, an enemy standing on you. Contact events fire
|
|
4973
5118
|
* only on entry/exit; this is the "and it keeps hurting" knob.
|
|
4974
|
-
* - `destroySelf` frees the hazard after a hit (single-use projectiles)
|
|
5119
|
+
* - `destroySelf` frees the hazard after a hit (single-use projectiles), and
|
|
5120
|
+
* `freeParent` makes that free the PARENT — a bullet whose hitbox is a child,
|
|
5121
|
+
* which is the only shape a node-carries-one-script engine allows.
|
|
4975
5122
|
*
|
|
4976
5123
|
* SCORING PATTERN (clone-safe): wire the KILLER's `dealtDamage` →
|
|
4977
5124
|
* `ScoreKeeper.addScore`. The weapon is usually a non-cloned node (it lives on
|
|
@@ -4989,7 +5136,8 @@ var DamageOnContact = class extends Behavior {
|
|
|
4989
5136
|
/** Re-damage targets still overlapping every N seconds (0 = entry only). */
|
|
4990
5137
|
repeatEvery: { default: 0 },
|
|
4991
5138
|
/** queueFree() this node after the first successful hit. */
|
|
4992
|
-
destroySelf: { default: false }
|
|
5139
|
+
destroySelf: { default: false },
|
|
5140
|
+
...FREE_PARENT_PROP
|
|
4993
5141
|
};
|
|
4994
5142
|
static signals = ["dealtDamage"];
|
|
4995
5143
|
amount = 10;
|
|
@@ -4997,6 +5145,7 @@ var DamageOnContact = class extends Behavior {
|
|
|
4997
5145
|
oncePerTarget = true;
|
|
4998
5146
|
repeatEvery = 0;
|
|
4999
5147
|
destroySelf = false;
|
|
5148
|
+
freeParent = false;
|
|
5000
5149
|
hit = /* @__PURE__ */ new WeakSet();
|
|
5001
5150
|
/** Targets currently overlapping → seconds until their next repeat tick. */
|
|
5002
5151
|
inside = /* @__PURE__ */ new Map();
|
|
@@ -5032,7 +5181,7 @@ var DamageOnContact = class extends Behavior {
|
|
|
5032
5181
|
if (this.oncePerTarget) this.hit.add(other);
|
|
5033
5182
|
found.health.damage(this.amount);
|
|
5034
5183
|
this.emit("dealtDamage", this.amount, found.owner);
|
|
5035
|
-
if (this.destroySelf) this.
|
|
5184
|
+
if (this.destroySelf) freeOwner(this, this.freeParent, "DamageOnContact");
|
|
5036
5185
|
}
|
|
5037
5186
|
};
|
|
5038
5187
|
/**
|
|
@@ -5146,6 +5295,109 @@ function phaseOf(hour) {
|
|
|
5146
5295
|
return "dusk";
|
|
5147
5296
|
}
|
|
5148
5297
|
//#endregion
|
|
5298
|
+
//#region src/gameplay/face-target.ts
|
|
5299
|
+
/**
|
|
5300
|
+
* Turn toward the nearest thing in a group, and say when you are on it.
|
|
5301
|
+
*
|
|
5302
|
+
* A turret is the shape every tower defense, sentry gun, security camera and
|
|
5303
|
+
* idle-NPC-that-watches-you needs, and it could not be composed. `Chase`
|
|
5304
|
+
* already finds the nearest target and turns toward it — and then MOVES, which
|
|
5305
|
+
* is the one thing a turret must not do; `Patrol`/`Chase`'s `facePath` only
|
|
5306
|
+
* turns as a side effect of locomotion, so a stationary node cannot use it.
|
|
5307
|
+
* A tower defense built on 0.65.0 hand-wrote acquisition (~20 lines) and
|
|
5308
|
+
* turn-and-gate-the-shot (~15) because of that.
|
|
5309
|
+
*
|
|
5310
|
+
* `aimed` fires when the facing settles onto the target and `lostAim` when it
|
|
5311
|
+
* comes off, so "only fire while actually pointed at it" is a wire rather than
|
|
5312
|
+
* an angle comparison you write yourself.
|
|
5313
|
+
*/
|
|
5314
|
+
var FaceTarget = class extends Behavior {
|
|
5315
|
+
static props = {
|
|
5316
|
+
/** Group to acquire from — the nearest live member wins. */
|
|
5317
|
+
targetGroup: {
|
|
5318
|
+
default: "",
|
|
5319
|
+
required: true
|
|
5320
|
+
},
|
|
5321
|
+
/** Only acquire within this distance (0 = anywhere). */
|
|
5322
|
+
range: { default: 0 },
|
|
5323
|
+
/** Node to TURN (usually a skin); empty turns this behavior's own node. */
|
|
5324
|
+
facePath: {
|
|
5325
|
+
default: "",
|
|
5326
|
+
nodePath: true
|
|
5327
|
+
},
|
|
5328
|
+
/** Turn rate rad/s; 100 is an instant snap, as on the controller. */
|
|
5329
|
+
turnSpeed: { default: 6 },
|
|
5330
|
+
/** Degrees of slop that still counts as pointed at it. */
|
|
5331
|
+
aimTolerance: { default: 6 }
|
|
5332
|
+
};
|
|
5333
|
+
static signals = [
|
|
5334
|
+
"acquired",
|
|
5335
|
+
"lostTarget",
|
|
5336
|
+
"aimed",
|
|
5337
|
+
"lostAim"
|
|
5338
|
+
];
|
|
5339
|
+
targetGroup = "";
|
|
5340
|
+
range = 0;
|
|
5341
|
+
facePath = "";
|
|
5342
|
+
turnSpeed = 6;
|
|
5343
|
+
aimTolerance = 6;
|
|
5344
|
+
/** The node currently being tracked, or null. */
|
|
5345
|
+
target = null;
|
|
5346
|
+
/** True while the facing is within `aimTolerance` of the target. */
|
|
5347
|
+
onTarget = false;
|
|
5348
|
+
onReady() {
|
|
5349
|
+
if (this.targetGroup === "") throw new IncantoError("PROP_TYPE_MISMATCH", `FaceTarget on '${this.node.getPath()}': "targetGroup" is required — it is the group this turret acquires from.`, { prop: "targetGroup" });
|
|
5350
|
+
}
|
|
5351
|
+
update(dt) {
|
|
5352
|
+
const self = this.node;
|
|
5353
|
+
if (!hasPosition$1(self)) return;
|
|
5354
|
+
const found = this.nearest();
|
|
5355
|
+
if (found !== this.target) {
|
|
5356
|
+
this.target = found;
|
|
5357
|
+
this.emit(found ? "acquired" : "lostTarget", found);
|
|
5358
|
+
if (!found) this.setAim(false);
|
|
5359
|
+
}
|
|
5360
|
+
if (!found) return;
|
|
5361
|
+
const turret = this.facePath === "" ? self : this.node.getNodeOrNull(this.facePath);
|
|
5362
|
+
if (!turret) return;
|
|
5363
|
+
const dir = found.position.map((v, i) => v - (self.position[i] ?? 0));
|
|
5364
|
+
faceTravel(turret, dir, dt, this.turnSpeed);
|
|
5365
|
+
this.setAim(this.pointedAt(turret, dir));
|
|
5366
|
+
}
|
|
5367
|
+
nearest() {
|
|
5368
|
+
const self = this.node;
|
|
5369
|
+
let best = null;
|
|
5370
|
+
let bestD = Number.POSITIVE_INFINITY;
|
|
5371
|
+
for (const candidate of this.node.tree?.getNodesInGroup(this.targetGroup) ?? []) {
|
|
5372
|
+
if (!hasPosition$1(candidate)) continue;
|
|
5373
|
+
const d = Math.hypot(...candidate.position.map((v, i) => v - (self.position[i] ?? 0)));
|
|
5374
|
+
if (this.range > 0 && d > this.range) continue;
|
|
5375
|
+
if (d < bestD) {
|
|
5376
|
+
bestD = d;
|
|
5377
|
+
best = candidate;
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5380
|
+
return best;
|
|
5381
|
+
}
|
|
5382
|
+
/** Is the turret's forward within tolerance of the direction to the target? */
|
|
5383
|
+
pointedAt(turret, dir) {
|
|
5384
|
+
const rot = turret.rotation;
|
|
5385
|
+
const is3d = Array.isArray(rot);
|
|
5386
|
+
const [a, b] = is3d ? [dir[0] ?? 0, dir[2] ?? 0] : [dir[0] ?? 0, dir[1] ?? 0];
|
|
5387
|
+
const len = Math.hypot(a, b);
|
|
5388
|
+
if (len < 1e-6) return true;
|
|
5389
|
+
const yaw = (is3d ? rot[1] ?? 0 : rot ?? 0) * Math.PI / 180;
|
|
5390
|
+
const fx = is3d ? Math.sin(yaw) : Math.cos(yaw);
|
|
5391
|
+
const fy = is3d ? Math.cos(yaw) : Math.sin(yaw);
|
|
5392
|
+
return (fx * a + fy * b) / len >= Math.cos(this.aimTolerance * Math.PI / 180);
|
|
5393
|
+
}
|
|
5394
|
+
setAim(on) {
|
|
5395
|
+
if (on === this.onTarget) return;
|
|
5396
|
+
this.onTarget = on;
|
|
5397
|
+
this.emit(on ? "aimed" : "lostAim", this.target);
|
|
5398
|
+
}
|
|
5399
|
+
};
|
|
5400
|
+
//#endregion
|
|
5149
5401
|
//#region src/gameplay/float-away.ts
|
|
5150
5402
|
/**
|
|
5151
5403
|
* Rise, fade, and be gone — the second half of a damage number.
|
|
@@ -5780,6 +6032,10 @@ const hitStops = /* @__PURE__ */ new Map();
|
|
|
5780
6032
|
* pickups that vanish. Accumulates `dt`; on elapse emits `expired` then
|
|
5781
6033
|
* `queueFree()`s its node.
|
|
5782
6034
|
*
|
|
6035
|
+
* `freeParent: true` frees the node's PARENT instead — the shape a bullet needs,
|
|
6036
|
+
* since a node carries ONE script so `Projectile`, the damage and the timer have
|
|
6037
|
+
* to live on separate nodes.
|
|
6038
|
+
*
|
|
5783
6039
|
* With `startOnSignal: true` the countdown is armed manually via `startTimer()`
|
|
5784
6040
|
* (wire a signal → `startTimer`), so the lifetime begins on an event rather
|
|
5785
6041
|
* than at spawn.
|
|
@@ -5789,11 +6045,13 @@ var Lifetime = class extends Behavior {
|
|
|
5789
6045
|
/** Seconds before the node frees itself. */
|
|
5790
6046
|
seconds: { default: 1 },
|
|
5791
6047
|
/** Defer the countdown until `startTimer()` is called (default: start at ready). */
|
|
5792
|
-
startOnSignal: { default: false }
|
|
6048
|
+
startOnSignal: { default: false },
|
|
6049
|
+
...FREE_PARENT_PROP
|
|
5793
6050
|
};
|
|
5794
6051
|
static signals = ["expired"];
|
|
5795
6052
|
seconds = 1;
|
|
5796
6053
|
startOnSignal = false;
|
|
6054
|
+
freeParent = false;
|
|
5797
6055
|
elapsed = 0;
|
|
5798
6056
|
running = false;
|
|
5799
6057
|
fired = false;
|
|
@@ -5814,7 +6072,7 @@ var Lifetime = class extends Behavior {
|
|
|
5814
6072
|
this.fired = true;
|
|
5815
6073
|
this.running = false;
|
|
5816
6074
|
this.emit("expired");
|
|
5817
|
-
this.
|
|
6075
|
+
freeOwner(this, this.freeParent, "Lifetime");
|
|
5818
6076
|
}
|
|
5819
6077
|
}
|
|
5820
6078
|
};
|
|
@@ -7102,6 +7360,7 @@ const GAMEPLAY_BEHAVIORS = {
|
|
|
7102
7360
|
Health,
|
|
7103
7361
|
Lifetime,
|
|
7104
7362
|
ScoreKeeper,
|
|
7363
|
+
Currency,
|
|
7105
7364
|
Pickup,
|
|
7106
7365
|
Collector,
|
|
7107
7366
|
DamageOnContact,
|
|
@@ -7111,6 +7370,7 @@ const GAMEPLAY_BEHAVIORS = {
|
|
|
7111
7370
|
FollowCamera,
|
|
7112
7371
|
Patrol,
|
|
7113
7372
|
Chase,
|
|
7373
|
+
FaceTarget,
|
|
7114
7374
|
Wander,
|
|
7115
7375
|
ZombieAI,
|
|
7116
7376
|
MoveTo,
|
|
@@ -7131,4 +7391,4 @@ function registerGameplayBehaviors(opts) {
|
|
|
7131
7391
|
for (const [name, ctor] of Object.entries(GAMEPLAY_BEHAVIORS)) registerBehavior(name, ctor, { replace });
|
|
7132
7392
|
}
|
|
7133
7393
|
//#endregion
|
|
7134
|
-
export {
|
|
7394
|
+
export { DamageOnContact as A, rejectScale as B, restartScene as C, FaceTarget as D, FloatAway as E, localFromWorld as F, StaticBody3D as G, CharacterBody3D as H, worldPosition as I, createCausticsQuad as J, Node3D as K, Water3D as L, Currency as M, Collector as N, DayNight as O, Chase as P, WATER_CUTOUT_MAX as R, goToScene as S, FollowCamera as T, PhysicsBody3D as U, Area3D as V, RigidBody3D as W, colliderFootDrop as X, WATER_MAX_RIPPLES as Y, Cooldown as _, Wander as a, Interactable as b, SavePoint as c, Patrol as d, PathFollow as f, CameraShake as g, Lifetime as h, WaveSpawner as i, Health as j, phaseOf as k, Projectile as l, MoveTo as m, registerGameplayBehaviors as n, Spawner as o, Oscillate as p, validateCollider3D as q, ZombieAI as r, ScoreKeeper as s, GAMEPLAY_BEHAVIORS as t, Pickup as u, hitStop as v, tolerateUnknownAction as w, GameFlow as x, screenFlash as y, WaterCutout3D as z };
|
package/dist/gameplay.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-
|
|
1
|
+
import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-BXNLfIJk.js";
|
|
2
2
|
import { c as JsonValue, s as JsonObject } from "./schema-CFeioQRE.js";
|
|
3
3
|
|
|
4
4
|
//#region src/gameplay/chase.d.ts
|
|
@@ -60,6 +60,37 @@ declare class Collector extends Behavior {
|
|
|
60
60
|
override deserialize(data: JsonValue): void;
|
|
61
61
|
}
|
|
62
62
|
//#endregion
|
|
63
|
+
//#region src/gameplay/currency.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* Money. Earn it, spend it, and refuse what you cannot afford.
|
|
66
|
+
*
|
|
67
|
+
* `ScoreKeeper` is the closest thing the library had and it is a SCORE: it
|
|
68
|
+
* counts up, it has no spend, no affordability question, and its counter is
|
|
69
|
+
* already wired to the win condition. So a tower defense built on 0.65.0 wrote
|
|
70
|
+
* its own wallet — and so does every shop, every build mode, every upgrade tree
|
|
71
|
+
* and every economy game.
|
|
72
|
+
*
|
|
73
|
+
* `spend` is the whole point: it returns whether it went through, and emits
|
|
74
|
+
* `refused` when it did not, so "you cannot afford that" is a wire rather than
|
|
75
|
+
* a comparison every caller repeats and one caller forgets.
|
|
76
|
+
*/
|
|
77
|
+
declare class Currency extends Behavior {
|
|
78
|
+
static readonly props: PropSchema;
|
|
79
|
+
static readonly signals: readonly string[];
|
|
80
|
+
amount: number;
|
|
81
|
+
max: number;
|
|
82
|
+
/** Can this be paid right now? */
|
|
83
|
+
canAfford(cost: number): boolean;
|
|
84
|
+
/** Pay `cost` if it is there. Returns whether it went through. */
|
|
85
|
+
spend(cost: number): boolean;
|
|
86
|
+
/** Take payment in. */
|
|
87
|
+
earn(gain: number): void;
|
|
88
|
+
/** Set it outright (a shop that grants, a cheat, a restore). */
|
|
89
|
+
setAmount(next: number): void;
|
|
90
|
+
override serialize(): JsonValue;
|
|
91
|
+
override deserialize(data: JsonValue): void;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
63
94
|
//#region src/gameplay/health.d.ts
|
|
64
95
|
/**
|
|
65
96
|
* Hit points with regeneration and post-hit invulnerability (i-frames) —
|
|
@@ -162,7 +193,9 @@ declare class Health extends Behavior {
|
|
|
162
193
|
* - `repeatEvery` (seconds, 0 = off) re-damages targets that STAY overlapped —
|
|
163
194
|
* lava pools, poison clouds, an enemy standing on you. Contact events fire
|
|
164
195
|
* only on entry/exit; this is the "and it keeps hurting" knob.
|
|
165
|
-
* - `destroySelf` frees the hazard after a hit (single-use projectiles)
|
|
196
|
+
* - `destroySelf` frees the hazard after a hit (single-use projectiles), and
|
|
197
|
+
* `freeParent` makes that free the PARENT — a bullet whose hitbox is a child,
|
|
198
|
+
* which is the only shape a node-carries-one-script engine allows.
|
|
166
199
|
*
|
|
167
200
|
* SCORING PATTERN (clone-safe): wire the KILLER's `dealtDamage` →
|
|
168
201
|
* `ScoreKeeper.addScore`. The weapon is usually a non-cloned node (it lives on
|
|
@@ -177,6 +210,7 @@ declare class DamageOnContact extends Behavior {
|
|
|
177
210
|
oncePerTarget: boolean;
|
|
178
211
|
repeatEvery: number;
|
|
179
212
|
destroySelf: boolean;
|
|
213
|
+
freeParent: boolean;
|
|
180
214
|
private readonly hit;
|
|
181
215
|
/** Targets currently overlapping → seconds until their next repeat tick. */
|
|
182
216
|
private readonly inside;
|
|
@@ -185,6 +219,42 @@ declare class DamageOnContact extends Behavior {
|
|
|
185
219
|
private tryDamage;
|
|
186
220
|
}
|
|
187
221
|
//#endregion
|
|
222
|
+
//#region src/gameplay/face-target.d.ts
|
|
223
|
+
/**
|
|
224
|
+
* Turn toward the nearest thing in a group, and say when you are on it.
|
|
225
|
+
*
|
|
226
|
+
* A turret is the shape every tower defense, sentry gun, security camera and
|
|
227
|
+
* idle-NPC-that-watches-you needs, and it could not be composed. `Chase`
|
|
228
|
+
* already finds the nearest target and turns toward it — and then MOVES, which
|
|
229
|
+
* is the one thing a turret must not do; `Patrol`/`Chase`'s `facePath` only
|
|
230
|
+
* turns as a side effect of locomotion, so a stationary node cannot use it.
|
|
231
|
+
* A tower defense built on 0.65.0 hand-wrote acquisition (~20 lines) and
|
|
232
|
+
* turn-and-gate-the-shot (~15) because of that.
|
|
233
|
+
*
|
|
234
|
+
* `aimed` fires when the facing settles onto the target and `lostAim` when it
|
|
235
|
+
* comes off, so "only fire while actually pointed at it" is a wire rather than
|
|
236
|
+
* an angle comparison you write yourself.
|
|
237
|
+
*/
|
|
238
|
+
declare class FaceTarget extends Behavior {
|
|
239
|
+
static readonly props: PropSchema;
|
|
240
|
+
static readonly signals: readonly string[];
|
|
241
|
+
targetGroup: string;
|
|
242
|
+
range: number;
|
|
243
|
+
facePath: string;
|
|
244
|
+
turnSpeed: number;
|
|
245
|
+
aimTolerance: number;
|
|
246
|
+
/** The node currently being tracked, or null. */
|
|
247
|
+
target: Node | null;
|
|
248
|
+
/** True while the facing is within `aimTolerance` of the target. */
|
|
249
|
+
onTarget: boolean;
|
|
250
|
+
override onReady(): void;
|
|
251
|
+
override update(dt: number): void;
|
|
252
|
+
private nearest;
|
|
253
|
+
/** Is the turret's forward within tolerance of the direction to the target? */
|
|
254
|
+
private pointedAt;
|
|
255
|
+
private setAim;
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
188
258
|
//#region src/gameplay/follow-camera.d.ts
|
|
189
259
|
/**
|
|
190
260
|
* Make the node it sits on chase a target's position — THE camera-follow
|
|
@@ -239,6 +309,10 @@ declare class Interactable extends Behavior {
|
|
|
239
309
|
* pickups that vanish. Accumulates `dt`; on elapse emits `expired` then
|
|
240
310
|
* `queueFree()`s its node.
|
|
241
311
|
*
|
|
312
|
+
* `freeParent: true` frees the node's PARENT instead — the shape a bullet needs,
|
|
313
|
+
* since a node carries ONE script so `Projectile`, the damage and the timer have
|
|
314
|
+
* to live on separate nodes.
|
|
315
|
+
*
|
|
242
316
|
* With `startOnSignal: true` the countdown is armed manually via `startTimer()`
|
|
243
317
|
* (wire a signal → `startTimer`), so the lifetime begins on an event rather
|
|
244
318
|
* than at spawn.
|
|
@@ -248,6 +322,7 @@ declare class Lifetime extends Behavior {
|
|
|
248
322
|
static readonly signals: readonly string[];
|
|
249
323
|
seconds: number;
|
|
250
324
|
startOnSignal: boolean;
|
|
325
|
+
freeParent: boolean;
|
|
251
326
|
private elapsed;
|
|
252
327
|
private running;
|
|
253
328
|
private fired;
|
|
@@ -987,4 +1062,4 @@ declare function registerGameplayBehaviors(opts?: {
|
|
|
987
1062
|
replace?: boolean;
|
|
988
1063
|
}): void;
|
|
989
1064
|
//#endregion
|
|
990
|
-
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, type DayPhase, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, type GameFlowState, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
|
1065
|
+
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, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
package/dist/gameplay.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FloatAway, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, SavePoint, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
|
1
|
+
import { A as DamageOnContact, C as restartScene, D as FaceTarget, E as FloatAway, M as Currency, N as Collector, O as DayNight, P as Chase, S as goToScene, T as FollowCamera, _ 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 Health, k as phaseOf, 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-D1RADWu3.js";
|
|
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, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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-BXNLfIJk.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
|
-
import { n as loadScene, t as LoadSceneOptions } from "./loader-
|
|
3
|
+
import { n as loadScene, t as LoadSceneOptions } from "./loader-Cga7FVP4.js";
|
|
4
4
|
import { i as resolveFrames, n as AnimationEntry, r as resolveAnimation, t as AnimationDef } from "./sprite-animation-CMr6f1K2.js";
|
|
5
|
-
import { a as ParticleSimConfig, i as ParticleSim, n as AudioPlayer, o as ParticleView, t as AudioElementLike } from "./audio-player-
|
|
5
|
+
import { a as ParticleSimConfig, i as ParticleSim, n as AudioPlayer, o as ParticleView, t as AudioElementLike } from "./audio-player-_UAcHxnC.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-BHoB6fCU.js";
|
|
8
8
|
|
|
9
9
|
//#region src/core/audio/crossfade.d.ts
|
|
10
10
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { A as describeRefProblem, B as registeredBehaviors, C as ORDER_GROUP_BASE, E as InputMap, F as behaviorSchema, I as behaviorSignals, L as clearBehaviors, M as resolveRefInJson, N as parseNodePath, O as Node, P as Behavior, R as getBehavior, S as createSaveStore, T as resolveOrderGroups, V as Signal, _ as SaveSlots, a as serializeNode, b as restoreBehaviors, d as computeViewport, f as resolveViewport, g as resolveConstants, h as isConstRef, i as Scene, j as nodeRefWarnings, m as CONST_REF_KEY, n as loadScene, o as SCENE_FORMAT, p as SceneTree, v as behaviorsWithoutSave, w as effectiveOrder, x as savesWithoutUid, y as captureBehaviors, z as registerBehavior } from "./loader-lQDCwNag.js";
|
|
2
|
-
import { A as UiBanner, B as isAudioContextAvailable, D as EffectLog, E as LogManager, F as T_PREFIX, G as SFX_PRESET_NAMES, H as spatialGain, I as suggestLocale, J as MusicManager, K as sfxDuration, M as UiText, N as BASE_LOCALE, O as HudLayer, P as Localization, Q as AudioBuses, R as translationKey, S as qualityEnvironment, T as suggestQuality, U as spatialPan, V as ROLLOFF_MODELS, W as SFX_PRESETS, X as crossfadeGains, Y as WebAudioMusicBackend, Z as fadeGain, _ as AudioPlayer, a as UiMuteToggle, b as Settings, c as UiRenderScaleSelect, d as UiToggle, f as UiVolumeSlider, g as UiDialogue, h as UiButton, i as UiLanguageSelect, j as UiBar, l as UiSelect, m as Respawn, n as UiFrameCapSelect, o as UiPanel, p as Timer, q as synthSfx, r as UiImage, s as UiQualitySelect, t as registerCoreNodes, u as UiSlider, v as Engine, w as readDeviceHints, z as SfxEngine } from "./register-
|
|
2
|
+
import { A as UiBanner, B as isAudioContextAvailable, D as EffectLog, E as LogManager, F as T_PREFIX, G as SFX_PRESET_NAMES, H as spatialGain, I as suggestLocale, J as MusicManager, K as sfxDuration, M as UiText, N as BASE_LOCALE, O as HudLayer, P as Localization, Q as AudioBuses, R as translationKey, S as qualityEnvironment, T as suggestQuality, U as spatialPan, V as ROLLOFF_MODELS, W as SFX_PRESETS, X as crossfadeGains, Y as WebAudioMusicBackend, Z as fadeGain, _ as AudioPlayer, a as UiMuteToggle, b as Settings, c as UiRenderScaleSelect, d as UiToggle, f as UiVolumeSlider, g as UiDialogue, h as UiButton, i as UiLanguageSelect, j as UiBar, l as UiSelect, m as Respawn, n as UiFrameCapSelect, o as UiPanel, p as Timer, q as synthSfx, r as UiImage, s as UiQualitySelect, t as registerCoreNodes, u as UiSlider, v as Engine, w as readDeviceHints, z as SfxEngine } from "./register-BmuqYTiY.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 { n as jsonEquals, r as jsonKind, t as jsonClone } from "./json-CwwhxQgb.js";
|
|
6
6
|
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-CF70EArN.js";
|
|
7
|
-
import { n as startRecording, r as auditScene, t as replay } from "./replay-
|
|
7
|
+
import { n as startRecording, r as auditScene, t as replay } from "./replay-IsZbNu6d.js";
|
|
8
8
|
import { a as logReport, i as resolveRendering, n as attachTouchControls, o as logText, r as joystickVector, s as parseDrive, t as TouchControls } from "./touch-DESwnpOc.js";
|
|
9
9
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
10
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-CY-mrr1L.js";
|
|
11
|
-
import { a as preloadUrls, i as preloadSceneAssets, n as newUid, o as findPath, r as assetUrls, s as gridFromRows, t as VERSION } from "./src-
|
|
11
|
+
import { a as preloadUrls, i as preloadSceneAssets, n as newUid, o as findPath, r as assetUrls, s as gridFromRows, t as VERSION } from "./src-BTLbXFPZ.js";
|
|
12
12
|
import { t as duplicateNode } from "./duplicate-CqSAtdrh.js";
|
|
13
13
|
export { AudioBuses, AudioPlayer, BASE_LOCALE, Behavior, CONST_REF_KEY, EffectLog, Engine, HudLayer, IncantoError, InputMap, Localization, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Respawn, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, SaveSlots, Scene, SceneTree, Settings, SfxEngine, Signal, T_PREFIX, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiFrameCapSelect, UiImage, UiLanguageSelect, UiMuteToggle, UiPanel, UiQualitySelect, UiRenderScaleSelect, UiSelect, UiSlider, UiText, UiToggle, UiVolumeSlider, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, behaviorSchema, behaviorSignals, behaviorsWithoutSave, captureBehaviors, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, describeRefProblem, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, logReport, logText, mergeStaticSignals, newUid, nodeRefWarnings, parseDrive, parseNodePath, preloadSceneAssets, preloadUrls, qualityEnvironment, readDeviceHints, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveAnimation, resolveConstants, resolveFrames, resolveOrderGroups, resolveRefInJson, resolveRendering, resolveViewport, restoreBehaviors, savesWithoutUid, serializeNode, sfxDuration, spatialGain, spatialPan, startRecording, suggestLocale, suggestQuality, synthSfx, translationKey };
|
package/dist/net.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as PropSchema, jt as Node } from "./behavior-
|
|
2
|
-
import { a as NetworkManagerOptions, c as LocalGameServer, d as ServerClass, f as createLocalGameServer, g as Unsubscribe, h as NetworkTransport, i as NetworkManager, l as LocalGameServerOptions, m as LoopbackTransport, n as SplitScreenPlayer, o as applySyncPatch, p as LoopbackHub, r as createSplitScreen, s as CollectionOptions, t as SplitScreenOptions, u as LocalGameServerTransport } from "./split-screen-
|
|
1
|
+
import { d as PropSchema, jt as Node } from "./behavior-BXNLfIJk.js";
|
|
2
|
+
import { a as NetworkManagerOptions, c as LocalGameServer, d as ServerClass, f as createLocalGameServer, g as Unsubscribe, h as NetworkTransport, i as NetworkManager, l as LocalGameServerOptions, m as LoopbackTransport, n as SplitScreenPlayer, o as applySyncPatch, p as LoopbackHub, r as createSplitScreen, s as CollectionOptions, t as SplitScreenOptions, u as LocalGameServerTransport } from "./split-screen-eJUFjhi1.js";
|
|
3
3
|
|
|
4
4
|
//#region src/net/agent8.d.ts
|
|
5
5
|
/**
|
package/dist/net.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as createAgent8Server } from "./agent8-CvsfVskX.js";
|
|
2
|
-
import { a as NetworkManager, d as createLocalGameServer, f as LoopbackHub, l as LocalGameServer, n as registerNodesNet, o as applySyncPatch, p as LoopbackTransport, r as NetworkSpawner, t as createSplitScreen, u as LocalGameServerTransport } from "./split-screen-
|
|
2
|
+
import { a as NetworkManager, d as createLocalGameServer, f as LoopbackHub, l as LocalGameServer, n as registerNodesNet, o as applySyncPatch, p as LoopbackTransport, r as NetworkSpawner, t as createSplitScreen, u as LocalGameServerTransport } from "./split-screen-D_i7GRcY.js";
|
|
3
3
|
export { LocalGameServer, LocalGameServerTransport, LoopbackHub, LoopbackTransport, NetworkManager, NetworkSpawner, applySyncPatch, createAgent8Server, createLocalGameServer, createSplitScreen, registerNodesNet };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
2
|
import { k as diagnose } from "./loader-lQDCwNag.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-D0CxCveZ.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
|
-
import { t as withoutRapierInitNoise } from "./quiet-rapier-
|
|
6
|
+
import { n as jointContacts, t as withoutRapierInitNoise } from "./quiet-rapier-C6fW4zcW.js";
|
|
7
7
|
//#region src/2d/physics/physics-2d.ts
|
|
8
8
|
var physics_2d_exports = /* @__PURE__ */ __exportAll({
|
|
9
9
|
Physics2D: () => Physics2D,
|
|
@@ -119,6 +119,8 @@ var Physics2D = class {
|
|
|
119
119
|
const b = this.byColliderHandle.get(h2);
|
|
120
120
|
if (!a || !b) return;
|
|
121
121
|
const sig = started ? "triggerEnter" : "triggerExit";
|
|
122
|
+
this.trackOverlap(a, b, started);
|
|
123
|
+
this.trackOverlap(b, a, started);
|
|
122
124
|
try {
|
|
123
125
|
a.emit(sig, b);
|
|
124
126
|
b.emit(sig, a);
|
|
@@ -284,9 +286,33 @@ var Physics2D = class {
|
|
|
284
286
|
else if (joint.type === "rope") data = R.JointData.rope(length, a1, a2);
|
|
285
287
|
else if (joint.type === "spring") data = R.JointData.spring(length, joint.stiffness, joint.damping, a1, a2);
|
|
286
288
|
else data = R.JointData.revolute(a1, a2);
|
|
287
|
-
|
|
289
|
+
const made = this.world.createImpulseJoint(data, ea.body, eb.body, true);
|
|
290
|
+
made.setContactsEnabled(jointContacts(joint.type, joint.collide));
|
|
291
|
+
this.joints.set(joint, made);
|
|
288
292
|
}
|
|
289
293
|
}
|
|
294
|
+
/** Who is currently inside each sensor/body, maintained from the event drain. */
|
|
295
|
+
overlaps = /* @__PURE__ */ new Map();
|
|
296
|
+
trackOverlap(self, other, started) {
|
|
297
|
+
let set = this.overlaps.get(self);
|
|
298
|
+
if (started) {
|
|
299
|
+
if (!set) {
|
|
300
|
+
set = /* @__PURE__ */ new Set();
|
|
301
|
+
this.overlaps.set(self, set);
|
|
302
|
+
}
|
|
303
|
+
set.add(other);
|
|
304
|
+
} else if (set) {
|
|
305
|
+
set.delete(other);
|
|
306
|
+
if (set.size === 0) this.overlaps.delete(self);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** The bodies currently overlapping `node`. Freed nodes are dropped on read. */
|
|
310
|
+
overlapping(node) {
|
|
311
|
+
const set = this.overlaps.get(node);
|
|
312
|
+
if (!set) return [];
|
|
313
|
+
for (const other of set) if (other.tree === null) set.delete(other);
|
|
314
|
+
return [...set];
|
|
315
|
+
}
|
|
290
316
|
/**
|
|
291
317
|
* World-space raycast in PIXELS (y-down). `exclude` skips that body — a
|
|
292
318
|
* shooter probing from inside its own collider needs it. Sensors (Area2D)
|