incanto 0.64.1 → 0.65.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.
Files changed (50) hide show
  1. package/dist/2d.d.ts +3 -3
  2. package/dist/2d.js +3 -3
  3. package/dist/3d.d.ts +3 -3
  4. package/dist/3d.js +5 -5
  5. package/dist/{audio-player-D5GJgb_x.d.ts → audio-player-BrEHwbK1.d.ts} +1 -1
  6. package/dist/{behavior-DsgayMsH.d.ts → behavior-CmMuQ6CL.d.ts} +109 -0
  7. package/dist/{create-game-B1KM6dA6.js → create-game-DIyh5Zy9.js} +6 -6
  8. package/dist/{create-game-B746rYbr.js → create-game-W2xzTJhs.js} +6 -6
  9. package/dist/debug.d.ts +1 -1
  10. package/dist/{duplicate-BOOKmkQ7.js → duplicate-CqSAtdrh.js} +1 -1
  11. package/dist/{environment-presets-D2vzw583.js → environment-presets-BvHs6HEk.js} +3 -3
  12. package/dist/{gameplay-CLgFdkh5.js → gameplay-D-H986A4.js} +107 -11
  13. package/dist/gameplay.d.ts +17 -1
  14. package/dist/gameplay.js +1 -1
  15. package/dist/index.d.ts +4 -4
  16. package/dist/index.js +5 -5
  17. package/dist/{loader-DolLJWJn.d.ts → loader-CTB441z4.d.ts} +1 -1
  18. package/dist/{loader-zDynoew_.js → loader-lQDCwNag.js} +59 -3
  19. package/dist/net.d.ts +2 -2
  20. package/dist/net.js +1 -1
  21. package/dist/{physics-2d-BPJcJRRP.js → physics-2d-CmnunaR2.js} +4 -2
  22. package/dist/{physics-3d-BOO58xzw.js → physics-3d-DULB1lD1.js} +5 -3
  23. package/dist/react.d.ts +1 -1
  24. package/dist/react.js +1 -1
  25. package/dist/{register-Btm7_Emq.js → register-CgeR4ckF.js} +15 -1
  26. package/dist/{register-dGsbnJ87.js → register-DO5_Qp0Q.js} +3 -3
  27. package/dist/{replay-DKRmiVjk.js → replay-CEw2xAhG.js} +2 -2
  28. package/dist/{replay-C5x2vPF5.d.ts → replay-CThvwkcQ.d.ts} +1 -1
  29. package/dist/{split-screen-D7OopelJ.d.ts → split-screen-DxZzC1nm.d.ts} +2 -2
  30. package/dist/{split-screen-Dx0LvzqS.js → split-screen-gb0c3xdb.js} +2 -2
  31. package/dist/{src-CNS2xQB1.js → src-DYffzHbd.js} +1 -1
  32. package/dist/{teardown-BwhkcNt8.js → teardown-BordHL9o.js} +1 -1
  33. package/dist/{test-Ccob3X5i.js → test-CXZuXs8k.js} +13 -13
  34. package/dist/test.d.ts +4 -4
  35. package/dist/test.js +2 -2
  36. package/dist/vite.js +2 -2
  37. package/editor/assets/{agent8-Di-UEn5O.js → agent8-DO5qzIOD.js} +1 -1
  38. package/editor/assets/{debug-DWztJ5_y.js → debug-DntG9CVD.js} +1 -1
  39. package/editor/assets/{index-fct4H89G.js → index-CqEUVaPN.js} +72 -72
  40. package/editor/index.html +1 -1
  41. package/package.json +1 -1
  42. package/skills/incanto-3d-character.md +11 -1
  43. package/skills/incanto-behaviors-and-scripts.md +21 -0
  44. package/skills/incanto-gameplay-behaviors.md +92 -3
  45. package/skills/incanto-physics-and-input.md +15 -1
  46. package/templates-app/beacon-isle-3d/package.json +1 -1
  47. package/templates-app/platformer-2d/package.json +1 -1
  48. package/templates-app/star-survivor/package.json +1 -1
  49. package/templates-app/tps-3d/package.json +1 -1
  50. package/templates-app/village-quest-3d/package.json +1 -1
