@jgengine/core 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -2
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/ai/spawnDirector.d.ts +7 -2
- package/dist/ai/spawnDirector.js +18 -15
- package/dist/ai/spawnPoint.d.ts +3 -1
- package/dist/ai/spawnPoint.js +3 -1
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/authoring.d.ts +2 -1
- package/dist/authoring.js +2 -1
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +5 -1
- package/dist/combat/dotField.js +5 -1
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +5 -0
- package/dist/combat/projectiles.js +32 -14
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +5 -1
- package/dist/combat/regenShield.js +5 -1
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +18 -1
- package/dist/combat/shotOrigin.js +39 -0
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +35 -0
- package/dist/combat.js +35 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +235 -7
- package/dist/editor/commands.js +82 -124
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +194 -13
- package/dist/editor/document.js +1166 -19
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +98 -6
- package/dist/editor/index.js +13 -2
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +250 -1
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/connectedPlayers.d.ts +6 -4
- package/dist/game/connectedPlayers.js +2 -2
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +110 -5
- package/dist/game/defineGame.js +49 -4
- package/dist/game/defineSystem.d.ts +90 -0
- package/dist/game/defineSystem.js +47 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +63 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +19 -2
- package/dist/game/lootTable.js +15 -5
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +116 -432
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +19 -0
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +30 -3
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +3 -1
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +93 -0
- package/dist/gameplay.js +93 -0
- package/dist/index.d.ts +5 -14
- package/dist/index.js +5 -14
- package/dist/input/actionBindings.d.ts +23 -6
- package/dist/input/actionBindings.js +23 -6
- package/dist/input/axisInput.d.ts +7 -2
- package/dist/input/axisInput.js +7 -2
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +2 -0
- package/dist/interaction/proximityPrompt.js +2 -0
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +6 -3
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +39 -2
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +50 -9
- package/dist/movement/movementModel.js +75 -29
- package/dist/movement/playerMovement.js +167 -12
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +16 -8
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +11 -1
- package/dist/multiplayer/presenceModel.js +17 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +31 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +108 -1
- package/dist/physics/kinematicVehicle.js +212 -15
- package/dist/physics/physicsWorld.d.ts +50 -12
- package/dist/physics/physicsWorld.js +120 -122
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +26 -1
- package/dist/random/rng.js +32 -9
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +20 -0
- package/dist/render/postProcessing.js +21 -1
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +55 -3
- package/dist/runtime/adapter.js +57 -1
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +130 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/scene.d.ts +59 -0
- package/dist/runtime/context/scene.js +291 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +157 -0
- package/dist/runtime/descriptors/features.d.ts +79 -0
- package/dist/runtime/descriptors/features.js +299 -0
- package/dist/runtime/gameContext.d.ts +2 -327
- package/dist/runtime/gameContext.js +273 -778
- package/dist/runtime/gameContextTypes.d.ts +467 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +62 -0
- package/dist/runtime/headlessRunner.js +45 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +11 -4
- package/dist/runtime/hostedGameRunner.js +27 -3
- package/dist/runtime/hostedWorldSession.d.ts +15 -5
- package/dist/runtime/hostedWorldSession.js +12 -4
- package/dist/runtime/inputSnapshot.d.ts +8 -3
- package/dist/runtime/inputSnapshot.js +6 -2
- package/dist/runtime/motionIntents.d.ts +11 -2
- package/dist/runtime/motionIntents.js +16 -2
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +7 -3
- package/dist/runtime/worldChannel.js +51 -6
- package/dist/runtime/worldMirror.d.ts +14 -2
- package/dist/runtime/worldMirror.js +15 -2
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +30 -7
- package/dist/runtime/worldReplication.js +41 -9
- package/dist/runtime/worldSnapshot.d.ts +42 -3
- package/dist/runtime/worldSnapshot.js +34 -7
- package/dist/scene/assetCatalog.d.ts +26 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +257 -0
- package/dist/scene/authoredTriggers.d.ts +219 -0
- package/dist/scene/authoredTriggers.js +454 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +67 -0
- package/dist/scene/colliders.d.ts +71 -1
- package/dist/scene/colliders.js +145 -1
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +18 -11
- package/dist/scene/entityStats.js +21 -16
- package/dist/scene/entityStore.d.ts +12 -1
- package/dist/scene/entityStore.js +15 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +256 -0
- package/dist/scene/sceneKinds.js +218 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/sceneRaycast.js +15 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +59 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +7 -0
- package/dist/store/observableKeyedStore.js +35 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -57
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +6 -3
- package/dist/tactics/fallingGrid.d.ts +4 -2
- package/dist/tactics/fallingGrid.js +4 -2
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +30 -11
- package/dist/ui/gameLayout.js +30 -11
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +38 -1
- package/dist/ui/hudLayout.js +220 -17
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +72 -0
- package/dist/world/authoredObjects.js +81 -0
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/features.d.ts +133 -10
- package/dist/world/features.js +66 -6
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathNetwork.d.ts +159 -0
- package/dist/world/pathNetwork.js +684 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +79 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +88 -0
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +8 -0
- package/dist/world/roads.js +38 -0
- package/dist/world/scatter.js +2 -20
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +29 -0
- package/dist/world/streets.js +55 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +627 -22
- package/dist/world/terrain.d.ts +164 -20
- package/dist/world/terrain.js +325 -41
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +141 -0
- package/dist/world.js +141 -0
- package/package.json +32 -8
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +54 -0
- package/skills/jgengine/api.md +527 -0
- package/skills/jgengine/capabilities.md +131 -0
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +38 -0
- package/skills/jgengine-combat/api.md +585 -0
- package/skills/jgengine-combat/capabilities.md +213 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/reference.md +108 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1920 -0
- package/skills/jgengine-gameplay/capabilities.md +454 -0
- package/skills/jgengine-gameplay/reference-systems.md +56 -0
- package/skills/jgengine-world/SKILL.md +51 -0
- package/skills/jgengine-world/api.md +3056 -0
- package/skills/jgengine-world/capabilities.md +476 -0
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +261 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -5389
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<!-- GENERATED by scripts/gen-capability-index.ts — do not edit. Regenerate: bun run gen:capabilities -->
|
|
2
|
+
|
|
3
|
+
# jgengine-combat — capability index
|
|
4
|
+
|
|
5
|
+
Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
|
|
6
|
+
|
|
7
|
+
## ability-bar — a bar of cooldown-gated abilities the player triggers by slot
|
|
8
|
+
|
|
9
|
+
- `createAbilityKit` (function) · `import { createAbilityKit } from "@jgengine/core/combat"`
|
|
10
|
+
|
|
11
|
+
## anti-one-shot — clamp a near-lethal hit to leave a health floor then grant recovery immunity
|
|
12
|
+
|
|
13
|
+
- `createAntiOneShotPolicy` (function) · `import { createAntiOneShotPolicy } from "@jgengine/core/combat"`
|
|
14
|
+
|
|
15
|
+
## capture-bonus-levels — convert wild level and capture effectiveness into bonus levels
|
|
16
|
+
|
|
17
|
+
- `captureBonusLevels` (function) · `import { captureBonusLevels } from "@jgengine/core/stats/spawnLevelStats"`
|
|
18
|
+
|
|
19
|
+
## capture-effectiveness-tame — apply capture effectiveness to grant and distribute bonus levels
|
|
20
|
+
|
|
21
|
+
- `applyCaptureEffectiveness` (function) · `import { applyCaptureEffectiveness } from "@jgengine/core/stats/spawnLevelStats"`
|
|
22
|
+
|
|
23
|
+
## cast-bar — run a channeled cast timer that movement or damage can interrupt
|
|
24
|
+
|
|
25
|
+
- `createCastRunner` (function) · `import { createCastRunner } from "@jgengine/core/combat"`
|
|
26
|
+
|
|
27
|
+
## charge-meter — fill a gauge toward named tier thresholds as a value accumulates
|
|
28
|
+
|
|
29
|
+
- `createAccumulatorMeter` (function) · `import { createAccumulatorMeter } from "@jgengine/core/combat"`
|
|
30
|
+
|
|
31
|
+
## combo-chain — advance a chained melee string from timed button inputs
|
|
32
|
+
|
|
33
|
+
- `createComboRunner` (function) · `import { createComboRunner } from "@jgengine/core/combat"`
|
|
34
|
+
|
|
35
|
+
## combo-points — build up and spend finisher/combo points
|
|
36
|
+
|
|
37
|
+
- `createComboPoints` (function) · `import { createComboPoints } from "@jgengine/core/combat"`
|
|
38
|
+
|
|
39
|
+
## damage-clamp — cap incoming damage per hit at a configured maximum
|
|
40
|
+
|
|
41
|
+
- `createDamageClamp` (function) · `import { createDamageClamp } from "@jgengine/core/combat"`
|
|
42
|
+
|
|
43
|
+
## damage-hit — resolve a full data-defined damage hit — matchup, impact, receiver modifiers, and status application — with provenance
|
|
44
|
+
|
|
45
|
+
- `resolveDamageHit` (function) · `import { resolveDamageHit } from "@jgengine/core/combat"`
|
|
46
|
+
|
|
47
|
+
## damage-interception — intercept a pending damage application before lethal resolution with ordered, inspectable stages
|
|
48
|
+
|
|
49
|
+
- `resolveDamage` (function) · `import { resolveDamage } from "@jgengine/core/combat"`
|
|
50
|
+
|
|
51
|
+
## damage-matchup — score a data-defined damage channel against a target's traits into independent typed multipliers
|
|
52
|
+
|
|
53
|
+
- `resolveMatchup` (function) · `import { resolveMatchup } from "@jgengine/core/combat"`
|
|
54
|
+
|
|
55
|
+
## damage-pipeline — install and remove ordered damage interceptors that transitions toggle at runtime
|
|
56
|
+
|
|
57
|
+
- `createDamagePipeline` (function) · `import { createDamagePipeline } from "@jgengine/core/combat"`
|
|
58
|
+
|
|
59
|
+
## death-system — resolve entity death and its on-death consequences
|
|
60
|
+
|
|
61
|
+
- `createDeathSystem` (function) · `import { createDeathSystem } from "@jgengine/core/combat"`
|
|
62
|
+
|
|
63
|
+
## dice-check — resolve a pass/fail roll against a target number with modifiers and crits
|
|
64
|
+
|
|
65
|
+
- `rollCheck` (function) · `import { rollCheck } from "@jgengine/core/combat"`
|
|
66
|
+
|
|
67
|
+
## domestic-level-spend — spend an earned post-capture level into a chosen stat under a cap
|
|
68
|
+
|
|
69
|
+
- `spendDomesticLevel` (function) · `import { spendDomesticLevel } from "@jgengine/core/stats/spawnLevelStats"`
|
|
70
|
+
|
|
71
|
+
## dot-field — track stacking damage-over-time effects and drain damage each frame
|
|
72
|
+
|
|
73
|
+
- `createDotField` (function) · `import { createDotField } from "@jgengine/core/combat"`
|
|
74
|
+
|
|
75
|
+
## downed-revive — a downed/bleed-out state teammates can revive before death
|
|
76
|
+
|
|
77
|
+
- `createDownedState` (function) · `import { createDownedState } from "@jgengine/core/combat"`
|
|
78
|
+
|
|
79
|
+
## encounter-active-phase — read the id of the phase an encounter is currently waiting on
|
|
80
|
+
|
|
81
|
+
- `activePhaseId` (function) · `import { activePhaseId } from "@jgengine/core/combat"`
|
|
82
|
+
|
|
83
|
+
## encounter-advance — step a hierarchical encounter, resolving predicate-gated completion, repeats, and nested advance with lifecycle events
|
|
84
|
+
|
|
85
|
+
- `updateEncounter` (function) · `import { updateEncounter } from "@jgengine/core/combat"`
|
|
86
|
+
|
|
87
|
+
## encounter-force-complete — externally complete an active encounter phase to drive scripted or failure-retry transitions
|
|
88
|
+
|
|
89
|
+
- `forceCompletePhase` (function) · `import { forceCompletePhase } from "@jgengine/core/combat"`
|
|
90
|
+
|
|
91
|
+
## encounter-inject-phase — dynamically insert a phase or branch into a running encounter, e.g. a boss on the final wave
|
|
92
|
+
|
|
93
|
+
- `injectPhase` (function) · `import { injectPhase } from "@jgengine/core/combat"`
|
|
94
|
+
|
|
95
|
+
## encounter-phase-status — read whether a specific encounter phase is pending, active, or complete
|
|
96
|
+
|
|
97
|
+
- `phaseStatus` (function) · `import { phaseStatus } from "@jgengine/core/combat"`
|
|
98
|
+
|
|
99
|
+
## encounter-predicates — gate encounter phase completion on timers, cleared spawns, metrics, events, or a quorum of conditions
|
|
100
|
+
|
|
101
|
+
- `BUILTIN_COMPLETION_PREDICATES` (const) · `import { BUILTIN_COMPLETION_PREDICATES } from "@jgengine/core/combat"`
|
|
102
|
+
|
|
103
|
+
## encounter-progress — read completed-vs-total progress across a hierarchical encounter for HUD or objective display
|
|
104
|
+
|
|
105
|
+
- `encounterProgress` (function) · `import { encounterProgress } from "@jgengine/core/combat"`
|
|
106
|
+
|
|
107
|
+
## encounter-spawn-providers — turn an entered encounter phase into spawn requests from authored scene points or an inline list
|
|
108
|
+
|
|
109
|
+
- `BUILTIN_SPAWN_PROVIDERS` (const) · `import { BUILTIN_SPAWN_PROVIDERS } from "@jgengine/core/combat"`
|
|
110
|
+
|
|
111
|
+
## encounter-start — enter the first phase of a hierarchical encounter and emit its opening spawn events
|
|
112
|
+
|
|
113
|
+
- `startEncounter` (function) · `import { startEncounter } from "@jgengine/core/combat"`
|
|
114
|
+
|
|
115
|
+
## encounter-state — create the serializable starting state of a hierarchical encounter sequence
|
|
116
|
+
|
|
117
|
+
- `createEncounterState` (function) · `import { createEncounterState } from "@jgengine/core/combat"`
|
|
118
|
+
|
|
119
|
+
## event-meter — a heat/streak gauge that builds from repeated hits and cools down over time
|
|
120
|
+
|
|
121
|
+
- `createEventMeter` (function) · `import { createEventMeter } from "@jgengine/core/combat"`
|
|
122
|
+
|
|
123
|
+
## immunity-window — reject damage during a per-target invulnerability window installed by transitions
|
|
124
|
+
|
|
125
|
+
- `createImmunityWindow` (function) · `import { createImmunityWindow } from "@jgengine/core/combat"`
|
|
126
|
+
|
|
127
|
+
## impact-feel — calibrated hitstop + trauma preset for a named impact event
|
|
128
|
+
|
|
129
|
+
- `impactPresets` (const) · `import { impactPresets } from "@jgengine/core/combat"`
|
|
130
|
+
- `resolveHitReaction` (function) · `import { resolveHitReaction } from "@jgengine/core/combat"`
|
|
131
|
+
|
|
132
|
+
## magazine — a weapon magazine with capacity, timed reload, and reserve-pool interaction
|
|
133
|
+
|
|
134
|
+
- `createMagazine` (function) · `import { createMagazine } from "@jgengine/core/combat"`
|
|
135
|
+
|
|
136
|
+
## parry-window — time a block/parry/i-frame defensive window against incoming hits
|
|
137
|
+
|
|
138
|
+
- `createDefensiveWindow` (function) · `import { createDefensiveWindow } from "@jgengine/core/combat"`
|
|
139
|
+
|
|
140
|
+
## portable-stat-pool — apply deterministic bounded resource changes through a caller-owned stat adapter
|
|
141
|
+
|
|
142
|
+
- `applyStatPoolDelta` (function) · `import { applyStatPoolDelta } from "@jgengine/core/combat"`
|
|
143
|
+
|
|
144
|
+
## projectiles — spawn and advance projectiles with travel and hit resolution
|
|
145
|
+
|
|
146
|
+
- `createProjectileSystem` (function) · `import { createProjectileSystem } from "@jgengine/core/combat"`
|
|
147
|
+
|
|
148
|
+
## received-damage — apply data-defined receiver-side damage modifiers (amplify, reduce, cap, convert, redirect, immunity) with typed predicates
|
|
149
|
+
|
|
150
|
+
- `resolveReceivedDamage` (function) · `import { resolveReceivedDamage } from "@jgengine/core/combat"`
|
|
151
|
+
|
|
152
|
+
## regen-shield — a rechargeable overshield that absorbs damage and refills after a lull
|
|
153
|
+
|
|
154
|
+
- `createRegenShield` (function) · `import { createRegenShield } from "@jgengine/core/combat"`
|
|
155
|
+
|
|
156
|
+
## resource-pool — a regenerating pool like mana or stamina that actions spend from
|
|
157
|
+
|
|
158
|
+
- `createResourcePool` (function) · `import { createResourcePool } from "@jgengine/core/combat"`
|
|
159
|
+
|
|
160
|
+
## reward-allocation — distribute reward results among multiplayer participants deterministically
|
|
161
|
+
|
|
162
|
+
- `allocateRewards` (function) · `import { allocateRewards } from "@jgengine/core/combat"`
|
|
163
|
+
- `filterOutcomeFor` (function) · `import { filterOutcomeFor } from "@jgengine/core/combat"`
|
|
164
|
+
- `resolveClaim` (function) · `import { resolveClaim } from "@jgengine/core/combat"`
|
|
165
|
+
|
|
166
|
+
## spawn-instance-restore — rehydrate a creature stat instance from decoded snapshot data
|
|
167
|
+
|
|
168
|
+
- `restoreSpawnInstance` (function) · `import { restoreSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
169
|
+
|
|
170
|
+
## spawn-instance-snapshot — deep-copy a creature stat instance into a serializable record
|
|
171
|
+
|
|
172
|
+
- `snapshotSpawnInstance` (function) · `import { snapshotSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
173
|
+
|
|
174
|
+
## spawn-level-roll — distribute a wild creature's spawn level into random per-stat points
|
|
175
|
+
|
|
176
|
+
- `rollSpawnInstance` (function) · `import { rollSpawnInstance } from "@jgengine/core/stats/spawnLevelStats"`
|
|
177
|
+
|
|
178
|
+
## spawn-stat-values — resolve a creature's per-stat values from its distributed points
|
|
179
|
+
|
|
180
|
+
- `resolveSpawnStats` (function) · `import { resolveSpawnStats } from "@jgengine/core/stats/spawnLevelStats"`
|
|
181
|
+
|
|
182
|
+
## stagger-meter — accumulate an ailment buildup (bleed, freeze) until it procs
|
|
183
|
+
|
|
184
|
+
- `createBuildupMeter` (function) · `import { createBuildupMeter } from "@jgengine/core/combat"`
|
|
185
|
+
- `createStaggerMeter` (function) · `import { createStaggerMeter } from "@jgengine/core/combat"`
|
|
186
|
+
|
|
187
|
+
## stat-block — base stats with stacking, expiring buffs and debuffs applied on read
|
|
188
|
+
|
|
189
|
+
- `createStats` (function) · `import { createStats } from "@jgengine/core/combat"`
|
|
190
|
+
|
|
191
|
+
## stat-pool — create a serializable current/min/max pool for any caller-named resource
|
|
192
|
+
|
|
193
|
+
- `createStatPool` (function) · `import { createStatPool } from "@jgengine/core/combat"`
|
|
194
|
+
|
|
195
|
+
## stat-pool-change — immutably increase or decrease any named bounded resource with clamp evidence
|
|
196
|
+
|
|
197
|
+
- `changeStatPool` (function) · `import { changeStatPool } from "@jgengine/core/combat"`
|
|
198
|
+
|
|
199
|
+
## stat-pool-patch — immutably retune a bounded resource's current value or bounds
|
|
200
|
+
|
|
201
|
+
- `patchStatPool` (function) · `import { patchStatPool } from "@jgengine/core/combat"`
|
|
202
|
+
|
|
203
|
+
## status-application — resolve a data-defined status application with chance, matchup scaling, and stacking policy
|
|
204
|
+
|
|
205
|
+
- `resolveStatusApplication` (function) · `import { resolveStatusApplication } from "@jgengine/core/combat"`
|
|
206
|
+
|
|
207
|
+
## status-effects — apply and tick timed status effects and buffs on entities
|
|
208
|
+
|
|
209
|
+
- `createEffectSystem` (function) · `import { createEffectSystem } from "@jgengine/core/combat"`
|
|
210
|
+
|
|
211
|
+
## threshold-crossings — emit ordered crossing events as a numeric source passes named thresholds with hysteresis and once/repeat policy
|
|
212
|
+
|
|
213
|
+
- `createThresholdTracker` (function) · `import { createThresholdTracker } from "@jgengine/core/combat"`
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Use JGengine stat pools with an existing save model
|
|
2
|
+
|
|
3
|
+
Use this recipe when a project already owns its entities and persistence but
|
|
4
|
+
needs deterministic bounded resources such as shields, energy, stamina, XP, or
|
|
5
|
+
durability. Resource names and meaning remain caller data; the portable
|
|
6
|
+
contract has no privileged health field.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
bun add @jgengine/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Import the focused, renderer-free module:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import {
|
|
18
|
+
applyStatPoolDelta,
|
|
19
|
+
createStatPool,
|
|
20
|
+
type StatPool,
|
|
21
|
+
type StatPoolAccess,
|
|
22
|
+
} from "@jgengine/core/stats/statPool";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`@jgengine/core` has no runtime dependencies and does not require a JGengine
|
|
26
|
+
entity store, game loop, renderer, React provider, or backend.
|
|
27
|
+
|
|
28
|
+
## Minimal adapter
|
|
29
|
+
|
|
30
|
+
Suppose the existing project saves resources inline on its own units:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
interface UnitSave {
|
|
34
|
+
id: string;
|
|
35
|
+
resources: Record<string, StatPool>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface WorldSave {
|
|
39
|
+
units: Record<string, UnitSave>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const world: WorldSave = {
|
|
43
|
+
units: {
|
|
44
|
+
rover: {
|
|
45
|
+
id: "rover",
|
|
46
|
+
resources: {
|
|
47
|
+
energy: createStatPool({ current: 8, max: 10 }),
|
|
48
|
+
durability: createStatPool({ max: 40 }),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const resources: StatPoolAccess = {
|
|
55
|
+
get(ownerId, statId) {
|
|
56
|
+
return world.units[ownerId]?.resources[statId] ?? null;
|
|
57
|
+
},
|
|
58
|
+
set(ownerId, statId, next) {
|
|
59
|
+
const unit = world.units[ownerId];
|
|
60
|
+
if (unit !== undefined) unit.resources[statId] = next;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The adapter performs structural reads and complete replacement writes. It does
|
|
66
|
+
not expose the caller's store implementation or hand mutation authority to the
|
|
67
|
+
engine.
|
|
68
|
+
|
|
69
|
+
## Apply a resource change
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const spent = applyStatPoolDelta(resources, "rover", "energy", -3);
|
|
73
|
+
|
|
74
|
+
if (spent.status === "ok") {
|
|
75
|
+
console.log(spent.pool.current); // 5
|
|
76
|
+
console.log(spent.applied); // -3 (after clamping)
|
|
77
|
+
console.log(spent.hitMin); // false
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Positive amounts increase a pool and negative amounts decrease it. The result
|
|
82
|
+
records the previous and next values, the exact clamped amount, and whether a
|
|
83
|
+
bound was reached. Missing owners or stat ids return a rejected result without
|
|
84
|
+
writing.
|
|
85
|
+
|
|
86
|
+
For reducer-style stores, call the pure `changeStatPool(pool, amount)` or
|
|
87
|
+
`patchStatPool(pool, patch)` transition inside the project's existing action
|
|
88
|
+
and commit the returned `pool` through that store's normal update path.
|
|
89
|
+
|
|
90
|
+
## Save and restore
|
|
91
|
+
|
|
92
|
+
`StatPool` is plain JSON data, so keep it in the project's existing save:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const serialized = JSON.stringify(world);
|
|
96
|
+
const restored = JSON.parse(serialized) as WorldSave;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
After restore, point the same adapter at `restored`. There is no second JGengine
|
|
100
|
+
snapshot to reconcile, no registry to rebuild, and no required migration away
|
|
101
|
+
from the caller's schema. If the existing schema uses different field names,
|
|
102
|
+
translate only at `get`/`set`.
|
|
103
|
+
|
|
104
|
+
## Ownership
|
|
105
|
+
|
|
106
|
+
The existing project owns resource ids, entity ids, storage layout,
|
|
107
|
+
persistence, replication, authority, UI, scheduling, and the decision to apply
|
|
108
|
+
a change. JGengine owns normalization, clamping, pure transitions, and the
|
|
109
|
+
small structural access contract. Native JGengine entity stats implement the
|
|
110
|
+
same portable behavior through their existing API.
|
|
111
|
+
|
|
112
|
+
## Common traps
|
|
113
|
+
|
|
114
|
+
- Do not copy caller resources into a parallel `StatValueMap`; adapt the state
|
|
115
|
+
where it already lives.
|
|
116
|
+
- Do not mutate the object returned by `get`. Commit the complete returned
|
|
117
|
+
`pool` through `set` or the caller's reducer/action.
|
|
118
|
+
- Pool changes are signed: positive restores/fills, negative spends/drains.
|
|
119
|
+
- Keep formulas, regeneration schedules, damage meaning, and resource names in
|
|
120
|
+
caller code. A stat pool only enforces bounds.
|
|
121
|
+
- Persist `current`, `max`, and `min` together so a restored value is clamped
|
|
122
|
+
against the same bounds.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# jgengine domain API — Combat
|
|
2
|
+
|
|
3
|
+
Reference module for the [`jgengine-combat` API](SKILL.md) skill. Load this when you need the combat surface — effects, projectiles, death, feel, and abilities.
|
|
4
|
+
|
|
5
|
+
## Portable named resources
|
|
6
|
+
|
|
7
|
+
`StatPool` (`@jgengine/core/stats/statPool`) is the plain
|
|
8
|
+
`{ current, max, min }` model for any caller-named bounded resource. Existing
|
|
9
|
+
projects implement the two-method `StatPoolAccess` over their own ECS, reducer,
|
|
10
|
+
or save model, then use `applyStatPoolDelta`; reducer-style integrations use
|
|
11
|
+
the pure `createStatPool` / `patchStatPool` / `changeStatPool` transitions.
|
|
12
|
+
Native scene entity stats are a compatibility bridge over the same model. See
|
|
13
|
+
the [portable stat-pool recipe](recipes/portable-stat-pools.md) for complete
|
|
14
|
+
imports, adapter code, ownership, and JSON save/restore.
|
|
15
|
+
|
|
16
|
+
## Effects and projectiles
|
|
17
|
+
|
|
18
|
+
Effect ids are **game-defined strings**. Magnitudes **drain** stats: positive subtracts down `receive.<effect>.order` (spilling to the next stat in the order), negative restores. Heals pass a negative amount (`via: { amount: -flashHeal }`, typically read from a `weapon.heal` stat).
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
ctx.scene.entity.canReceive(instanceId, effect, magnitude?) // null | reason — reads catalog receive
|
|
22
|
+
ctx.scene.entity.preview({ from, to, effect, via }) // magnitude, no state change
|
|
23
|
+
ctx.scene.entity.effect({ from, to, effect, via }) // single target
|
|
24
|
+
ctx.scene.entity.effect({ from, effect, via, at, radius, falloff?, los? }) // AoE at a point
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
AoE: `inRadius(at, radius)` → LoS filter (default on) → `canReceive` per target → absorption; `falloff: "linear" | "none"`. `via` = `{ item }` (magnitude from weapon stats) or `{ amount }`. `canReceive`'s `pools-depleted` reason checks headroom in the effect's direction: a positive (draining) magnitude needs a stat above its min, a negative (restorative) magnitude needs a stat below its max — so a heal can still raise a stat sitting at its minimum. Omitting `magnitude` assumes the draining direction.
|
|
28
|
+
|
|
29
|
+
`canReceive`'s optional signed `magnitude` makes the check direction-aware: positive (or omitted) keeps the standard `"pools-depleted"` check; negative checks the opposite direction and returns `"pools-full"` only when every stat in the receive order is already at max — so a heal (`via: { amount: -n }`) correctly reaches a fully-depleted target and is rejected only when there's nothing left to restore.
|
|
30
|
+
|
|
31
|
+
**Projectiles** (aim-based — no target ids):
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
willHitProjectile({ from, via, aim, effect }) // prediction only, for crosshair UI
|
|
35
|
+
fireProjectile({ from, via, aim, effect }) // → shotId (pending)
|
|
36
|
+
settleProjectile(shotId) // authoritative → { at, hits } | rejection
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`Aim = { origin, direction } | { yaw, pitch, spread? }`. A free `{ yaw, pitch }` aim defaults to `converge`: the bullet leaves the gun `muzzle` (so a tracer visibly comes from the barrel, not the camera) yet bends toward whatever the eye ray's crosshair covers, so the reticle stays truth. An explicit `{ origin, direction }` aim (enemy AI, turrets) passes through unchanged. Shot origin otherwise resolves via `ShotOriginPolicy` (`eye`: shooter position raised to eye height — 90% of the shooter's own hitbox top when colliders are known, ~1.6m otherwise — so shots trace the sightline and the crosshair is truth; `muzzle`/`camera`/`world` for custom rigs, `legacy` = raw entity position). Hitboxes auto-fit the rendered model: an entity kind mapped in `entityModels` (or an object catalog id in `objectModels`) gets a grounded AABB matching its model's measured bounds — footprint x height composed with `scale`/`targetHeight` exactly like the renderer — so the damage box equals the visual without hand-tuning. Unmodeled entities keep the body-covering humanoid AABB default (feet to ~1.8m); unmodeled objects with a `visual.scale` get a matching grounded physical body. Catalog assets opted into `COLLISION_MESH_ASSET_IDS` (`@jgengine/assets`) go one step further: the fit raycasts the asset's actual triangles (BVH over a quantized mesh shipped in the index), so a shot through a torus hole or archway passes clean instead of hitting the fitted box — same shape on client and headless host. Explicit catalog `colliders`/`halfExtents` and per-instance `setColliders` always override the fit. Hitscan settles into per-hit effects; ballistic shots (`weapon.projectile` with `fuseTime`/`settleOn`) settle to a landing point — the handler then calls `effect({ at: settle.at, radius })`. Settling twice rejects. Prediction is never authority.
|
|
40
|
+
|
|
41
|
+
Raycasts are **object-aware**: the default raycast checks placed scene objects as well as entities, discriminated by `RaycastHit.kind` (`"entity" | "object"` — an `ObjectRaycastHit` also carries `catalogId`). A crate or wall between shooter and target blocks or absorbs the shot instead of every projectile passing through scenery; supply `ProjectileSystemDeps.objects` (`{ list(), halfExtents?(catalogId) }`, matching `ObjectStore.list()` structurally) to opt in, with a `[0.5, 0.5, 0.5]` half-extent default per object.
|
|
42
|
+
|
|
43
|
+
## Death
|
|
44
|
+
|
|
45
|
+
Resolved **once** by the engine when the last stat in the receive order hits min. No HP polling in `onTick`, ever.
|
|
46
|
+
|
|
47
|
+
- `entity.died` is emitted (before despawn — handlers can still read the victim's stats), then reason-matching `onDeath` entries run.
|
|
48
|
+
- `DeathReason = { kind: "player_kill", killerUserId, via? } | { kind: "environment", source } | { kind: "self", source }`. Kills by the local player attribute automatically.
|
|
49
|
+
- `onDeath.drops` tables are rolled and **granted to the killer** on player kills (emits `loot.granted`) when `onDeath.dropMode` is `"grant"` (default); `onDeath.command` runs through `ctx.game.commands`.
|
|
50
|
+
- `onDeath.dropMode: "world"` routes item drops through a scatter impulse into ground `worldItem`s instead of straight to inventory (currency drops still grant directly) — tune the impulse with `onDeath.scatter: { radius, minRadius?, height? }` (defaults from `game/worldItem`'s `DEFAULT_SCATTER`).
|
|
51
|
+
- Respawning under the same instance id revives it (it can die again). Same-id respawn must not happen synchronously inside the `entity.died` handler — defer a tick.
|
|
52
|
+
- `quest.bind("entity.died")` credits kill objectives from the same event; leaderboards and kill feeds hang off it too.
|
|
53
|
+
|
|
54
|
+
## Damage interception and threshold transitions
|
|
55
|
+
|
|
56
|
+
Two genre-agnostic seams that sit **before** lethal resolution and drive **phase** logic, so games never hand-code "crossed threshold" branches or a boss-only invuln path. Both are pure/serializable `@jgengine/core/combat` factories.
|
|
57
|
+
|
|
58
|
+
- **Interception pipeline** (`combat/damageInterceptors`) — `resolveDamage(interceptors, pending, ctx)` runs a `PendingDamage` through an ordered list; each `DamageInterceptor.intercept` returns `pass | transform | clamp | redirect | split | defer | reject`, and every decision lands in `DamageResolution.provenance` (no hidden callbacks). Split parts continue at the *next* interceptor and total work is capped by `MAX_INTERCEPT_STEPS`, so redirect/split can't recurse. `createDamagePipeline()` is the mutable install/remove chain a transition toggles (`install`/`remove`/`has`). `ctx` carries `nowMs` (deterministic clock) and optional `healthOf(target)`.
|
|
59
|
+
- **Reusable policies** — `createDamageClamp({ maxPerHit })` caps a hit; `createImmunityWindow(id)` is a per-target invuln window (`grant`/`grantFor`/`active`/`clear`/`clearExpired`, `snapshot`/`restore`) installed and removed by transitions — i-frames and phase invuln are ordinary policies, not a boss branch; `createAntiOneShotPolicy({ guardAboveFraction, leaveFraction, recoverMs })` is the "cannot cross lethal while above X, leave Y, recover for Z" composition (clamps the killing blow to a health floor, then arms recovery immunity).
|
|
60
|
+
- **Threshold crossings** (`combat/thresholdCrossings`) — `createThresholdTracker({ thresholds, trigger?, hysteresis?, policy?, initial? })` watches any numeric source (boss HP %, stamina, armor, an objective counter). `update(value)` returns ordered `ThresholdCrossing[]` with `direction` (`falling`/`rising`), honoring `trigger` filtering, a `hysteresis` dead-band, `once`/`repeat` policy, and skipped-threshold handling (a single big jump emits every mark it passed, in travel order). `snapshot`/`restore` round-trip the sides + once-ledger for save/load. Wire crossings to whatever a phase owns — installing an immunity interceptor, swapping AI, music, objectives. Non-health consumers (resource warnings) use the same tracker.
|
|
61
|
+
## Reward allocation (multiplayer distribution)
|
|
62
|
+
|
|
63
|
+
Generation and allocation are different operations. A loot table (`@jgengine/core/game/lootTable`) or any roll produces `RewardResult`s; `@jgengine/core/combat`'s `allocateRewards(kind, request)` then decides **who gets what** among participants — the co-op question single-player kills never ask. It is deterministic and serializable: the same seeds, recipients, and results yield a byte-identical `AllocationOutcome` on host and every peer regardless of join order, so allocation replicates as data without re-rolling.
|
|
64
|
+
|
|
65
|
+
- Policies (`kind`): `instanced` (each recipient rolls its own results from a stable per-id stream — private by default), `copy` (full copy to everyone), `shared` (weight-split one count with a conserving largest-remainder distribution), `roundRobin` (one result each in deterministic rotation), `assigned` (caller `assignment` map), `claimed` (defer results into a `ClaimablePool`).
|
|
66
|
+
- Keep `allocationSeed` (ordering, splits, rotation, reservation) separate from `generationSeed` (per-recipient `instanced` rolls) so a late joiner never perturbs existing players' rolls. Recipient order is seed-shuffled, never input order.
|
|
67
|
+
- Claims resolve authoritatively via `resolveClaim(pool, claimantId, { nowMs })` — idempotent (re-claiming your own pool re-returns the same grants), with eligibility, `reservedFor`, and `expiresAtMs` enforced by the authority, not UI hiding. `first` pools are open/contested; `reserved` pools tie to one recipient (personal quest reward).
|
|
68
|
+
- `filterOutcomeFor(outcome, viewerId)` is the replication filter: private grants for other recipients and pools the viewer cannot claim are dropped, so private rewards never leak. Provenance (`grant.via`) survives projection.
|
|
69
|
+
- Works for any reward, not just items — split XP/currency by contribution weight the same way.
|
|
70
|
+
|
|
71
|
+
## Combat feel (melee, defense, telegraphs)
|
|
72
|
+
|
|
73
|
+
Layered on top of effects/projectiles/death — none of it replaces them, it adds **feel**. All models are renderer-free pure `@jgengine/core` factories a game composes per entity (like the `ctx`-vs-factory split above); the shell renders the telegraphs, styled damage numbers, hitstop shake.
|
|
74
|
+
|
|
75
|
+
- **Animation state machine** (`combat/animationState`) is the root the rest hangs on. A `AnimationClip` is catalog data — `{ frames, fps, ranges }` where each `FrameRange` tags a window `windup | active | recovery | cancel` (cancel may overlap recovery). `createAnimationState({ clips })` gives a per-entity SM: `play(clipId)`, `tick(dt)` → `{ entered, exited, completed }`, and queries combat/defense subscribe to — `inPhase("active")`, `isActive()`, `canCancel()`, `activeWindowMs()`. Frame ranges are the "commit frame" contract for delayed/feinted attacks.
|
|
76
|
+
- **Attack tags** (`combat/attackTags`) — `attackMeta(["unblockable" | "thrust" | "sweep" | "grab" | …], { effect, power })`. Defense logic reads them: `isBlockable`, `isParryable`, `isDodgeable`, `counters(meta, "mikiri")`. A grab beats all defenses; an unblockable is parry/dodge-only.
|
|
77
|
+
- **Defensive window** (`combat/defensiveWindow`) — a parry/block/dodge with `{ startupMs, activeMs, recoveryMs, iframes }`. `resolveDefense({ config, elapsedMs, attack })` is the pure overlap of the defender's window against the moment the attacker's `active` frames land → `parry | block | iframe | hit`. `createDefensiveWindow(config)` tracks the open time (`open(now)` / `evaluate(now, attack)` / `isInvulnerable(now)`).
|
|
78
|
+
- **Combo strings** (`combat/comboString`) — `ComboStep`s with `cancelInto` + `cancelPhases` + optional `stance`, over the anim SM. `advanceCombo(...)` (pure) accepts the next attack only inside the current step's cancel window and matching stance; `createComboRunner(combo, anim)` drives the SM.
|
|
79
|
+
- **Meters share one accumulator** (`stats/accumulatorMeter`) — `createAccumulatorMeter({ max, mode: "hold" | "reset", decayPerSecond, decayDelayMs, tiers })`: fill via `add(n)` → `MeterAddResult { fired, overflow, tier, tierChanged }`, `tick(dt)` decays after an idle grace, reading its current tier off the pure `tierAt(value, tiers)` lookup. `combat/breakMeters` builds two on it: `createStaggerMeter` (mode `hold` — fills from hits, `broke()` stays true until `recover()` after a riposte/deathblow) and `createBuildupMeter` (mode `reset` — `add(n)` returns a `BuildupProc { status, durationMs }` at threshold for bleed/frost/rot, then decays). The same base backs G6's ult/streak meters.
|
|
80
|
+
- **Delayed-regen shield** (`combat/regenShield`) — `createRegenShield(config)` is a shield pool that pauses regen for `regenDelayMs` after every hit, then refills at `regenPerSecond`; `damage`/`tick` replace snapshot-comparing a stat to detect "took damage."
|
|
81
|
+
- **DoT field** (`combat/dotField`) — `createDotField()` schedules recurring damage-over-time instances (bleed/poison/burn) keyed by id; `tick` drains due damage per interval. Pairs with `combat/breakMeters`' `BuildupProc` — a fired buildup applies a DoT instead of one-shot damage.
|
|
82
|
+
- **Magazine** (`combat/magazine`) — `createMagazine({ capacity, reloadMs, loaded?, reserve? })` is the per-weapon mag-size/reload/reserve-pool primitive (#536.2): `fire(rounds?)` spends loaded ammo, `startReload()`/`tick(dt)` run the timed refill, `canFire`/`canReload`/`isEmpty`/`isFull`/`reloadFraction` drive the HUD. `reserve` is a plain number for a self-contained pool, a `MagazineReserve` (`{ current, spend, gain? }`) to bridge reload draws into an externally-owned pool (a shared ammo-type stat, another `ResourcePool`), or omitted for an infinite reserve.
|
|
83
|
+
- **Dash / dodge** (`movement/dash`) — `createDashState({ distance, durationMs, iframes, staminaCost, staminaMax, staminaRegenPerSecond, cooldownMs })`: `tryDash(dir, now)` → burst or `{ reason: "no-stamina" | "cooldown" | "dashing" }`, `isInvulnerable(now)` for the i-frame window, `offset(now)` for the burst displacement, `tick(dt, now)` regens stamina.
|
|
84
|
+
- **Hit reaction** (`combat/hitReaction`) — `resolveHitReaction(config, { attackerPos, targetPos, power })` (pure) → `{ hitstopMs, impulse, shake, trauma, timescale }`. `config` is a raw `HitReactionConfig` **or** a named `impactPresets` event — `resolveHitReaction("explosion", input)` gives calibrated hitstop + trauma with zero hand-tuning (`pickup` 0.15 / `jumpLand` 0.2 / `enemyKilled` 0.3 @ 40ms hitstop / `playerHit` 0.4 @ 70ms / `explosion` 0.7 @ 90ms, heavy hits at `timescale: 0.05`; trauma clamps to 1.0). Wired on `ctx`: `ctx.scene.entity.hitReaction({ from, to, config, power? })` knocks the target back and emits `combat.hitReaction` with `trauma` set when the config resolved from `trauma` — the shell's `CombatCameraShake` feeds it into the trauma² camera-shake channel (`@jgengine/shell/camera`'s `traumaShake`; see `jgengine-ui`), or reads `shake` for the amplitude/decay channel when `config.shake` is set instead.
|
|
85
|
+
- **Render cues** (`combat/renderCues`, #542) - the pure math behind a custom `renderEntity`/viewmodel rig's motion feel: `EntityRenderCues { speed, bobPhase, firing, reloading, recoil, hit, dead }`, `advanceMotionCues(cues, speed, dt, tuning?)` advances `bobPhase`/decays `recoil` from a live `groundSpeed(entity)` sample, `applyRenderAnimationEvent(cues, event)` folds in `"fire"` / `"reload"` / `"reloadEnd"` from `ctx.game.playEntityAnimation`, `applyRenderHitEvent`/`applyRenderDeathEvent` fold in `combat.hitReaction`/`entity.died`. `RenderCueTuning` overrides `cyclesPerUnit`/`recoilDecayPerSecond`/`firePulseSeconds`/`hitPulseSeconds`. A game never calls these directly — `@jgengine/shell/render`'s `useEntityRenderCues(instanceId)` (see `jgengine-ui`) wires all four into one ref-returning hook for `useFrame` consumers.
|
|
86
|
+
- **Telegraph** (`combat/telegraph`) — a `TelegraphShape` (`circle | ring | cone | line`) + `windupMs`. `ctx.scene.entity.telegraph({ from, shape, at, dir?, windupMs, kind?, effect? })` emits `combat.telegraph` for the shell to draw a ground decal that fills over the windup, and — if `effect` is bound — applies that effect to everyone inside the shape (`pointInTelegraph`) at activation. Returns a cancel handle. **Turn-scoped variant**, for tactics/turn-based enemy intents instead of a real-time windup: set `TelegraphConfig.turns` (a count of turns instead of `windupMs`), then read `telegraphTurnProgress(config, startedTurn, currentTurn)` (0..1 fill fraction), `telegraphFiredAtTurn(config, startedTurn, currentTurn)` (has it resolved), and `telegraphTurnsRemaining(config, startedTurn, currentTurn)` — the same "enemy will hit this tile" decal, advanced by `turnLoop.round()`/`active()` instead of a clock.
|
|
87
|
+
- **Damage-number typing** — `ctx.scene.entity.floatText({ …, crit?, element?, hitType?, scale? })` (and the `entity.floatText` event) carry hit metadata; the shell's `resolveFloatTextStyle` (`@jgengine/shell/world/floatTextStyle`) maps crit/element to color + scale + glow.
|
|
88
|
+
- **VFX — one-shot vs retained** — `ctx.scene.entity.vfx({ kind, color, from?, to?, radius?, durationMs? })` fires a **one-shot** burst (`combat.vfx`, `kind: projectile | beam | nova | glow | spark`) the shell renders once and expires. For a **long-lived** effect whose endpoints/params move over time (held beam, tether, zone, target line, looping emitter) use the retained registry `ctx.scene.entity.vfxInstance` (`createVfxInstanceStore`, `@jgengine/core/game/vfxInstance`): `upsert({ id?, kind, color, from?, to?, radius?, params?, ttlMs? })` creates or replaces by stable id, `update(id, patch)` nudges dynamic params (a missing id is a no-op, not a throw), `stop(id, { fadeMs? })` disposes with an optional fade, and `tick(now)` enforces the TTL heartbeat; `list()`/`count()` are for debug. Endpoints are `VfxRef`s — an entity **instance id** (the shell resolves its live pose each frame, so the effect follows a moving entity with no per-frame commands) or a fixed `[x, y, z]` world point. State is headless/serializable and the store is renderer-independent; each op emits `combat.vfxInstance` which the shell's `RetainedVfx` overlay binds to render resources (beam is the first shipped retained renderer). Call `vfxInstance.clear()` on scene/level reset. Duet Keys' prism beam is the first adopter (driven from its `onTick`).
|
|
89
|
+
|
|
90
|
+
## Abilities, resources, auto-target, resistance, run drafts
|
|
91
|
+
|
|
92
|
+
Genre systems layered over the same effects/projectiles/targeting/loot primitives — all renderer-free pure `@jgengine/core` factories a game holds per player and ticks on **game-time** `dt` (so pause/fast-forward carry through). The ability kit is deliberately **separate from inventory items**: an item is a stackable id, an ability slot is cooldown/charge/resource state the HUD's four slot-states bind to.
|
|
93
|
+
|
|
94
|
+
- **Ability kit** (`combat/abilityKit`) — `createAbilityKit([{ id, cooldownMs, chargesMax?, resourceCost?, castType?, flashMs? }])`. `state(id, resourceAvailable?)` → `AbilitySlotSnapshot { state: "ready" | "cooldown" | "no-resource" | "just-cast", charges, chargesMax, cooldownRemainingMs, cooldownFraction, justCast, ready }`; `cast(id, resourceAvailable?)` consumes a charge, starts the recharge, and flashes just-cast; `canCast` / `tick(dt)` / `reset` / `retuneSlot(id, { cooldownMs?, resourceCost? })` (rebalance a slot at runtime — patches the config in place without touching charges or an in-flight cooldown timer, returns `false` for an unknown slot). The kit is resource-**agnostic** — it reports `no-resource` by comparing `resourceCost` to a supplied `resourceAvailable` (a mana stat, or an ult meter), and never spends the resource itself; the game's handler spends it and calls `cast`. Charges recharge one at a time; the four states drive the hotbar slot art. Cooldowns tick on `dt`, so hang `kit.tick(dt)` in `onTick`.
|
|
95
|
+
- **Event-fed meters** (`stats/eventMeter`, built on `stats/accumulatorMeter`) — `createEventMeter({ max, mode, gains, resets?, tiers?, decayPerSecond? })`. `feed(tag, scale?)` maps a tagged combat event to a gain (or a reset when `tag ∈ resets`) → `EventMeterFeedResult { fired, ready, tier, tierChanged, reset }`. Mode `"hold"` is the **ult/adrenaline** economy — charges off `{ damageDealt, damageTaken, kill }` events, `ready()` at full, `consume()` spends it (Overwatch/Marvel Rivals). Mode `"reset"` is the **streak/combo** meter — builds on `kill`, resets on a break tag like `damageTaken`, climbs ascending `tiers` (Returnal adrenaline, DMC style rank). One primitive, two catalog configs.
|
|
96
|
+
- **Auto-target policy** (`scene/autoTarget`) — `selectAutoTarget(policy, fromId, deps)` / `createAutoTargeter(policy, deps)` evaluated each tick with zero input: `"nearest" | "farthest" | "random" | "strongest" | "weakest" | "first" | "last"`. `deps` supplies `candidates`/`distance` and optional `strength` (health/threat) + `progress` (path progress for first/last-on-path). Bullet-heaven auto-fire (Vampire Survivors nearest), Bloons tower priority (first/last on path). Feed the picked id to `abilityKit.cast` + `effect`.
|
|
97
|
+
- **Resistance matrix** (`combat/resistance`) — a damage-category × target-property table distinct from `combat/attackTags` (those are defense tags). `resolveResistance(matrix, category, targetProperties)` → `{ verdict: "immune" | "resist" | "normal" | "vulnerable", multiplier, immune }`; `resistanceScale` returns just the multiplier (default `immune:0, resist:0.5, normal:1, vulnerable:2`, overridable). Immune on any property wins; resists stack multiplicatively. Sits over the `receive` gate — the handler multiplies its effect `amount` by the scale (Bloons lead/camo immunities, elemental RPG weaknesses).
|
|
98
|
+
- **Run draft** (`game/runDraft`, built on `world/scatterItems` `pickWeighted` + `stats/statModifiers`) — `createRunModifierStack(offers)` accumulates stacking picks (`add`, `count`, `atMax`, `total(stat)` aggregating adds × exponentiated multiplies, `apply(stats)` onto a `createStats` source). `createRunDraft({ offers, rng? })` adds the pause-flow: `present(n)` draws N distinct weighted offers (excluding maxed-out ones), `choose(id)` applies to the stack. Pause/resume is game-side (`ctx.time.pause()` before `present`, `play()` after `choose`). Vampire Survivors level-up picks, Hades boons, Risk of Rain stacking items.
|
|
99
|
+
|
|
100
|
+
## Encounter sequencing
|
|
101
|
+
|
|
102
|
+
`combat/encounterSequence` is the genre-agnostic hierarchical sequencer behind arenas, raids, tutorials, races, defense phases, and scripted objectives — a serializable state machine over caller-defined phase `data` with **no built-in wave/boss concept**. State is plain JSON (the working tree, per-node runtime, active path, elapsed) so a mid-encounter save round-trips; the predicate/spawn registries live in the config you re-supply alongside it, the way `advanceSpawnDirector` pairs config with state.
|
|
103
|
+
|
|
104
|
+
- **Tree + lifecycle** — `createEncounterState(config)` deep-copies the authored phase tree (unique ids enforced) and leaves it pending; `startEncounter` enters the first leaf; `updateEncounter(config, state, dt, ctx)` advances one bounded step, emitting provenance-rich `enter`/`spawn`/`complete`/`done` events. A group (has `children`) runs them in order and completes when they do — plus its own predicate if set (survive-the-timer-while-adds-run); a leaf without a predicate is an immediate marker. `activePhaseId` / `phaseStatus` / `encounterProgress` drive the HUD. A phase that spawns is deferred one tick before it can complete, so freshly-spawned "cleared" gates never satisfy against stale counts.
|
|
105
|
+
- **Completion predicates** — `completion: { kind, params }` names a registered evaluator; `BUILTIN_COMPLETION_PREDICATES` ships `immediate`, `manual`/`flag`, `timer` (phase seconds), `cleared` (tagged count drained), `metric` (live threshold), `event` (cumulative count), and `quorum` (N of nested predicates). Signals (`counts`/`metrics`/`events`/`flags`) come in through `ctx.signals`; evaluation is deterministic. Register your own via `config.predicates`.
|
|
106
|
+
- **Spawn providers** — spawning is one optional node adapter: `spawn: { kind, params }` invoked on enter. `BUILTIN_SPAWN_PROVIDERS.points` reads a named authored scene point list from `ctx.spawnPoints` (coordinates stay in the scene, referenced by key — never embedded in the sequence); `list` echoes inline requests. Register catalog/director-backed providers via `config.spawnProviders`.
|
|
107
|
+
- **Injection & scripted control** — `injectPhase(state, phase, { after | before | childOf })` inserts a phase or branch at runtime (e.g. a boss after the final wave) into the serializable tree without disturbing active/completed nodes; `forceCompletePhase` completes the active phase regardless of its predicate for scripted skips and failure/retry, restoring the authored predicate afterward.
|
|
108
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jgengine-gameplay
|
|
3
|
+
description: Compose serializable game state, systems, progression, and non-combat rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JGengine gameplay
|
|
7
|
+
|
|
8
|
+
## Ownership
|
|
9
|
+
|
|
10
|
+
This skill owns non-combat rules and state: systems, catalogs, inventory/items, crafting, economy, quests, dialogue, social state, puzzles, survival, turns, tactics, sessions, and saveable game models. Combat math belongs to `jgengine-combat`; host persistence adapters belong to `jgengine-multiplayer`.
|
|
11
|
+
|
|
12
|
+
Use [capabilities.md](capabilities.md) for intent discovery, [api.md](api.md) for signatures, and [reference-systems.md](reference-systems.md) for scheduling details before hand-rolling a subsystem.
|
|
13
|
+
|
|
14
|
+
## Canonical workflow
|
|
15
|
+
|
|
16
|
+
1. Define plain serializable state and stable ids.
|
|
17
|
+
2. Put definitions in typed catalogs; keep per-instance mutable state separate.
|
|
18
|
+
3. Express behavior as narrow systems or pure transitions with explicit inputs.
|
|
19
|
+
4. Route player/AI intent through commands; emit typed results/events.
|
|
20
|
+
5. Attach save/restore boundaries and versioning where state persists.
|
|
21
|
+
6. Bind UI through selectors/hooks rather than duplicating state.
|
|
22
|
+
|
|
23
|
+
Prefer `defineSystem` and `defineGame({ systems })` for scheduled capabilities. Keep boot/join in the game loop only when it is truly lifecycle glue. System ordering, frequency, and serialization are explicit; avoid a giant per-frame callback.
|
|
24
|
+
|
|
25
|
+
## Design rules
|
|
26
|
+
|
|
27
|
+
- Caller data owns nouns, formulas, tables, costs, tiers, and content.
|
|
28
|
+
- Pure-data operations are the reusable core; stateful conveniences wrap them.
|
|
29
|
+
- Transactions validate before mutation and return inspectable outcomes.
|
|
30
|
+
- Random selection accepts injected RNG and stable ordering.
|
|
31
|
+
- Large collections use indexes, queues, or bounded reconciliation rather than repeated scans.
|
|
32
|
+
|
|
33
|
+
## Traps
|
|
34
|
+
|
|
35
|
+
- A bare export mention is not an example; use capabilities for discovery and real imports/tests for adoption.
|
|
36
|
+
- Do not invent a parallel store when an existing game-context feature owns the state.
|
|
37
|
+
- Do not fuse save semantics with a specific cloud/backend adapter.
|
|
38
|
+
- Targeting, damage, effects, abilities, and loot resolution route to `jgengine-combat`.
|
|
39
|
+
- World movement/input/interaction route to `jgengine-world`; HUD rendering routes to `jgengine-ui`.
|