@jgengine/core 0.10.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 +13 -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/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 +1 -0
- package/dist/authoring.js +1 -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 +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 +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 +190 -7
- package/dist/editor/commands.js +727 -55
- package/dist/editor/document.d.ts +159 -13
- package/dist/editor/document.js +750 -19
- 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 +73 -6
- package/dist/editor/index.js +6 -2
- 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 +107 -1
- 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 +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 +100 -2
- package/dist/game/defineGame.js +39 -2
- 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 +35 -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 +92 -7
- 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 +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/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 -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/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 +16 -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 +35 -8
- package/dist/movement/movementModel.js +42 -14
- package/dist/movement/playerMovement.js +65 -10
- 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 +22 -0
- package/dist/random/rng.js +28 -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 +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 +42 -3
- package/dist/runtime/adapter.js +44 -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/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 +114 -13
- package/dist/runtime/gameContext.js +303 -395
- 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 +8 -3
- package/dist/runtime/hostedGameRunner.js +26 -3
- package/dist/runtime/hostedWorldSession.d.ts +12 -4
- package/dist/runtime/hostedWorldSession.js +11 -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 +30 -3
- package/dist/runtime/worldSnapshot.js +20 -5
- package/dist/scene/assetCatalog.d.ts +21 -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 +13 -1
- package/dist/scene/colliders.js +37 -1
- package/dist/scene/entityStats.d.ts +11 -2
- package/dist/scene/entityStats.js +11 -2
- 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 +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 +5 -0
- package/dist/store/observableKeyedStore.js +34 -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 +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 +33 -1
- package/dist/ui/hudLayout.js +204 -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/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/features.d.ts +115 -7
- package/dist/world/features.js +56 -5
- 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 +8 -0
- package/dist/world/roads.js +38 -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/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +119 -20
- package/dist/world/terrain.js +247 -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 +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 -5389
|
@@ -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;
|
|
@@ -11,6 +11,11 @@ export interface StaggerMeter {
|
|
|
11
11
|
recover(): void;
|
|
12
12
|
tick(dtSeconds: number): void;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
|
|
16
|
+
*
|
|
17
|
+
* @capability stagger-meter build toward a stagger/poise-break threshold from landed hits
|
|
18
|
+
*/
|
|
14
19
|
export declare function createStaggerMeter(config: StaggerMeterConfig): StaggerMeter;
|
|
15
20
|
export interface BuildupMeterConfig {
|
|
16
21
|
status: string;
|
|
@@ -29,4 +34,9 @@ export interface BuildupMeter {
|
|
|
29
34
|
fraction(): number;
|
|
30
35
|
tick(dtSeconds: number): void;
|
|
31
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
|
|
39
|
+
*
|
|
40
|
+
* @capability stagger-meter accumulate an ailment buildup (bleed, freeze) until it procs
|
|
41
|
+
*/
|
|
32
42
|
export declare function createBuildupMeter(config: BuildupMeterConfig): BuildupMeter;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { createAccumulatorMeter } from "../stats/accumulatorMeter.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
|
|
4
|
+
*
|
|
5
|
+
* @capability stagger-meter build toward a stagger/poise-break threshold from landed hits
|
|
6
|
+
*/
|
|
2
7
|
export function createStaggerMeter(config) {
|
|
3
8
|
const meter = createAccumulatorMeter({
|
|
4
9
|
max: config.max,
|
|
@@ -27,6 +32,11 @@ export function createStaggerMeter(config) {
|
|
|
27
32
|
},
|
|
28
33
|
};
|
|
29
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
|
|
37
|
+
*
|
|
38
|
+
* @capability stagger-meter accumulate an ailment buildup (bleed, freeze) until it procs
|
|
39
|
+
*/
|
|
30
40
|
export function createBuildupMeter(config) {
|
|
31
41
|
const meter = createAccumulatorMeter({
|
|
32
42
|
max: config.max,
|
|
@@ -37,4 +37,9 @@ export interface CastRunner {
|
|
|
37
37
|
/** Advance by `dtSeconds`; `movedDistance` accumulates toward the config's `moveTolerance`. */
|
|
38
38
|
tick(dtSeconds: number, movedDistance?: number): CastEvent | null;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Run a channeled cast/charge timer that movement or damage can interrupt — the spell cast bar.
|
|
42
|
+
*
|
|
43
|
+
* @capability cast-bar run a channeled cast timer that movement or damage can interrupt
|
|
44
|
+
*/
|
|
40
45
|
export declare function createCastRunner(): CastRunner;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
const DEFAULT_MOVE_TOLERANCE = 0.04;
|
|
2
|
+
/**
|
|
3
|
+
* Run a channeled cast/charge timer that movement or damage can interrupt — the spell cast bar.
|
|
4
|
+
*
|
|
5
|
+
* @capability cast-bar run a channeled cast timer that movement or damage can interrupt
|
|
6
|
+
*/
|
|
2
7
|
export function createCastRunner() {
|
|
3
8
|
let active = null;
|
|
4
9
|
function snapshot() {
|
|
@@ -11,4 +11,9 @@ export interface ComboPoints {
|
|
|
11
11
|
expiresIn(): number | null;
|
|
12
12
|
clear(): void;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
|
|
16
|
+
*
|
|
17
|
+
* @capability combo-points build up and spend finisher/combo points
|
|
18
|
+
*/
|
|
14
19
|
export declare function createComboPoints(config: ComboPointsConfig): ComboPoints;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
|
|
3
|
+
*
|
|
4
|
+
* @capability combo-points build up and spend finisher/combo points
|
|
5
|
+
*/
|
|
1
6
|
export function createComboPoints(config) {
|
|
2
7
|
const max = config.max;
|
|
3
8
|
const expireAfterSeconds = config.expireAfterSeconds;
|
|
@@ -32,4 +32,9 @@ export interface ComboRunner {
|
|
|
32
32
|
request(stepId: string, stance?: string): AdvanceComboResult;
|
|
33
33
|
reset(): void;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
|
|
37
|
+
*
|
|
38
|
+
* @capability combo-chain advance a chained melee string from timed button inputs
|
|
39
|
+
*/
|
|
35
40
|
export declare function createComboRunner(combo: ComboString, anim: AnimationState): ComboRunner;
|
|
@@ -32,6 +32,11 @@ export function advanceCombo(input) {
|
|
|
32
32
|
}
|
|
33
33
|
return { accepted: true, step: requested };
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
|
|
37
|
+
*
|
|
38
|
+
* @capability combo-chain advance a chained melee string from timed button inputs
|
|
39
|
+
*/
|
|
35
40
|
export function createComboRunner(combo, anim) {
|
|
36
41
|
let current = null;
|
|
37
42
|
return {
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordered, inspectable damage-resolution interception (#931).
|
|
3
|
+
*
|
|
4
|
+
* A pending damage application flows through an ordered list of interceptors
|
|
5
|
+
* BEFORE lethality is resolved. Each interceptor may pass, transform, clamp,
|
|
6
|
+
* redirect, split, defer, or reject the application, and every decision is
|
|
7
|
+
* recorded as provenance so combat resolution stays auditable — no hidden
|
|
8
|
+
* callbacks. Invulnerability, i-frames, and anti-one-shot clamps are ordinary
|
|
9
|
+
* interceptors installed and removed by state transitions, not a boss branch.
|
|
10
|
+
*
|
|
11
|
+
* All state is serializable (`Record<string, number>` maps), all randomness is
|
|
12
|
+
* absent (pure), and work is bounded by `MAX_INTERCEPT_STEPS` so split/redirect
|
|
13
|
+
* can never recurse without limit.
|
|
14
|
+
*/
|
|
15
|
+
/** A damage application queued for resolution against a target. `amount` is always non-negative; healing is a separate concern. */
|
|
16
|
+
export interface PendingDamage {
|
|
17
|
+
/** Instance receiving the damage. */
|
|
18
|
+
target: string;
|
|
19
|
+
/** Instance dealing the damage. */
|
|
20
|
+
source: string;
|
|
21
|
+
/** Damage magnitude, non-negative. */
|
|
22
|
+
amount: number;
|
|
23
|
+
/** Optional caller tag (weapon id, effect id, channel) carried through for provenance and downstream routing. */
|
|
24
|
+
tag?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What an interceptor decides to do with the pending application it was handed.
|
|
28
|
+
* `split` parts continue at the NEXT interceptor (never re-entering the splitter),
|
|
29
|
+
* which is what keeps the pipeline bounded and recursion-free.
|
|
30
|
+
*/
|
|
31
|
+
export type InterceptDecision = {
|
|
32
|
+
kind: "pass";
|
|
33
|
+
} | {
|
|
34
|
+
kind: "transform";
|
|
35
|
+
amount: number;
|
|
36
|
+
note?: string;
|
|
37
|
+
} | {
|
|
38
|
+
kind: "clamp";
|
|
39
|
+
max: number;
|
|
40
|
+
note?: string;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "redirect";
|
|
43
|
+
target: string;
|
|
44
|
+
note?: string;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "split";
|
|
47
|
+
parts: readonly PendingDamage[];
|
|
48
|
+
note?: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "defer";
|
|
51
|
+
note?: string;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "reject";
|
|
54
|
+
note?: string;
|
|
55
|
+
};
|
|
56
|
+
/** Read-only context an interceptor may consult — deterministic clock and optional health lookup for HP-relative policies. */
|
|
57
|
+
export interface InterceptContext {
|
|
58
|
+
/** Deterministic current time in milliseconds; interceptors never read a wall clock. */
|
|
59
|
+
nowMs: number;
|
|
60
|
+
/** Optional current/max pool lookup for the target, enabling HP-relative clamps like anti-one-shot. */
|
|
61
|
+
healthOf?(target: string): {
|
|
62
|
+
current: number;
|
|
63
|
+
max: number;
|
|
64
|
+
} | undefined;
|
|
65
|
+
}
|
|
66
|
+
/** A named stage in the interception pipeline. The `id` is stable so it can be installed, removed, and cited in provenance. */
|
|
67
|
+
export interface DamageInterceptor {
|
|
68
|
+
/** Stable identifier used for install/remove and provenance. */
|
|
69
|
+
id: string;
|
|
70
|
+
/** Decide what happens to `pending`; must be deterministic given `ctx`. */
|
|
71
|
+
intercept(pending: PendingDamage, ctx: InterceptContext): InterceptDecision;
|
|
72
|
+
}
|
|
73
|
+
/** One row of provenance: which interceptor acted, what it decided, and the amount before/after it acted. */
|
|
74
|
+
export interface InterceptRecord {
|
|
75
|
+
interceptor: string;
|
|
76
|
+
kind: InterceptDecision["kind"];
|
|
77
|
+
target: string;
|
|
78
|
+
before: number;
|
|
79
|
+
after: number;
|
|
80
|
+
note?: string;
|
|
81
|
+
}
|
|
82
|
+
/** The outcome of running a pending application through the pipeline: what to apply, what was deferred, and why each value changed. */
|
|
83
|
+
export interface DamageResolution {
|
|
84
|
+
/** Final applications to commit (0..n after splits/rejections). */
|
|
85
|
+
applications: PendingDamage[];
|
|
86
|
+
/** Applications held back by a `defer` decision for the caller to resubmit later. */
|
|
87
|
+
deferred: PendingDamage[];
|
|
88
|
+
/** Ordered record of every interceptor decision. */
|
|
89
|
+
provenance: InterceptRecord[];
|
|
90
|
+
}
|
|
91
|
+
/** Upper bound on interceptor evaluations for a single resolution; guards against runaway `split`/`redirect` loops. */
|
|
92
|
+
export declare const MAX_INTERCEPT_STEPS = 256;
|
|
93
|
+
/**
|
|
94
|
+
* Run one pending damage application through an ordered interceptor list before
|
|
95
|
+
* lethality resolves, returning the final applications, any deferred ones, and
|
|
96
|
+
* full provenance. Pure and deterministic; bounded by `MAX_INTERCEPT_STEPS`.
|
|
97
|
+
*
|
|
98
|
+
* @capability damage-interception intercept a pending damage application before lethal resolution with ordered, inspectable stages
|
|
99
|
+
*/
|
|
100
|
+
export declare function resolveDamage(interceptors: readonly DamageInterceptor[], pending: PendingDamage, ctx: InterceptContext): DamageResolution;
|
|
101
|
+
/** A mutable ordered interceptor chain that transitions can install into and remove from at runtime. */
|
|
102
|
+
export interface DamagePipeline {
|
|
103
|
+
/** Append an interceptor, or replace an existing one with the same `id` in place. */
|
|
104
|
+
install(interceptor: DamageInterceptor): void;
|
|
105
|
+
/** Remove the interceptor with `id`; returns whether one was removed. */
|
|
106
|
+
remove(id: string): boolean;
|
|
107
|
+
/** Whether an interceptor with `id` is currently installed. */
|
|
108
|
+
has(id: string): boolean;
|
|
109
|
+
/** Installed interceptor ids in evaluation order (serializable install record). */
|
|
110
|
+
interceptorIds(): string[];
|
|
111
|
+
/** Resolve one pending application through the current chain. */
|
|
112
|
+
resolve(pending: PendingDamage, ctx: InterceptContext): DamageResolution;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a mutable damage interception chain that state transitions install into
|
|
116
|
+
* and remove from — e.g. add an invulnerability interceptor on phase enter and
|
|
117
|
+
* drop it on phase exit. Evaluation order is install order.
|
|
118
|
+
*
|
|
119
|
+
* @capability damage-pipeline install and remove ordered damage interceptors that transitions toggle at runtime
|
|
120
|
+
*/
|
|
121
|
+
export declare function createDamagePipeline(initial?: readonly DamageInterceptor[]): DamagePipeline;
|
|
122
|
+
/** Caller data for a flat per-hit damage cap. */
|
|
123
|
+
export interface DamageClampConfig {
|
|
124
|
+
/** Interceptor id; defaults to `"damage-clamp"`. */
|
|
125
|
+
id?: string;
|
|
126
|
+
/** Maximum damage a single application may carry. */
|
|
127
|
+
maxPerHit: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* A stateless interceptor that caps any single application at `maxPerHit`.
|
|
131
|
+
*
|
|
132
|
+
* @capability damage-clamp cap incoming damage per hit at a configured maximum
|
|
133
|
+
*/
|
|
134
|
+
export declare function createDamageClamp(config: DamageClampConfig): DamageInterceptor;
|
|
135
|
+
/** A per-target timed immunity policy: an interceptor plus grant/query/serialize controls, toggled by transitions. */
|
|
136
|
+
export interface ImmunityWindow {
|
|
137
|
+
/** The interceptor to install; rejects damage to any target whose immunity has not expired. */
|
|
138
|
+
interceptor: DamageInterceptor;
|
|
139
|
+
/** Make `target` immune until `untilMs` (extends, never shortens, an existing window). */
|
|
140
|
+
grant(target: string, untilMs: number): void;
|
|
141
|
+
/** Make `target` immune for `durationMs` starting at `nowMs`. */
|
|
142
|
+
grantFor(target: string, nowMs: number, durationMs: number): void;
|
|
143
|
+
/** Whether `target` is immune at `nowMs`. */
|
|
144
|
+
active(target: string, nowMs: number): boolean;
|
|
145
|
+
/** Drop `target`'s immunity immediately. */
|
|
146
|
+
clear(target: string): void;
|
|
147
|
+
/** Drop every window that has expired at `nowMs` (bounded housekeeping for save size). */
|
|
148
|
+
clearExpired(nowMs: number): void;
|
|
149
|
+
/** Serializable snapshot: target → expiry ms. */
|
|
150
|
+
snapshot(): Record<string, number>;
|
|
151
|
+
/** Restore from a snapshot. */
|
|
152
|
+
restore(snap: Record<string, number>): void;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A per-target immunity/invulnerability window as an ordinary damage policy —
|
|
156
|
+
* granted and cleared by state transitions (i-frames, phase invuln), rejecting
|
|
157
|
+
* damage while active. Deterministic (time is passed in) and serializable.
|
|
158
|
+
*
|
|
159
|
+
* @capability immunity-window reject damage during a per-target invulnerability window installed by transitions
|
|
160
|
+
*/
|
|
161
|
+
export declare function createImmunityWindow(id?: string): ImmunityWindow;
|
|
162
|
+
/** Caller data for the anti-one-shot composition: "cannot cross lethal while above X, leave Y, then recover for Z". */
|
|
163
|
+
export interface AntiOneShotConfig {
|
|
164
|
+
/** Interceptor id; defaults to `"anti-one-shot"`. */
|
|
165
|
+
id?: string;
|
|
166
|
+
/** Only intervene when the target's HP fraction is strictly above this (X). Below it, lethal hits pass. */
|
|
167
|
+
guardAboveFraction: number;
|
|
168
|
+
/** HP fraction to leave the target at after an intercepted near-lethal hit (Y). */
|
|
169
|
+
leaveFraction: number;
|
|
170
|
+
/** Immunity granted after an intercepted hit, in milliseconds (Z). */
|
|
171
|
+
recoverMs: number;
|
|
172
|
+
}
|
|
173
|
+
/** The anti-one-shot policy: an interceptor plus its serializable recovery-immunity state. */
|
|
174
|
+
export interface AntiOneShotPolicy {
|
|
175
|
+
/** The interceptor to install ahead of lethal resolution. */
|
|
176
|
+
interceptor: DamageInterceptor;
|
|
177
|
+
/** Whether `target` is in the post-hit recovery i-frame at `nowMs`. */
|
|
178
|
+
immune(target: string, nowMs: number): boolean;
|
|
179
|
+
/** Serializable snapshot: target → recovery expiry ms. */
|
|
180
|
+
snapshot(): Record<string, number>;
|
|
181
|
+
/** Restore from a snapshot. */
|
|
182
|
+
restore(snap: Record<string, number>): void;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Compose a reusable anti-one-shot / chip-guard clamp from caller data:
|
|
186
|
+
* while above `guardAboveFraction` a hit cannot drop the target below
|
|
187
|
+
* `leaveFraction`, and after such a save the target gets `recoverMs` of
|
|
188
|
+
* immunity. Below the guard fraction, lethal hits pass unchanged.
|
|
189
|
+
*
|
|
190
|
+
* @capability anti-one-shot clamp a near-lethal hit to leave a health floor then grant recovery immunity
|
|
191
|
+
*/
|
|
192
|
+
export declare function createAntiOneShotPolicy(config: AntiOneShotConfig): AntiOneShotPolicy;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordered, inspectable damage-resolution interception (#931).
|
|
3
|
+
*
|
|
4
|
+
* A pending damage application flows through an ordered list of interceptors
|
|
5
|
+
* BEFORE lethality is resolved. Each interceptor may pass, transform, clamp,
|
|
6
|
+
* redirect, split, defer, or reject the application, and every decision is
|
|
7
|
+
* recorded as provenance so combat resolution stays auditable — no hidden
|
|
8
|
+
* callbacks. Invulnerability, i-frames, and anti-one-shot clamps are ordinary
|
|
9
|
+
* interceptors installed and removed by state transitions, not a boss branch.
|
|
10
|
+
*
|
|
11
|
+
* All state is serializable (`Record<string, number>` maps), all randomness is
|
|
12
|
+
* absent (pure), and work is bounded by `MAX_INTERCEPT_STEPS` so split/redirect
|
|
13
|
+
* can never recurse without limit.
|
|
14
|
+
*/
|
|
15
|
+
/** Upper bound on interceptor evaluations for a single resolution; guards against runaway `split`/`redirect` loops. */
|
|
16
|
+
export const MAX_INTERCEPT_STEPS = 256;
|
|
17
|
+
/**
|
|
18
|
+
* Run one pending damage application through an ordered interceptor list before
|
|
19
|
+
* lethality resolves, returning the final applications, any deferred ones, and
|
|
20
|
+
* full provenance. Pure and deterministic; bounded by `MAX_INTERCEPT_STEPS`.
|
|
21
|
+
*
|
|
22
|
+
* @capability damage-interception intercept a pending damage application before lethal resolution with ordered, inspectable stages
|
|
23
|
+
*/
|
|
24
|
+
export function resolveDamage(interceptors, pending, ctx) {
|
|
25
|
+
const applications = [];
|
|
26
|
+
const deferred = [];
|
|
27
|
+
const provenance = [];
|
|
28
|
+
const queue = [{ pending: normalize(pending), next: 0 }];
|
|
29
|
+
let steps = 0;
|
|
30
|
+
while (queue.length > 0) {
|
|
31
|
+
if (++steps > MAX_INTERCEPT_STEPS)
|
|
32
|
+
break;
|
|
33
|
+
const item = queue.shift();
|
|
34
|
+
if (item === undefined)
|
|
35
|
+
break;
|
|
36
|
+
if (item.next >= interceptors.length) {
|
|
37
|
+
applications.push(item.pending);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const interceptor = interceptors[item.next];
|
|
41
|
+
if (interceptor === undefined) {
|
|
42
|
+
applications.push(item.pending);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const current = item.pending;
|
|
46
|
+
const interceptorId = interceptor.id;
|
|
47
|
+
const decision = interceptor.intercept(current, ctx);
|
|
48
|
+
const before = current.amount;
|
|
49
|
+
function record(after, note) {
|
|
50
|
+
const row = {
|
|
51
|
+
interceptor: interceptorId,
|
|
52
|
+
kind: decision.kind,
|
|
53
|
+
target: current.target,
|
|
54
|
+
before,
|
|
55
|
+
after,
|
|
56
|
+
};
|
|
57
|
+
if (note !== undefined)
|
|
58
|
+
row.note = note;
|
|
59
|
+
provenance.push(row);
|
|
60
|
+
}
|
|
61
|
+
const nextIndex = item.next + 1;
|
|
62
|
+
switch (decision.kind) {
|
|
63
|
+
case "pass":
|
|
64
|
+
record(before);
|
|
65
|
+
queue.push({ pending: current, next: nextIndex });
|
|
66
|
+
break;
|
|
67
|
+
case "transform": {
|
|
68
|
+
const amount = Math.max(0, decision.amount);
|
|
69
|
+
record(amount, decision.note);
|
|
70
|
+
queue.push({ pending: { ...current, amount }, next: nextIndex });
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "clamp": {
|
|
74
|
+
const amount = Math.min(current.amount, Math.max(0, decision.max));
|
|
75
|
+
record(amount, decision.note);
|
|
76
|
+
queue.push({ pending: { ...current, amount }, next: nextIndex });
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case "redirect":
|
|
80
|
+
record(before, decision.note);
|
|
81
|
+
queue.push({ pending: { ...current, target: decision.target }, next: nextIndex });
|
|
82
|
+
break;
|
|
83
|
+
case "split":
|
|
84
|
+
record(before, decision.note);
|
|
85
|
+
for (const part of decision.parts)
|
|
86
|
+
queue.push({ pending: normalize(part), next: nextIndex });
|
|
87
|
+
break;
|
|
88
|
+
case "defer":
|
|
89
|
+
record(before, decision.note);
|
|
90
|
+
deferred.push(current);
|
|
91
|
+
break;
|
|
92
|
+
case "reject":
|
|
93
|
+
record(0, decision.note);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { applications, deferred, provenance };
|
|
98
|
+
}
|
|
99
|
+
function normalize(pending) {
|
|
100
|
+
return pending.amount >= 0 ? pending : { ...pending, amount: 0 };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Create a mutable damage interception chain that state transitions install into
|
|
104
|
+
* and remove from — e.g. add an invulnerability interceptor on phase enter and
|
|
105
|
+
* drop it on phase exit. Evaluation order is install order.
|
|
106
|
+
*
|
|
107
|
+
* @capability damage-pipeline install and remove ordered damage interceptors that transitions toggle at runtime
|
|
108
|
+
*/
|
|
109
|
+
export function createDamagePipeline(initial) {
|
|
110
|
+
const interceptors = initial === undefined ? [] : [...initial];
|
|
111
|
+
function indexOf(id) {
|
|
112
|
+
return interceptors.findIndex((entry) => entry.id === id);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
install(interceptor) {
|
|
116
|
+
const idx = indexOf(interceptor.id);
|
|
117
|
+
if (idx >= 0)
|
|
118
|
+
interceptors[idx] = interceptor;
|
|
119
|
+
else
|
|
120
|
+
interceptors.push(interceptor);
|
|
121
|
+
},
|
|
122
|
+
remove(id) {
|
|
123
|
+
const idx = indexOf(id);
|
|
124
|
+
if (idx < 0)
|
|
125
|
+
return false;
|
|
126
|
+
interceptors.splice(idx, 1);
|
|
127
|
+
return true;
|
|
128
|
+
},
|
|
129
|
+
has(id) {
|
|
130
|
+
return indexOf(id) >= 0;
|
|
131
|
+
},
|
|
132
|
+
interceptorIds() {
|
|
133
|
+
return interceptors.map((entry) => entry.id);
|
|
134
|
+
},
|
|
135
|
+
resolve(pending, ctx) {
|
|
136
|
+
return resolveDamage(interceptors, pending, ctx);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A stateless interceptor that caps any single application at `maxPerHit`.
|
|
142
|
+
*
|
|
143
|
+
* @capability damage-clamp cap incoming damage per hit at a configured maximum
|
|
144
|
+
*/
|
|
145
|
+
export function createDamageClamp(config) {
|
|
146
|
+
const id = config.id ?? "damage-clamp";
|
|
147
|
+
return {
|
|
148
|
+
id,
|
|
149
|
+
intercept(pending) {
|
|
150
|
+
if (pending.amount <= config.maxPerHit)
|
|
151
|
+
return { kind: "pass" };
|
|
152
|
+
return { kind: "clamp", max: config.maxPerHit, note: `capped at ${config.maxPerHit}` };
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A per-target immunity/invulnerability window as an ordinary damage policy —
|
|
158
|
+
* granted and cleared by state transitions (i-frames, phase invuln), rejecting
|
|
159
|
+
* damage while active. Deterministic (time is passed in) and serializable.
|
|
160
|
+
*
|
|
161
|
+
* @capability immunity-window reject damage during a per-target invulnerability window installed by transitions
|
|
162
|
+
*/
|
|
163
|
+
export function createImmunityWindow(id = "immunity") {
|
|
164
|
+
const until = new Map();
|
|
165
|
+
const window = {
|
|
166
|
+
interceptor: {
|
|
167
|
+
id,
|
|
168
|
+
intercept(pending, ctx) {
|
|
169
|
+
const expiry = until.get(pending.target);
|
|
170
|
+
if (expiry !== undefined && ctx.nowMs < expiry)
|
|
171
|
+
return { kind: "reject", note: `immune until ${expiry}` };
|
|
172
|
+
return { kind: "pass" };
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
grant(target, untilMs) {
|
|
176
|
+
const prev = until.get(target);
|
|
177
|
+
until.set(target, prev === undefined ? untilMs : Math.max(prev, untilMs));
|
|
178
|
+
},
|
|
179
|
+
grantFor(target, nowMs, durationMs) {
|
|
180
|
+
window.grant(target, nowMs + durationMs);
|
|
181
|
+
},
|
|
182
|
+
active(target, nowMs) {
|
|
183
|
+
const expiry = until.get(target);
|
|
184
|
+
return expiry !== undefined && nowMs < expiry;
|
|
185
|
+
},
|
|
186
|
+
clear(target) {
|
|
187
|
+
until.delete(target);
|
|
188
|
+
},
|
|
189
|
+
clearExpired(nowMs) {
|
|
190
|
+
for (const [target, expiry] of [...until])
|
|
191
|
+
if (nowMs >= expiry)
|
|
192
|
+
until.delete(target);
|
|
193
|
+
},
|
|
194
|
+
snapshot() {
|
|
195
|
+
return Object.fromEntries(until);
|
|
196
|
+
},
|
|
197
|
+
restore(snap) {
|
|
198
|
+
until.clear();
|
|
199
|
+
for (const [target, expiry] of Object.entries(snap))
|
|
200
|
+
until.set(target, expiry);
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
return window;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Compose a reusable anti-one-shot / chip-guard clamp from caller data:
|
|
207
|
+
* while above `guardAboveFraction` a hit cannot drop the target below
|
|
208
|
+
* `leaveFraction`, and after such a save the target gets `recoverMs` of
|
|
209
|
+
* immunity. Below the guard fraction, lethal hits pass unchanged.
|
|
210
|
+
*
|
|
211
|
+
* @capability anti-one-shot clamp a near-lethal hit to leave a health floor then grant recovery immunity
|
|
212
|
+
*/
|
|
213
|
+
export function createAntiOneShotPolicy(config) {
|
|
214
|
+
const id = config.id ?? "anti-one-shot";
|
|
215
|
+
const immuneUntil = new Map();
|
|
216
|
+
const policy = {
|
|
217
|
+
interceptor: {
|
|
218
|
+
id,
|
|
219
|
+
intercept(pending, ctx) {
|
|
220
|
+
const expiry = immuneUntil.get(pending.target);
|
|
221
|
+
if (expiry !== undefined && ctx.nowMs < expiry)
|
|
222
|
+
return { kind: "reject", note: "anti-one-shot i-frame" };
|
|
223
|
+
const hp = ctx.healthOf?.(pending.target);
|
|
224
|
+
if (hp === undefined || hp.max <= 0)
|
|
225
|
+
return { kind: "pass" };
|
|
226
|
+
const fraction = hp.current / hp.max;
|
|
227
|
+
if (fraction <= config.guardAboveFraction)
|
|
228
|
+
return { kind: "pass" };
|
|
229
|
+
const floor = config.leaveFraction * hp.max;
|
|
230
|
+
if (hp.current - pending.amount >= floor)
|
|
231
|
+
return { kind: "pass" };
|
|
232
|
+
const clamped = Math.max(0, hp.current - floor);
|
|
233
|
+
immuneUntil.set(pending.target, ctx.nowMs + config.recoverMs);
|
|
234
|
+
return { kind: "clamp", max: clamped, note: `anti-one-shot: leave ${floor}, recover ${config.recoverMs}ms` };
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
immune(target, nowMs) {
|
|
238
|
+
const expiry = immuneUntil.get(target);
|
|
239
|
+
return expiry !== undefined && nowMs < expiry;
|
|
240
|
+
},
|
|
241
|
+
snapshot() {
|
|
242
|
+
return Object.fromEntries(immuneUntil);
|
|
243
|
+
},
|
|
244
|
+
restore(snap) {
|
|
245
|
+
immuneUntil.clear();
|
|
246
|
+
for (const [target, expiry] of Object.entries(snap))
|
|
247
|
+
immuneUntil.set(target, expiry);
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
return policy;
|
|
251
|
+
}
|