@jgengine/core 0.10.0 → 0.12.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 +39 -2
- 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/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/ai/spawnDirector.d.ts +7 -2
- package/dist/ai/spawnDirector.js +18 -15
- package/dist/ai/spawnPoint.d.ts +3 -1
- package/dist/ai/spawnPoint.js +3 -1
- 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/authoring.d.ts +2 -1
- package/dist/authoring.js +2 -1
- 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 +5 -1
- package/dist/combat/dotField.js +5 -1
- 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 +5 -0
- package/dist/combat/projectiles.js +32 -14
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +5 -1
- package/dist/combat/regenShield.js +5 -1
- 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 +18 -1
- package/dist/combat/shotOrigin.js +39 -0
- 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 +35 -0
- package/dist/combat.js +35 -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/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -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/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -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/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -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/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +235 -7
- package/dist/editor/commands.js +82 -124
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +194 -13
- package/dist/editor/document.js +1166 -19
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -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 +98 -6
- package/dist/editor/index.js +13 -2
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +250 -1
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -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/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/connectedPlayers.d.ts +6 -4
- package/dist/game/connectedPlayers.js +2 -2
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +110 -5
- package/dist/game/defineGame.js +49 -4
- package/dist/game/defineSystem.d.ts +90 -0
- package/dist/game/defineSystem.js +47 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +63 -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/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- 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 +19 -2
- package/dist/game/lootTable.js +15 -5
- 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 +116 -432
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +19 -0
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +30 -3
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +3 -1
- 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/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -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 +93 -0
- package/dist/gameplay.js +93 -0
- package/dist/index.d.ts +5 -14
- package/dist/index.js +5 -14
- package/dist/input/actionBindings.d.ts +23 -6
- package/dist/input/actionBindings.js +23 -6
- package/dist/input/axisInput.d.ts +7 -2
- package/dist/input/axisInput.js +7 -2
- 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/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +2 -0
- package/dist/interaction/proximityPrompt.js +2 -0
- 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/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -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 +6 -3
- 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 +39 -2
- 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 +50 -9
- package/dist/movement/movementModel.js +75 -29
- package/dist/movement/playerMovement.js +167 -12
- 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 +16 -8
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +11 -1
- package/dist/multiplayer/presenceModel.js +17 -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 +31 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +108 -1
- package/dist/physics/kinematicVehicle.js +212 -15
- package/dist/physics/physicsWorld.d.ts +50 -12
- package/dist/physics/physicsWorld.js +120 -122
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -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 +26 -1
- package/dist/random/rng.js +32 -9
- 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 +20 -0
- package/dist/render/postProcessing.js +21 -1
- 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 +55 -3
- package/dist/runtime/adapter.js +57 -1
- 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/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +130 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/scene.d.ts +59 -0
- package/dist/runtime/context/scene.js +291 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -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 +157 -0
- package/dist/runtime/descriptors/features.d.ts +79 -0
- package/dist/runtime/descriptors/features.js +299 -0
- package/dist/runtime/gameContext.d.ts +2 -327
- package/dist/runtime/gameContext.js +273 -778
- package/dist/runtime/gameContextTypes.d.ts +467 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +62 -0
- package/dist/runtime/headlessRunner.js +45 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +11 -4
- package/dist/runtime/hostedGameRunner.js +27 -3
- package/dist/runtime/hostedWorldSession.d.ts +15 -5
- package/dist/runtime/hostedWorldSession.js +12 -4
- package/dist/runtime/inputSnapshot.d.ts +8 -3
- package/dist/runtime/inputSnapshot.js +6 -2
- package/dist/runtime/motionIntents.d.ts +11 -2
- package/dist/runtime/motionIntents.js +16 -2
- 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 +7 -3
- package/dist/runtime/worldChannel.js +51 -6
- package/dist/runtime/worldMirror.d.ts +14 -2
- package/dist/runtime/worldMirror.js +15 -2
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +30 -7
- package/dist/runtime/worldReplication.js +41 -9
- package/dist/runtime/worldSnapshot.d.ts +42 -3
- package/dist/runtime/worldSnapshot.js +34 -7
- package/dist/scene/assetCatalog.d.ts +26 -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 +257 -0
- package/dist/scene/authoredTriggers.d.ts +219 -0
- package/dist/scene/authoredTriggers.js +454 -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 +67 -0
- package/dist/scene/colliders.d.ts +71 -1
- package/dist/scene/colliders.js +145 -1
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +18 -11
- package/dist/scene/entityStats.js +21 -16
- package/dist/scene/entityStore.d.ts +12 -1
- package/dist/scene/entityStore.js +15 -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 +256 -0
- package/dist/scene/sceneKinds.js +218 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/sceneRaycast.js +15 -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/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +59 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -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 +7 -0
- package/dist/store/observableKeyedStore.js +35 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -57
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +6 -3
- package/dist/tactics/fallingGrid.d.ts +4 -2
- package/dist/tactics/fallingGrid.js +4 -2
- 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 +30 -11
- package/dist/ui/gameLayout.js +30 -11
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +38 -1
- package/dist/ui/hudLayout.js +220 -17
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -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/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/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +72 -0
- package/dist/world/authoredObjects.js +81 -0
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -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/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/features.d.ts +133 -10
- package/dist/world/features.js +66 -6
- 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/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathNetwork.d.ts +159 -0
- package/dist/world/pathNetwork.js +684 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +79 -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/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +88 -0
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +8 -0
- package/dist/world/roads.js +38 -0
- package/dist/world/scatter.js +2 -20
- 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 +29 -0
- package/dist/world/streets.js +55 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +627 -22
- package/dist/world/terrain.d.ts +164 -20
- package/dist/world/terrain.js +325 -41
- 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 +141 -0
- package/dist/world.js +141 -0
- package/package.json +32 -8
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +54 -0
- package/skills/jgengine/api.md +527 -0
- package/skills/jgengine/capabilities.md +131 -0
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +38 -0
- package/skills/jgengine-combat/api.md +585 -0
- package/skills/jgengine-combat/capabilities.md +213 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/reference.md +108 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1920 -0
- package/skills/jgengine-gameplay/capabilities.md +454 -0
- package/skills/jgengine-gameplay/reference-systems.md +56 -0
- package/skills/jgengine-world/SKILL.md +51 -0
- package/skills/jgengine-world/api.md +3056 -0
- package/skills/jgengine-world/capabilities.md +476 -0
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +261 -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 -5389
|
@@ -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
|
+
}
|
package/dist/authoring.d.ts
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* advanced composition, but this module intentionally exposes common authored
|
|
6
6
|
* concepts without requiring callers to understand the repository layout.
|
|
7
7
|
*/
|
|
8
|
-
export {
|
|
8
|
+
export { type GameDefinition, type GameDefinitionConfig, type GameLoop, type InventoryDeclaration, type PhysicsConfig, type GameServerConfig, } from "./game/defineGame.js";
|
|
9
9
|
export { lootTable, type LootTableDef, type LootEntry, type Drop, } from "./game/lootTable.js";
|
|
10
10
|
export { biomes, voxel, plots, tilemap, flat, environment, terrain, rain, snow, grass, ocean, building, road, type WorldFeature, } from "./world/features.js";
|
|
11
11
|
export { seededRng, seededStreams } from "./random/rng.js";
|
|
12
12
|
export { selectSpawnPoint, type SpawnPointSelectionOptions, type SpawnPointDistanceBias, } from "./ai/spawnPoint.js";
|
|
13
13
|
export { contextVerb } from "./interaction/contextMenu.js";
|
|
14
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";
|
package/dist/authoring.js
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* advanced composition, but this module intentionally exposes common authored
|
|
6
6
|
* concepts without requiring callers to understand the repository layout.
|
|
7
7
|
*/
|
|
8
|
-
export {
|
|
8
|
+
export {} from "./game/defineGame.js";
|
|
9
9
|
export { lootTable, } from "./game/lootTable.js";
|
|
10
10
|
export { biomes, voxel, plots, tilemap, flat, environment, terrain, rain, snow, grass, ocean, building, road, } from "./world/features.js";
|
|
11
11
|
export { seededRng, seededStreams } from "./random/rng.js";
|
|
12
12
|
export { selectSpawnPoint, } from "./ai/spawnPoint.js";
|
|
13
13
|
export { contextVerb } from "./interaction/contextMenu.js";
|
|
14
14
|
export {} from "./input/actionBindings.js";
|
|
15
|
+
export { classifyOwnership, collectOwnershipDiagnostics, auditManifest, ownershipKey, isSceneOwnershipManifest, SCENE_OWNERSHIP_MANIFEST_VERSION, } from "./scene/sceneOwnership.js";
|
|
@@ -43,12 +43,19 @@ export interface LanePlaceRejected {
|
|
|
43
43
|
reason: LaneRejection;
|
|
44
44
|
}
|
|
45
45
|
export type LaneResult<C> = LanePlaceResult<C> | LanePlaceRejected;
|
|
46
|
+
/** @internal */
|
|
46
47
|
export declare function createLaneBoardState<C>(config: LaneBoardConfig<C>): LaneBoardState<C>;
|
|
48
|
+
/** @internal */
|
|
47
49
|
export declare function placeCard<C>(state: LaneBoardState<C>, config: LaneBoardConfig<C>, lane: number, side: Side, card: C): LaneResult<C>;
|
|
50
|
+
/** @internal */
|
|
48
51
|
export declare function removeCard<C>(state: LaneBoardState<C>, lane: number, side: Side, predicate: (card: C, index: number) => boolean): LaneResult<C>;
|
|
52
|
+
/** @internal */
|
|
49
53
|
export declare function laneAggregate<C>(state: LaneBoardState<C>, config: LaneBoardConfig<C>, lane: number, side: Side): LaneAggregate;
|
|
54
|
+
/** @internal */
|
|
50
55
|
export declare function laneOutcome<C>(state: LaneBoardState<C>, config: LaneBoardConfig<C>, lane: number): LaneOutcome;
|
|
56
|
+
/** @internal */
|
|
51
57
|
export declare function boardTotals<C>(state: LaneBoardState<C>, config: LaneBoardConfig<C>): Readonly<Record<Side, number>>;
|
|
58
|
+
/** @internal */
|
|
52
59
|
export declare function lanesWon<C>(state: LaneBoardState<C>, config: LaneBoardConfig<C>): Readonly<Record<Side, number>>;
|
|
53
60
|
export interface LaneBoard<C> {
|
|
54
61
|
state(): LaneBoardState<C>;
|
|
@@ -60,4 +67,10 @@ export interface LaneBoard<C> {
|
|
|
60
67
|
lanesWon(): Readonly<Record<Side, number>>;
|
|
61
68
|
reset(next?: LaneBoardState<C>): void;
|
|
62
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* A lane-based board where cards resolve per lane — the lane card-battler layout.
|
|
72
|
+
*
|
|
73
|
+
* @capability lane-board a lane-based card-battler board with per-lane outcomes
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
63
76
|
export declare function createLaneBoard<C>(config: LaneBoardConfig<C>): LaneBoard<C>;
|
package/dist/board/laneBoard.js
CHANGED
|
@@ -4,6 +4,7 @@ function emptyLane(sides) {
|
|
|
4
4
|
cells[side] = [];
|
|
5
5
|
return cells;
|
|
6
6
|
}
|
|
7
|
+
/** @internal */
|
|
7
8
|
export function createLaneBoardState(config) {
|
|
8
9
|
if (config.laneCount <= 0)
|
|
9
10
|
throw new Error("laneBoard needs at least one lane");
|
|
@@ -17,6 +18,7 @@ export function createLaneBoardState(config) {
|
|
|
17
18
|
function validLane(state, lane) {
|
|
18
19
|
return Number.isInteger(lane) && lane >= 0 && lane < state.lanes.length;
|
|
19
20
|
}
|
|
21
|
+
/** @internal */
|
|
20
22
|
export function placeCard(state, config, lane, side, card) {
|
|
21
23
|
if (!validLane(state, lane))
|
|
22
24
|
return { status: "rejected", reason: "invalid-lane" };
|
|
@@ -27,6 +29,7 @@ export function placeCard(state, config, lane, side, card) {
|
|
|
27
29
|
lanes[lane] = { ...cell, [side]: [...cell[side], card] };
|
|
28
30
|
return { status: "ok", state: { lanes } };
|
|
29
31
|
}
|
|
32
|
+
/** @internal */
|
|
30
33
|
export function removeCard(state, lane, side, predicate) {
|
|
31
34
|
if (!validLane(state, lane))
|
|
32
35
|
return { status: "rejected", reason: "invalid-lane" };
|
|
@@ -37,6 +40,7 @@ export function removeCard(state, lane, side, predicate) {
|
|
|
37
40
|
lanes[lane] = { ...cell, [side]: cell[side].filter((card, index) => !predicate(card, index)) };
|
|
38
41
|
return { status: "ok", state: { lanes } };
|
|
39
42
|
}
|
|
43
|
+
/** @internal */
|
|
40
44
|
export function laneAggregate(state, config, lane, side) {
|
|
41
45
|
const cards = state.lanes[lane]?.[side] ?? [];
|
|
42
46
|
let subtotal = 0;
|
|
@@ -46,6 +50,7 @@ export function laneAggregate(state, config, lane, side) {
|
|
|
46
50
|
const total = rule ? rule.apply({ lane, side, cards, subtotal }) : subtotal;
|
|
47
51
|
return { lane, side, subtotal, total, count: cards.length };
|
|
48
52
|
}
|
|
53
|
+
/** @internal */
|
|
49
54
|
export function laneOutcome(state, config, lane) {
|
|
50
55
|
const totals = {};
|
|
51
56
|
let winner = null;
|
|
@@ -65,6 +70,7 @@ export function laneOutcome(state, config, lane) {
|
|
|
65
70
|
}
|
|
66
71
|
return { lane, totals, winner: tie ? null : winner };
|
|
67
72
|
}
|
|
73
|
+
/** @internal */
|
|
68
74
|
export function boardTotals(state, config) {
|
|
69
75
|
const totals = {};
|
|
70
76
|
for (const side of config.sides)
|
|
@@ -76,6 +82,7 @@ export function boardTotals(state, config) {
|
|
|
76
82
|
}
|
|
77
83
|
return totals;
|
|
78
84
|
}
|
|
85
|
+
/** @internal */
|
|
79
86
|
export function lanesWon(state, config) {
|
|
80
87
|
const won = {};
|
|
81
88
|
for (const side of config.sides)
|
|
@@ -87,6 +94,12 @@ export function lanesWon(state, config) {
|
|
|
87
94
|
}
|
|
88
95
|
return won;
|
|
89
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* A lane-based board where cards resolve per lane — the lane card-battler layout.
|
|
99
|
+
*
|
|
100
|
+
* @capability lane-board a lane-based card-battler board with per-lane outcomes
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
90
103
|
export function createLaneBoard(config) {
|
|
91
104
|
let state = createLaneBoardState(config);
|
|
92
105
|
return {
|
|
@@ -23,9 +23,13 @@ export interface TimelineTickResult {
|
|
|
23
23
|
state: TimelineBoardState;
|
|
24
24
|
fires: readonly TimelineFire[];
|
|
25
25
|
}
|
|
26
|
+
/** @internal */
|
|
26
27
|
export declare function createTimelineBoardState(slots: readonly TimelineSlotConfig[]): TimelineBoardState;
|
|
28
|
+
/** @internal */
|
|
27
29
|
export declare function tickTimeline(state: TimelineBoardState, dtMs: number): TimelineTickResult;
|
|
30
|
+
/** @internal */
|
|
28
31
|
export declare function setSlotEnabled(state: TimelineBoardState, slotId: string, enabled: boolean): TimelineBoardState;
|
|
32
|
+
/** @internal */
|
|
29
33
|
export declare function resetSlot(state: TimelineBoardState, slotId: string, remainingMs?: number): TimelineBoardState;
|
|
30
34
|
export interface TimelineBoard {
|
|
31
35
|
state(): TimelineBoardState;
|
|
@@ -33,4 +37,10 @@ export interface TimelineBoard {
|
|
|
33
37
|
setEnabled(slotId: string, enabled: boolean): void;
|
|
34
38
|
reset(slotId?: string, remainingMs?: number): void;
|
|
35
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* A step-sequencer timeline board of timed, toggleable slots.
|
|
42
|
+
*
|
|
43
|
+
* @capability timeline-board a step-sequencer timeline board of timed slots
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
36
46
|
export declare function createTimelineBoard(slots: readonly TimelineSlotConfig[]): TimelineBoard;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @internal */
|
|
1
2
|
export function createTimelineBoardState(slots) {
|
|
2
3
|
const seen = new Set();
|
|
3
4
|
const built = [];
|
|
@@ -16,6 +17,7 @@ export function createTimelineBoardState(slots) {
|
|
|
16
17
|
}
|
|
17
18
|
return { slots: built, elapsedMs: 0 };
|
|
18
19
|
}
|
|
20
|
+
/** @internal */
|
|
19
21
|
export function tickTimeline(state, dtMs) {
|
|
20
22
|
if (dtMs <= 0)
|
|
21
23
|
return { state, fires: [] };
|
|
@@ -38,18 +40,26 @@ export function tickTimeline(state, dtMs) {
|
|
|
38
40
|
fires,
|
|
39
41
|
};
|
|
40
42
|
}
|
|
43
|
+
/** @internal */
|
|
41
44
|
export function setSlotEnabled(state, slotId, enabled) {
|
|
42
45
|
return {
|
|
43
46
|
...state,
|
|
44
47
|
slots: state.slots.map((slot) => (slot.id === slotId ? { ...slot, enabled } : slot)),
|
|
45
48
|
};
|
|
46
49
|
}
|
|
50
|
+
/** @internal */
|
|
47
51
|
export function resetSlot(state, slotId, remainingMs) {
|
|
48
52
|
return {
|
|
49
53
|
...state,
|
|
50
54
|
slots: state.slots.map((slot) => slot.id === slotId ? { ...slot, remainingMs: remainingMs ?? slot.cooldownMs } : slot),
|
|
51
55
|
};
|
|
52
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* A step-sequencer timeline board of timed, toggleable slots.
|
|
59
|
+
*
|
|
60
|
+
* @capability timeline-board a step-sequencer timeline board of timed slots
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
53
63
|
export function createTimelineBoard(slots) {
|
|
54
64
|
const initial = slots;
|
|
55
65
|
let state = createTimelineBoardState(slots);
|
|
@@ -15,8 +15,21 @@ export interface AbilityCooldownGroup {
|
|
|
15
15
|
id: string;
|
|
16
16
|
cooldownMs: number;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A spendable resource pool (mana, energy, rage) bound to an ability kit. When bound, `cast` deducts a
|
|
20
|
+
* slot's `resourceCost` on success and `state`/`snapshot`/`canCast` reflect affordability without a
|
|
21
|
+
* per-call `resourceAvailable` argument — the cast path actually spends instead of only gating (#357).
|
|
22
|
+
*/
|
|
23
|
+
export interface AbilityResource {
|
|
24
|
+
/** Current spendable amount, read fresh on each cast/snapshot. */
|
|
25
|
+
available(): number;
|
|
26
|
+
/** Deduct `cost` from the pool after a successful cast. */
|
|
27
|
+
spend(cost: number): void;
|
|
28
|
+
}
|
|
18
29
|
export interface AbilityKitOptions {
|
|
19
30
|
groups?: readonly AbilityCooldownGroup[];
|
|
31
|
+
/** Bind a resource pool so casting charges `resourceCost` and snapshots reflect affordability automatically. Passing an explicit `resourceAvailable` to a method overrides the bound pool for that call and never auto-spends. */
|
|
32
|
+
resource?: AbilityResource;
|
|
20
33
|
}
|
|
21
34
|
export interface AbilitySlotSnapshot {
|
|
22
35
|
id: string;
|
|
@@ -59,4 +72,9 @@ export interface AbilityKit {
|
|
|
59
72
|
reset(slotId?: string): void;
|
|
60
73
|
retuneSlot(slotId: string, patch: AbilitySlotRetune): boolean;
|
|
61
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
|
|
77
|
+
*
|
|
78
|
+
* @capability ability-bar a bar of cooldown-gated abilities the player triggers by slot
|
|
79
|
+
*/
|
|
62
80
|
export declare function createAbilityKit(configs: readonly AbilitySlotConfig[], options?: AbilityKitOptions): AbilityKit;
|
|
@@ -39,7 +39,18 @@ function snapshotOf(runtime, resourceAvailable, group) {
|
|
|
39
39
|
ready: runtime.charges > 0 && group.remainingMs <= 0 && resourceAvailable >= config.resourceCost,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
|
|
44
|
+
*
|
|
45
|
+
* @capability ability-bar a bar of cooldown-gated abilities the player triggers by slot
|
|
46
|
+
*/
|
|
42
47
|
export function createAbilityKit(configs, options = {}) {
|
|
48
|
+
const boundResource = options.resource;
|
|
49
|
+
function currentResource(explicit) {
|
|
50
|
+
if (explicit !== undefined)
|
|
51
|
+
return explicit;
|
|
52
|
+
return boundResource === undefined ? Number.POSITIVE_INFINITY : boundResource.available();
|
|
53
|
+
}
|
|
43
54
|
const groupCooldowns = new Map();
|
|
44
55
|
const groupRemaining = new Map();
|
|
45
56
|
for (const group of options.groups ?? []) {
|
|
@@ -103,21 +114,22 @@ export function createAbilityKit(configs, options = {}) {
|
|
|
103
114
|
config(slotId) {
|
|
104
115
|
return runtimes.get(slotId)?.config ?? null;
|
|
105
116
|
},
|
|
106
|
-
state(slotId, resourceAvailable
|
|
117
|
+
state(slotId, resourceAvailable) {
|
|
107
118
|
const runtime = runtimes.get(slotId);
|
|
108
|
-
return runtime === undefined ? null : snapshotOf(runtime, resourceAvailable, groupBlockOf(runtime));
|
|
119
|
+
return runtime === undefined ? null : snapshotOf(runtime, currentResource(resourceAvailable), groupBlockOf(runtime));
|
|
109
120
|
},
|
|
110
|
-
snapshot(resourceAvailable
|
|
121
|
+
snapshot(resourceAvailable) {
|
|
122
|
+
const available = currentResource(resourceAvailable);
|
|
111
123
|
return order.map((slotId) => {
|
|
112
124
|
const runtime = runtimes.get(slotId);
|
|
113
|
-
return snapshotOf(runtime,
|
|
125
|
+
return snapshotOf(runtime, available, groupBlockOf(runtime));
|
|
114
126
|
});
|
|
115
127
|
},
|
|
116
|
-
canCast(slotId, resourceAvailable
|
|
117
|
-
return evaluate(slotId, resourceAvailable);
|
|
128
|
+
canCast(slotId, resourceAvailable) {
|
|
129
|
+
return evaluate(slotId, currentResource(resourceAvailable));
|
|
118
130
|
},
|
|
119
|
-
cast(slotId, resourceAvailable
|
|
120
|
-
const result = evaluate(slotId, resourceAvailable);
|
|
131
|
+
cast(slotId, resourceAvailable) {
|
|
132
|
+
const result = evaluate(slotId, currentResource(resourceAvailable));
|
|
121
133
|
if (!result.ok)
|
|
122
134
|
return result;
|
|
123
135
|
const runtime = runtimes.get(slotId);
|
|
@@ -128,7 +140,10 @@ export function createAbilityKit(configs, options = {}) {
|
|
|
128
140
|
for (const groupId of runtime.config.groups) {
|
|
129
141
|
groupRemaining.set(groupId, groupCooldowns.get(groupId) ?? 0);
|
|
130
142
|
}
|
|
131
|
-
|
|
143
|
+
if (resourceAvailable === undefined && boundResource !== undefined && runtime.config.resourceCost > 0) {
|
|
144
|
+
boundResource.spend(runtime.config.resourceCost);
|
|
145
|
+
}
|
|
146
|
+
return { ok: true, slot: snapshotOf(runtime, currentResource(resourceAvailable), groupBlockOf(runtime)) };
|
|
132
147
|
},
|
|
133
148
|
tick(dtSeconds) {
|
|
134
149
|
if (dtSeconds <= 0)
|
|
@@ -23,9 +23,13 @@ export interface AnimationTickResult {
|
|
|
23
23
|
exited: readonly FramePhase[];
|
|
24
24
|
completed: boolean;
|
|
25
25
|
}
|
|
26
|
+
/** @internal */
|
|
26
27
|
export declare function clipDurationMs(clip: AnimationClip): number;
|
|
28
|
+
/** @internal */
|
|
27
29
|
export declare function frameAtMs(clip: AnimationClip, elapsedMs: number): number;
|
|
30
|
+
/** @internal */
|
|
28
31
|
export declare function phasesAtFrame(clip: AnimationClip, frame: number): FramePhase[];
|
|
32
|
+
/** @internal */
|
|
29
33
|
export declare function activeRangeAtFrame(clip: AnimationClip, frame: number): FrameRange | null;
|
|
30
34
|
export interface AnimationState {
|
|
31
35
|
play(clipId: string): void;
|
|
@@ -44,4 +48,5 @@ export interface AnimationState {
|
|
|
44
48
|
export interface AnimationStateConfig {
|
|
45
49
|
clips: readonly AnimationClip[];
|
|
46
50
|
}
|
|
51
|
+
/** @internal */
|
|
47
52
|
export declare function createAnimationState(config: AnimationStateConfig): AnimationState;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
/** @internal */
|
|
1
2
|
export function clipDurationMs(clip) {
|
|
2
3
|
return (clip.frames / clip.fps) * 1000;
|
|
3
4
|
}
|
|
5
|
+
/** @internal */
|
|
4
6
|
export function frameAtMs(clip, elapsedMs) {
|
|
5
7
|
const raw = (elapsedMs / 1000) * clip.fps;
|
|
6
8
|
if (clip.loop === true) {
|
|
@@ -9,6 +11,7 @@ export function frameAtMs(clip, elapsedMs) {
|
|
|
9
11
|
}
|
|
10
12
|
return Math.min(raw, clip.frames);
|
|
11
13
|
}
|
|
14
|
+
/** @internal */
|
|
12
15
|
export function phasesAtFrame(clip, frame) {
|
|
13
16
|
const phases = [];
|
|
14
17
|
for (const range of clip.ranges) {
|
|
@@ -18,6 +21,7 @@ export function phasesAtFrame(clip, frame) {
|
|
|
18
21
|
}
|
|
19
22
|
return phases;
|
|
20
23
|
}
|
|
24
|
+
/** @internal */
|
|
21
25
|
export function activeRangeAtFrame(clip, frame) {
|
|
22
26
|
for (const range of clip.ranges) {
|
|
23
27
|
if (range.phase === "active" && frame >= range.from && frame < range.to)
|
|
@@ -25,6 +29,7 @@ export function activeRangeAtFrame(clip, frame) {
|
|
|
25
29
|
}
|
|
26
30
|
return null;
|
|
27
31
|
}
|
|
32
|
+
/** @internal */
|
|
28
33
|
export function createAnimationState(config) {
|
|
29
34
|
const clips = new Map(config.clips.map((clip) => [clip.id, clip]));
|
|
30
35
|
let activeClip = null;
|