@jgengine/core 0.18.1 → 0.21.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/CHANGELOG.md +504 -7
- package/dist/ai/decisionGraph.d.ts +50 -4
- package/dist/ai/decisionGraph.js +159 -23
- package/dist/ai/flock.d.ts +1 -1
- package/dist/ai/flock.js +7 -4
- package/dist/ai/groupAssist.d.ts +10 -0
- package/dist/ai/groupAssist.js +11 -0
- package/dist/ai/pursuit.d.ts +1 -1
- package/dist/ai/pursuit.js +1 -1
- package/dist/ai/threat.d.ts +8 -0
- package/dist/ai/threat.js +10 -0
- package/dist/anim/animGraph.d.ts +43 -1
- package/dist/anim/animGraph.js +326 -10
- package/dist/anim/boneTexture.d.ts +55 -0
- package/dist/anim/boneTexture.js +43 -0
- package/dist/anim/footPlacement.d.ts +57 -0
- package/dist/anim/footPlacement.js +67 -0
- package/dist/anim/locomotionGraph.d.ts +18 -1
- package/dist/anim/locomotionGraph.js +42 -3
- package/dist/audio/audioFalloff.d.ts +6 -0
- package/dist/audio/doppler.d.ts +21 -0
- package/dist/audio/doppler.js +32 -0
- package/dist/audio/engineLayers.d.ts +83 -0
- package/dist/audio/engineLayers.js +115 -0
- package/dist/audio/voiceAllocator.d.ts +46 -0
- package/dist/audio/voiceAllocator.js +76 -0
- package/dist/combat/abilityKit.d.ts +20 -0
- package/dist/combat/abilityKit.js +41 -4
- package/dist/combat/death.d.ts +11 -3
- package/dist/combat/death.js +3 -3
- package/dist/combat/magazine.d.ts +9 -0
- package/dist/combat/magazine.js +24 -2
- package/dist/combat/projectiles.d.ts +94 -2
- package/dist/combat/projectiles.js +282 -61
- package/dist/combat/regenShield.d.ts +14 -0
- package/dist/combat/regenShield.js +23 -7
- package/dist/combat/shotOrigin.d.ts +6 -0
- package/dist/combat/shotOrigin.js +6 -0
- package/dist/combat/weaponFeedback.d.ts +36 -0
- package/dist/combat/weaponFeedback.js +42 -0
- package/dist/combat/weaponHandling.d.ts +161 -0
- package/dist/combat/weaponHandling.js +202 -0
- package/dist/combat/weaponPresentation.d.ts +115 -0
- package/dist/combat/weaponPresentation.js +96 -0
- package/dist/crafting/recipeCatalog.d.ts +16 -0
- package/dist/crafting/recipeCatalog.js +55 -0
- package/dist/devtools/warnOnce.d.ts +8 -0
- package/dist/devtools/warnOnce.js +18 -0
- package/dist/economy/auctionBook.d.ts +1 -1
- package/dist/economy/auctionBook.js +11 -1
- package/dist/economy/listingBook.d.ts +1 -1
- package/dist/economy/listingBook.js +11 -1
- package/dist/economy/resourceLedger.js +3 -3
- package/dist/economy/shopStock.js +7 -6
- package/dist/economy/techTree.js +7 -6
- package/dist/economy/unlockPoints.js +3 -6
- package/dist/editor/commandApply.js +89 -16
- package/dist/editor/commands.d.ts +38 -1
- package/dist/editor/commands.js +320 -3
- package/dist/editor/creatorStorage.d.ts +59 -0
- package/dist/editor/creatorStorage.js +164 -0
- package/dist/editor/document.d.ts +4 -0
- package/dist/editor/document.js +119 -18
- package/dist/editor/environment.js +8 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/liveSync.d.ts +4 -1
- package/dist/editor/liveSync.js +26 -10
- package/dist/editor/materialAuthoring.d.ts +14 -0
- package/dist/editor/materialAuthoring.js +38 -0
- package/dist/editor/modelNodeVisibility.d.ts +11 -0
- package/dist/editor/modelNodeVisibility.js +29 -0
- package/dist/editor/movementCatalog.d.ts +90 -0
- package/dist/editor/movementCatalog.js +144 -0
- package/dist/editor/simulation.d.ts +60 -0
- package/dist/editor/simulation.js +202 -0
- package/dist/editor/staticPrefab.d.ts +17 -0
- package/dist/editor/staticPrefab.js +51 -0
- package/dist/editor/types.d.ts +15 -0
- package/dist/faction/reputation.d.ts +6 -0
- package/dist/faction/reputation.js +11 -0
- package/dist/game/cameraConfig.d.ts +54 -2
- package/dist/game/clipRoles.d.ts +2 -1
- package/dist/game/clipRoles.js +7 -3
- package/dist/game/contentValidation.d.ts +69 -0
- package/dist/game/contentValidation.js +118 -0
- package/dist/game/controlGate.d.ts +8 -0
- package/dist/game/controlGate.js +43 -6
- package/dist/game/defineGame.d.ts +32 -3
- package/dist/game/dialogueGraph.d.ts +20 -0
- package/dist/game/dialogueGraph.js +107 -0
- package/dist/game/events.d.ts +11 -0
- package/dist/game/keyValueStore.d.ts +17 -4
- package/dist/game/keyValueStore.js +35 -23
- package/dist/game/lootModifiers.d.ts +17 -0
- package/dist/game/lootModifiers.js +26 -0
- package/dist/game/lootTable.d.ts +4 -0
- package/dist/game/lootTable.js +16 -0
- package/dist/game/narrativeAuthoring.d.ts +67 -0
- package/dist/game/narrativeAuthoring.js +122 -0
- package/dist/game/playableGame.d.ts +134 -35
- package/dist/game/quest.d.ts +15 -0
- package/dist/game/quest.js +209 -63
- package/dist/game/questCatalog.d.ts +50 -0
- package/dist/game/questCatalog.js +205 -0
- package/dist/game/saveStore.d.ts +6 -5
- package/dist/game/saveStore.js +57 -57
- package/dist/game/systemRuntime.d.ts +2 -2
- package/dist/game/systemRuntime.js +84 -33
- package/dist/game/toasts.d.ts +8 -0
- package/dist/game/toasts.js +7 -0
- package/dist/game/vfxInstance.d.ts +9 -0
- package/dist/game/vfxInstance.js +12 -1
- package/dist/game/viewports.d.ts +43 -0
- package/dist/game/viewports.js +46 -0
- package/dist/game/worldItem.d.ts +5 -1
- package/dist/game/worldItem.js +0 -1
- package/dist/gameplay.d.ts +3 -0
- package/dist/gameplay.js +3 -0
- package/dist/input/actionBindings.d.ts +15 -1
- package/dist/input/actionBindings.js +14 -3
- package/dist/input/actionContexts.d.ts +25 -1
- package/dist/input/actionContexts.js +82 -25
- package/dist/input/axisInput.d.ts +4 -0
- package/dist/input/axisInput.js +4 -0
- package/dist/input/axisShaper.d.ts +73 -0
- package/dist/input/axisShaper.js +105 -0
- package/dist/input/gamepadModel.d.ts +36 -2
- package/dist/input/gamepadModel.js +69 -30
- package/dist/input/haptics.d.ts +50 -0
- package/dist/input/haptics.js +74 -0
- package/dist/input/inputBuffer.d.ts +40 -0
- package/dist/input/inputBuffer.js +59 -0
- package/dist/input/lookChannel.d.ts +10 -0
- package/dist/input/lookChannel.js +6 -0
- package/dist/input/pointer.d.ts +2 -0
- package/dist/input/pointer.js +4 -0
- package/dist/interaction/promptRegistry.d.ts +5 -4
- package/dist/interaction/promptRegistry.js +8 -2
- package/dist/inventory/inventoryModel.js +9 -6
- package/dist/inventory/shapedGrid.d.ts +48 -9
- package/dist/inventory/shapedGrid.js +69 -10
- package/dist/item/affix.d.ts +6 -0
- package/dist/item/affix.js +6 -0
- package/dist/item/durability.js +4 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -1
- package/dist/item/itemInstanceRegistry.js +111 -7
- package/dist/item/itemgen.d.ts +1 -1
- package/dist/item/itemgen.js +1 -1
- package/dist/item/modularItem.js +7 -1
- package/dist/material/appearanceSignals.d.ts +53 -0
- package/dist/material/appearanceSignals.js +47 -0
- package/dist/material/hairCards.d.ts +47 -0
- package/dist/material/hairCards.js +136 -0
- package/dist/material/materialAsset.d.ts +162 -0
- package/dist/material/materialAsset.js +382 -0
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +444 -1
- package/dist/movement/characterController.d.ts +5 -2
- package/dist/movement/characterController.js +50 -23
- package/dist/movement/freeFlight.d.ts +2 -2
- package/dist/movement/freeFlight.js +3 -3
- package/dist/movement/glideModel.d.ts +3 -0
- package/dist/movement/glideModel.js +6 -0
- package/dist/movement/grappleSwing.d.ts +2 -0
- package/dist/movement/grappleSwing.js +5 -1
- package/dist/movement/movementModel.d.ts +63 -1
- package/dist/movement/movementModel.js +136 -26
- package/dist/movement/movementProbe.d.ts +51 -0
- package/dist/movement/movementProbe.js +119 -0
- package/dist/movement/playerMovement.d.ts +48 -2
- package/dist/movement/playerMovement.js +493 -87
- package/dist/movement/poseState.d.ts +2 -0
- package/dist/movement/poseState.js +29 -1
- package/dist/movement/solidObstacles.d.ts +11 -1
- package/dist/movement/solidObstacles.js +48 -3
- package/dist/movement/terrainGrade.d.ts +13 -0
- package/dist/movement/terrainGrade.js +33 -0
- package/dist/movement/voxelController.d.ts +2 -2
- package/dist/movement/voxelController.js +10 -10
- package/dist/nav/navFromEnvironment.d.ts +9 -3
- package/dist/nav/navFromEnvironment.js +18 -12
- package/dist/nav/navGrid.d.ts +19 -1
- package/dist/nav/navGrid.js +26 -10
- package/dist/nav/navMesh.d.ts +43 -2
- package/dist/nav/navMesh.js +534 -128
- package/dist/nav/solidRoute.d.ts +50 -0
- package/dist/nav/solidRoute.js +144 -0
- package/dist/physics/aircraftDynamics.d.ts +390 -0
- package/dist/physics/aircraftDynamics.js +704 -0
- package/dist/physics/ballisticSweep.d.ts +10 -3
- package/dist/physics/ballisticSweep.js +53 -29
- package/dist/physics/boatDynamics.d.ts +116 -0
- package/dist/physics/boatDynamics.js +160 -0
- package/dist/physics/drivableVehicle.d.ts +22 -8
- package/dist/physics/drivableVehicle.js +4 -2
- package/dist/physics/flightDynamics.d.ts +21 -4
- package/dist/physics/flightDynamics.js +28 -5
- package/dist/physics/forceVolume.d.ts +41 -0
- package/dist/physics/forceVolume.js +88 -0
- package/dist/physics/handlingProbe.d.ts +249 -0
- package/dist/physics/handlingProbe.js +606 -0
- package/dist/physics/kinematicVehicle.d.ts +40 -5
- package/dist/physics/kinematicVehicle.js +17 -2
- package/dist/physics/physicsBackend.d.ts +12 -0
- package/dist/physics/physicsBackendConformance.js +34 -0
- package/dist/physics/physicsWorldBackend.d.ts +1 -0
- package/dist/physics/physicsWorldBackend.js +52 -3
- package/dist/physics/spatialGrid.d.ts +1 -1
- package/dist/physics/spatialGrid.js +8 -9
- package/dist/physics/vehicleBackendLink.d.ts +49 -0
- package/dist/physics/vehicleBackendLink.js +102 -0
- package/dist/physics/vehicleDynamics.d.ts +375 -0
- package/dist/physics/vehicleDynamics.js +737 -0
- package/dist/physics/vehicleObstacles.d.ts +3 -2
- package/dist/physics/vehicleObstacles.js +29 -5
- package/dist/physics/worldColliders.d.ts +1 -1
- package/dist/physics/worldColliders.js +35 -3
- package/dist/puzzle/cellGrid.d.ts +15 -9
- package/dist/puzzle/cellGrid.js +13 -9
- package/dist/render/lookPreset.d.ts +9 -2
- package/dist/render/lookPreset.js +29 -2
- package/dist/render/postProcessing.d.ts +30 -0
- package/dist/render/postProcessing.js +1 -1
- package/dist/runtime/cameraDirector.d.ts +54 -3
- package/dist/runtime/cameraDirector.js +187 -0
- package/dist/runtime/commandDispatch.d.ts +14 -0
- package/dist/runtime/commandDispatch.js +19 -0
- package/dist/runtime/commandInput.d.ts +37 -0
- package/dist/runtime/commandInput.js +58 -0
- package/dist/runtime/commandRunner.d.ts +27 -0
- package/dist/runtime/commandRunner.js +31 -3
- package/dist/runtime/context/combat.d.ts +12 -4
- package/dist/runtime/context/combat.js +179 -11
- package/dist/runtime/context/deathLoot.d.ts +11 -8
- package/dist/runtime/context/deathLoot.js +17 -16
- package/dist/runtime/context/scene.d.ts +2 -0
- package/dist/runtime/context/scene.js +13 -21
- package/dist/runtime/descriptors/baseline.js +34 -3
- package/dist/runtime/descriptors/features.d.ts +2 -1
- package/dist/runtime/descriptors/features.js +18 -0
- package/dist/runtime/gameContext.js +86 -13
- package/dist/runtime/gameContextTypes.d.ts +33 -3
- package/dist/runtime/gameRuntime.d.ts +3 -1
- package/dist/runtime/gameRuntime.js +4 -0
- package/dist/runtime/headlessRunner.d.ts +3 -1
- package/dist/runtime/headlessRunner.js +11 -11
- package/dist/runtime/hostedGameRunner.d.ts +24 -1
- package/dist/runtime/hostedGameRunner.js +156 -10
- package/dist/runtime/hostedWorldSession.d.ts +17 -5
- package/dist/runtime/hostedWorldSession.js +154 -16
- package/dist/runtime/hostedWorldStore.d.ts +2 -2
- package/dist/runtime/inputRecorder.d.ts +1 -1
- package/dist/runtime/inputRecorder.js +21 -1
- package/dist/runtime/inputSnapshot.d.ts +22 -4
- package/dist/runtime/inputSnapshot.js +41 -3
- package/dist/runtime/localPlayers.d.ts +73 -0
- package/dist/runtime/localPlayers.js +119 -0
- package/dist/runtime/runtimeSave.d.ts +10 -6
- package/dist/runtime/runtimeSave.js +11 -5
- package/dist/runtime/simContext.d.ts +8 -3
- package/dist/runtime/simContext.js +7 -3
- package/dist/runtime/simSnapshot.js +2 -0
- package/dist/runtime/transport.d.ts +9 -0
- package/dist/runtime/transport.js +7 -1
- package/dist/runtime/worldReplication.d.ts +2 -0
- package/dist/runtime/worldReplication.js +1 -1
- package/dist/scene/assetCatalog.d.ts +2 -0
- package/dist/scene/behaviorRuntime.d.ts +38 -7
- package/dist/scene/behaviorRuntime.js +293 -30
- package/dist/scene/behaviors.d.ts +35 -2
- package/dist/scene/behaviors.js +29 -0
- package/dist/scene/entityStore.d.ts +14 -3
- package/dist/scene/entityStore.js +45 -9
- package/dist/scene/mount.d.ts +9 -0
- package/dist/scene/mount.js +35 -0
- package/dist/scene/possession.d.ts +2 -0
- package/dist/scene/possession.js +21 -1
- package/dist/scene/sceneKinds.d.ts +9 -0
- package/dist/scene/sceneRaycast.d.ts +7 -0
- package/dist/scene/sceneRaycast.js +55 -0
- package/dist/scene/spatial.d.ts +20 -1
- package/dist/scene/spatial.js +94 -2
- package/dist/scene/vehicleSeat.d.ts +41 -3
- package/dist/scene/vehicleSeat.js +94 -3
- package/dist/sensor/concealment.d.ts +6 -0
- package/dist/sensor/concealment.js +8 -0
- package/dist/sensor/freezeMonitor.d.ts +6 -0
- package/dist/sensor/freezeMonitor.js +8 -0
- package/dist/sensor/perception.d.ts +11 -1
- package/dist/sensor/perception.js +57 -10
- package/dist/sensor/recordingBuffer.d.ts +3 -0
- package/dist/sensor/recordingBuffer.js +8 -0
- package/dist/session/roundState.d.ts +4 -0
- package/dist/session/roundState.js +11 -0
- package/dist/settings/frameRateLimit.d.ts +16 -0
- package/dist/settings/frameRateLimit.js +37 -0
- package/dist/settings/graphicsProfile.d.ts +2 -0
- package/dist/settings/graphicsProfile.js +12 -0
- package/dist/settings/graphicsSettings.d.ts +40 -0
- package/dist/settings/graphicsSettings.js +81 -0
- package/dist/settings/settingsModel.d.ts +9 -1
- package/dist/settings/settingsModel.js +10 -0
- package/dist/stats/accumulatorMeter.d.ts +10 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +10 -3
- package/dist/stats/eventMeter.js +6 -3
- package/dist/store/defineStore.d.ts +3 -1
- package/dist/store/defineStore.js +3 -1
- package/dist/store/observableKeyedStore.d.ts +1 -1
- package/dist/store/observableKeyedStore.js +8 -6
- package/dist/time/simClock.d.ts +6 -2
- package/dist/time/simClock.js +5 -0
- package/dist/vfx/feedbackMixer.d.ts +61 -0
- package/dist/vfx/feedbackMixer.js +106 -0
- package/dist/vfx/particleDirector.d.ts +58 -6
- package/dist/vfx/particleDirector.js +113 -22
- package/dist/vfx/particles.d.ts +68 -5
- package/dist/vfx/particles.js +284 -32
- package/dist/visibility/assetStreaming.d.ts +21 -3
- package/dist/visibility/assetStreaming.js +108 -24
- package/dist/visibility/settings.d.ts +8 -2
- package/dist/visibility/settings.js +3 -0
- package/dist/visibility/simulationCulling.d.ts +8 -1
- package/dist/visibility/simulationCulling.js +7 -0
- package/dist/visibility/spatialIndex.d.ts +21 -0
- package/dist/visibility/spatialIndex.js +16 -0
- package/dist/visibility/visibilitySystem.js +1 -0
- package/dist/work/expedition.d.ts +110 -0
- package/dist/work/expedition.js +195 -0
- package/dist/work/staffedStation.d.ts +29 -0
- package/dist/work/staffedStation.js +27 -0
- package/dist/world/authoredAnimation.d.ts +38 -0
- package/dist/world/authoredAnimation.js +99 -0
- package/dist/world/authoredObjects.d.ts +24 -4
- package/dist/world/authoredObjects.js +43 -16
- package/dist/world/authoredSimulation.d.ts +74 -0
- package/dist/world/authoredSimulation.js +302 -0
- package/dist/world/authoredSolids.d.ts +46 -0
- package/dist/world/authoredSolids.js +75 -0
- package/dist/world/authoredWeather.d.ts +120 -0
- package/dist/world/authoredWeather.js +314 -0
- package/dist/world/buildingGenerator.js +2 -2
- package/dist/world/buildingKit.d.ts +11 -4
- package/dist/world/buildingKit.js +21 -8
- package/dist/world/buildings.d.ts +34 -2
- package/dist/world/buildings.js +11 -1
- package/dist/world/cityKind.d.ts +7 -0
- package/dist/world/cityKind.js +52 -1
- package/dist/world/environmentForces.d.ts +21 -0
- package/dist/world/environmentForces.js +42 -0
- package/dist/world/features.d.ts +32 -5
- package/dist/world/features.js +6 -0
- package/dist/world/footprintGrid.d.ts +62 -0
- package/dist/world/footprintGrid.js +217 -0
- package/dist/world/interiors.d.ts +1 -0
- package/dist/world/interiors.js +5 -3
- package/dist/world/lod.d.ts +6 -0
- package/dist/world/lod.js +8 -0
- package/dist/world/pathTerrain.d.ts +1 -1
- package/dist/world/terraform.d.ts +9 -1
- package/dist/world/terraform.js +53 -18
- package/dist/world/walls.d.ts +7 -0
- package/dist/world/walls.js +7 -0
- package/dist/world/weather.d.ts +17 -0
- package/dist/world/weather.js +116 -20
- package/dist/world/worldSolids.d.ts +95 -0
- package/dist/world/worldSolids.js +351 -0
- package/dist/world.d.ts +6 -6
- package/dist/world.js +5 -5
- package/package.json +1 -1
- package/skills/ce-handoff/SKILL.md +2 -2
- package/skills/game-design/SKILL.md +2 -2
- package/skills/jgengine/SKILL.md +28 -6
- package/skills/jgengine/api.md +139 -99
- package/skills/jgengine/capabilities.md +28 -0
- package/skills/jgengine/recipes/minimal-game.md +10 -2
- package/skills/jgengine-combat/SKILL.md +13 -2
- package/skills/jgengine-combat/api.md +150 -103
- package/skills/jgengine-combat/capabilities.md +29 -1
- package/skills/jgengine-combat/recipes/portable-runtime-state.md +60 -6
- package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +37 -3
- package/skills/jgengine-combat/recipes/weapon-feel.md +50 -0
- package/skills/jgengine-combat/reference.md +24 -2
- package/skills/jgengine-gameplay/SKILL.md +63 -0
- package/skills/jgengine-gameplay/api.md +583 -463
- package/skills/jgengine-gameplay/capabilities.md +92 -0
- package/skills/jgengine-gameplay/recipes/device-save-status.md +46 -0
- package/skills/jgengine-gameplay/recipes/expeditions.md +108 -0
- package/skills/jgengine-gameplay/recipes/narrative-authoring.md +76 -0
- package/skills/jgengine-gameplay/recipes/paged-item-storage.md +101 -0
- package/skills/jgengine-gameplay/recipes/quest-authoring.md +63 -0
- package/skills/jgengine-gameplay/recipes/shaped-inventory.md +50 -0
- package/skills/jgengine-gameplay/reference-content-validation.md +74 -0
- package/skills/jgengine-gameplay/reference-systems.md +123 -0
- package/skills/jgengine-world/SKILL.md +25 -4
- package/skills/jgengine-world/api.md +1045 -655
- package/skills/jgengine-world/capabilities.md +246 -9
- package/skills/jgengine-world/recipes/character-animation.md +62 -0
- package/skills/jgengine-world/recipes/controls.md +48 -0
- package/skills/jgengine-world/recipes/flight-feel.md +76 -0
- package/skills/jgengine-world/recipes/npc-senses.md +55 -0
- package/skills/jgengine-world/recipes/vehicle-feel.md +87 -0
- package/skills/jgengine-world/reference.md +180 -4
- package/skills/jgengine-world/visibility.md +139 -0
|
@@ -4,13 +4,23 @@ export type BlackboardValue = number | boolean | string;
|
|
|
4
4
|
export type Blackboard = Record<string, BlackboardValue>;
|
|
5
5
|
/** Comparison operators supported by decision conditions. */
|
|
6
6
|
export type DecisionOperator = "=" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "eq" | "ne" | "lt" | "lte" | "gt" | "gte";
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Serializable decision node.
|
|
9
|
+
* - `selector` runs children in order until one does not fail; `sequence` until one does not finish.
|
|
10
|
+
* With `memory`, a composite whose child was running last tick resumes at that child instead of re-checking earlier ones.
|
|
11
|
+
* - `condition` compares a blackboard key; `action` calls a registered action.
|
|
12
|
+
* - `utility` runs the option with the highest weighted blackboard score.
|
|
13
|
+
* - `invert` swaps `done` and `failed`; `cooldown` fails for `seconds` after its child finishes;
|
|
14
|
+
* `wait` stays running for `seconds`; `random` picks a child by `weights` from the runtime's `rng` and keeps it while it runs.
|
|
15
|
+
*/
|
|
8
16
|
export type DecisionNode = {
|
|
9
17
|
kind: "selector";
|
|
10
18
|
children: DecisionNode[];
|
|
19
|
+
memory?: boolean;
|
|
11
20
|
} | {
|
|
12
21
|
kind: "sequence";
|
|
13
22
|
children: DecisionNode[];
|
|
23
|
+
memory?: boolean;
|
|
14
24
|
} | {
|
|
15
25
|
kind: "condition";
|
|
16
26
|
key: string;
|
|
@@ -29,6 +39,20 @@ export type DecisionNode = {
|
|
|
29
39
|
}[];
|
|
30
40
|
node: DecisionNode;
|
|
31
41
|
}[];
|
|
42
|
+
} | {
|
|
43
|
+
kind: "invert";
|
|
44
|
+
child: DecisionNode;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "cooldown";
|
|
47
|
+
seconds: number;
|
|
48
|
+
child: DecisionNode;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "wait";
|
|
51
|
+
seconds: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "random";
|
|
54
|
+
children: DecisionNode[];
|
|
55
|
+
weights?: number[];
|
|
32
56
|
};
|
|
33
57
|
/** Root node for a serializable AI decision graph. */
|
|
34
58
|
export type DecisionGraph = DecisionNode;
|
|
@@ -36,17 +60,39 @@ export type DecisionGraph = DecisionNode;
|
|
|
36
60
|
export type DecisionStatus = "running" | "done" | "failed";
|
|
37
61
|
/** Callback implementation for an action node. */
|
|
38
62
|
export type DecisionAction<Context = unknown> = (ctx: Context, params: Record<string, BlackboardValue> | undefined, blackboard: Blackboard) => DecisionStatus;
|
|
39
|
-
/**
|
|
63
|
+
/** Called when an action that was running last tick is not reached this tick, so it can release what it holds. */
|
|
64
|
+
export type DecisionAbort<Context = unknown> = (action: string, ctx: Context, params: Record<string, BlackboardValue> | undefined, blackboard: Blackboard) => void;
|
|
65
|
+
/** Optional hooks and injected randomness for {@link createDecisionGraphRuntime}. */
|
|
66
|
+
export interface DecisionGraphOptions<Context = unknown> {
|
|
67
|
+
onAbort?: DecisionAbort<Context>;
|
|
68
|
+
/** `[0, 1)` source for `random` nodes; pass `ctx.rng`. Required only when the graph has one. */
|
|
69
|
+
rng?: () => number;
|
|
70
|
+
}
|
|
71
|
+
/** Progress of a memory composite, `random` choice, or `wait` timer, keyed by node id (depth-first order). */
|
|
72
|
+
export interface DecisionNodeMemory {
|
|
73
|
+
index: number;
|
|
74
|
+
elapsed: number;
|
|
75
|
+
tick: number;
|
|
76
|
+
}
|
|
77
|
+
/** Serializable state retained by an active decision graph. Fields besides `runningPath` are absent in older saves. */
|
|
40
78
|
export interface DecisionGraphSnapshot {
|
|
41
79
|
runningPath: number[] | null;
|
|
80
|
+
tick?: number;
|
|
81
|
+
clock?: number;
|
|
82
|
+
nodes?: Record<string, DecisionNodeMemory>;
|
|
83
|
+
cooldowns?: Record<string, number>;
|
|
42
84
|
}
|
|
43
85
|
/** Stateful evaluator for a serializable decision graph. */
|
|
44
86
|
export interface DecisionGraphRuntime<Context = unknown> {
|
|
45
87
|
tick(ctx: Context, blackboard: Blackboard, dt: number): DecisionStatus;
|
|
88
|
+
/** Name of the action left running by the last tick, or null. */
|
|
89
|
+
running(): string | null;
|
|
90
|
+
/** Abort the compiled running action once, retaining graph memory/timers. Clears ownership before invoking user onAbort, even if it throws. */
|
|
91
|
+
abort(ctx: Context, blackboard: Blackboard): void;
|
|
46
92
|
snapshot(): DecisionGraphSnapshot;
|
|
47
93
|
restore(next: DecisionGraphSnapshot): void;
|
|
48
94
|
}
|
|
49
95
|
/** Creates a deterministic runtime for a serializable decision graph.
|
|
50
|
-
* @capability ai-decision-graph Evaluate serializable selector, sequence, condition, action, and
|
|
96
|
+
* @capability ai-decision-graph Evaluate serializable selector, sequence, condition, action, utility, timer, and random AI decisions with interrupt hooks.
|
|
51
97
|
*/
|
|
52
|
-
export declare function createDecisionGraphRuntime<Context = unknown>(graph: DecisionGraph, actions: Record<string, DecisionAction<Context
|
|
98
|
+
export declare function createDecisionGraphRuntime<Context = unknown>(graph: DecisionGraph, actions: Record<string, DecisionAction<Context>>, options?: DecisionGraphOptions<Context>): DecisionGraphRuntime<Context>;
|
package/dist/ai/decisionGraph.js
CHANGED
|
@@ -21,12 +21,53 @@ function compare(left, op, right) {
|
|
|
21
21
|
return typeof left === "number" && typeof right === "number" && left >= right;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
function childrenOf(node) {
|
|
25
|
+
switch (node.kind) {
|
|
26
|
+
case "selector":
|
|
27
|
+
case "sequence":
|
|
28
|
+
case "random":
|
|
29
|
+
return node.children;
|
|
30
|
+
case "utility":
|
|
31
|
+
return node.options.map((option) => option.node);
|
|
32
|
+
case "invert":
|
|
33
|
+
case "cooldown":
|
|
34
|
+
return [node.child];
|
|
35
|
+
default:
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function compile(root) {
|
|
40
|
+
const byId = [];
|
|
41
|
+
const visit = (node, path) => {
|
|
42
|
+
const entry = { node, id: byId.length, path, children: [] };
|
|
43
|
+
byId.push(entry);
|
|
44
|
+
childrenOf(node).forEach((child, index) => entry.children.push(visit(child, [...path, index])));
|
|
45
|
+
return entry;
|
|
46
|
+
};
|
|
47
|
+
visit(root, []);
|
|
48
|
+
return byId;
|
|
49
|
+
}
|
|
24
50
|
/** Creates a deterministic runtime for a serializable decision graph.
|
|
25
|
-
* @capability ai-decision-graph Evaluate serializable selector, sequence, condition, action, and
|
|
51
|
+
* @capability ai-decision-graph Evaluate serializable selector, sequence, condition, action, utility, timer, and random AI decisions with interrupt hooks.
|
|
26
52
|
*/
|
|
27
|
-
export function createDecisionGraphRuntime(graph, actions) {
|
|
28
|
-
|
|
29
|
-
|
|
53
|
+
export function createDecisionGraphRuntime(graph, actions, options = {}) {
|
|
54
|
+
const nodes = compile(graph);
|
|
55
|
+
const root = nodes[0];
|
|
56
|
+
let runningId = -1;
|
|
57
|
+
let tickCount = 0;
|
|
58
|
+
let clock = 0;
|
|
59
|
+
const memory = new Map();
|
|
60
|
+
const cooldowns = new Map();
|
|
61
|
+
const lastReached = new Float64Array(nodes.length).fill(-1);
|
|
62
|
+
function carried(id) {
|
|
63
|
+
const entry = memory.get(id);
|
|
64
|
+
return entry !== undefined && entry.tick === tickCount - 1 ? entry : undefined;
|
|
65
|
+
}
|
|
66
|
+
function hold(id, index, elapsed) {
|
|
67
|
+
memory.set(id, { index, elapsed, tick: tickCount });
|
|
68
|
+
}
|
|
69
|
+
function run(entry, ctx, blackboard, dt) {
|
|
70
|
+
const node = entry.node;
|
|
30
71
|
switch (node.kind) {
|
|
31
72
|
case "condition":
|
|
32
73
|
return compare(blackboard[node.key], node.op, node.value) ? "done" : "failed";
|
|
@@ -34,49 +75,144 @@ export function createDecisionGraphRuntime(graph, actions) {
|
|
|
34
75
|
const action = actions[node.action];
|
|
35
76
|
if (action === undefined)
|
|
36
77
|
throw new Error(`Decision action '${node.action}' is not registered`);
|
|
78
|
+
lastReached[entry.id] = tickCount;
|
|
37
79
|
const status = action(ctx, node.params, blackboard);
|
|
38
80
|
if (status === "running")
|
|
39
|
-
|
|
81
|
+
runningId = entry.id;
|
|
40
82
|
return status;
|
|
41
83
|
}
|
|
42
84
|
case "selector":
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
85
|
+
case "sequence": {
|
|
86
|
+
const stopOn = node.kind === "selector" ? "failed" : "done";
|
|
87
|
+
const start = node.memory === true ? (carried(entry.id)?.index ?? 0) : 0;
|
|
88
|
+
memory.delete(entry.id);
|
|
89
|
+
for (let index = start; index < entry.children.length; index += 1) {
|
|
90
|
+
const status = run(entry.children[index], ctx, blackboard, dt);
|
|
91
|
+
if (status === stopOn)
|
|
92
|
+
continue;
|
|
93
|
+
if (status === "running" && node.memory === true)
|
|
94
|
+
hold(entry.id, index, 0);
|
|
95
|
+
return status;
|
|
47
96
|
}
|
|
48
|
-
return "failed";
|
|
49
|
-
|
|
50
|
-
for (let index = 0; index < node.children.length; index += 1) {
|
|
51
|
-
const status = run(node.children[index], ctx, blackboard, dt, [...path, index]);
|
|
52
|
-
if (status !== "done")
|
|
53
|
-
return status;
|
|
54
|
-
}
|
|
55
|
-
return "done";
|
|
97
|
+
return node.kind === "selector" ? "failed" : "done";
|
|
98
|
+
}
|
|
56
99
|
case "utility": {
|
|
57
100
|
let best = -Infinity;
|
|
58
101
|
let bestIndex = -1;
|
|
59
102
|
for (let index = 0; index < node.options.length; index += 1) {
|
|
60
|
-
|
|
103
|
+
let score = 0;
|
|
104
|
+
for (const term of node.options[index].score) {
|
|
105
|
+
const value = blackboard[term.key];
|
|
106
|
+
if (typeof value === "number")
|
|
107
|
+
score += value * term.weight;
|
|
108
|
+
}
|
|
61
109
|
if (score > best) {
|
|
62
110
|
best = score;
|
|
63
111
|
bestIndex = index;
|
|
64
112
|
}
|
|
65
113
|
}
|
|
66
|
-
return bestIndex < 0 ? "failed" : run(
|
|
114
|
+
return bestIndex < 0 ? "failed" : run(entry.children[bestIndex], ctx, blackboard, dt);
|
|
115
|
+
}
|
|
116
|
+
case "invert": {
|
|
117
|
+
const status = run(entry.children[0], ctx, blackboard, dt);
|
|
118
|
+
return status === "running" ? status : status === "done" ? "failed" : "done";
|
|
119
|
+
}
|
|
120
|
+
case "cooldown": {
|
|
121
|
+
if (clock < (cooldowns.get(entry.id) ?? -Infinity))
|
|
122
|
+
return "failed";
|
|
123
|
+
const status = run(entry.children[0], ctx, blackboard, dt);
|
|
124
|
+
if (status === "done")
|
|
125
|
+
cooldowns.set(entry.id, clock + Math.max(0, node.seconds));
|
|
126
|
+
return status;
|
|
127
|
+
}
|
|
128
|
+
case "wait": {
|
|
129
|
+
const elapsed = (carried(entry.id)?.elapsed ?? 0) + dt;
|
|
130
|
+
if (elapsed >= node.seconds) {
|
|
131
|
+
memory.delete(entry.id);
|
|
132
|
+
return "done";
|
|
133
|
+
}
|
|
134
|
+
hold(entry.id, 0, elapsed);
|
|
135
|
+
runningId = entry.id;
|
|
136
|
+
return "running";
|
|
137
|
+
}
|
|
138
|
+
case "random": {
|
|
139
|
+
if (entry.children.length === 0)
|
|
140
|
+
return "failed";
|
|
141
|
+
let index = carried(entry.id)?.index ?? -1;
|
|
142
|
+
if (index < 0) {
|
|
143
|
+
if (options.rng === undefined)
|
|
144
|
+
throw new Error("A random decision node needs options.rng (pass ctx.rng)");
|
|
145
|
+
const weights = entry.children.map((_, i) => Math.max(0, node.weights?.[i] ?? 1));
|
|
146
|
+
const total = weights.reduce((sum, weight) => sum + weight, 0);
|
|
147
|
+
if (total <= 0)
|
|
148
|
+
return "failed";
|
|
149
|
+
let roll = options.rng() * total;
|
|
150
|
+
index = 0;
|
|
151
|
+
while (index < weights.length - 1 && roll >= weights[index])
|
|
152
|
+
roll -= weights[index++];
|
|
153
|
+
}
|
|
154
|
+
memory.delete(entry.id);
|
|
155
|
+
const status = run(entry.children[index], ctx, blackboard, dt);
|
|
156
|
+
if (status === "running")
|
|
157
|
+
hold(entry.id, index, 0);
|
|
158
|
+
return status;
|
|
67
159
|
}
|
|
68
160
|
}
|
|
69
161
|
}
|
|
162
|
+
function idFromPath(path) {
|
|
163
|
+
let entry = root;
|
|
164
|
+
for (const index of path)
|
|
165
|
+
entry = entry?.children[index];
|
|
166
|
+
return entry?.id ?? -1;
|
|
167
|
+
}
|
|
70
168
|
return {
|
|
71
169
|
tick(ctx, blackboard, dt) {
|
|
72
|
-
|
|
73
|
-
|
|
170
|
+
const previous = runningId;
|
|
171
|
+
tickCount += 1;
|
|
172
|
+
clock += Math.max(0, dt);
|
|
173
|
+
runningId = -1;
|
|
174
|
+
const status = run(root, ctx, blackboard, Math.max(0, dt));
|
|
175
|
+
const abandoned = previous >= 0 ? nodes[previous].node : null;
|
|
176
|
+
if (abandoned?.kind === "action" && lastReached[previous] !== tickCount) {
|
|
177
|
+
options.onAbort?.(abandoned.action, ctx, abandoned.params, blackboard);
|
|
178
|
+
}
|
|
179
|
+
return status;
|
|
180
|
+
},
|
|
181
|
+
running() {
|
|
182
|
+
const node = runningId >= 0 ? nodes[runningId].node : null;
|
|
183
|
+
return node?.kind === "action" ? node.action : null;
|
|
184
|
+
},
|
|
185
|
+
abort(ctx, blackboard) {
|
|
186
|
+
const node = runningId >= 0 ? nodes[runningId].node : null;
|
|
187
|
+
runningId = -1;
|
|
188
|
+
if (node?.kind === "action")
|
|
189
|
+
options.onAbort?.(node.action, ctx, node.params, blackboard);
|
|
74
190
|
},
|
|
75
191
|
snapshot() {
|
|
76
|
-
|
|
192
|
+
const nodeState = {};
|
|
193
|
+
for (const [id, entry] of memory)
|
|
194
|
+
nodeState[id] = { ...entry };
|
|
195
|
+
const cooldownState = {};
|
|
196
|
+
for (const [id, readyAt] of cooldowns)
|
|
197
|
+
cooldownState[id] = readyAt;
|
|
198
|
+
return {
|
|
199
|
+
runningPath: runningId >= 0 ? [...nodes[runningId].path] : null,
|
|
200
|
+
tick: tickCount,
|
|
201
|
+
clock,
|
|
202
|
+
nodes: nodeState,
|
|
203
|
+
cooldowns: cooldownState,
|
|
204
|
+
};
|
|
77
205
|
},
|
|
78
206
|
restore(next) {
|
|
79
|
-
|
|
207
|
+
runningId = next.runningPath === null ? -1 : idFromPath(next.runningPath);
|
|
208
|
+
tickCount = next.tick ?? 0;
|
|
209
|
+
clock = next.clock ?? 0;
|
|
210
|
+
memory.clear();
|
|
211
|
+
cooldowns.clear();
|
|
212
|
+
for (const [id, entry] of Object.entries(next.nodes ?? {}))
|
|
213
|
+
memory.set(Number(id), { ...entry });
|
|
214
|
+
for (const [id, readyAt] of Object.entries(next.cooldowns ?? {}))
|
|
215
|
+
cooldowns.set(Number(id), readyAt);
|
|
80
216
|
},
|
|
81
217
|
};
|
|
82
218
|
}
|
package/dist/ai/flock.d.ts
CHANGED
|
@@ -36,4 +36,4 @@ export interface FlockStepAgent {
|
|
|
36
36
|
/** Integrate one tick in place: steer every agent, clamp to `maxSpeed`, advance positions.
|
|
37
37
|
* @internal
|
|
38
38
|
*/
|
|
39
|
-
export declare function stepFlock(agents: FlockStepAgent[], config: FlockConfig, dt: number, target?: FlockVec3): void;
|
|
39
|
+
export declare function stepFlock(agents: FlockStepAgent[], config: FlockConfig, dt: number, target?: FlockVec3, acceleration?: (agent: Readonly<FlockStepAgent>, index: number) => FlockVec3): void;
|
package/dist/ai/flock.js
CHANGED
|
@@ -134,7 +134,7 @@ function fillNeighbors(agents, agentIndex, invCell, gridCells, neighborScratch)
|
|
|
134
134
|
/** Integrate one tick in place: steer every agent, clamp to `maxSpeed`, advance positions.
|
|
135
135
|
* @internal
|
|
136
136
|
*/
|
|
137
|
-
export function stepFlock(agents, config, dt, target) {
|
|
137
|
+
export function stepFlock(agents, config, dt, target, acceleration) {
|
|
138
138
|
const count = agents.length;
|
|
139
139
|
if (count === 0)
|
|
140
140
|
return;
|
|
@@ -148,9 +148,12 @@ export function stepFlock(agents, config, dt, target) {
|
|
|
148
148
|
fillNeighbors(agents, i, invCell, gridCells, neighborScratch);
|
|
149
149
|
const steer = flockSteer(agents[i], neighborScratch, config, target);
|
|
150
150
|
const base = i * 3;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
const external = acceleration?.(agents[i], i);
|
|
152
|
+
if (external !== undefined && (external.length !== 3 || external.some((axis) => !Number.isFinite(axis))))
|
|
153
|
+
throw new Error("flock acceleration must contain three finite components");
|
|
154
|
+
steerScratch[base] = steer[0] + (external?.[0] ?? 0);
|
|
155
|
+
steerScratch[base + 1] = steer[1] + (external?.[1] ?? 0);
|
|
156
|
+
steerScratch[base + 2] = steer[2] + (external?.[2] ?? 0);
|
|
154
157
|
}
|
|
155
158
|
for (let i = 0; i < count; i += 1) {
|
|
156
159
|
const agent = agents[i];
|
package/dist/ai/groupAssist.d.ts
CHANGED
|
@@ -9,12 +9,22 @@ export interface AssistNetworkConfig {
|
|
|
9
9
|
shareFraction?: number;
|
|
10
10
|
distanceBetween?: (a: string, b: string) => number;
|
|
11
11
|
}
|
|
12
|
+
/** Plain JSON membership of an {@link AssistNetwork}, in registration order; threat lives in each member's own table. */
|
|
13
|
+
export interface AssistNetworkState {
|
|
14
|
+
members: {
|
|
15
|
+
id: string;
|
|
16
|
+
groupId: string;
|
|
17
|
+
}[];
|
|
18
|
+
}
|
|
12
19
|
export interface AssistNetwork {
|
|
13
20
|
register(member: AssistMember): void;
|
|
14
21
|
remove(memberId: string): void;
|
|
15
22
|
memberIds(groupId?: string): string[];
|
|
16
23
|
assistersOf(memberId: string): string[];
|
|
17
24
|
addThreat(memberId: string, sourceId: string, amount: number): string[];
|
|
25
|
+
snapshot(): AssistNetworkState;
|
|
26
|
+
/** Replaces the membership; `tableOf` supplies each member's (separately restored) threat table. */
|
|
27
|
+
restore(next: AssistNetworkState, tableOf: (memberId: string) => ThreatTable): void;
|
|
18
28
|
}
|
|
19
29
|
/** @internal */
|
|
20
30
|
export declare function createAssistNetwork(config?: AssistNetworkConfig): AssistNetwork;
|
package/dist/ai/groupAssist.js
CHANGED
|
@@ -56,5 +56,16 @@ export function createAssistNetwork(config = {}) {
|
|
|
56
56
|
members.get(id).table.add(sourceId, amount * shareFraction);
|
|
57
57
|
return assisters;
|
|
58
58
|
},
|
|
59
|
+
snapshot() {
|
|
60
|
+
return { members: order.map((id) => ({ id, groupId: members.get(id).groupId })) };
|
|
61
|
+
},
|
|
62
|
+
restore(next, tableOf) {
|
|
63
|
+
members.clear();
|
|
64
|
+
order.length = 0;
|
|
65
|
+
for (const { id, groupId } of next.members) {
|
|
66
|
+
order.push(id);
|
|
67
|
+
members.set(id, { id, groupId, table: tableOf(id) });
|
|
68
|
+
}
|
|
69
|
+
},
|
|
59
70
|
};
|
|
60
71
|
}
|
package/dist/ai/pursuit.d.ts
CHANGED
|
@@ -51,6 +51,6 @@ export declare function armPursuit(state: PursuitState, intervalSeconds: number)
|
|
|
51
51
|
*
|
|
52
52
|
* On `"attack"` the caller applies the hit and calls {@link armPursuit} with the next interval.
|
|
53
53
|
*
|
|
54
|
-
* @capability pursuit chase-to-reach cooldown-gated attack
|
|
54
|
+
* @capability pursuit enemy/mob aggro chase-to-reach with a cooldown-gated attack and optional leash-to-home; owns the attack cooldown
|
|
55
55
|
*/
|
|
56
56
|
export declare function advancePursuit(state: PursuitState, dt: number, targetDistance: number | null, stopDistance: number, cooldownMode?: CooldownMode, homeDistance?: number, leashRange?: number): PursuitAction;
|
package/dist/ai/pursuit.js
CHANGED
|
@@ -36,7 +36,7 @@ function tickCooldown(state, dt) {
|
|
|
36
36
|
*
|
|
37
37
|
* On `"attack"` the caller applies the hit and calls {@link armPursuit} with the next interval.
|
|
38
38
|
*
|
|
39
|
-
* @capability pursuit chase-to-reach cooldown-gated attack
|
|
39
|
+
* @capability pursuit enemy/mob aggro chase-to-reach with a cooldown-gated attack and optional leash-to-home; owns the attack cooldown
|
|
40
40
|
*/
|
|
41
41
|
export function advancePursuit(state, dt, targetDistance, stopDistance, cooldownMode = "always", homeDistance = Number.NEGATIVE_INFINITY, leashRange = Number.POSITIVE_INFINITY) {
|
|
42
42
|
if (cooldownMode === "always")
|
package/dist/ai/threat.d.ts
CHANGED
|
@@ -11,6 +11,12 @@ export interface HighestThreatOptions {
|
|
|
11
11
|
current?: string | null;
|
|
12
12
|
stickiness?: number;
|
|
13
13
|
}
|
|
14
|
+
/** Plain JSON state of a {@link ThreatTable}; `entries` keeps insertion order, which breaks ties in `highest`. */
|
|
15
|
+
export interface ThreatTableState {
|
|
16
|
+
entries: [sourceId: string, threat: number][];
|
|
17
|
+
forcedSource: string | null;
|
|
18
|
+
forcedRemaining: number;
|
|
19
|
+
}
|
|
14
20
|
export interface ThreatTable {
|
|
15
21
|
add(sourceId: string, amount: number): number;
|
|
16
22
|
set(sourceId: string, amount: number): void;
|
|
@@ -23,5 +29,7 @@ export interface ThreatTable {
|
|
|
23
29
|
remove(sourceId: string): void;
|
|
24
30
|
clear(): void;
|
|
25
31
|
size(): number;
|
|
32
|
+
snapshot(): ThreatTableState;
|
|
33
|
+
restore(next: ThreatTableState): void;
|
|
26
34
|
}
|
|
27
35
|
export declare function createThreatTable(config?: ThreatTableConfig): ThreatTable;
|
package/dist/ai/threat.js
CHANGED
|
@@ -97,5 +97,15 @@ export function createThreatTable(config = {}) {
|
|
|
97
97
|
size() {
|
|
98
98
|
return table.size;
|
|
99
99
|
},
|
|
100
|
+
snapshot() {
|
|
101
|
+
return { entries: [...table], forcedSource, forcedRemaining };
|
|
102
|
+
},
|
|
103
|
+
restore(next) {
|
|
104
|
+
table.clear();
|
|
105
|
+
for (const [sourceId, threat] of next.entries)
|
|
106
|
+
table.set(sourceId, threat);
|
|
107
|
+
forcedSource = next.forcedSource;
|
|
108
|
+
forcedRemaining = next.forcedRemaining;
|
|
109
|
+
},
|
|
100
110
|
};
|
|
101
111
|
}
|
package/dist/anim/animGraph.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type AnimParams = Readonly<Record<string, AnimParamValue>>;
|
|
|
6
6
|
export type AnimState = {
|
|
7
7
|
kind: "clip";
|
|
8
8
|
clip: string;
|
|
9
|
+
variants?: readonly string[];
|
|
9
10
|
speed?: number;
|
|
10
11
|
loop?: boolean;
|
|
11
12
|
rootMotion?: boolean;
|
|
@@ -88,11 +89,17 @@ interface LayerTransitionState {
|
|
|
88
89
|
duration: number;
|
|
89
90
|
fromWeights: Record<string, number>;
|
|
90
91
|
fromTimes: Record<string, number>;
|
|
92
|
+
fromPlayback?: Record<string, {
|
|
93
|
+
speed: number;
|
|
94
|
+
loop: boolean;
|
|
95
|
+
rootMotion?: boolean;
|
|
96
|
+
}>;
|
|
91
97
|
}
|
|
92
98
|
interface LayerState {
|
|
93
99
|
current: string;
|
|
94
100
|
time: number;
|
|
95
101
|
transition: LayerTransitionState | null;
|
|
102
|
+
selectedClip?: string;
|
|
96
103
|
}
|
|
97
104
|
/** Serializable evaluator state. */
|
|
98
105
|
export interface AnimGraphState {
|
|
@@ -113,7 +120,10 @@ export interface AnimGraphOutput {
|
|
|
113
120
|
name: string;
|
|
114
121
|
clip: string;
|
|
115
122
|
}[];
|
|
123
|
+
/** Root-bone travel over this advance from `rootMotion` states, in the rig's local units. */
|
|
116
124
|
rootDelta?: [number, number, number];
|
|
125
|
+
/** `true` while an influencing current or fading-out state has `rootMotion`, even with no travel. */
|
|
126
|
+
rootMotion?: true;
|
|
117
127
|
}
|
|
118
128
|
/** The evaluator handle: arm triggers, advance, inspect, snapshot and restore. */
|
|
119
129
|
export interface AnimGraphRuntime {
|
|
@@ -128,6 +138,10 @@ export interface AnimGraphRuntime {
|
|
|
128
138
|
stateOf(layerId: string): string | null;
|
|
129
139
|
advance(dt: number, params: AnimParams, clips: AnimGraphClipInfo): AnimGraphOutput;
|
|
130
140
|
}
|
|
141
|
+
/** Randomness used only when entering a clip state with variants. Omit to choose the first variant. */
|
|
142
|
+
export interface AnimGraphRuntimeOptions {
|
|
143
|
+
rng?: () => number;
|
|
144
|
+
}
|
|
131
145
|
/** Entity blackboard key the shell reads extra graph parameters from: `ctx.scene.entity.blackboard.set(id, ANIM_PARAMS_KEY, { aiming: true })`. */
|
|
132
146
|
export declare const ANIM_PARAMS_KEY = "anim.params";
|
|
133
147
|
/** Static clip weights of a state at `params`, before any crossfade. */
|
|
@@ -140,5 +154,33 @@ export declare function stateClipWeights(state: AnimState, params: AnimParams):
|
|
|
140
154
|
*
|
|
141
155
|
* @capability anim-graph data-first animation state machine with blend trees, crossfades, layers, and clip events
|
|
142
156
|
*/
|
|
143
|
-
export declare function createAnimGraphRuntime(initial: AnimGraph): AnimGraphRuntime;
|
|
157
|
+
export declare function createAnimGraphRuntime(initial: AnimGraph, options?: AnimGraphRuntimeOptions): AnimGraphRuntime;
|
|
158
|
+
/**
|
|
159
|
+
* Validates untrusted JSON (a saved scene document, a network payload) as an {@link AnimGraph}.
|
|
160
|
+
* Malformed states, transitions to unknown states, and bad conditions are dropped; a layer whose
|
|
161
|
+
* entry state is missing is dropped; the result is `undefined` when no layer survives.
|
|
162
|
+
*
|
|
163
|
+
* @capability anim-graph load an animation graph from saved JSON without trusting its shape
|
|
164
|
+
*/
|
|
165
|
+
export declare function parseAnimGraph(value: unknown): AnimGraph | undefined;
|
|
166
|
+
/** A located, repairable error in an authored animation graph; paths are relative to the graph value. */
|
|
167
|
+
export interface AnimGraphDiagnostic {
|
|
168
|
+
path: string;
|
|
169
|
+
message: string;
|
|
170
|
+
repair: string;
|
|
171
|
+
}
|
|
172
|
+
/** The whole authored graph is retained unchanged only when every supported field is valid. */
|
|
173
|
+
export interface AnimGraphValidation {
|
|
174
|
+
graph: AnimGraph | undefined;
|
|
175
|
+
diagnostics: readonly AnimGraphDiagnostic[];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Validate an authored graph without dropping broken combat states or weakening transition conditions.
|
|
179
|
+
* Known malformed fields and dangling references reject the whole graph with relative repair locations;
|
|
180
|
+
* valid data, including authored object/array order, is returned unchanged. Unknown extension fields are
|
|
181
|
+
* retained. Clip availability belongs to the imported-rig diagnostics. Use {@link parseAnimGraph} when
|
|
182
|
+
* permissive repair is intentional.
|
|
183
|
+
* @capability anim-graph validate authored animation graphs with located repair diagnostics without partial fallback
|
|
184
|
+
*/
|
|
185
|
+
export declare function validateAnimGraph(value: unknown): AnimGraphValidation;
|
|
144
186
|
export {};
|