@jgengine/core 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -3
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/spawnDirector.d.ts +19 -1
- package/dist/ai/spawnDirector.js +53 -26
- package/dist/ai/spawnPoint.d.ts +7 -0
- package/dist/ai/spawnPoint.js +7 -0
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/audio/audioFalloff.d.ts +5 -2
- package/dist/audio/music.d.ts +53 -0
- package/dist/audio/music.js +34 -0
- package/dist/audio/synth.d.ts +60 -0
- package/dist/audio/synth.js +8 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +15 -0
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +47 -0
- package/dist/combat/dotField.js +52 -0
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +7 -2
- package/dist/combat/projectiles.js +48 -17
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +39 -0
- package/dist/combat/regenShield.js +49 -0
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +30 -1
- package/dist/combat/shotOrigin.js +70 -2
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +34 -0
- package/dist/combat.js +34 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commands.d.ts +248 -0
- package/dist/editor/commands.js +865 -0
- package/dist/editor/document.d.ts +186 -0
- package/dist/editor/document.js +884 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +97 -0
- package/dist/editor/index.js +10 -0
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/types.d.ts +175 -0
- package/dist/editor/types.js +29 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/connectedPlayers.d.ts +30 -0
- package/dist/game/connectedPlayers.js +21 -0
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +141 -2
- package/dist/game/defineGame.js +39 -1
- package/dist/game/defineSystem.d.ts +88 -0
- package/dist/game/defineSystem.js +45 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +50 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/keyValueStore.d.ts +25 -0
- package/dist/game/keyValueStore.js +61 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/levelSequence.d.ts +24 -2
- package/dist/game/levelSequence.js +51 -2
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +21 -0
- package/dist/game/lootTable.js +15 -4
- package/dist/game/modelAnimation.d.ts +8 -0
- package/dist/game/modelAnimation.js +18 -0
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +160 -12
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +29 -0
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +5 -5
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +91 -0
- package/dist/gameplay.js +91 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -7
- package/dist/input/actionBindings.d.ts +24 -5
- package/dist/input/actionBindings.js +23 -5
- package/dist/input/axisInput.d.ts +13 -1
- package/dist/input/axisInput.js +22 -1
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/contextMenu.d.ts +1 -0
- package/dist/interaction/contextMenu.js +1 -0
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +5 -1
- package/dist/interaction/proximityPrompt.js +5 -3
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +5 -0
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +36 -1
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +38 -7
- package/dist/movement/movementModel.js +54 -13
- package/dist/movement/playerMovement.d.ts +41 -0
- package/dist/movement/playerMovement.js +236 -0
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +3 -0
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +9 -1
- package/dist/multiplayer/presenceModel.js +9 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +29 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/kinematicVehicle.d.ts +21 -1
- package/dist/physics/kinematicVehicle.js +23 -8
- package/dist/physics/physicsWorld.d.ts +24 -12
- package/dist/physics/physicsWorld.js +11 -5
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +24 -0
- package/dist/random/rng.js +30 -8
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +76 -0
- package/dist/render/postProcessing.js +21 -0
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +58 -0
- package/dist/runtime/adapter.js +54 -5
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +134 -0
- package/dist/runtime/descriptors/features.d.ts +74 -0
- package/dist/runtime/descriptors/features.js +281 -0
- package/dist/runtime/gameContext.d.ts +163 -19
- package/dist/runtime/gameContext.js +385 -339
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +60 -0
- package/dist/runtime/headlessRunner.js +44 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostedGameRunner.d.ts +54 -0
- package/dist/runtime/hostedGameRunner.js +85 -0
- package/dist/runtime/hostedWorldSession.d.ts +73 -0
- package/dist/runtime/hostedWorldSession.js +64 -0
- package/dist/runtime/inputSnapshot.d.ts +21 -3
- package/dist/runtime/inputSnapshot.js +8 -2
- package/dist/runtime/motionIntents.d.ts +12 -1
- package/dist/runtime/motionIntents.js +26 -1
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +62 -0
- package/dist/runtime/worldChannel.js +114 -0
- package/dist/runtime/worldMirror.d.ts +36 -0
- package/dist/runtime/worldMirror.js +44 -0
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +69 -0
- package/dist/runtime/worldReplication.js +217 -0
- package/dist/runtime/worldSnapshot.d.ts +44 -0
- package/dist/runtime/worldSnapshot.js +30 -0
- package/dist/scene/assetCatalog.d.ts +22 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +259 -0
- package/dist/scene/authoredTriggers.d.ts +169 -0
- package/dist/scene/authoredTriggers.js +340 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +62 -0
- package/dist/scene/colliders.d.ts +18 -0
- package/dist/scene/colliders.js +61 -1
- package/dist/scene/entityStats.d.ts +13 -0
- package/dist/scene/entityStats.js +30 -0
- package/dist/scene/entityStore.d.ts +41 -1
- package/dist/scene/entityStore.js +75 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +240 -0
- package/dist/scene/sceneKinds.js +214 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +9 -0
- package/dist/store/observableKeyedStore.js +43 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -55
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +5 -0
- package/dist/tactics/fallingGrid.d.ts +6 -4
- package/dist/tactics/fallingGrid.js +6 -4
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +144 -0
- package/dist/ui/gameLayout.js +148 -0
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +33 -1
- package/dist/ui/hudLayout.js +204 -17
- package/dist/ui/orientation.d.ts +39 -0
- package/dist/ui/orientation.js +49 -0
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/swingTimer.d.ts +42 -0
- package/dist/ui/swingTimer.js +38 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/visibility/spatialIndex.js +34 -20
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredObjects.d.ts +58 -0
- package/dist/world/authoredObjects.js +69 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/environmentSummary.d.ts +11 -2
- package/dist/world/environmentSummary.js +11 -1
- package/dist/world/features.d.ts +244 -7
- package/dist/world/features.js +92 -4
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +77 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +81 -0
- package/dist/world/roads.d.ts +55 -0
- package/dist/world/roads.js +184 -0
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +80 -0
- package/dist/world/streets.js +144 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +138 -12
- package/dist/world/terrain.js +346 -28
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +132 -0
- package/dist/world.js +132 -0
- package/package.json +32 -8
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-combat/SKILL.md +34 -0
- package/skills/jgengine-combat/api.md +549 -0
- package/skills/jgengine-combat/capabilities.md +169 -0
- package/skills/jgengine-combat/reference.md +98 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1794 -0
- package/skills/jgengine-gameplay/capabilities.md +378 -0
- package/skills/jgengine-gameplay/reference-systems.md +60 -0
- package/skills/jgengine-world/SKILL.md +38 -0
- package/skills/jgengine-world/api.md +2652 -0
- package/skills/jgengine-world/capabilities.md +370 -0
- package/skills/jgengine-world/reference.md +222 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -4983
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
function selfManagedReserve(initial) {
|
|
2
|
+
let value = Math.max(0, initial);
|
|
3
|
+
return {
|
|
4
|
+
current: () => value,
|
|
5
|
+
spend(amount) {
|
|
6
|
+
if (amount <= 0)
|
|
7
|
+
return true;
|
|
8
|
+
if (amount > value)
|
|
9
|
+
return false;
|
|
10
|
+
value -= amount;
|
|
11
|
+
return true;
|
|
12
|
+
},
|
|
13
|
+
gain(amount) {
|
|
14
|
+
if (amount > 0)
|
|
15
|
+
value += amount;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const INFINITE_RESERVE = {
|
|
20
|
+
current: () => Number.POSITIVE_INFINITY,
|
|
21
|
+
spend: () => true,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Builds a {@link Magazine}: discrete loaded ammo, a timed reload, and reserve-pool interaction.
|
|
25
|
+
*
|
|
26
|
+
* @capability magazine a weapon magazine with capacity, timed reload, and reserve-pool interaction
|
|
27
|
+
*/
|
|
28
|
+
export function createMagazine(config) {
|
|
29
|
+
const capacity = Math.max(0, config.capacity);
|
|
30
|
+
const reloadMs = Math.max(0, config.reloadMs);
|
|
31
|
+
const isInfiniteReserve = config.reserve === undefined;
|
|
32
|
+
const reserve = isInfiniteReserve
|
|
33
|
+
? INFINITE_RESERVE
|
|
34
|
+
: typeof config.reserve === "number"
|
|
35
|
+
? selfManagedReserve(config.reserve)
|
|
36
|
+
: config.reserve;
|
|
37
|
+
function clampLoaded(value) {
|
|
38
|
+
return Math.max(0, Math.min(capacity, value));
|
|
39
|
+
}
|
|
40
|
+
let loaded = clampLoaded(config.loaded ?? capacity);
|
|
41
|
+
let reloadElapsedMs = null;
|
|
42
|
+
return {
|
|
43
|
+
loaded: () => loaded,
|
|
44
|
+
capacity: () => capacity,
|
|
45
|
+
reserve: () => (isInfiniteReserve ? null : reserve.current()),
|
|
46
|
+
isReloading: () => reloadElapsedMs !== null,
|
|
47
|
+
reloadFraction: () => (reloadElapsedMs === null || reloadMs <= 0 ? 0 : Math.min(1, reloadElapsedMs / reloadMs)),
|
|
48
|
+
isEmpty: () => loaded <= 0,
|
|
49
|
+
isFull: () => loaded >= capacity,
|
|
50
|
+
canFire(rounds = 1) {
|
|
51
|
+
return rounds <= 0 || rounds <= loaded;
|
|
52
|
+
},
|
|
53
|
+
fire(rounds = 1) {
|
|
54
|
+
if (rounds <= 0)
|
|
55
|
+
return true;
|
|
56
|
+
if (rounds > loaded)
|
|
57
|
+
return false;
|
|
58
|
+
loaded -= rounds;
|
|
59
|
+
return true;
|
|
60
|
+
},
|
|
61
|
+
canReload() {
|
|
62
|
+
if (reloadElapsedMs !== null)
|
|
63
|
+
return false;
|
|
64
|
+
if (loaded >= capacity)
|
|
65
|
+
return false;
|
|
66
|
+
return isInfiniteReserve || reserve.current() > 0;
|
|
67
|
+
},
|
|
68
|
+
startReload() {
|
|
69
|
+
if (!this.canReload())
|
|
70
|
+
return false;
|
|
71
|
+
reloadElapsedMs = 0;
|
|
72
|
+
return true;
|
|
73
|
+
},
|
|
74
|
+
cancelReload() {
|
|
75
|
+
reloadElapsedMs = null;
|
|
76
|
+
},
|
|
77
|
+
addReserve(amount) {
|
|
78
|
+
if (amount > 0)
|
|
79
|
+
reserve.gain?.(amount);
|
|
80
|
+
},
|
|
81
|
+
tick(dtSeconds) {
|
|
82
|
+
if (dtSeconds <= 0 || reloadElapsedMs === null)
|
|
83
|
+
return;
|
|
84
|
+
reloadElapsedMs += dtSeconds * 1000;
|
|
85
|
+
if (reloadElapsedMs < reloadMs)
|
|
86
|
+
return;
|
|
87
|
+
const need = capacity - loaded;
|
|
88
|
+
if (need > 0) {
|
|
89
|
+
const take = isInfiniteReserve ? need : Math.min(need, reserve.current());
|
|
90
|
+
if (take > 0 && reserve.spend(take))
|
|
91
|
+
loaded = clampLoaded(loaded + take);
|
|
92
|
+
}
|
|
93
|
+
reloadElapsedMs = null;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BallisticSweep } from "../physics/ballisticSweep.js";
|
|
2
2
|
import type { EntityPosition } from "../scene/entityStore.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type EntityColliderSet } from "../scene/colliders.js";
|
|
4
4
|
import { type SceneRaycastApi } from "../scene/sceneRaycast.js";
|
|
5
5
|
import type { Aim } from "../scene/spatial.js";
|
|
6
6
|
import type { CombatSpatialDeps, EffectResult, EffectSystem, EffectVia } from "./effects.js";
|
|
@@ -10,7 +10,7 @@ export interface ProjectileShotInput {
|
|
|
10
10
|
via: EffectVia;
|
|
11
11
|
aim: Aim;
|
|
12
12
|
effect: string;
|
|
13
|
-
/** Defaults to `{ kind: "
|
|
13
|
+
/** Defaults to `{ kind: "eye" }` — aim.origin when given, else shooter position at eye height. */
|
|
14
14
|
originPolicy?: ShotOriginPolicy;
|
|
15
15
|
}
|
|
16
16
|
export interface EntityRaycastHit {
|
|
@@ -108,4 +108,9 @@ export interface ProjectileSystem {
|
|
|
108
108
|
fireProjectile(input: ProjectileShotInput): string;
|
|
109
109
|
settleProjectile(shotId: string): SettleResult;
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
|
|
113
|
+
*
|
|
114
|
+
* @capability projectiles spawn and advance projectiles with travel and hit resolution
|
|
115
|
+
*/
|
|
111
116
|
export declare function createProjectileSystem(deps: ProjectileSystemDeps): ProjectileSystem;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { defaultEntityColliders, resolveColliders } from "../scene/colliders.js";
|
|
1
2
|
import { createSceneRaycast, firstImpact, hitsUntilBlocked, } from "../scene/sceneRaycast.js";
|
|
2
|
-
import { aimDirection, aimSpreadDeg, resolveShot, } from "./shotOrigin.js";
|
|
3
|
+
import { aimDirection, aimSpreadDeg, convergeShot, resolveShot, } from "./shotOrigin.js";
|
|
3
4
|
const DEFAULT_RANGE = 100;
|
|
4
5
|
const DEFAULT_PROJECTILE_SPEED = 15;
|
|
5
6
|
const GRAVITY = 9.8;
|
|
@@ -66,11 +67,16 @@ function asSceneHits(hits) {
|
|
|
66
67
|
normal: [0, 1, 0],
|
|
67
68
|
}));
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
|
|
72
|
+
*
|
|
73
|
+
* @capability projectiles spawn and advance projectiles with travel and hit resolution
|
|
74
|
+
*/
|
|
69
75
|
export function createProjectileSystem(deps) {
|
|
70
76
|
const shots = new Map();
|
|
71
77
|
let shotCounter = 0;
|
|
72
78
|
const now = deps.now ?? (() => Date.now());
|
|
73
|
-
const defaultPolicy = deps.defaultOriginPolicy ?? { kind: "
|
|
79
|
+
const defaultPolicy = deps.defaultOriginPolicy ?? { kind: "converge" };
|
|
74
80
|
function itemStat(via, stat) {
|
|
75
81
|
return via.item === undefined ? null : deps.getStat(via.item, stat);
|
|
76
82
|
}
|
|
@@ -80,11 +86,25 @@ export function createProjectileSystem(deps) {
|
|
|
80
86
|
const spread = itemStat(via, "spread");
|
|
81
87
|
return spread === null ? aim : { ...aim, spread };
|
|
82
88
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
const shotOriginDeps = {
|
|
90
|
+
positionOf: deps.spatial.positionOf,
|
|
91
|
+
rotationYOf: deps.rotationYOf,
|
|
92
|
+
collidersOf: deps.entityCollidersOf,
|
|
93
|
+
};
|
|
94
|
+
function resolveShotFor(from, aim, policy, range) {
|
|
95
|
+
const active = policy ?? defaultPolicy;
|
|
96
|
+
if (active.kind === "converge") {
|
|
97
|
+
return convergeShot(shotOriginDeps, from, aim, range, (origin, direction) => {
|
|
98
|
+
const all = internalSceneRaycast.raycastAll({
|
|
99
|
+
origin,
|
|
100
|
+
direction,
|
|
101
|
+
maxDistance: range,
|
|
102
|
+
excludeInstanceIds: [from],
|
|
103
|
+
});
|
|
104
|
+
return hitsUntilBlocked(all)[0]?.point ?? null;
|
|
105
|
+
}, active.muzzle);
|
|
106
|
+
}
|
|
107
|
+
return resolveShot(shotOriginDeps, from, aim, active);
|
|
88
108
|
}
|
|
89
109
|
const internalSceneRaycast = deps.sceneRaycast ??
|
|
90
110
|
createSceneRaycast({
|
|
@@ -132,7 +152,7 @@ export function createProjectileSystem(deps) {
|
|
|
132
152
|
});
|
|
133
153
|
const raycast = deps.raycast ??
|
|
134
154
|
((from, aim, range, originPolicy) => {
|
|
135
|
-
const resolved = resolveShotFor(from, aim, originPolicy);
|
|
155
|
+
const resolved = resolveShotFor(from, aim, originPolicy, range);
|
|
136
156
|
if (resolved === null)
|
|
137
157
|
return [];
|
|
138
158
|
const { origin, direction } = resolved;
|
|
@@ -149,15 +169,26 @@ export function createProjectileSystem(deps) {
|
|
|
149
169
|
if (hit.targetKind === "entity" && spreadRad > 0) {
|
|
150
170
|
const position = deps.spatial.positionOf(hit.instanceId);
|
|
151
171
|
if (position !== undefined) {
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
const
|
|
172
|
+
const colliders = resolveColliders(deps.entityCollidersOf?.(hit.instanceId) ?? defaultEntityColliders());
|
|
173
|
+
const collider = colliders.find((candidate) => candidate.name === hit.colliderName) ?? colliders[0];
|
|
174
|
+
const localOffset = collider?.shape.offset ?? [0, 0, 0];
|
|
175
|
+
const slack = collider === undefined
|
|
176
|
+
? BASE_HIT_RADIUS
|
|
177
|
+
: collider.shape.kind === "sphere"
|
|
178
|
+
? collider.shape.radius
|
|
179
|
+
: Math.hypot(...collider.shape.halfExtents);
|
|
180
|
+
const rotationY = deps.rotationYOf?.(hit.instanceId) ?? 0;
|
|
181
|
+
const cos = Math.cos(rotationY);
|
|
182
|
+
const sin = Math.sin(rotationY);
|
|
183
|
+
const dx = position[0] + localOffset[0] * cos + localOffset[2] * sin - origin[0];
|
|
184
|
+
const dy = position[1] + localOffset[1] - origin[1];
|
|
185
|
+
const dz = position[2] - localOffset[0] * sin + localOffset[2] * cos - origin[2];
|
|
155
186
|
const along = dx * direction[0] + dy * direction[1] + dz * direction[2];
|
|
156
187
|
const px = dx - direction[0] * along;
|
|
157
188
|
const py = dy - direction[1] * along;
|
|
158
189
|
const pz = dz - direction[2] * along;
|
|
159
190
|
const perpendicular = Math.sqrt(px * px + py * py + pz * pz);
|
|
160
|
-
if (perpendicular >
|
|
191
|
+
if (perpendicular > slack + Math.tan(spreadRad) * along)
|
|
161
192
|
continue;
|
|
162
193
|
}
|
|
163
194
|
}
|
|
@@ -172,7 +203,7 @@ export function createProjectileSystem(deps) {
|
|
|
172
203
|
return itemStat(via, "projectile.fuseTime") !== null || itemStat(via, "explosion.radius") !== null;
|
|
173
204
|
}
|
|
174
205
|
function ballisticArc(input) {
|
|
175
|
-
const resolved = resolveShotFor(input.from, input.aim, input.originPolicy);
|
|
206
|
+
const resolved = resolveShotFor(input.from, input.aim, input.originPolicy, resolveRange(input.via));
|
|
176
207
|
const origin = resolved?.origin ?? [0, 0, 0];
|
|
177
208
|
const direction = resolved?.direction ?? aimDirection(input.aim) ?? [0, 0, 1];
|
|
178
209
|
const speed = itemStat(input.via, "projectile.speed") ?? DEFAULT_PROJECTILE_SPEED;
|
|
@@ -210,7 +241,7 @@ export function createProjectileSystem(deps) {
|
|
|
210
241
|
}
|
|
211
242
|
function predictHits(input) {
|
|
212
243
|
const aim = withWeaponSpread(input.via, input.aim);
|
|
213
|
-
const resolved = resolveShotFor(input.from, aim, input.originPolicy);
|
|
244
|
+
const resolved = resolveShotFor(input.from, aim, input.originPolicy, resolveRange(input.via));
|
|
214
245
|
const rawHits = raycast(input.from, aim, resolveRange(input.via), input.originPolicy);
|
|
215
246
|
const visible = rawHits.filter((hit) => isObjectHit(hit) || deps.spatial.hasLineOfSight(input.from, hit.instanceId));
|
|
216
247
|
return {
|
|
@@ -221,10 +252,10 @@ export function createProjectileSystem(deps) {
|
|
|
221
252
|
};
|
|
222
253
|
}
|
|
223
254
|
function missPoint(input) {
|
|
224
|
-
const
|
|
255
|
+
const range = resolveRange(input.via);
|
|
256
|
+
const resolved = resolveShotFor(input.from, input.aim, input.originPolicy, range);
|
|
225
257
|
if (resolved === null)
|
|
226
258
|
return [0, 0, 0];
|
|
227
|
-
const range = resolveRange(input.via);
|
|
228
259
|
return [
|
|
229
260
|
resolved.origin[0] + resolved.direction[0] * range,
|
|
230
261
|
resolved.origin[1] + resolved.direction[1] * range,
|
|
@@ -262,7 +293,7 @@ export function createProjectileSystem(deps) {
|
|
|
262
293
|
return { status: "rejected", shotId, reason: "already-settled" };
|
|
263
294
|
shot.settled = true;
|
|
264
295
|
const { input } = shot;
|
|
265
|
-
const resolved = resolveShotFor(input.from, input.aim, input.originPolicy);
|
|
296
|
+
const resolved = resolveShotFor(input.from, input.aim, input.originPolicy, resolveRange(input.via));
|
|
266
297
|
const origin = resolved?.origin ?? [0, 0, 0];
|
|
267
298
|
const originTuple = [origin[0], origin[1], origin[2]];
|
|
268
299
|
if (isBallistic(input.via)) {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { DamageChannelId } from "./damageMatchup.js";
|
|
2
|
+
/**
|
|
3
|
+
* The facts a received-damage modifier predicates over: the incoming `channel`, who dealt it,
|
|
4
|
+
* the statuses the target currently carries, and any caller tags. All caller-owned strings; the
|
|
5
|
+
* engine never assigns meaning to a channel, source, status, or tag.
|
|
6
|
+
*/
|
|
7
|
+
export interface DamageContext {
|
|
8
|
+
channel: DamageChannelId;
|
|
9
|
+
/** Attacker/source id, when known. */
|
|
10
|
+
source?: string;
|
|
11
|
+
/** The receiving target's id. */
|
|
12
|
+
target: string;
|
|
13
|
+
/** Status ids currently on the target — lets a modifier fire only `whileStatus`. */
|
|
14
|
+
targetStatuses?: readonly string[];
|
|
15
|
+
/** Arbitrary caller tags on the hit (`"crit"`, `"melee"`, `"aoe"`). */
|
|
16
|
+
tags?: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A typed predicate over a {@link DamageContext}. Every listed facet must match (AND); a facet
|
|
20
|
+
* matches when the context value is in the list (channels/sources) or shares any member
|
|
21
|
+
* (targetStatuses/tags). An empty predicate matches every hit.
|
|
22
|
+
*/
|
|
23
|
+
export interface DamagePredicate {
|
|
24
|
+
/** Fire only for these channels. */
|
|
25
|
+
channels?: readonly DamageChannelId[];
|
|
26
|
+
/** Fire only for these attacker sources. */
|
|
27
|
+
sources?: readonly string[];
|
|
28
|
+
/** Fire only while the target carries one of these statuses. */
|
|
29
|
+
whileStatus?: readonly string[];
|
|
30
|
+
/** Fire only when the hit carries one of these tags. */
|
|
31
|
+
tags?: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a matched modifier does to the incoming amount. Amplification is one policy beside
|
|
35
|
+
* reduction — both are `scale` (factor `> 1` amplifies, `< 1` reduces). `cap`/`floor` clamp,
|
|
36
|
+
* `flat` adds/subtracts, `convert` moves a portion to another channel on the same target,
|
|
37
|
+
* `redirect` moves a portion to another target, and `immune` zeroes the hit outright.
|
|
38
|
+
*/
|
|
39
|
+
export type ReceivedPolicy = {
|
|
40
|
+
kind: "scale";
|
|
41
|
+
factor: number;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "flat";
|
|
44
|
+
delta: number;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "cap";
|
|
47
|
+
max: number;
|
|
48
|
+
} | {
|
|
49
|
+
kind: "floor";
|
|
50
|
+
min: number;
|
|
51
|
+
} | {
|
|
52
|
+
kind: "convert";
|
|
53
|
+
toChannel: DamageChannelId;
|
|
54
|
+
portion?: number;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "redirect";
|
|
57
|
+
toTarget: string;
|
|
58
|
+
portion?: number;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "immune";
|
|
61
|
+
};
|
|
62
|
+
/** One serializable receiver-side rule: an optional predicate, a policy, and an ordering key. */
|
|
63
|
+
export interface ReceivedModifier {
|
|
64
|
+
/** Stable id echoed in provenance; helps UI/debug attribute a change. */
|
|
65
|
+
id?: string;
|
|
66
|
+
/** When the modifier fires; omitted means always. */
|
|
67
|
+
when?: DamagePredicate;
|
|
68
|
+
policy: ReceivedPolicy;
|
|
69
|
+
/** Lower runs first; ties keep declaration order. Defaults to 0. */
|
|
70
|
+
order?: number;
|
|
71
|
+
}
|
|
72
|
+
/** One recorded transformation — the provenance a UI or debugger reads to explain a final number. */
|
|
73
|
+
export interface ReceivedStep {
|
|
74
|
+
modifierId: string | null;
|
|
75
|
+
kind: ReceivedPolicy["kind"];
|
|
76
|
+
before: number;
|
|
77
|
+
after: number;
|
|
78
|
+
/** Portion diverted to a redirect target or converted channel, when the policy did so. */
|
|
79
|
+
diverted?: number;
|
|
80
|
+
}
|
|
81
|
+
/** A portion of the hit sent elsewhere by a `redirect`/`convert` policy. */
|
|
82
|
+
export interface DamageDivert {
|
|
83
|
+
/** For a redirect: the receiving target. For a convert: unset. */
|
|
84
|
+
target?: string;
|
|
85
|
+
/** For a convert: the channel the portion becomes. For a redirect: unset. */
|
|
86
|
+
channel?: DamageChannelId;
|
|
87
|
+
amount: number;
|
|
88
|
+
}
|
|
89
|
+
/** The full, provenance-rich outcome of running received modifiers over one hit. */
|
|
90
|
+
export interface ReceivedDamageResult {
|
|
91
|
+
/** Final amount landing on the primary target/channel; never negative. */
|
|
92
|
+
amount: number;
|
|
93
|
+
/** True when an `immune` policy zeroed the hit. */
|
|
94
|
+
immune: boolean;
|
|
95
|
+
/** Portions redirected to other targets. */
|
|
96
|
+
redirects: DamageDivert[];
|
|
97
|
+
/** Portions converted to other channels on the same target. */
|
|
98
|
+
conversions: DamageDivert[];
|
|
99
|
+
/** Ordered record of every modifier that ran and what it changed. */
|
|
100
|
+
steps: ReceivedStep[];
|
|
101
|
+
}
|
|
102
|
+
/** The incoming amount, its {@link DamageContext}, and the receiver's modifier list to run over it. */
|
|
103
|
+
export interface ReceivedDamageInput {
|
|
104
|
+
amount: number;
|
|
105
|
+
context: DamageContext;
|
|
106
|
+
modifiers: readonly ReceivedModifier[];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Run receiver-side modifiers over an incoming hit, in ascending `order`, recording every step.
|
|
110
|
+
* Amplification, reduction, caps, conversion, redirection, and immunity are all data — the engine
|
|
111
|
+
* applies whichever policies the target's modifiers declare and never branches on channel names.
|
|
112
|
+
* Pure over serializable data with bounded work (one pass over the modifier list); an `immune`
|
|
113
|
+
* policy short-circuits the remaining modifiers.
|
|
114
|
+
*
|
|
115
|
+
* @capability received-damage apply data-defined receiver-side damage modifiers (amplify, reduce, cap, convert, redirect, immunity) with typed predicates
|
|
116
|
+
*/
|
|
117
|
+
export declare function resolveReceivedDamage(input: ReceivedDamageInput): ReceivedDamageResult;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
function sharesAny(a, b) {
|
|
2
|
+
if (a === undefined)
|
|
3
|
+
return false;
|
|
4
|
+
for (const value of a)
|
|
5
|
+
if (b.includes(value))
|
|
6
|
+
return true;
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
function matches(predicate, ctx) {
|
|
10
|
+
if (predicate === undefined)
|
|
11
|
+
return true;
|
|
12
|
+
if (predicate.channels !== undefined && !predicate.channels.includes(ctx.channel))
|
|
13
|
+
return false;
|
|
14
|
+
if (predicate.sources !== undefined && (ctx.source === undefined || !predicate.sources.includes(ctx.source))) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (predicate.whileStatus !== undefined && !sharesAny(ctx.targetStatuses, predicate.whileStatus))
|
|
18
|
+
return false;
|
|
19
|
+
if (predicate.tags !== undefined && !sharesAny(ctx.tags, predicate.tags))
|
|
20
|
+
return false;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run receiver-side modifiers over an incoming hit, in ascending `order`, recording every step.
|
|
25
|
+
* Amplification, reduction, caps, conversion, redirection, and immunity are all data — the engine
|
|
26
|
+
* applies whichever policies the target's modifiers declare and never branches on channel names.
|
|
27
|
+
* Pure over serializable data with bounded work (one pass over the modifier list); an `immune`
|
|
28
|
+
* policy short-circuits the remaining modifiers.
|
|
29
|
+
*
|
|
30
|
+
* @capability received-damage apply data-defined receiver-side damage modifiers (amplify, reduce, cap, convert, redirect, immunity) with typed predicates
|
|
31
|
+
*/
|
|
32
|
+
export function resolveReceivedDamage(input) {
|
|
33
|
+
const ctx = input.context;
|
|
34
|
+
const ordered = input.modifiers
|
|
35
|
+
.map((modifier, index) => ({ modifier, index }))
|
|
36
|
+
.filter((entry) => matches(entry.modifier.when, ctx))
|
|
37
|
+
.sort((a, b) => (a.modifier.order ?? 0) - (b.modifier.order ?? 0) || a.index - b.index);
|
|
38
|
+
let amount = Math.max(0, input.amount);
|
|
39
|
+
let immune = false;
|
|
40
|
+
const redirects = [];
|
|
41
|
+
const conversions = [];
|
|
42
|
+
const steps = [];
|
|
43
|
+
for (const { modifier } of ordered) {
|
|
44
|
+
const policy = modifier.policy;
|
|
45
|
+
const before = amount;
|
|
46
|
+
const id = modifier.id ?? null;
|
|
47
|
+
switch (policy.kind) {
|
|
48
|
+
case "scale":
|
|
49
|
+
amount = Math.max(0, amount * policy.factor);
|
|
50
|
+
steps.push({ modifierId: id, kind: "scale", before, after: amount });
|
|
51
|
+
break;
|
|
52
|
+
case "flat":
|
|
53
|
+
amount = Math.max(0, amount + policy.delta);
|
|
54
|
+
steps.push({ modifierId: id, kind: "flat", before, after: amount });
|
|
55
|
+
break;
|
|
56
|
+
case "cap":
|
|
57
|
+
amount = Math.min(amount, policy.max);
|
|
58
|
+
steps.push({ modifierId: id, kind: "cap", before, after: amount });
|
|
59
|
+
break;
|
|
60
|
+
case "floor":
|
|
61
|
+
amount = Math.max(amount, policy.min);
|
|
62
|
+
steps.push({ modifierId: id, kind: "floor", before, after: amount });
|
|
63
|
+
break;
|
|
64
|
+
case "convert": {
|
|
65
|
+
const portion = policy.portion ?? 1;
|
|
66
|
+
const moved = amount * Math.max(0, Math.min(1, portion));
|
|
67
|
+
amount -= moved;
|
|
68
|
+
if (moved > 0)
|
|
69
|
+
conversions.push({ channel: policy.toChannel, amount: moved });
|
|
70
|
+
steps.push({ modifierId: id, kind: "convert", before, after: amount, diverted: moved });
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "redirect": {
|
|
74
|
+
const portion = policy.portion ?? 1;
|
|
75
|
+
const moved = amount * Math.max(0, Math.min(1, portion));
|
|
76
|
+
amount -= moved;
|
|
77
|
+
if (moved > 0)
|
|
78
|
+
redirects.push({ target: policy.toTarget, amount: moved });
|
|
79
|
+
steps.push({ modifierId: id, kind: "redirect", before, after: amount, diverted: moved });
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "immune":
|
|
83
|
+
amount = 0;
|
|
84
|
+
immune = true;
|
|
85
|
+
steps.push({ modifierId: id, kind: "immune", before, after: 0 });
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (immune)
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
return { amount, immune, redirects, conversions, steps };
|
|
92
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Tuning for `createRegenShield`: pool size, refill rate, and the post-damage grace period. */
|
|
2
|
+
export interface RegenShieldConfig {
|
|
3
|
+
max: number;
|
|
4
|
+
/** Points restored per second once the post-damage grace period has elapsed. */
|
|
5
|
+
regenPerSecond: number;
|
|
6
|
+
/** Grace period after the last damage before regen resumes. */
|
|
7
|
+
regenDelayMs: number;
|
|
8
|
+
/** Starting value; defaults to `max` (full). */
|
|
9
|
+
current?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A shield pool that stops regenerating for `regenDelayMs` after every hit, then refills at
|
|
13
|
+
* `regenPerSecond` — the delayed-regen primitive that replaces snapshot-comparing stat values per
|
|
14
|
+
* tick to detect "damage taken" (#536.3). `damage` resets the grace timer; `tick` counts it down and
|
|
15
|
+
* regenerates once it elapses.
|
|
16
|
+
*/
|
|
17
|
+
export interface RegenShield {
|
|
18
|
+
current(): number;
|
|
19
|
+
max(): number;
|
|
20
|
+
setMax(value: number): void;
|
|
21
|
+
fraction(): number;
|
|
22
|
+
isFull(): boolean;
|
|
23
|
+
isBroken(): boolean;
|
|
24
|
+
/** True while the post-damage grace period is suppressing regen. */
|
|
25
|
+
suppressed(): boolean;
|
|
26
|
+
/** Absorb `amount` and reset the regen grace timer; returns damage that got through (0 while the shield holds). */
|
|
27
|
+
damage(amount: number): number;
|
|
28
|
+
/** Add `amount` without touching the regen timer (a pickup or scripted refill). */
|
|
29
|
+
restore(amount: number): void;
|
|
30
|
+
set(value: number): void;
|
|
31
|
+
/** Advance time: count down the grace period, then regenerate once it has elapsed. */
|
|
32
|
+
tick(dtSeconds: number): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Builds a {@link RegenShield} that suppresses regen for `regenDelayMs` after each hit.
|
|
36
|
+
*
|
|
37
|
+
* @capability regen-shield a rechargeable overshield that absorbs damage and refills after a lull
|
|
38
|
+
*/
|
|
39
|
+
export declare function createRegenShield(config: RegenShieldConfig): RegenShield;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a {@link RegenShield} that suppresses regen for `regenDelayMs` after each hit.
|
|
3
|
+
*
|
|
4
|
+
* @capability regen-shield a rechargeable overshield that absorbs damage and refills after a lull
|
|
5
|
+
*/
|
|
6
|
+
export function createRegenShield(config) {
|
|
7
|
+
let max = Math.max(0, config.max);
|
|
8
|
+
const regenPerSecond = Math.max(0, config.regenPerSecond);
|
|
9
|
+
const regenDelayMs = Math.max(0, config.regenDelayMs);
|
|
10
|
+
function clamp(value, ceiling) {
|
|
11
|
+
return Math.max(0, Math.min(ceiling, value));
|
|
12
|
+
}
|
|
13
|
+
let current = clamp(config.current ?? max, max);
|
|
14
|
+
let sinceDamageMs = regenDelayMs;
|
|
15
|
+
return {
|
|
16
|
+
current: () => current,
|
|
17
|
+
max: () => max,
|
|
18
|
+
setMax(value) {
|
|
19
|
+
max = Math.max(0, value);
|
|
20
|
+
current = clamp(current, max);
|
|
21
|
+
},
|
|
22
|
+
fraction: () => (max <= 0 ? 0 : current / max),
|
|
23
|
+
isFull: () => current >= max,
|
|
24
|
+
isBroken: () => current <= 0,
|
|
25
|
+
suppressed: () => sinceDamageMs < regenDelayMs,
|
|
26
|
+
damage(amount) {
|
|
27
|
+
if (amount <= 0)
|
|
28
|
+
return 0;
|
|
29
|
+
sinceDamageMs = 0;
|
|
30
|
+
const overflow = Math.max(0, amount - current);
|
|
31
|
+
current = clamp(current - amount, max);
|
|
32
|
+
return overflow;
|
|
33
|
+
},
|
|
34
|
+
restore(amount) {
|
|
35
|
+
if (amount > 0)
|
|
36
|
+
current = clamp(current + amount, max);
|
|
37
|
+
},
|
|
38
|
+
set(value) {
|
|
39
|
+
current = clamp(value, max);
|
|
40
|
+
},
|
|
41
|
+
tick(dtSeconds) {
|
|
42
|
+
if (dtSeconds <= 0)
|
|
43
|
+
return;
|
|
44
|
+
sinceDamageMs += dtSeconds * 1000;
|
|
45
|
+
if (sinceDamageMs >= regenDelayMs)
|
|
46
|
+
current = clamp(current + regenPerSecond * dtSeconds, max);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-entity render cues: the motion/animation signal a custom `renderEntity`
|
|
3
|
+
* or first-person viewmodel component needs to drive gait, muzzle flash,
|
|
4
|
+
* reload poses, and hit reactions — without diffing the parent group's
|
|
5
|
+
* position itself or reading a game-side module map for attack timing.
|
|
6
|
+
*/
|
|
7
|
+
export interface EntityRenderCues {
|
|
8
|
+
/** Horizontal ground speed in world units/sec (e.g. `groundSpeed(entity)`). */
|
|
9
|
+
speed: number;
|
|
10
|
+
/** 0..1 walk-cycle phase, advancing with `speed`; wraps every full stride. */
|
|
11
|
+
bobPhase: number;
|
|
12
|
+
/** True for a short pulse after a `"fire"` `entity.animation` event. */
|
|
13
|
+
firing: boolean;
|
|
14
|
+
/** True from a `"reload"` `entity.animation` event until `"reloadEnd"`. */
|
|
15
|
+
reloading: boolean;
|
|
16
|
+
/** 0..1 recoil kick, set to 1 on `"fire"` and decaying over time. */
|
|
17
|
+
recoil: number;
|
|
18
|
+
/** True for a short pulse after a `combat.hitReaction` event. */
|
|
19
|
+
hit: boolean;
|
|
20
|
+
/** True once `entity.died` fires for this instance; stays true. */
|
|
21
|
+
dead: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Neutral starting cue set: idle, unarmed, undamaged. */
|
|
24
|
+
export declare const DEFAULT_RENDER_CUES: Readonly<EntityRenderCues>;
|
|
25
|
+
/** Tuning knobs for `advanceMotionCues` / `useEntityRenderCues`; every field has a default, override only what a weapon/rig's feel needs to differ. */
|
|
26
|
+
export interface RenderCueTuning {
|
|
27
|
+
/** Bob-cycle phase advanced per world unit of travel. Default 0.6. */
|
|
28
|
+
cyclesPerUnit?: number;
|
|
29
|
+
/** Recoil decay toward 0, per second. Default 6. */
|
|
30
|
+
recoilDecayPerSecond?: number;
|
|
31
|
+
/** Seconds `firing` stays true after a `"fire"` event. Default 0.12. */
|
|
32
|
+
firePulseSeconds?: number;
|
|
33
|
+
/** Seconds `hit` stays true after a `combat.hitReaction` event. Default 0.2. */
|
|
34
|
+
hitPulseSeconds?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Default `RenderCueTuning.cyclesPerUnit`. */
|
|
37
|
+
export declare const DEFAULT_CYCLES_PER_UNIT = 0.6;
|
|
38
|
+
/** Default `RenderCueTuning.recoilDecayPerSecond`. */
|
|
39
|
+
export declare const DEFAULT_RECOIL_DECAY_PER_SECOND = 6;
|
|
40
|
+
/** Default `RenderCueTuning.firePulseSeconds`. */
|
|
41
|
+
export declare const DEFAULT_FIRE_PULSE_SECONDS = 0.12;
|
|
42
|
+
/** Default `RenderCueTuning.hitPulseSeconds`. */
|
|
43
|
+
export declare const DEFAULT_HIT_PULSE_SECONDS = 0.2;
|
|
44
|
+
/** Advances `bobPhase` and decays `recoil` from a live `speed` sample (e.g. `groundSpeed(entity)`); leaves event-driven fields untouched. */
|
|
45
|
+
export declare function advanceMotionCues(cues: EntityRenderCues, speed: number, dt: number, tuning?: RenderCueTuning): EntityRenderCues;
|
|
46
|
+
/** Applies a `entity.animation` event (`"fire"` / `"reload"` / `"reloadEnd"`, or any game-defined name) to the cue set. Unknown event names are a no-op. */
|
|
47
|
+
export declare function applyRenderAnimationEvent(cues: EntityRenderCues, event: string): EntityRenderCues;
|
|
48
|
+
/** Marks a `combat.hitReaction` pulse; the caller clears `hit` again after its own pulse window. */
|
|
49
|
+
export declare function applyRenderHitEvent(cues: EntityRenderCues): EntityRenderCues;
|
|
50
|
+
/** Marks the cue set dead after `entity.died`; sticky for the lifetime of the render component. */
|
|
51
|
+
export declare function applyRenderDeathEvent(cues: EntityRenderCues): EntityRenderCues;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Neutral starting cue set: idle, unarmed, undamaged. */
|
|
2
|
+
export const DEFAULT_RENDER_CUES = Object.freeze({
|
|
3
|
+
speed: 0,
|
|
4
|
+
bobPhase: 0,
|
|
5
|
+
firing: false,
|
|
6
|
+
reloading: false,
|
|
7
|
+
recoil: 0,
|
|
8
|
+
hit: false,
|
|
9
|
+
dead: false,
|
|
10
|
+
});
|
|
11
|
+
/** Default `RenderCueTuning.cyclesPerUnit`. */
|
|
12
|
+
export const DEFAULT_CYCLES_PER_UNIT = 0.6;
|
|
13
|
+
/** Default `RenderCueTuning.recoilDecayPerSecond`. */
|
|
14
|
+
export const DEFAULT_RECOIL_DECAY_PER_SECOND = 6;
|
|
15
|
+
/** Default `RenderCueTuning.firePulseSeconds`. */
|
|
16
|
+
export const DEFAULT_FIRE_PULSE_SECONDS = 0.12;
|
|
17
|
+
/** Default `RenderCueTuning.hitPulseSeconds`. */
|
|
18
|
+
export const DEFAULT_HIT_PULSE_SECONDS = 0.2;
|
|
19
|
+
/** Advances `bobPhase` and decays `recoil` from a live `speed` sample (e.g. `groundSpeed(entity)`); leaves event-driven fields untouched. */
|
|
20
|
+
export function advanceMotionCues(cues, speed, dt, tuning) {
|
|
21
|
+
const cyclesPerUnit = tuning?.cyclesPerUnit ?? DEFAULT_CYCLES_PER_UNIT;
|
|
22
|
+
const recoilDecayPerSecond = tuning?.recoilDecayPerSecond ?? DEFAULT_RECOIL_DECAY_PER_SECOND;
|
|
23
|
+
const bobPhase = speed > 0.05 ? (cues.bobPhase + speed * cyclesPerUnit * dt) % 1 : cues.bobPhase;
|
|
24
|
+
const recoil = Math.max(0, cues.recoil - recoilDecayPerSecond * dt);
|
|
25
|
+
return { ...cues, speed, bobPhase, recoil };
|
|
26
|
+
}
|
|
27
|
+
/** Applies a `entity.animation` event (`"fire"` / `"reload"` / `"reloadEnd"`, or any game-defined name) to the cue set. Unknown event names are a no-op. */
|
|
28
|
+
export function applyRenderAnimationEvent(cues, event) {
|
|
29
|
+
if (event === "fire")
|
|
30
|
+
return { ...cues, firing: true, recoil: 1 };
|
|
31
|
+
if (event === "reload")
|
|
32
|
+
return { ...cues, reloading: true };
|
|
33
|
+
if (event === "reloadEnd")
|
|
34
|
+
return { ...cues, reloading: false };
|
|
35
|
+
return cues;
|
|
36
|
+
}
|
|
37
|
+
/** Marks a `combat.hitReaction` pulse; the caller clears `hit` again after its own pulse window. */
|
|
38
|
+
export function applyRenderHitEvent(cues) {
|
|
39
|
+
return { ...cues, hit: true };
|
|
40
|
+
}
|
|
41
|
+
/** Marks the cue set dead after `entity.died`; sticky for the lifetime of the render component. */
|
|
42
|
+
export function applyRenderDeathEvent(cues) {
|
|
43
|
+
return { ...cues, dead: true };
|
|
44
|
+
}
|
|
@@ -17,4 +17,9 @@ export interface ResourcePool {
|
|
|
17
17
|
isFull(): boolean;
|
|
18
18
|
isEmpty(): boolean;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
|
|
22
|
+
*
|
|
23
|
+
* @capability resource-pool a regenerating pool like mana or stamina that actions spend from
|
|
24
|
+
*/
|
|
20
25
|
export declare function createResourcePool(config: ResourcePoolConfig): ResourcePool;
|