@jgengine/core 0.9.0 → 0.11.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 +34 -3
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/spawnDirector.d.ts +19 -1
- package/dist/ai/spawnDirector.js +53 -26
- package/dist/ai/spawnPoint.d.ts +7 -0
- package/dist/ai/spawnPoint.js +7 -0
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/audio/audioFalloff.d.ts +5 -2
- package/dist/audio/music.d.ts +53 -0
- package/dist/audio/music.js +34 -0
- package/dist/audio/synth.d.ts +60 -0
- package/dist/audio/synth.js +8 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +15 -0
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +47 -0
- package/dist/combat/dotField.js +52 -0
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +7 -2
- package/dist/combat/projectiles.js +48 -17
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +39 -0
- package/dist/combat/regenShield.js +49 -0
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +30 -1
- package/dist/combat/shotOrigin.js +70 -2
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +34 -0
- package/dist/combat.js +34 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commands.d.ts +248 -0
- package/dist/editor/commands.js +865 -0
- package/dist/editor/document.d.ts +186 -0
- package/dist/editor/document.js +884 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +97 -0
- package/dist/editor/index.js +10 -0
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/types.d.ts +175 -0
- package/dist/editor/types.js +29 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/connectedPlayers.d.ts +30 -0
- package/dist/game/connectedPlayers.js +21 -0
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +141 -2
- package/dist/game/defineGame.js +39 -1
- package/dist/game/defineSystem.d.ts +88 -0
- package/dist/game/defineSystem.js +45 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +50 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/keyValueStore.d.ts +25 -0
- package/dist/game/keyValueStore.js +61 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/levelSequence.d.ts +24 -2
- package/dist/game/levelSequence.js +51 -2
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +21 -0
- package/dist/game/lootTable.js +15 -4
- package/dist/game/modelAnimation.d.ts +8 -0
- package/dist/game/modelAnimation.js +18 -0
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +160 -12
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +29 -0
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +5 -5
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +91 -0
- package/dist/gameplay.js +91 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -7
- package/dist/input/actionBindings.d.ts +24 -5
- package/dist/input/actionBindings.js +23 -5
- package/dist/input/axisInput.d.ts +13 -1
- package/dist/input/axisInput.js +22 -1
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/contextMenu.d.ts +1 -0
- package/dist/interaction/contextMenu.js +1 -0
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +5 -1
- package/dist/interaction/proximityPrompt.js +5 -3
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +5 -0
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +36 -1
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +38 -7
- package/dist/movement/movementModel.js +54 -13
- package/dist/movement/playerMovement.d.ts +41 -0
- package/dist/movement/playerMovement.js +236 -0
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +3 -0
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +9 -1
- package/dist/multiplayer/presenceModel.js +9 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +29 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/kinematicVehicle.d.ts +21 -1
- package/dist/physics/kinematicVehicle.js +23 -8
- package/dist/physics/physicsWorld.d.ts +24 -12
- package/dist/physics/physicsWorld.js +11 -5
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +24 -0
- package/dist/random/rng.js +30 -8
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +76 -0
- package/dist/render/postProcessing.js +21 -0
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +58 -0
- package/dist/runtime/adapter.js +54 -5
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +134 -0
- package/dist/runtime/descriptors/features.d.ts +74 -0
- package/dist/runtime/descriptors/features.js +281 -0
- package/dist/runtime/gameContext.d.ts +163 -19
- package/dist/runtime/gameContext.js +385 -339
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +60 -0
- package/dist/runtime/headlessRunner.js +44 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostedGameRunner.d.ts +54 -0
- package/dist/runtime/hostedGameRunner.js +85 -0
- package/dist/runtime/hostedWorldSession.d.ts +73 -0
- package/dist/runtime/hostedWorldSession.js +64 -0
- package/dist/runtime/inputSnapshot.d.ts +21 -3
- package/dist/runtime/inputSnapshot.js +8 -2
- package/dist/runtime/motionIntents.d.ts +12 -1
- package/dist/runtime/motionIntents.js +26 -1
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +62 -0
- package/dist/runtime/worldChannel.js +114 -0
- package/dist/runtime/worldMirror.d.ts +36 -0
- package/dist/runtime/worldMirror.js +44 -0
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +69 -0
- package/dist/runtime/worldReplication.js +217 -0
- package/dist/runtime/worldSnapshot.d.ts +44 -0
- package/dist/runtime/worldSnapshot.js +30 -0
- package/dist/scene/assetCatalog.d.ts +22 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +259 -0
- package/dist/scene/authoredTriggers.d.ts +169 -0
- package/dist/scene/authoredTriggers.js +340 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +62 -0
- package/dist/scene/colliders.d.ts +18 -0
- package/dist/scene/colliders.js +61 -1
- package/dist/scene/entityStats.d.ts +13 -0
- package/dist/scene/entityStats.js +30 -0
- package/dist/scene/entityStore.d.ts +41 -1
- package/dist/scene/entityStore.js +75 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +240 -0
- package/dist/scene/sceneKinds.js +214 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +9 -0
- package/dist/store/observableKeyedStore.js +43 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -55
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +5 -0
- package/dist/tactics/fallingGrid.d.ts +6 -4
- package/dist/tactics/fallingGrid.js +6 -4
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +144 -0
- package/dist/ui/gameLayout.js +148 -0
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +33 -1
- package/dist/ui/hudLayout.js +204 -17
- package/dist/ui/orientation.d.ts +39 -0
- package/dist/ui/orientation.js +49 -0
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/swingTimer.d.ts +42 -0
- package/dist/ui/swingTimer.js +38 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/visibility/spatialIndex.js +34 -20
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredObjects.d.ts +58 -0
- package/dist/world/authoredObjects.js +69 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/environmentSummary.d.ts +11 -2
- package/dist/world/environmentSummary.js +11 -1
- package/dist/world/features.d.ts +244 -7
- package/dist/world/features.js +92 -4
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +77 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +81 -0
- package/dist/world/roads.d.ts +55 -0
- package/dist/world/roads.js +184 -0
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +80 -0
- package/dist/world/streets.js +144 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +138 -12
- package/dist/world/terrain.js +346 -28
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +132 -0
- package/dist/world.js +132 -0
- package/package.json +32 -8
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-combat/SKILL.md +34 -0
- package/skills/jgengine-combat/api.md +549 -0
- package/skills/jgengine-combat/capabilities.md +169 -0
- package/skills/jgengine-combat/reference.md +98 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1794 -0
- package/skills/jgengine-gameplay/capabilities.md +378 -0
- package/skills/jgengine-gameplay/reference-systems.md +60 -0
- package/skills/jgengine-world/SKILL.md +38 -0
- package/skills/jgengine-world/api.md +2652 -0
- package/skills/jgengine-world/capabilities.md +370 -0
- package/skills/jgengine-world/reference.md +222 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -4983
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Sawtooth ramp: rises 0→1 over each `period` then resets, for looping sweeps and scrolls.
|
|
2
|
+
* @internal
|
|
3
|
+
*/
|
|
4
|
+
export function sawWave(time, period) {
|
|
5
|
+
if (!(period > 0))
|
|
6
|
+
return 0;
|
|
7
|
+
const phase = ((time % period) + period) % period;
|
|
8
|
+
return phase / period;
|
|
9
|
+
}
|
|
10
|
+
/** Triangle wave: ramps 0→1→0 across each `period`, for patrols, searchlights, and pulsing glows.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export function triangleWave(time, period) {
|
|
14
|
+
const up = sawWave(time, period);
|
|
15
|
+
return up < 0.5 ? up * 2 : 2 - up * 2;
|
|
16
|
+
}
|
|
17
|
+
/** Ping-pong a value across `[0, length]`, bouncing at each edge — the index/position analog of {@link triangleWave}.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export function pingPong(value, length) {
|
|
21
|
+
if (!(length > 0))
|
|
22
|
+
return 0;
|
|
23
|
+
const t = ((value % (length * 2)) + length * 2) % (length * 2);
|
|
24
|
+
return t <= length ? t : length * 2 - t;
|
|
25
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous area-effect membership: moving sources emit an area that follows them each tick,
|
|
3
|
+
* receivers that move in and out get enter / refresh / leave edges, and membership is cleaned up
|
|
4
|
+
* when a source is removed, disabled, or the field is cleared. A pure lifecycle machine — it never
|
|
5
|
+
* applies damage, heals, or stat changes itself; the caller routes each edge through its own
|
|
6
|
+
* effect pipeline (see `combat/effects`, `combat/dotField`, `stats/statModifiers`). This is the
|
|
7
|
+
* dynamic, source-following counterpart to `scene/authoredTriggers` (static document volumes).
|
|
8
|
+
*
|
|
9
|
+
* Bounded by design: the caller supplies a broad-phase `candidates(shape)` query (e.g.
|
|
10
|
+
* `visibility/spatialIndex`'s `querySphere`) plus a `positionOf` lookup, so a step visits only
|
|
11
|
+
* receivers near each source — never the whole world. Serializable: `serialize()` captures the
|
|
12
|
+
* membership set and each member's refresh phase so cadence and enter/leave edges survive save/load.
|
|
13
|
+
*/
|
|
14
|
+
import type { EntityPosition } from "../scene/entityStore.js";
|
|
15
|
+
/**
|
|
16
|
+
* The area a source occupies this tick. `sphere` is first-class; `custom` leaves a seam for authored
|
|
17
|
+
* volumes and other shapes while still exposing a bounding sphere (`center`/`radius`) for the caller's
|
|
18
|
+
* broad-phase candidate query.
|
|
19
|
+
*/
|
|
20
|
+
export type AreaShape = {
|
|
21
|
+
readonly kind: "sphere";
|
|
22
|
+
readonly center: EntityPosition;
|
|
23
|
+
readonly radius: number;
|
|
24
|
+
} | {
|
|
25
|
+
readonly kind: "custom";
|
|
26
|
+
/** Bounding-sphere center the caller's broad-phase `candidates` query is built from. */
|
|
27
|
+
readonly center: EntityPosition;
|
|
28
|
+
/** Bounding-sphere radius the caller's broad-phase `candidates` query is built from. */
|
|
29
|
+
readonly radius: number;
|
|
30
|
+
/** Authoritative containment test applied to each broad-phase candidate. */
|
|
31
|
+
readonly contains: (point: EntityPosition) => boolean;
|
|
32
|
+
};
|
|
33
|
+
/** Descriptor for one continuous area source; re-supplied each tick so its shape follows the emitter. */
|
|
34
|
+
export interface AreaSourceSpec<P> {
|
|
35
|
+
/** Stable source id (the emitter). Re-using an id updates the descriptor and preserves membership. */
|
|
36
|
+
readonly id: string;
|
|
37
|
+
/** The source's area this tick — pass the emitter's live position so membership follows it. */
|
|
38
|
+
readonly shape: AreaShape;
|
|
39
|
+
/** Caller data describing what this source does (damage amount, heal, buff key, capture rate…). */
|
|
40
|
+
readonly payload: P;
|
|
41
|
+
/** Milliseconds between `refresh` edges emitted for each member; omit for enter/leave only. */
|
|
42
|
+
readonly refreshMs?: number;
|
|
43
|
+
/** Aggregation group key for stacking policies; defaults to the source id. */
|
|
44
|
+
readonly stackKey?: string;
|
|
45
|
+
/** When false the source keeps its descriptor but holds no members (current members `leave`). Default true. */
|
|
46
|
+
readonly enabled?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Why a `leave` edge fired. */
|
|
49
|
+
export type AreaLeaveReason = "exit" | "source-removed" | "disabled" | "cleared";
|
|
50
|
+
/** The three membership edges a step can emit. */
|
|
51
|
+
export type AreaEventKind = "enter" | "refresh" | "leave";
|
|
52
|
+
/** One membership edge emitted by `step`, `removeSource`, or `clear`. */
|
|
53
|
+
export interface AreaEffectEvent<P> {
|
|
54
|
+
readonly kind: AreaEventKind;
|
|
55
|
+
readonly sourceId: string;
|
|
56
|
+
readonly receiverId: string;
|
|
57
|
+
readonly stackKey: string;
|
|
58
|
+
readonly payload: P;
|
|
59
|
+
/** Number of refresh cadences crossed this step (>= 1 on `refresh`; a large dt can cross several). */
|
|
60
|
+
readonly ticks?: number;
|
|
61
|
+
/** Present only on `leave`. */
|
|
62
|
+
readonly reason?: AreaLeaveReason;
|
|
63
|
+
}
|
|
64
|
+
/** One active (source, receiver) membership — feed a receiver's list to a stacking policy. */
|
|
65
|
+
export interface AreaMembership<P> {
|
|
66
|
+
readonly sourceId: string;
|
|
67
|
+
readonly receiverId: string;
|
|
68
|
+
readonly stackKey: string;
|
|
69
|
+
readonly payload: P;
|
|
70
|
+
}
|
|
71
|
+
/** Per-tick inputs the field needs to reconcile membership without scanning the world. */
|
|
72
|
+
export interface AreaStepInput {
|
|
73
|
+
/** Milliseconds since the previous step; negative values are clamped to 0. */
|
|
74
|
+
readonly dtMs: number;
|
|
75
|
+
/** Bounded broad-phase: receiver ids possibly inside `shape` (e.g. `spatialIndex.querySphere`). */
|
|
76
|
+
readonly candidates: (shape: AreaShape) => Iterable<string>;
|
|
77
|
+
/** Precise receiver position; `undefined` means the receiver is gone (removed/dead) and is dropped. */
|
|
78
|
+
readonly positionOf: (receiverId: string) => EntityPosition | undefined;
|
|
79
|
+
/** Optional per-pair gate (team filter, immunity, line-of-sight already resolved by the caller). */
|
|
80
|
+
readonly eligible?: (sourceId: string, receiverId: string, payload: unknown) => boolean;
|
|
81
|
+
}
|
|
82
|
+
/** Serialized field state: source descriptors (minus their transient shape) and per-member refresh phase. */
|
|
83
|
+
export interface AreaFieldState<P> {
|
|
84
|
+
readonly sources: {
|
|
85
|
+
readonly id: string;
|
|
86
|
+
readonly payload: P;
|
|
87
|
+
readonly refreshMs?: number;
|
|
88
|
+
readonly stackKey: string;
|
|
89
|
+
readonly enabled: boolean;
|
|
90
|
+
}[];
|
|
91
|
+
readonly memberships: {
|
|
92
|
+
readonly sourceId: string;
|
|
93
|
+
readonly receiverId: string;
|
|
94
|
+
readonly sinceRefreshMs: number;
|
|
95
|
+
}[];
|
|
96
|
+
}
|
|
97
|
+
/** Runtime handle tracking continuous area membership across ticks. */
|
|
98
|
+
export interface AreaEffectField<P> {
|
|
99
|
+
/** Register or update a source (upsert by id); an update preserves existing membership and refresh phase. */
|
|
100
|
+
setSource(spec: AreaSourceSpec<P>): void;
|
|
101
|
+
/** Remove a source and return a `leave` (reason `source-removed`) for each of its members. */
|
|
102
|
+
removeSource(id: string): AreaEffectEvent<P>[];
|
|
103
|
+
hasSource(id: string): boolean;
|
|
104
|
+
sourceIds(): string[];
|
|
105
|
+
/** Reconcile every source against the receivers its `candidates` query returns; emit enter/refresh/leave. */
|
|
106
|
+
step(input: AreaStepInput): AreaEffectEvent<P>[];
|
|
107
|
+
/** Receiver ids currently inside `sourceId`. */
|
|
108
|
+
members(sourceId: string): string[];
|
|
109
|
+
isMember(sourceId: string, receiverId: string): boolean;
|
|
110
|
+
/** Every active membership across all sources. */
|
|
111
|
+
memberships(): AreaMembership<P>[];
|
|
112
|
+
/** Active memberships affecting a single receiver — the input to a stacking policy. */
|
|
113
|
+
membershipsOf(receiverId: string): AreaMembership<P>[];
|
|
114
|
+
/** Drop all sources and members; returns a `leave` (reason `cleared`) for each member. */
|
|
115
|
+
clear(): AreaEffectEvent<P>[];
|
|
116
|
+
/** Snapshot the persistent membership lifecycle for save/load; shapes are transient and re-supplied via `setSource`. */
|
|
117
|
+
serialize(): AreaFieldState<P>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Build a continuous area-effect field. Drive it with `setSource` (once per live source per tick, so
|
|
121
|
+
* shapes follow their emitters) and `step` (to reconcile membership and drain enter/refresh/leave edges).
|
|
122
|
+
* Optionally restore prior membership by passing a `serialize()` snapshot; re-`setSource` live shapes
|
|
123
|
+
* before the first `step` after restore, since shapes are transient.
|
|
124
|
+
*
|
|
125
|
+
* @capability area-effect-field source-following area membership with enter/refresh/leave edges, stacking, and cleanup
|
|
126
|
+
*/
|
|
127
|
+
export declare function createAreaEffectField<P = unknown>(state?: AreaFieldState<P>): AreaEffectField<P>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous area-effect membership: moving sources emit an area that follows them each tick,
|
|
3
|
+
* receivers that move in and out get enter / refresh / leave edges, and membership is cleaned up
|
|
4
|
+
* when a source is removed, disabled, or the field is cleared. A pure lifecycle machine — it never
|
|
5
|
+
* applies damage, heals, or stat changes itself; the caller routes each edge through its own
|
|
6
|
+
* effect pipeline (see `combat/effects`, `combat/dotField`, `stats/statModifiers`). This is the
|
|
7
|
+
* dynamic, source-following counterpart to `scene/authoredTriggers` (static document volumes).
|
|
8
|
+
*
|
|
9
|
+
* Bounded by design: the caller supplies a broad-phase `candidates(shape)` query (e.g.
|
|
10
|
+
* `visibility/spatialIndex`'s `querySphere`) plus a `positionOf` lookup, so a step visits only
|
|
11
|
+
* receivers near each source — never the whole world. Serializable: `serialize()` captures the
|
|
12
|
+
* membership set and each member's refresh phase so cadence and enter/leave edges survive save/load.
|
|
13
|
+
*/
|
|
14
|
+
const SENTINEL_SHAPE = { kind: "sphere", center: [0, 0, 0], radius: 0 };
|
|
15
|
+
function shapeContains(shape, point) {
|
|
16
|
+
if (shape.kind === "custom")
|
|
17
|
+
return shape.contains(point);
|
|
18
|
+
const dx = point[0] - shape.center[0];
|
|
19
|
+
const dy = point[1] - shape.center[1];
|
|
20
|
+
const dz = point[2] - shape.center[2];
|
|
21
|
+
return dx * dx + dy * dy + dz * dz <= shape.radius * shape.radius;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build a continuous area-effect field. Drive it with `setSource` (once per live source per tick, so
|
|
25
|
+
* shapes follow their emitters) and `step` (to reconcile membership and drain enter/refresh/leave edges).
|
|
26
|
+
* Optionally restore prior membership by passing a `serialize()` snapshot; re-`setSource` live shapes
|
|
27
|
+
* before the first `step` after restore, since shapes are transient.
|
|
28
|
+
*
|
|
29
|
+
* @capability area-effect-field source-following area membership with enter/refresh/leave edges, stacking, and cleanup
|
|
30
|
+
*/
|
|
31
|
+
export function createAreaEffectField(state) {
|
|
32
|
+
const sources = new Map();
|
|
33
|
+
if (state !== undefined) {
|
|
34
|
+
for (const source of state.sources) {
|
|
35
|
+
sources.set(source.id, {
|
|
36
|
+
shape: SENTINEL_SHAPE,
|
|
37
|
+
payload: source.payload,
|
|
38
|
+
refreshMs: source.refreshMs,
|
|
39
|
+
stackKey: source.stackKey,
|
|
40
|
+
enabled: source.enabled,
|
|
41
|
+
members: new Map(),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
for (const membership of state.memberships) {
|
|
45
|
+
sources.get(membership.sourceId)?.members.set(membership.receiverId, {
|
|
46
|
+
sinceRefreshMs: membership.sinceRefreshMs,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function leaveAll(rec, sourceId, reason) {
|
|
51
|
+
const events = [];
|
|
52
|
+
for (const receiverId of rec.members.keys()) {
|
|
53
|
+
events.push({ kind: "leave", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, reason });
|
|
54
|
+
}
|
|
55
|
+
rec.members.clear();
|
|
56
|
+
return events;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
setSource(spec) {
|
|
60
|
+
const stackKey = spec.stackKey ?? spec.id;
|
|
61
|
+
const enabled = spec.enabled ?? true;
|
|
62
|
+
const existing = sources.get(spec.id);
|
|
63
|
+
if (existing !== undefined) {
|
|
64
|
+
existing.shape = spec.shape;
|
|
65
|
+
existing.payload = spec.payload;
|
|
66
|
+
existing.refreshMs = spec.refreshMs;
|
|
67
|
+
existing.stackKey = stackKey;
|
|
68
|
+
existing.enabled = enabled;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
sources.set(spec.id, {
|
|
72
|
+
shape: spec.shape,
|
|
73
|
+
payload: spec.payload,
|
|
74
|
+
refreshMs: spec.refreshMs,
|
|
75
|
+
stackKey,
|
|
76
|
+
enabled,
|
|
77
|
+
members: new Map(),
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
removeSource(id) {
|
|
81
|
+
const rec = sources.get(id);
|
|
82
|
+
if (rec === undefined)
|
|
83
|
+
return [];
|
|
84
|
+
const events = leaveAll(rec, id, "source-removed");
|
|
85
|
+
sources.delete(id);
|
|
86
|
+
return events;
|
|
87
|
+
},
|
|
88
|
+
hasSource: (id) => sources.has(id),
|
|
89
|
+
sourceIds: () => [...sources.keys()],
|
|
90
|
+
step(input) {
|
|
91
|
+
const dtMs = Math.max(0, input.dtMs);
|
|
92
|
+
const events = [];
|
|
93
|
+
for (const [sourceId, rec] of sources) {
|
|
94
|
+
if (!rec.enabled) {
|
|
95
|
+
events.push(...leaveAll(rec, sourceId, "disabled"));
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
for (const receiverId of input.candidates(rec.shape)) {
|
|
100
|
+
if (seen.has(receiverId))
|
|
101
|
+
continue;
|
|
102
|
+
const position = input.positionOf(receiverId);
|
|
103
|
+
if (position === undefined)
|
|
104
|
+
continue;
|
|
105
|
+
if (!shapeContains(rec.shape, position))
|
|
106
|
+
continue;
|
|
107
|
+
if (input.eligible !== undefined && !input.eligible(sourceId, receiverId, rec.payload))
|
|
108
|
+
continue;
|
|
109
|
+
seen.add(receiverId);
|
|
110
|
+
const member = rec.members.get(receiverId);
|
|
111
|
+
if (member === undefined) {
|
|
112
|
+
rec.members.set(receiverId, { sinceRefreshMs: 0 });
|
|
113
|
+
events.push({ kind: "enter", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (rec.refreshMs !== undefined && rec.refreshMs > 0) {
|
|
117
|
+
member.sinceRefreshMs += dtMs;
|
|
118
|
+
let ticks = 0;
|
|
119
|
+
while (member.sinceRefreshMs >= rec.refreshMs) {
|
|
120
|
+
member.sinceRefreshMs -= rec.refreshMs;
|
|
121
|
+
ticks += 1;
|
|
122
|
+
}
|
|
123
|
+
if (ticks > 0) {
|
|
124
|
+
events.push({ kind: "refresh", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, ticks });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (const receiverId of [...rec.members.keys()]) {
|
|
129
|
+
if (seen.has(receiverId))
|
|
130
|
+
continue;
|
|
131
|
+
rec.members.delete(receiverId);
|
|
132
|
+
events.push({ kind: "leave", sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload, reason: "exit" });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return events;
|
|
136
|
+
},
|
|
137
|
+
members: (sourceId) => [...(sources.get(sourceId)?.members.keys() ?? [])],
|
|
138
|
+
isMember: (sourceId, receiverId) => sources.get(sourceId)?.members.has(receiverId) ?? false,
|
|
139
|
+
memberships() {
|
|
140
|
+
const out = [];
|
|
141
|
+
for (const [sourceId, rec] of sources) {
|
|
142
|
+
for (const receiverId of rec.members.keys()) {
|
|
143
|
+
out.push({ sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
},
|
|
148
|
+
membershipsOf(receiverId) {
|
|
149
|
+
const out = [];
|
|
150
|
+
for (const [sourceId, rec] of sources) {
|
|
151
|
+
if (rec.members.has(receiverId)) {
|
|
152
|
+
out.push({ sourceId, receiverId, stackKey: rec.stackKey, payload: rec.payload });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
},
|
|
157
|
+
clear() {
|
|
158
|
+
const events = [];
|
|
159
|
+
for (const [sourceId, rec] of sources)
|
|
160
|
+
events.push(...leaveAll(rec, sourceId, "cleared"));
|
|
161
|
+
sources.clear();
|
|
162
|
+
return events;
|
|
163
|
+
},
|
|
164
|
+
serialize() {
|
|
165
|
+
const out = { sources: [], memberships: [] };
|
|
166
|
+
for (const [id, rec] of sources) {
|
|
167
|
+
out.sources.push({ id, payload: rec.payload, refreshMs: rec.refreshMs, stackKey: rec.stackKey, enabled: rec.enabled });
|
|
168
|
+
for (const [receiverId, member] of rec.members) {
|
|
169
|
+
out.memberships.push({ sourceId: id, receiverId, sinceRefreshMs: member.sinceRefreshMs });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlap aggregation for {@link AreaMembership} lists: when several area sources cover the same
|
|
3
|
+
* receiver, a policy decides which memberships actually apply. Genre-agnostic and pure — policies
|
|
4
|
+
* are `(memberships) => memberships` reducers over one receiver's memberships, so the caller stays
|
|
5
|
+
* in control of magnitude and meaning. Pair with `createAreaEffectField().membershipsOf(receiverId)`.
|
|
6
|
+
*/
|
|
7
|
+
import type { AreaMembership } from "./areaEffectField.js";
|
|
8
|
+
/** Reduce one receiver's overlapping memberships to the subset that applies under a stacking rule. */
|
|
9
|
+
export type AreaStackPolicy<P> = (memberships: readonly AreaMembership<P>[]) => AreaMembership<P>[];
|
|
10
|
+
/** Read a comparable magnitude from a membership (e.g. buff strength, damage per tick). */
|
|
11
|
+
export type MagnitudeOf<P> = (membership: AreaMembership<P>) => number;
|
|
12
|
+
/**
|
|
13
|
+
* Every overlapping membership applies independently (no deduplication) — the default for hazards,
|
|
14
|
+
* fields, and lights where two sources genuinely stack.
|
|
15
|
+
*
|
|
16
|
+
* @capability area-stack-independent apply every overlapping area membership independently
|
|
17
|
+
*/
|
|
18
|
+
export declare function independentStacks<P>(): AreaStackPolicy<P>;
|
|
19
|
+
/**
|
|
20
|
+
* Keep at most one membership per `stackKey`. With `magnitudeOf` the strongest per key wins (ties
|
|
21
|
+
* broken by `sourceId` for determinism); without it the first-seen per key wins. Use for
|
|
22
|
+
* unique-by-key buffs where reapplying the same aura should not stack.
|
|
23
|
+
*
|
|
24
|
+
* @capability area-stack-unique keep one area membership per stack key, strongest wins
|
|
25
|
+
*/
|
|
26
|
+
export declare function uniqueByStackKey<P>(magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P>;
|
|
27
|
+
/**
|
|
28
|
+
* Keep at most `limit` memberships per `stackKey` (the highest-magnitude ones when `magnitudeOf` is
|
|
29
|
+
* given, else the first-seen). Models capped stacks — e.g. a poison that stacks up to 5 times.
|
|
30
|
+
*
|
|
31
|
+
* @capability area-stack-capped cap area memberships per stack key at a maximum count
|
|
32
|
+
*/
|
|
33
|
+
export declare function cappedStacks<P>(limit: number, magnitudeOf?: MagnitudeOf<P>): AreaStackPolicy<P>;
|
|
34
|
+
/**
|
|
35
|
+
* Reduce to the single strongest membership overall (`weakest = false` picks the weakest); ties broken
|
|
36
|
+
* by `sourceId`. Use when only the best or worst overlapping source should apply.
|
|
37
|
+
*
|
|
38
|
+
* @capability area-stack-extremum keep only the strongest or weakest overlapping area membership
|
|
39
|
+
*/
|
|
40
|
+
export declare function extremumStack<P>(magnitudeOf: MagnitudeOf<P>, weakest?: boolean): AreaStackPolicy<P>;
|
|
41
|
+
/**
|
|
42
|
+
* Sum a numeric magnitude across memberships — additive aggregation for a total field strength
|
|
43
|
+
* (total damage per tick, total slow). A terminal reducer, not a filter, so it returns the number.
|
|
44
|
+
*
|
|
45
|
+
* @capability area-stack-additive sum a magnitude across overlapping area memberships
|
|
46
|
+
*/
|
|
47
|
+
export declare function sumMagnitude<P>(memberships: readonly AreaMembership<P>[], magnitudeOf: MagnitudeOf<P>): number;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlap aggregation for {@link AreaMembership} lists: when several area sources cover the same
|
|
3
|
+
* receiver, a policy decides which memberships actually apply. Genre-agnostic and pure — policies
|
|
4
|
+
* are `(memberships) => memberships` reducers over one receiver's memberships, so the caller stays
|
|
5
|
+
* in control of magnitude and meaning. Pair with `createAreaEffectField().membershipsOf(receiverId)`.
|
|
6
|
+
*/
|
|
7
|
+
function byMagnitudeDesc(magnitudeOf) {
|
|
8
|
+
return (a, b) => {
|
|
9
|
+
const diff = magnitudeOf(b) - magnitudeOf(a);
|
|
10
|
+
if (diff !== 0)
|
|
11
|
+
return diff;
|
|
12
|
+
return a.sourceId < b.sourceId ? -1 : a.sourceId > b.sourceId ? 1 : 0;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function groupByStackKey(memberships) {
|
|
16
|
+
const groups = new Map();
|
|
17
|
+
for (const membership of memberships) {
|
|
18
|
+
const list = groups.get(membership.stackKey);
|
|
19
|
+
if (list === undefined)
|
|
20
|
+
groups.set(membership.stackKey, [membership]);
|
|
21
|
+
else
|
|
22
|
+
list.push(membership);
|
|
23
|
+
}
|
|
24
|
+
return groups;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Every overlapping membership applies independently (no deduplication) — the default for hazards,
|
|
28
|
+
* fields, and lights where two sources genuinely stack.
|
|
29
|
+
*
|
|
30
|
+
* @capability area-stack-independent apply every overlapping area membership independently
|
|
31
|
+
*/
|
|
32
|
+
export function independentStacks() {
|
|
33
|
+
return (memberships) => [...memberships];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Keep at most one membership per `stackKey`. With `magnitudeOf` the strongest per key wins (ties
|
|
37
|
+
* broken by `sourceId` for determinism); without it the first-seen per key wins. Use for
|
|
38
|
+
* unique-by-key buffs where reapplying the same aura should not stack.
|
|
39
|
+
*
|
|
40
|
+
* @capability area-stack-unique keep one area membership per stack key, strongest wins
|
|
41
|
+
*/
|
|
42
|
+
export function uniqueByStackKey(magnitudeOf) {
|
|
43
|
+
return (memberships) => {
|
|
44
|
+
const out = [];
|
|
45
|
+
for (const group of groupByStackKey(memberships).values()) {
|
|
46
|
+
if (magnitudeOf === undefined) {
|
|
47
|
+
out.push(group[0]);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
out.push([...group].sort(byMagnitudeDesc(magnitudeOf))[0]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Keep at most `limit` memberships per `stackKey` (the highest-magnitude ones when `magnitudeOf` is
|
|
58
|
+
* given, else the first-seen). Models capped stacks — e.g. a poison that stacks up to 5 times.
|
|
59
|
+
*
|
|
60
|
+
* @capability area-stack-capped cap area memberships per stack key at a maximum count
|
|
61
|
+
*/
|
|
62
|
+
export function cappedStacks(limit, magnitudeOf) {
|
|
63
|
+
const cap = Math.max(0, Math.floor(limit));
|
|
64
|
+
return (memberships) => {
|
|
65
|
+
const out = [];
|
|
66
|
+
for (const group of groupByStackKey(memberships).values()) {
|
|
67
|
+
const ordered = magnitudeOf === undefined ? group : [...group].sort(byMagnitudeDesc(magnitudeOf));
|
|
68
|
+
for (const membership of ordered.slice(0, cap))
|
|
69
|
+
out.push(membership);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Reduce to the single strongest membership overall (`weakest = false` picks the weakest); ties broken
|
|
76
|
+
* by `sourceId`. Use when only the best or worst overlapping source should apply.
|
|
77
|
+
*
|
|
78
|
+
* @capability area-stack-extremum keep only the strongest or weakest overlapping area membership
|
|
79
|
+
*/
|
|
80
|
+
export function extremumStack(magnitudeOf, weakest = false) {
|
|
81
|
+
return (memberships) => {
|
|
82
|
+
if (memberships.length === 0)
|
|
83
|
+
return [];
|
|
84
|
+
const ordered = [...memberships].sort(byMagnitudeDesc(magnitudeOf));
|
|
85
|
+
return [weakest ? ordered[ordered.length - 1] : ordered[0]];
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Sum a numeric magnitude across memberships — additive aggregation for a total field strength
|
|
90
|
+
* (total damage per tick, total slow). A terminal reducer, not a filter, so it returns the number.
|
|
91
|
+
*
|
|
92
|
+
* @capability area-stack-additive sum a magnitude across overlapping area memberships
|
|
93
|
+
*/
|
|
94
|
+
export function sumMagnitude(memberships, magnitudeOf) {
|
|
95
|
+
let total = 0;
|
|
96
|
+
for (const membership of memberships)
|
|
97
|
+
total += magnitudeOf(membership);
|
|
98
|
+
return total;
|
|
99
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SynthPatch } from "./synth.js";
|
|
1
2
|
export type AudioBusId = string;
|
|
2
3
|
export type FalloffCurve = "linear" | "inverse" | "none";
|
|
3
4
|
export interface AudioFalloffConfig {
|
|
@@ -15,8 +16,10 @@ export interface AudioBusDef {
|
|
|
15
16
|
}
|
|
16
17
|
export interface SoundDef {
|
|
17
18
|
id: string;
|
|
18
|
-
/**
|
|
19
|
-
url
|
|
19
|
+
/** Sample source — a URL/data URI the shell's Web Audio glue fetches and decodes. Provide exactly one of `url` or `synth`. */
|
|
20
|
+
url?: string;
|
|
21
|
+
/** Procedural source — a pure synth patch the shell realises on Web Audio, no file fetch. Provide exactly one of `url` or `synth`. */
|
|
22
|
+
synth?: SynthPatch;
|
|
20
23
|
bus: AudioBusId;
|
|
21
24
|
/** Base gain before bus/falloff multipliers. Default 1. */
|
|
22
25
|
gain?: number;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named synthesised instrument. Each maps to a voice in the shell's instrument
|
|
3
|
+
* library (`@jgengine/shell/audio/musicVoices`); an unknown name falls back to a
|
|
4
|
+
* plain sine voice so a theme is never silent.
|
|
5
|
+
*/
|
|
6
|
+
export type MusicInstrument = "strings" | "flute" | "harp" | "horn" | "choir" | "bell" | "timpani" | "bass" | "stacc" | "pad" | "lute" | "dulcimer" | "frameDrum" | "warDrum" | "reed" | "pipe" | "squareLead" | "woodBlock" | "tinyBell" | "piano" | "shaker" | "brassStab" | "cymSwell" | "oboe";
|
|
7
|
+
/** One scheduled note in a theme, positioned on the loop's quarter-note grid. */
|
|
8
|
+
export interface NoteEvent {
|
|
9
|
+
/** Quarter-note position within the loop (0-based). */
|
|
10
|
+
beat: number;
|
|
11
|
+
/** MIDI note number (60 = middle C). */
|
|
12
|
+
midi: number;
|
|
13
|
+
/** Sounding length in quarter-note beats. */
|
|
14
|
+
dur: number;
|
|
15
|
+
/** Velocity 0..1. */
|
|
16
|
+
vel: number;
|
|
17
|
+
/** Which instrument voice plays it. */
|
|
18
|
+
inst: MusicInstrument;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A through-composed, looping music track. `events` need not be sorted; the
|
|
22
|
+
* director schedules them ahead against a fixed anchor so loops are seamless.
|
|
23
|
+
*/
|
|
24
|
+
export interface MusicTheme {
|
|
25
|
+
id: string;
|
|
26
|
+
/** Tempo in beats (quarter notes) per minute. */
|
|
27
|
+
bpm: number;
|
|
28
|
+
/** Loop length in 4/4 bars; the loop is `bars * 4` beats long. */
|
|
29
|
+
bars: number;
|
|
30
|
+
events: readonly NoteEvent[];
|
|
31
|
+
/**
|
|
32
|
+
* Per-theme loudness normalisation multiplied into the crossfade target, so
|
|
33
|
+
* dense and sparse themes sit at the same perceived level. Default 1.
|
|
34
|
+
*/
|
|
35
|
+
trim?: number;
|
|
36
|
+
}
|
|
37
|
+
/** A resolved note occurrence: the source note plus its absolute onset in seconds. */
|
|
38
|
+
export interface ScheduledNote {
|
|
39
|
+
event: NoteEvent;
|
|
40
|
+
/** Absolute onset in seconds, on the timeline of the `anchorSec`/window args. */
|
|
41
|
+
when: number;
|
|
42
|
+
}
|
|
43
|
+
/** Standard equal-temperament MIDI-to-frequency (A4 = 440 Hz at MIDI 69). */
|
|
44
|
+
export declare function mtof(midi: number): number;
|
|
45
|
+
/** Loop length of a theme in seconds. */
|
|
46
|
+
export declare function themeLoopSeconds(theme: MusicTheme): number;
|
|
47
|
+
/**
|
|
48
|
+
* Pure lookahead scheduler: every note occurrence of `theme` whose onset falls
|
|
49
|
+
* in the half-open window `(fromSec, toSec]`, given the theme's loop-zero at
|
|
50
|
+
* `anchorSec`. Handles any number of loop wraps, so a director calls it once per
|
|
51
|
+
* tick with a non-overlapping window and never double-schedules a note.
|
|
52
|
+
*/
|
|
53
|
+
export declare function notesInWindow(theme: MusicTheme, anchorSec: number, fromSec: number, toSec: number): ScheduledNote[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Standard equal-temperament MIDI-to-frequency (A4 = 440 Hz at MIDI 69). */
|
|
2
|
+
export function mtof(midi) {
|
|
3
|
+
return 440 * 2 ** ((midi - 69) / 12);
|
|
4
|
+
}
|
|
5
|
+
/** Loop length of a theme in seconds. */
|
|
6
|
+
export function themeLoopSeconds(theme) {
|
|
7
|
+
return (theme.bars * 4 * 60) / theme.bpm;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Pure lookahead scheduler: every note occurrence of `theme` whose onset falls
|
|
11
|
+
* in the half-open window `(fromSec, toSec]`, given the theme's loop-zero at
|
|
12
|
+
* `anchorSec`. Handles any number of loop wraps, so a director calls it once per
|
|
13
|
+
* tick with a non-overlapping window and never double-schedules a note.
|
|
14
|
+
*/
|
|
15
|
+
export function notesInWindow(theme, anchorSec, fromSec, toSec) {
|
|
16
|
+
const loop = themeLoopSeconds(theme);
|
|
17
|
+
if (loop <= 0 || toSec <= fromSec)
|
|
18
|
+
return [];
|
|
19
|
+
const spb = 60 / theme.bpm;
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const event of theme.events) {
|
|
22
|
+
const onset = event.beat * spb;
|
|
23
|
+
let k = Math.max(0, Math.floor((fromSec - anchorSec - onset) / loop));
|
|
24
|
+
for (;;) {
|
|
25
|
+
const when = anchorSec + onset + k * loop;
|
|
26
|
+
if (when > toSec)
|
|
27
|
+
break;
|
|
28
|
+
if (when > fromSec)
|
|
29
|
+
out.push({ event, when });
|
|
30
|
+
k += 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Oscillator waveform available to a pitched synth voice. */
|
|
2
|
+
export type SynthWave = "sine" | "square" | "sawtooth" | "triangle";
|
|
3
|
+
/** Biquad filter shape a noise voice is coloured through. */
|
|
4
|
+
export type SynthFilter = "lowpass" | "highpass" | "bandpass";
|
|
5
|
+
/**
|
|
6
|
+
* A pitched oscillator voice: a 12ms linear attack to `gain`, then an
|
|
7
|
+
* exponential decay to silence across `duration`, with an optional
|
|
8
|
+
* exponential pitch slide from `freq` to `slideTo`.
|
|
9
|
+
*/
|
|
10
|
+
export interface ToneVoice {
|
|
11
|
+
kind: "tone";
|
|
12
|
+
/** Start frequency in Hz. */
|
|
13
|
+
freq: number;
|
|
14
|
+
/** Total voice length in seconds (the decay spans this). */
|
|
15
|
+
duration: number;
|
|
16
|
+
/** Peak gain before patch/bus scaling. Default 1. */
|
|
17
|
+
gain?: number;
|
|
18
|
+
/** Oscillator waveform. Default "sine". */
|
|
19
|
+
wave?: SynthWave;
|
|
20
|
+
/** Start offset in seconds from the cue trigger. Default 0. */
|
|
21
|
+
delay?: number;
|
|
22
|
+
/** When set, pitch ramps exponentially from `freq` to this Hz across `duration`. */
|
|
23
|
+
slideTo?: number;
|
|
24
|
+
/** Attack ramp in seconds. Default 0.012. */
|
|
25
|
+
attack?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A filtered white-noise burst — impacts, whooshes, breath, crackle. Realised
|
|
29
|
+
* from a shared 1s noise buffer at a randomised playback rate and start offset,
|
|
30
|
+
* decaying exponentially to silence at `duration * decay`.
|
|
31
|
+
*/
|
|
32
|
+
export interface NoiseVoice {
|
|
33
|
+
kind: "noise";
|
|
34
|
+
/** Total voice length in seconds. */
|
|
35
|
+
duration: number;
|
|
36
|
+
/** Biquad cutoff/centre in Hz. */
|
|
37
|
+
filterFreq: number;
|
|
38
|
+
/** Peak gain before patch/bus scaling. Default 1. */
|
|
39
|
+
gain?: number;
|
|
40
|
+
/** Filter shape. Default "lowpass". */
|
|
41
|
+
filterType?: SynthFilter;
|
|
42
|
+
/** Fraction of `duration` over which the burst decays to silence. Default 0.9. */
|
|
43
|
+
decay?: number;
|
|
44
|
+
/** Start offset in seconds from the cue trigger. Default 0. */
|
|
45
|
+
delay?: number;
|
|
46
|
+
}
|
|
47
|
+
/** One layered voice of a synth cue. */
|
|
48
|
+
export type SynthVoice = ToneVoice | NoiseVoice;
|
|
49
|
+
/**
|
|
50
|
+
* A procedural sound cue: a set of voices triggered together, each with its own
|
|
51
|
+
* `delay`, summed into one one-shot. Pure serialisable data — the shell realises
|
|
52
|
+
* it on Web Audio, so the same catalog runs headless in tests with no `AudioContext`.
|
|
53
|
+
*/
|
|
54
|
+
export interface SynthPatch {
|
|
55
|
+
voices: readonly SynthVoice[];
|
|
56
|
+
/** Overall cue gain multiplier applied to every voice. Default 1. */
|
|
57
|
+
gain?: number;
|
|
58
|
+
}
|
|
59
|
+
/** Total wall-clock length of a patch in seconds — the latest voice end across all voices. */
|
|
60
|
+
export declare function patchDuration(patch: SynthPatch): number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Total wall-clock length of a patch in seconds — the latest voice end across all voices. */
|
|
2
|
+
export function patchDuration(patch) {
|
|
3
|
+
let end = 0;
|
|
4
|
+
for (const voice of patch.voices) {
|
|
5
|
+
end = Math.max(end, (voice.delay ?? 0) + voice.duration);
|
|
6
|
+
}
|
|
7
|
+
return end;
|
|
8
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task-first JGEngine authoring surface.
|
|
3
|
+
*
|
|
4
|
+
* Game code should begin here. Domain and runtime deep imports remain available for
|
|
5
|
+
* advanced composition, but this module intentionally exposes common authored
|
|
6
|
+
* concepts without requiring callers to understand the repository layout.
|
|
7
|
+
*/
|
|
8
|
+
export { defineGame, type GameDefinition, type GameDefinitionConfig, type GameLoop, type InventoryDeclaration, type PhysicsConfig, type GameServerConfig, } from "./game/defineGame.js";
|
|
9
|
+
export { lootTable, type LootTableDef, type LootEntry, type Drop, } from "./game/lootTable.js";
|
|
10
|
+
export { biomes, voxel, plots, tilemap, flat, environment, terrain, rain, snow, grass, ocean, building, road, type WorldFeature, } from "./world/features.js";
|
|
11
|
+
export { seededRng, seededStreams } from "./random/rng.js";
|
|
12
|
+
export { selectSpawnPoint, type SpawnPointSelectionOptions, type SpawnPointDistanceBias, } from "./ai/spawnPoint.js";
|
|
13
|
+
export { contextVerb } from "./interaction/contextMenu.js";
|
|
14
|
+
export { type ActionCodesMap } from "./input/actionBindings.js";
|
|
15
|
+
export { classifyOwnership, collectOwnershipDiagnostics, auditManifest, ownershipKey, isSceneOwnershipManifest, SCENE_OWNERSHIP_MANIFEST_VERSION, type SceneProvenance, type SceneProvenanceKind, type AuthoredProvenance, type GeneratedProvenance, type RuntimeProvenance, type TransientProvenance, type ProviderCapabilities, type SceneOwnershipDeclaration, type OwnershipDecision, type OwnershipVerdict, type OwnershipDiagnostic, type SceneOwnershipManifest, } from "./scene/sceneOwnership.js";
|