package/dist/2d.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats } from "./behavior-DsgayMsH.js";
1
+ import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats } from "./behavior-CmMuQ6CL.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DAvWQeld.js";
3
3
  import { i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
4
4
  import { r as FrameStats } from "./frame-report-DCnHFmto.js";
5
- import { t as LoadSceneOptions } from "./loader-DolLJWJn.js";
5
+ import { t as LoadSceneOptions } from "./loader-CTB441z4.js";
6
6
  import { n as AnimationEntry } from "./sprite-animation-CMr6f1K2.js";
7
- import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-D5GJgb_x.js";
7
+ import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-BrEHwbK1.js";
8
8
  import { Group, Mesh, Object3D, Scene, Texture } from "three";
9
9
  import * as RapierNs from "@dimforge/rapier2d-compat";
10
10
 
package/dist/2d.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-B1KM6dA6.js";
3
- import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-dGsbnJ87.js";
4
- import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-BPJcJRRP.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-DIyh5Zy9.js";
3
+ import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-DO5_Qp0Q.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-CmnunaR2.js";
5
5
  //#region src/2d/library-sprite.ts
6
6
  /**
7
7
  * What a `CharacterController2D`/`3D` will ask a skin to play, and the clip in
package/dist/3d.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats } from "./behavior-DsgayMsH.js";
1
+ import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats } from "./behavior-CmMuQ6CL.js";
2
2
  import { n as DiagnosticSink, t as EditorSwitchOptions } from "./editor-switch-DAvWQeld.js";
3
3
  import { i as SceneJson$1, s as JsonObject } from "./schema-CFeioQRE.js";
4
4
  import { a as GridCell, c as diffText, d as frameText, i as FrameStatsOptions, l as frameSignature, n as FrameSignature, o as SIGNATURE_GRID, r as FrameStats, s as diffSignatures, t as FrameDiff, u as frameStats } from "./frame-report-DCnHFmto.js";
5
- import { t as LoadSceneOptions } from "./loader-DolLJWJn.js";
6
- import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-D5GJgb_x.js";
5
+ import { t as LoadSceneOptions } from "./loader-CTB441z4.js";
6
+ import { i as ParticleSim, o as ParticleView, r as SpatialPose } from "./audio-player-BrEHwbK1.js";
7
7
  import { n as PathGrid } from "./pathfinding-_fGrCFmH.js";
8
8
  import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
9
9
  import { VRM } from "@pixiv/three-vrm";
package/dist/3d.js CHANGED
@@ -1,10 +1,10 @@
1
- import { c as parseEnvironment3D, l as sunDirectionFromElevationAzimuth, s as horizonColorFromSky, u as sunDirectionFromSky } from "./loader-zDynoew_.js";
1
+ import { c as parseEnvironment3D, l as sunDirectionFromElevationAzimuth, s as horizonColorFromSky, u as sunDirectionFromSky } from "./loader-lQDCwNag.js";
2
2
  import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-BSMny7oe.js";
3
- import { B as CharacterBody3D, F as Water3D, H as RigidBody3D, I as WATER_CUTOUT_MAX, L as WaterCutout3D, U as StaticBody3D, V as PhysicsBody3D, W as Node3D, q as WATER_MAX_RIPPLES, z as Area3D } from "./gameplay-CLgFdkh5.js";
4
- import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-D2vzw583.js";
5
- import { a as Environment3D, i as syncTree, o as setEnvironment3D, r as Renderer3D, s as AssetStore3D, t as createGame3D } from "./create-game-B746rYbr.js";
3
+ import { B as CharacterBody3D, F as Water3D, H as RigidBody3D, I as WATER_CUTOUT_MAX, L as WaterCutout3D, U as StaticBody3D, V as PhysicsBody3D, W as Node3D, q as WATER_MAX_RIPPLES, z as Area3D } from "./gameplay-D-H986A4.js";
4
+ import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-BvHs6HEk.js";
5
+ import { a as Environment3D, i as syncTree, o as setEnvironment3D, r as Renderer3D, s as AssetStore3D, t as createGame3D } from "./create-game-W2xzTJhs.js";
6
6
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
7
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-BOO58xzw.js";
7
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-DULB1lD1.js";
8
8
  //#region src/3d/model-verdict.ts
9
9
  /** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
10
10
  const MIXAMO = /^mixamorig[:_]?/i;
@@ -1,4 +1,4 @@
1
- import { d as PropSchema, dt as Listener, jt as Node } from "./behavior-DsgayMsH.js";
1
+ import { d as PropSchema, dt as Listener, jt as Node } from "./behavior-CmMuQ6CL.js";
2
2
  import { a as Rng } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/core/particle-sim.d.ts
@@ -1104,6 +1104,51 @@ declare function resolveOrderGroups(declared?: Record<string, number>): OrderGro
1104
1104
  */
1105
1105
  declare function effectiveOrder(group: string, renderOrder: number, table?: OrderGroupTable): number;
1106
1106
  //#endregion
1107
+ //#region src/core/physics-query.d.ts
1108
+ /** What a ray found: how far, the surface normal, and the body it belongs to. */
1109
+ interface RayHit {
1110
+ distance: number;
1111
+ normal: number[];
1112
+ node: Node | null;
1113
+ }
1114
+ /**
1115
+ * The physics world, as core knows it — the QUERIES a behavior asks, with no
1116
+ * mention of Rapier or three, so `Engine` can hold one without core learning
1117
+ * about either runtime. `Physics2D` and `Physics3D` satisfy it structurally
1118
+ * (2D in PIXELS y-down with 2-vectors, 3D in METERS y-up with 3-vectors).
1119
+ *
1120
+ * This exists because `incanto-physics-and-input.md` has always taught
1121
+ * `physics.castRay(origin, dir, maxLen, exclude?)` without ever saying where
1122
+ * that `physics` comes from. It lived only on the object `createGame2D/3D()`
1123
+ * returns — the BOOT site — so a `Behavior`, which is where AI lives and where
1124
+ * line of sight is decided, could not reach it. A stealth game's guard had to
1125
+ * cast the private `node._physics` to call a documented API.
1126
+ */
1127
+ interface PhysicsQuery {
1128
+ /**
1129
+ * Fire a ray and report the first thing it hits, or `null`.
1130
+ *
1131
+ * Sensors never block a ray. Pass `exclude` for the body you are casting from
1132
+ * — a ray starting inside its own collider hits itself at distance 0.
1133
+ */
1134
+ castRay(origin: readonly number[], dir: readonly number[], maxLen: number, exclude?: Node, opts?: {
1135
+ staticOnly?: boolean;
1136
+ }): RayHit | null;
1137
+ /**
1138
+ * A THICK ray (sphere sweep) — 3D only, hence optional. Use it where skimming
1139
+ * matters: a thin ray that passes 10 cm over a wall reports "clear" while the
1140
+ * wall still fills the frame.
1141
+ */
1142
+ castSphere?(origin: readonly number[], dir: readonly number[], radius: number, maxLen: number, exclude?: Node, opts?: {
1143
+ staticOnly?: boolean;
1144
+ }): {
1145
+ distance: number;
1146
+ node: Node | null;
1147
+ } | null;
1148
+ /** Tear the world down and detach from the engine. */
1149
+ dispose(): void;
1150
+ }
1151
+ //#endregion
1107
1152
  //#region src/core/save.d.ts
1108
1153
  /**
1109
1154
  * Namespaced game persistence — high scores, unlocks, settings. localStorage
@@ -1576,6 +1621,20 @@ declare class Engine {
1576
1621
  readonly sceneChanged: Signal<[Scene | null]>;
1577
1622
  /** Declarative input — scene `input{}` declarations load on setScene. */
1578
1623
  readonly input: InputMap;
1624
+ /**
1625
+ * The physics world, once something enabled it — `null` in a game that has
1626
+ * none, which is most 2D puzzle games and every menu scene.
1627
+ *
1628
+ * `enablePhysics2D/3D` set this, and `dispose()` clears it. It is the handle
1629
+ * `incanto-physics-and-input.md` has always assumed you had: the skill teaches
1630
+ * `physics.castRay(...)` but the object lived only where the game BOOTED, so
1631
+ * a `Behavior` — where AI lives, and where line of sight is decided — had no
1632
+ * way to reach it short of casting the private `node._physics`.
1633
+ *
1634
+ * Typed as the query surface rather than the concrete class so core never
1635
+ * learns about Rapier or three. From a behavior, prefer `this.physics`.
1636
+ */
1637
+ physics: PhysicsQuery | null;
1579
1638
  /** Seeded randomness for game logic (deterministic when `seed` is set). */
1580
1639
  readonly rng: Rng;
1581
1640
  /** The engine log channel (debug overlay + headless harness tail this). */
@@ -1942,8 +2001,44 @@ interface BehaviorCtor {
1942
2001
  * schema/defaults/delta model as node props.
1943
2002
  */
1944
2003
  declare abstract class Behavior {
2004
+ /**
2005
+ * Every behavior accepts `enabled`, inherited down the static chain — see
2006
+ * `enabled` below for why it is a universal prop rather than one each AI
2007
+ * behavior declares for itself.
2008
+ */
1945
2009
  static props?: PropSchema;
1946
2010
  /**
2011
+ * Whether this behavior's `update`/`fixedUpdate` run. `false` stops it
2012
+ * without removing it — and this is what makes ENEMY AI expressible in JSON.
2013
+ *
2014
+ * A node holds ONE behavior, so `Patrol` and `Chase` cannot share one. Both
2015
+ * can ride child nodes with `moveParent`, but then both run at once, and
2016
+ * before this nothing could stop either — so "patrols until it spots you,
2017
+ * then chases", the most ordinary AI there is, had to be hand-written in
2018
+ * TypeScript, which is exactly what the gameplay library exists to prevent.
2019
+ * With this the whole state machine is two wires:
2020
+ *
2021
+ * ```jsonc
2022
+ * { "signal": "spotted", "from": "Eyes", "to": "Walk", "handler": "disable" },
2023
+ * { "signal": "spotted", "from": "Eyes", "to": "Hunt", "handler": "enable" }
2024
+ * ```
2025
+ *
2026
+ * `Clickable` had already hand-rolled this exact prop for itself. One
2027
+ * behavior needed it and solved it locally; nothing generalized it.
2028
+ *
2029
+ * Asleep is NOT detached: the behavior keeps its props and its accumulated
2030
+ * state, stays reachable as `node.behavior`, keeps its signal connections,
2031
+ * and still saves through `serialize()`. Only the per-frame hooks pause. The
2032
+ * lifecycle hooks (`onEnterTree`/`onReady`/`onExitTree`) are not gated — they
2033
+ * are structural, they fire once, and a behavior that skipped its own
2034
+ * `onReady` would wake up uninitialized.
2035
+ */
2036
+ enabled: boolean;
2037
+ /** Start running again — a connection handler, so a wire can do it. */
2038
+ enable(): void;
2039
+ /** Stop running without being removed — a connection handler. */
2040
+ disable(): void;
2041
+ /**
1947
2042
  * Custom signals this behavior emits via `this.emit(...)` — declared onto
1948
2043
  * its node at load. Undeclared emits are hard errors (typo safety).
1949
2044
  */
@@ -1958,6 +2053,20 @@ declare abstract class Behavior {
1958
2053
  get rng(): Rng;
1959
2054
  /** The engine log channel (visible in the debug overlay and test harness). */
1960
2055
  get log(): LogManager;
2056
+ /**
2057
+ * The physics world, for the queries AI asks — `castRay` for line of sight,
2058
+ * `castSphere` for a probe that must not skim past a wall.
2059
+ *
2060
+ * ```ts
2061
+ * const hit = this.physics?.castRay(eye, dir, range, this.node);
2062
+ * const blocked = hit !== null && hit.node !== player;
2063
+ * ```
2064
+ *
2065
+ * `null` in a game with no physics, so a behavior that only sometimes needs
2066
+ * a ray degrades instead of throwing. Pass the caster as `exclude` — a ray
2067
+ * that starts inside its own collider hits itself at distance 0.
2068
+ */
2069
+ get physics(): PhysicsQuery | null;
1961
2070
  getNode(path: string): Node;
1962
2071
  emit(signal: string, ...args: unknown[]): void;
1963
2072
  on(signal: string, fn: SignalListener<unknown[]>, opts?: {
@@ -1,14 +1,14 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { d as computeViewport, f as resolveViewport, k as diagnose, n as loadScene, z as registerBehavior } from "./loader-zDynoew_.js";
3
- import { _ as AudioPlayer, v as Engine } from "./register-Btm7_Emq.js";
2
+ import { d as computeViewport, f as resolveViewport, k as diagnose, n as loadScene, z as registerBehavior } from "./loader-lQDCwNag.js";
3
+ import { _ as AudioPlayer, v as Engine } from "./register-CgeR4ckF.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-DESwnpOc.js";
6
- import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-BwhkcNt8.js";
6
+ import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-BordHL9o.js";
7
7
  import { o as frameStats } from "./frame-report-BSMny7oe.js";
8
- import { n as registerGameplayBehaviors } from "./gameplay-CLgFdkh5.js";
9
- import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-dGsbnJ87.js";
8
+ import { n as registerGameplayBehaviors } from "./gameplay-D-H986A4.js";
9
+ import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-DO5_Qp0Q.js";
10
10
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
11
- import { n as enablePhysics2D } from "./physics-2d-BPJcJRRP.js";
11
+ import { n as enablePhysics2D } from "./physics-2d-CmnunaR2.js";
12
12
  import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
13
13
  //#region src/2d/assets.ts
14
14
  /**
@@ -1,14 +1,14 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { c as parseEnvironment3D, k as diagnose, n as loadScene, s as horizonColorFromSky, u as sunDirectionFromSky, z as registerBehavior } from "./loader-zDynoew_.js";
3
- import { C as qualityRendering, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-Btm7_Emq.js";
2
+ import { c as parseEnvironment3D, k as diagnose, n as loadScene, s as horizonColorFromSky, u as sunDirectionFromSky, z as registerBehavior } from "./loader-lQDCwNag.js";
3
+ import { C as qualityRendering, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-CgeR4ckF.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-DESwnpOc.js";
6
- import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-BwhkcNt8.js";
6
+ import { a as openBundledEditor, c as claimCanvasGestures, i as devServerLibrary, l as audioErrors, n as pauseWhenHidden, o as poseFromRenderer, r as crossFade, s as wireDevChannel, t as teardown } from "./teardown-BordHL9o.js";
7
7
  import { o as frameStats } from "./frame-report-BSMny7oe.js";
8
- import { K as createCausticsQuad, V as PhysicsBody3D, W as Node3D, n as registerGameplayBehaviors } from "./gameplay-CLgFdkh5.js";
8
+ import { K as createCausticsQuad, V as PhysicsBody3D, W as Node3D, n as registerGameplayBehaviors } from "./gameplay-D-H986A4.js";
9
9
  import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
10
- import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-D2vzw583.js";
11
- import { n as enablePhysics3D } from "./physics-3d-BOO58xzw.js";
10
+ import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-BvHs6HEk.js";
11
+ import { n as enablePhysics3D } from "./physics-3d-DULB1lD1.js";
12
12
  import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
13
13
  import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
14
14
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
package/dist/debug.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-DsgayMsH.js";
1
+ import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-CmMuQ6CL.js";
2
2
 
3
3
  //#region src/debug/panel.d.ts
4
4
  /** Minimal document surface the overlay needs (injectable for tests). */
@@ -1,4 +1,4 @@
1
- import { a as serializeNode, t as buildNodeJson } from "./loader-zDynoew_.js";
1
+ import { a as serializeNode, t as buildNodeJson } from "./loader-lQDCwNag.js";
2
2
  //#region src/core/scene/duplicate.ts
3
3
  function stripUids(json) {
4
4
  const { uid: _uid, ...rest } = json;
@@ -1,11 +1,11 @@
1
- import { k as diagnose } from "./loader-zDynoew_.js";
2
- import { L as translateOn, t as registerCoreNodes } from "./register-Btm7_Emq.js";
1
+ import { k as diagnose } from "./loader-lQDCwNag.js";
2
+ import { L as translateOn, t as registerCoreNodes } from "./register-CgeR4ckF.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-CF70EArN.js";
6
6
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
7
7
  import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-CY-mrr1L.js";
8
- import { B as CharacterBody3D, F as Water3D, H as RigidBody3D, J as colliderFootDrop, L as WaterCutout3D, R as rejectScale, U as StaticBody3D, V as PhysicsBody3D, W as Node3D, w as tolerateUnknownAction, z as Area3D } from "./gameplay-CLgFdkh5.js";
8
+ import { B as CharacterBody3D, F as Water3D, H as RigidBody3D, J as colliderFootDrop, L as WaterCutout3D, R as rejectScale, U as StaticBody3D, V as PhysicsBody3D, W as Node3D, w as tolerateUnknownAction, z as Area3D } from "./gameplay-D-H986A4.js";
9
9
  import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
10
10
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
11
11
  import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, ClampToEdgeWrapping, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LinearMipmapLinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NoColorSpace, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
@@ -1,7 +1,7 @@
1
- import { O as Node, P as Behavior, _ as SaveSlots, k as diagnose, n as loadScene, w as effectiveOrder, z as registerBehavior } from "./loader-zDynoew_.js";
1
+ import { O as Node, P as Behavior, _ as SaveSlots, k as diagnose, n as loadScene, w as effectiveOrder, z as registerBehavior } from "./loader-lQDCwNag.js";
2
2
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
3
  import { t as jsonClone } from "./json-CwwhxQgb.js";
4
- import { t as duplicateNode } from "./duplicate-BOOKmkQ7.js";
4
+ import { t as duplicateNode } from "./duplicate-CqSAtdrh.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();
@@ -4360,6 +4360,65 @@ function firstWater(node) {
4360
4360
  return null;
4361
4361
  }
4362
4362
  //#endregion
4363
+ //#region src/gameplay/face-travel.ts
4364
+ const RAD2DEG = 180 / Math.PI;
4365
+ /**
4366
+ * Turn a node to face the direction something is travelling.
4367
+ *
4368
+ * `CharacterController3D` does this for the PLAYER (`skinPath`/`turnSpeed`) and
4369
+ * nothing did it for anyone else — so every game with a patrolling or chasing
4370
+ * enemy hand-wrote the same six lines, against a formula the docs simultaneously
4371
+ * teach and warn about: `incanto-3d-character.md` calls the wrong version of it
4372
+ * "the #1 recurring bug" (a character that runs BACKWARDS, showing you its back
4373
+ * while charging at you). This is the right version, once, in the engine.
4374
+ *
4375
+ * The rule, for 3D: the model is **+Z-FORWARD**, so `yaw = atan2(dx, dz)` — x
4376
+ * and z, never y, and NO 180° added. The 180° is only the at-rest mount for a
4377
+ * behind-the-shoulder camera, not a facing formula.
4378
+ *
4379
+ * In 2D `rotation` is a scalar and the plane is x/y, so it is `atan2(dy, dx)` —
4380
+ * correct for the top-down games that use `Patrol`/`Chase`. A platformer faces
4381
+ * with `flipX` instead and should not set `facePath`.
4382
+ *
4383
+ * `turnSpeed` is rad/s, the same units and the same shortest-arc, rate-limited
4384
+ * step the controller uses; at the default 100 it is effectively an instant
4385
+ * snap. A zero-length direction leaves the rotation alone — a node that is not
4386
+ * moving has nothing to face.
4387
+ */
4388
+ function faceTravel(target, dir, dt, turnSpeed) {
4389
+ const spatial = target;
4390
+ const rot = spatial.rotation;
4391
+ const is3d = Array.isArray(rot);
4392
+ const [a, b] = is3d ? [dir[0] ?? 0, dir[2] ?? 0] : [dir[0] ?? 0, dir[1] ?? 0];
4393
+ if (Math.hypot(a, b) < 1e-6) return;
4394
+ const want = (is3d ? Math.atan2(a, b) : Math.atan2(b, a)) * RAD2DEG;
4395
+ const current = is3d ? rot[1] ?? 0 : rot ?? 0;
4396
+ let delta = (want - current + 540) % 360 - 180;
4397
+ const step = turnSpeed * dt * RAD2DEG;
4398
+ if (Math.abs(delta) > step) delta = Math.sign(delta) * step;
4399
+ const next = current + delta;
4400
+ if (is3d) spatial.rotation = [
4401
+ rot[0] ?? 0,
4402
+ next,
4403
+ rot[2] ?? 0
4404
+ ];
4405
+ else spatial.rotation = next;
4406
+ }
4407
+ /** The shared `facePath`/`turnSpeed` prop pair for the AI movement behaviors. */
4408
+ const FACING_PROPS = {
4409
+ /**
4410
+ * Node path of the thing to TURN toward the travel direction — usually the
4411
+ * `ModelInstance3D` skin ('../Skin'). Empty (default) turns nothing, so a
4412
+ * scene that never asks is unchanged.
4413
+ */
4414
+ facePath: {
4415
+ default: "",
4416
+ nodePath: true
4417
+ },
4418
+ /** Turn rate in rad/s; 100 (default) is an instant snap, like the controller. */
4419
+ turnSpeed: { default: 100 }
4420
+ };
4421
+ //#endregion
4363
4422
  //#region src/gameplay/move-body.ts
4364
4423
  function moveBody(node, to, dt) {
4365
4424
  const body = node;
@@ -4521,6 +4580,8 @@ function localFromWorld(node, world) {
4521
4580
  * it leaves), so wire it to an attack.
4522
4581
  * - `loseRange` (>0) gives up the chase when the target gets that far away,
4523
4582
  * emitting `lostTarget` once.
4583
+ * - `facePath`/`turnSpeed` turn a skin toward the direction of travel — the job
4584
+ * `CharacterController3D` does for the player and nobody did for an NPC.
4524
4585
  * - `moveParent` (default false) moves the parent node instead of this one.
4525
4586
  * A node carries ONE behavior, so an enemy whose ROOT must hold `Health`
4526
4587
  * (e.g. for `Health.freeOnDeath` clone-safe cleanup) puts `Chase` on a CHILD
@@ -4542,7 +4603,8 @@ var Chase = class extends Behavior {
4542
4603
  /** Give up (emit lostTarget) beyond this distance (0 = never lose). */
4543
4604
  loseRange: { default: 0 },
4544
4605
  /** Move the parent node instead of this one (AI-on-a-child pattern). */
4545
- moveParent: { default: false }
4606
+ moveParent: { default: false },
4607
+ ...FACING_PROPS
4546
4608
  };
4547
4609
  static signals = ["reachedTarget", "lostTarget"];
4548
4610
  target = "";
@@ -4550,6 +4612,8 @@ var Chase = class extends Behavior {
4550
4612
  stopRange = 0;
4551
4613
  loseRange = 0;
4552
4614
  moveParent = false;
4615
+ facePath = "";
4616
+ turnSpeed = 100;
4553
4617
  inRange = false;
4554
4618
  lost = false;
4555
4619
  onReady() {
@@ -4586,8 +4650,13 @@ var Chase = class extends Behavior {
4586
4650
  }
4587
4651
  this.inRange = false;
4588
4652
  const step = Math.min(this.speed * dt, this.stopRange > 0 ? d - this.stopRange : d);
4653
+ const from = [...mover.position];
4589
4654
  const { position } = moveToward(mover.position, target.position, Math.max(0, step));
4590
4655
  moveBody(mover, position, dt);
4656
+ if (this.facePath !== "") {
4657
+ const skin = this.node.getNodeOrNull(this.facePath);
4658
+ if (skin) faceTravel(skin, position.map((v, i) => v - (from[i] ?? 0)), dt, this.turnSpeed);
4659
+ }
4591
4660
  }
4592
4661
  };
4593
4662
  //#endregion
@@ -4621,9 +4690,7 @@ var Clickable = class extends Behavior {
4621
4690
  /** Mouse button: 0 left, 1 middle, 2 right. */
4622
4691
  button: { default: 0 },
4623
4692
  /** Ignore clicks further away than this (0 = any distance). */
4624
- maxDistance: { default: 0 },
4625
- /** Stop responding without removing the behavior. */
4626
- enabled: { default: true }
4693
+ maxDistance: { default: 0 }
4627
4694
  };
4628
4695
  static signals = [
4629
4696
  "clicked",
@@ -4632,13 +4699,12 @@ var Clickable = class extends Behavior {
4632
4699
  ];
4633
4700
  button = 0;
4634
4701
  maxDistance = 0;
4635
- enabled = true;
4636
4702
  /** True while the cursor is over this node — read it to tint a hover state. */
4637
4703
  hovering = false;
4638
4704
  pressedHere = false;
4639
4705
  update() {
4640
4706
  const engine = this.node.tree?.engine;
4641
- if (!engine || !this.enabled) return;
4707
+ if (!engine) return;
4642
4708
  const picker = engine.picker;
4643
4709
  const pointer = engine.input.pointerPosition();
4644
4710
  if (!picker || !pointer) {
@@ -6004,6 +6070,13 @@ function distanceBetween(a, b) {
6004
6070
  *
6005
6071
  * - `loop` (default) — after the last point, head back to the first.
6006
6072
  * - `mode: 'pingpong'` — reverse direction at each end instead of wrapping.
6073
+ * - `moveParent` (default false) moves the parent node instead of this one,
6074
+ * exactly as `Chase` does. A node carries ONE behavior, so a guard that must
6075
+ * patrol AND hold `Health` on its body puts `Patrol` on a CHILD. Without
6076
+ * this the patrolling body had to carry `Patrol` itself and could hold
6077
+ * nothing else — so a patrolling enemy could not be hurt.
6078
+ * - `facePath`/`turnSpeed` turn a skin toward the direction of travel, the job
6079
+ * `CharacterController3D` does for the player and nobody did for an NPC.
6007
6080
  */
6008
6081
  var Patrol = class extends Behavior {
6009
6082
  static props = {
@@ -6022,7 +6095,10 @@ var Patrol = class extends Behavior {
6022
6095
  options: ["loop", "pingpong"]
6023
6096
  },
6024
6097
  /** Seconds to wait at each reached point before continuing. */
6025
- pauseAt: { default: 0 }
6098
+ pauseAt: { default: 0 },
6099
+ /** Move the parent node instead of this one (AI-on-a-child pattern). */
6100
+ moveParent: { default: false },
6101
+ ...FACING_PROPS
6026
6102
  };
6027
6103
  static signals = ["reachedPoint"];
6028
6104
  points = [];
@@ -6030,33 +6106,53 @@ var Patrol = class extends Behavior {
6030
6106
  loop = true;
6031
6107
  mode = "loop";
6032
6108
  pauseAt = 0;
6109
+ moveParent = false;
6110
+ facePath = "";
6111
+ turnSpeed = 100;
6033
6112
  index = 0;
6034
6113
  direction = 1;
6035
6114
  pauseTimer = 0;
6036
6115
  onReady() {
6037
6116
  if (!Array.isArray(this.points) || this.points.length === 0) throw new IncantoError("PROP_TYPE_MISMATCH", `Patrol on '${this.node.getPath()}': "points" must be a non-empty array of position arrays or node paths.`, { prop: "points" });
6038
6117
  if (this.mode !== "loop" && this.mode !== "pingpong") throw new IncantoError("PROP_TYPE_MISMATCH", `Patrol on '${this.node.getPath()}': "mode" must be 'loop' or 'pingpong', got '${this.mode}'.`, { prop: "mode" });
6039
- requirePosition(this);
6118
+ if (this.moveParent) {
6119
+ const parent = this.node.parent;
6120
+ if (!parent || !hasPosition$1(parent)) throw new IncantoError("PROP_TYPE_MISMATCH", `Patrol on '${this.node.getPath()}': "moveParent" needs a spatial parent (a Node2D/Node3D) to move. '${this.node.name}' has none.`, {
6121
+ prop: "moveParent",
6122
+ path: this.node.getPath()
6123
+ });
6124
+ } else requirePosition(this);
6040
6125
  }
6041
6126
  update(dt) {
6042
6127
  if (this.pauseTimer > 0) {
6043
6128
  this.pauseTimer = Math.max(0, this.pauseTimer - dt);
6044
6129
  return;
6045
6130
  }
6046
- const node = this.node;
6131
+ const mover = this.moveParent ? this.node.parent : this.node;
6132
+ if (!mover || !hasPosition$1(mover)) return;
6133
+ const node = mover;
6047
6134
  const target = this.pointAt(this.index);
6048
6135
  if (!target) {
6049
6136
  this.reportDeadWaypoint(this.index);
6050
6137
  return;
6051
6138
  }
6139
+ const from = [...node.position];
6052
6140
  const { position, reached } = moveToward(node.position, target, this.speed * dt);
6053
6141
  moveBody(node, position, dt);
6142
+ this.face(from, position, dt);
6054
6143
  if (reached) {
6055
6144
  this.emit("reachedPoint", this.index);
6056
6145
  this.advance();
6057
6146
  if (this.pauseAt > 0) this.pauseTimer = this.pauseAt;
6058
6147
  }
6059
6148
  }
6149
+ /** Turn the skin toward the step just taken. */
6150
+ face(from, to, dt) {
6151
+ if (this.facePath === "") return;
6152
+ const skin = this.node.getNodeOrNull(this.facePath);
6153
+ if (!skin) return;
6154
+ faceTravel(skin, to.map((v, i) => v - (from[i] ?? 0)), dt, this.turnSpeed);
6155
+ }
6060
6156
  /** Waypoints already reported dead, so a per-frame stall says it once. */
6061
6157
  reportedDead = /* @__PURE__ */ new Set();
6062
6158
  /**
@@ -1,4 +1,4 @@
1
- import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-DsgayMsH.js";
1
+ import { b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, t as Behavior } from "./behavior-CmMuQ6CL.js";
2
2
  import { c as JsonValue, s as JsonObject } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/gameplay/chase.d.ts
@@ -11,6 +11,8 @@ import { c as JsonValue, s as JsonObject } from "./schema-CFeioQRE.js";
11
11
  * it leaves), so wire it to an attack.
12
12
  * - `loseRange` (>0) gives up the chase when the target gets that far away,
13
13
  * emitting `lostTarget` once.
14
+ * - `facePath`/`turnSpeed` turn a skin toward the direction of travel — the job
15
+ * `CharacterController3D` does for the player and nobody did for an NPC.
14
16
  * - `moveParent` (default false) moves the parent node instead of this one.
15
17
  * A node carries ONE behavior, so an enemy whose ROOT must hold `Health`
16
18
  * (e.g. for `Health.freeOnDeath` clone-safe cleanup) puts `Chase` on a CHILD
@@ -25,6 +27,8 @@ declare class Chase extends Behavior {
25
27
  stopRange: number;
26
28
  loseRange: number;
27
29
  moveParent: boolean;
30
+ facePath: string;
31
+ turnSpeed: number;
28
32
  private inRange;
29
33
  private lost;
30
34
  override onReady(): void;
@@ -327,6 +331,13 @@ declare class Oscillate extends Behavior {
327
331
  *
328
332
  * - `loop` (default) — after the last point, head back to the first.
329
333
  * - `mode: 'pingpong'` — reverse direction at each end instead of wrapping.
334
+ * - `moveParent` (default false) moves the parent node instead of this one,
335
+ * exactly as `Chase` does. A node carries ONE behavior, so a guard that must
336
+ * patrol AND hold `Health` on its body puts `Patrol` on a CHILD. Without
337
+ * this the patrolling body had to carry `Patrol` itself and could hold
338
+ * nothing else — so a patrolling enemy could not be hurt.
339
+ * - `facePath`/`turnSpeed` turn a skin toward the direction of travel, the job
340
+ * `CharacterController3D` does for the player and nobody did for an NPC.
330
341
  */
331
342
  declare class Patrol extends Behavior {
332
343
  static readonly props: PropSchema;
@@ -336,11 +347,16 @@ declare class Patrol extends Behavior {
336
347
  loop: boolean;
337
348
  mode: string;
338
349
  pauseAt: number;
350
+ moveParent: boolean;
351
+ facePath: string;
352
+ turnSpeed: number;
339
353
  private index;
340
354
  private direction;
341
355
  private pauseTimer;
342
356
  override onReady(): void;
343
357
  override update(dt: number): void;
358
+ /** Turn the skin toward the step just taken. */
359
+ private face;
344
360
  /** Waypoints already reported dead, so a per-frame stall says it once. */
345
361
  private readonly reportedDead;
346
362
  /**
package/dist/gameplay.js CHANGED
@@ -1,2 +1,2 @@
1
- import { A as Health, C as restartScene, D as DayNight, E as FloatAway, M as Chase, O as phaseOf, 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 Collector, k as DamageOnContact, 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-CLgFdkh5.js";
1
+ import { A as Health, C as restartScene, D as DayNight, E as FloatAway, M as Chase, O as phaseOf, 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 Collector, k as DamageOnContact, 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-D-H986A4.js";
2
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 };
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-DsgayMsH.js";
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-CmMuQ6CL.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-DolLJWJn.js";
3
+ import { n as loadScene, t as LoadSceneOptions } from "./loader-CTB441z4.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-D5GJgb_x.js";
5
+ import { a as ParticleSimConfig, i as ParticleSim, n as AudioPlayer, o as ParticleView, t as AudioElementLike } from "./audio-player-BrEHwbK1.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-C5x2vPF5.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-CThvwkcQ.js";
8
8
 
9
9
  //#region src/core/audio/crossfade.d.ts
10
10
  /**
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
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-zDynoew_.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-Btm7_Emq.js";
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-CgeR4ckF.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-DKRmiVjk.js";
7
+ import { n as startRecording, r as auditScene, t as replay } from "./replay-CEw2xAhG.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-CNS2xQB1.js";
12
- import { t as duplicateNode } from "./duplicate-BOOKmkQ7.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-DYffzHbd.js";
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 };
@@ -1,4 +1,4 @@
1
- import { P as Scene, b as Engine } from "./behavior-DsgayMsH.js";
1
+ import { P as Scene, b as Engine } from "./behavior-CmMuQ6CL.js";
2
2
  import { i as SceneJson } from "./schema-CFeioQRE.js";
3
3
 
4
4
  //#region src/core/scene/loader.d.ts