@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,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reusable bridge from typed runtime events to effects. A triggered rule is pure data — which
|
|
3
|
+
* event it listens to, a declarative predicate over the event facts, how the affected target is
|
|
4
|
+
* resolved, an effect *reference* (never a callback), and how the resulting effect is gated, lived,
|
|
5
|
+
* and stacked. Affixes, talents, perks, quests, achievements, environment rules, and reactive AI all
|
|
6
|
+
* subscribe through this one seam instead of owning parallel trigger runtimes.
|
|
7
|
+
*
|
|
8
|
+
* Core stays decoupled from any specific effect system: `dispatch` returns provenance-rich firings
|
|
9
|
+
* and the game applies them to whatever effect/stat system it owns. Gate state (cooldowns, rate
|
|
10
|
+
* windows, remaining charges) and active timed effects serialize cleanly so future triggers survive
|
|
11
|
+
* save/load.
|
|
12
|
+
*/
|
|
13
|
+
import { evaluatePredicate, readPath } from "./predicate.js";
|
|
14
|
+
function roleId(event, role, owner) {
|
|
15
|
+
switch (role) {
|
|
16
|
+
case "subject":
|
|
17
|
+
return event.subject;
|
|
18
|
+
case "object":
|
|
19
|
+
return event.object;
|
|
20
|
+
case "source":
|
|
21
|
+
return event.source;
|
|
22
|
+
case "owner":
|
|
23
|
+
return owner;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function resolveTarget(rule, event) {
|
|
27
|
+
const selector = rule.target ?? { role: "subject" };
|
|
28
|
+
if ("literal" in selector)
|
|
29
|
+
return selector.literal;
|
|
30
|
+
if ("path" in selector) {
|
|
31
|
+
const value = readPath(event.facts ?? {}, selector.path);
|
|
32
|
+
return typeof value === "string" ? value : undefined;
|
|
33
|
+
}
|
|
34
|
+
return roleId(event, selector.role, rule.owner);
|
|
35
|
+
}
|
|
36
|
+
function cooldownKey(ruleId, target) {
|
|
37
|
+
return `${ruleId}\u0000${target}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create an empty triggered-rule engine. Rules are added as data; dispatching an event returns the
|
|
41
|
+
* firings the caller applies to its own effect system. Time is caller-supplied (`now` in ms), so the
|
|
42
|
+
* engine is deterministic and drives equally from a fixed-step loop or a save-restored timeline.
|
|
43
|
+
*
|
|
44
|
+
* @capability triggered-rules event-conditioned effects with declarative predicates, lifetimes, and stacking
|
|
45
|
+
*/
|
|
46
|
+
export function createTriggeredRuleEngine(rules = []) {
|
|
47
|
+
const ruleList = [];
|
|
48
|
+
const ruleIndex = new Map();
|
|
49
|
+
const remainingCharges = new Map();
|
|
50
|
+
const lastFire = new Map();
|
|
51
|
+
const fireWindows = new Map();
|
|
52
|
+
let active = [];
|
|
53
|
+
let seq = 0;
|
|
54
|
+
function indexRules() {
|
|
55
|
+
ruleIndex.clear();
|
|
56
|
+
for (let i = 0; i < ruleList.length; i++)
|
|
57
|
+
ruleIndex.set(ruleList[i].id, i);
|
|
58
|
+
}
|
|
59
|
+
function add(rule) {
|
|
60
|
+
const existing = ruleIndex.get(rule.id);
|
|
61
|
+
if (existing !== undefined)
|
|
62
|
+
ruleList[existing] = rule;
|
|
63
|
+
else
|
|
64
|
+
ruleList.push(rule);
|
|
65
|
+
indexRules();
|
|
66
|
+
if (rule.charges !== undefined)
|
|
67
|
+
remainingCharges.set(rule.id, rule.charges);
|
|
68
|
+
else
|
|
69
|
+
remainingCharges.delete(rule.id);
|
|
70
|
+
}
|
|
71
|
+
for (const rule of rules)
|
|
72
|
+
add(rule);
|
|
73
|
+
function dropRuleState(ruleId) {
|
|
74
|
+
remainingCharges.delete(ruleId);
|
|
75
|
+
fireWindows.delete(ruleId);
|
|
76
|
+
for (const key of [...lastFire.keys()]) {
|
|
77
|
+
if (key.startsWith(`${ruleId}\u0000`))
|
|
78
|
+
lastFire.delete(key);
|
|
79
|
+
}
|
|
80
|
+
active = active.filter((instance) => instance.ruleId !== ruleId);
|
|
81
|
+
}
|
|
82
|
+
function passesRate(rule, now) {
|
|
83
|
+
if (rule.rateLimit === undefined)
|
|
84
|
+
return true;
|
|
85
|
+
const window = fireWindows.get(rule.id) ?? [];
|
|
86
|
+
const cutoff = now - rule.rateLimit.windowMs;
|
|
87
|
+
const kept = window.filter((stamp) => stamp > cutoff);
|
|
88
|
+
fireWindows.set(rule.id, kept);
|
|
89
|
+
return kept.length < rule.rateLimit.count;
|
|
90
|
+
}
|
|
91
|
+
function recordFire(rule, target, now) {
|
|
92
|
+
lastFire.set(cooldownKey(rule.id, target), now);
|
|
93
|
+
if (rule.rateLimit !== undefined) {
|
|
94
|
+
const window = fireWindows.get(rule.id) ?? [];
|
|
95
|
+
window.push(now);
|
|
96
|
+
fireWindows.set(rule.id, window);
|
|
97
|
+
}
|
|
98
|
+
if (rule.charges !== undefined) {
|
|
99
|
+
remainingCharges.set(rule.id, (remainingCharges.get(rule.id) ?? 0) - 1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function applyTimed(rule, target, now) {
|
|
103
|
+
const duration = rule.durationMs;
|
|
104
|
+
const policy = rule.stacking ?? "refresh";
|
|
105
|
+
const expiresAt = now + duration;
|
|
106
|
+
if (policy !== "independent") {
|
|
107
|
+
const current = active.find((instance) => instance.ruleId === rule.id && instance.target === target);
|
|
108
|
+
if (current !== undefined) {
|
|
109
|
+
if (policy === "ignore")
|
|
110
|
+
return { blocked: "stack-ignored" };
|
|
111
|
+
const stacks = policy === "stack" ? Math.min(current.stacks + 1, Math.max(1, rule.maxStacks ?? 1)) : 1;
|
|
112
|
+
const updated = { ...current, expiresAt, stacks, appliedAt: now };
|
|
113
|
+
active = active.map((instance) => (instance === current ? updated : instance));
|
|
114
|
+
return { instanceId: updated.instanceId, stacks };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const instanceId = `${rule.id}#${seq++}`;
|
|
118
|
+
active.push({
|
|
119
|
+
instanceId,
|
|
120
|
+
ruleId: rule.id,
|
|
121
|
+
effectId: rule.effect.id,
|
|
122
|
+
owner: rule.owner,
|
|
123
|
+
target,
|
|
124
|
+
params: rule.effect.params,
|
|
125
|
+
appliedAt: now,
|
|
126
|
+
expiresAt,
|
|
127
|
+
stacks: 1,
|
|
128
|
+
});
|
|
129
|
+
return { instanceId, stacks: 1 };
|
|
130
|
+
}
|
|
131
|
+
function evaluate(rule, event, now) {
|
|
132
|
+
const base = { ruleId: rule.id, event: event.type, owner: rule.owner, effect: rule.effect, at: now };
|
|
133
|
+
if (!evaluatePredicate(rule.when, event.facts ?? {}))
|
|
134
|
+
return { ...base, target: "", blocked: "predicate" };
|
|
135
|
+
const target = resolveTarget(rule, event);
|
|
136
|
+
if (target === undefined || target === "")
|
|
137
|
+
return { ...base, target: "", blocked: "no-target" };
|
|
138
|
+
if (rule.charges !== undefined && (remainingCharges.get(rule.id) ?? 0) <= 0)
|
|
139
|
+
return { ...base, target, blocked: "no-charges" };
|
|
140
|
+
if (rule.cooldownMs !== undefined) {
|
|
141
|
+
const last = lastFire.get(cooldownKey(rule.id, target));
|
|
142
|
+
if (last !== undefined && now - last < rule.cooldownMs)
|
|
143
|
+
return { ...base, target, blocked: "cooldown" };
|
|
144
|
+
}
|
|
145
|
+
if (!passesRate(rule, now))
|
|
146
|
+
return { ...base, target, blocked: "rate-limit" };
|
|
147
|
+
if (rule.durationMs !== undefined) {
|
|
148
|
+
const outcome = applyTimed(rule, target, now);
|
|
149
|
+
if ("blocked" in outcome)
|
|
150
|
+
return { ...base, target, blocked: outcome.blocked };
|
|
151
|
+
recordFire(rule, target, now);
|
|
152
|
+
return { ...base, target, instanceId: outcome.instanceId, stacks: outcome.stacks };
|
|
153
|
+
}
|
|
154
|
+
recordFire(rule, target, now);
|
|
155
|
+
return { ...base, target };
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
add,
|
|
159
|
+
remove(ruleId) {
|
|
160
|
+
const index = ruleIndex.get(ruleId);
|
|
161
|
+
if (index === undefined)
|
|
162
|
+
return;
|
|
163
|
+
ruleList.splice(index, 1);
|
|
164
|
+
indexRules();
|
|
165
|
+
dropRuleState(ruleId);
|
|
166
|
+
},
|
|
167
|
+
removeByOwner(owner) {
|
|
168
|
+
const removed = ruleList.filter((rule) => rule.owner === owner).map((rule) => rule.id);
|
|
169
|
+
if (removed.length === 0) {
|
|
170
|
+
active = active.filter((instance) => instance.owner !== owner);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
for (let i = ruleList.length - 1; i >= 0; i--) {
|
|
174
|
+
if (ruleList[i].owner === owner)
|
|
175
|
+
ruleList.splice(i, 1);
|
|
176
|
+
}
|
|
177
|
+
indexRules();
|
|
178
|
+
for (const ruleId of removed)
|
|
179
|
+
dropRuleState(ruleId);
|
|
180
|
+
active = active.filter((instance) => instance.owner !== owner);
|
|
181
|
+
},
|
|
182
|
+
rules: () => ruleList.slice(),
|
|
183
|
+
dispatch(event, now) {
|
|
184
|
+
const firings = [];
|
|
185
|
+
for (const rule of ruleList) {
|
|
186
|
+
if (rule.event !== event.type)
|
|
187
|
+
continue;
|
|
188
|
+
firings.push(evaluate(rule, event, now));
|
|
189
|
+
}
|
|
190
|
+
return firings;
|
|
191
|
+
},
|
|
192
|
+
tick(now) {
|
|
193
|
+
const expired = active.filter((instance) => instance.expiresAt <= now);
|
|
194
|
+
if (expired.length > 0)
|
|
195
|
+
active = active.filter((instance) => instance.expiresAt > now);
|
|
196
|
+
return expired;
|
|
197
|
+
},
|
|
198
|
+
active: () => active.slice(),
|
|
199
|
+
activeFor: (target) => active.filter((instance) => instance.target === target),
|
|
200
|
+
clearActive() {
|
|
201
|
+
active = [];
|
|
202
|
+
},
|
|
203
|
+
reset() {
|
|
204
|
+
remainingCharges.clear();
|
|
205
|
+
lastFire.clear();
|
|
206
|
+
fireWindows.clear();
|
|
207
|
+
active = [];
|
|
208
|
+
for (const rule of ruleList) {
|
|
209
|
+
if (rule.charges !== undefined)
|
|
210
|
+
remainingCharges.set(rule.id, rule.charges);
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
snapshot() {
|
|
214
|
+
return {
|
|
215
|
+
seq,
|
|
216
|
+
rules: ruleList.map((rule) => ({ ...rule })),
|
|
217
|
+
charges: Object.fromEntries(remainingCharges),
|
|
218
|
+
cooldowns: Object.fromEntries(lastFire),
|
|
219
|
+
windows: Object.fromEntries([...fireWindows].map(([id, stamps]) => [id, stamps.slice()])),
|
|
220
|
+
active: active.map((instance) => ({ ...instance })),
|
|
221
|
+
};
|
|
222
|
+
},
|
|
223
|
+
hydrate(state) {
|
|
224
|
+
ruleList.length = 0;
|
|
225
|
+
for (const rule of state.rules)
|
|
226
|
+
ruleList.push({ ...rule });
|
|
227
|
+
indexRules();
|
|
228
|
+
remainingCharges.clear();
|
|
229
|
+
for (const [id, value] of Object.entries(state.charges))
|
|
230
|
+
remainingCharges.set(id, value);
|
|
231
|
+
lastFire.clear();
|
|
232
|
+
for (const [key, value] of Object.entries(state.cooldowns))
|
|
233
|
+
lastFire.set(key, value);
|
|
234
|
+
fireWindows.clear();
|
|
235
|
+
for (const [id, stamps] of Object.entries(state.windows))
|
|
236
|
+
fireWindows.set(id, stamps.slice());
|
|
237
|
+
active = state.active.map((instance) => ({ ...instance }));
|
|
238
|
+
seq = state.seq;
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
export type MultiplayerTopology = "shared" | "lobbies" | "private";
|
|
2
2
|
/**
|
|
3
|
-
* Where the world simulation is authoritative.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Where the world simulation is authoritative.
|
|
4
|
+
*
|
|
5
|
+
* - `"client"` (default when omitted) — **presence-only multiplayer**: each client runs its own `onTick` and
|
|
6
|
+
* syncs presence / feeds / chat. Not competitive-safe; do not treat it as a shared sim.
|
|
7
|
+
* - `"server"` — host-authoritative world replication: the host runs the loop; the shell mirrors the host's
|
|
8
|
+
* world into the local `ctx` instead of simulating locally.
|
|
9
|
+
*
|
|
10
|
+
* Prefer naming the product intent in game code: pass `authority: "server"` for shared worlds, leave unset or
|
|
11
|
+
* `"client"` only for co-op presence / lobbies that intentionally tick independently.
|
|
6
12
|
*/
|
|
7
13
|
export type MultiplayerAuthority = "server" | "client";
|
|
8
14
|
export type MultiplayerAdapterConfig = {
|
|
@@ -33,15 +39,36 @@ export type MultiplayerAdapterConfig = {
|
|
|
33
39
|
} | {
|
|
34
40
|
kind: "offline";
|
|
35
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* Convex transport. Omitting `authority` (or passing `"client"`) is **presence-only** — prefer
|
|
44
|
+
* `convexPresence()` to name that intent explicitly. Pass `{ authority: "server" }` for a shared,
|
|
45
|
+
* host-authoritative world — see `examples/HOSTED.md`.
|
|
46
|
+
*/
|
|
36
47
|
export declare function convex(config?: {
|
|
37
48
|
topology?: MultiplayerTopology;
|
|
38
49
|
authority?: MultiplayerAuthority;
|
|
39
50
|
}): MultiplayerAdapterConfig;
|
|
51
|
+
/** Presence-only Convex transport — each client runs its own `onTick`; only presence/feeds/chat sync. Sugar for `convex({ ...config, authority: "client" })`. */
|
|
52
|
+
export declare function convexPresence(config?: {
|
|
53
|
+
topology?: MultiplayerTopology;
|
|
54
|
+
}): MultiplayerAdapterConfig;
|
|
55
|
+
/**
|
|
56
|
+
* WebSocket transport. Omitting `authority` (or passing `"client"`) is **presence-only** — prefer
|
|
57
|
+
* `wsPresence()` to name that intent explicitly. Pass `{ authority: "server" }` for a shared,
|
|
58
|
+
* host-authoritative world — see `examples/HOSTED.md`.
|
|
59
|
+
*
|
|
60
|
+
* @capability multiplayer-ws server-hosted shared world over WebSocket — `multiplayer: ws({ authority: "server" })`
|
|
61
|
+
*/
|
|
40
62
|
export declare function ws(config?: {
|
|
41
63
|
topology?: MultiplayerTopology;
|
|
42
64
|
url?: string;
|
|
43
65
|
authority?: MultiplayerAuthority;
|
|
44
66
|
}): MultiplayerAdapterConfig;
|
|
67
|
+
/** Presence-only WebSocket transport — each client runs its own `onTick`; only presence/feeds/chat sync. Sugar for `ws({ ...config, authority: "client" })`. */
|
|
68
|
+
export declare function wsPresence(config?: {
|
|
69
|
+
topology?: MultiplayerTopology;
|
|
70
|
+
url?: string;
|
|
71
|
+
}): MultiplayerAdapterConfig;
|
|
45
72
|
export declare function fly(config: {
|
|
46
73
|
app: string;
|
|
47
74
|
topology?: MultiplayerTopology;
|
|
@@ -53,6 +80,11 @@ export declare function socketIo(config?: {
|
|
|
53
80
|
url?: string;
|
|
54
81
|
authority?: MultiplayerAuthority;
|
|
55
82
|
}): MultiplayerAdapterConfig;
|
|
83
|
+
/**
|
|
84
|
+
* Serverless peer-to-peer (WebRTC) session — one peer hosts, friends join by room code.
|
|
85
|
+
*
|
|
86
|
+
* @capability multiplayer-p2p serverless co-op over WebRTC — `multiplayer: p2p({ room })`
|
|
87
|
+
*/
|
|
56
88
|
export declare function p2p(config?: {
|
|
57
89
|
topology?: MultiplayerTopology;
|
|
58
90
|
room?: string;
|
|
@@ -66,6 +98,26 @@ export declare function lan(config?: {
|
|
|
66
98
|
}): MultiplayerAdapterConfig;
|
|
67
99
|
/** True when the adapter opts into host-authoritative world replication (`authority: "server"`). */
|
|
68
100
|
export declare function isServerAuthoritative(multiplayer: unknown): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Resolved authority for a multiplayer config.
|
|
103
|
+
* - `offline` / missing adapter → `null` (single-player; not multiplayer authority).
|
|
104
|
+
* - unset or `"client"` → `"client"` (presence-only; each client ticks).
|
|
105
|
+
* - `"server"` → host-authoritative shared sim.
|
|
106
|
+
*/
|
|
107
|
+
export declare function resolveAuthority(multiplayer: unknown): MultiplayerAuthority | null;
|
|
108
|
+
/**
|
|
109
|
+
* True when multiplayer is on but the world sim is not host-authoritative — presence/feeds/chat only.
|
|
110
|
+
* Equivalent to `resolveAuthority(m) === "client"`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function isPresenceOnly(multiplayer: unknown): boolean;
|
|
113
|
+
/** True for a single-player world — no adapter, or an explicit `offline()` one. Gates offline-only wiring like local whole-world save. */
|
|
114
|
+
export declare function isOffline(multiplayer: unknown): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Explicit single-player adapter. Solo games never need this — omitting `multiplayer` in the shell
|
|
117
|
+
* `defineGame` already defaults to offline; pass it only where an adapter value is structurally required.
|
|
118
|
+
*
|
|
119
|
+
* @capability multiplayer-offline explicit solo adapter — omit `multiplayer` instead; offline is the shell default
|
|
120
|
+
*/
|
|
69
121
|
export declare function offline(): MultiplayerAdapterConfig;
|
|
70
122
|
export declare function adapterOf(multiplayer: unknown): MultiplayerAdapterConfig | null;
|
|
71
123
|
export declare function multiplayerAdapterKind(multiplayer: unknown): string | null;
|
package/dist/runtime/adapter.js
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convex transport. Omitting `authority` (or passing `"client"`) is **presence-only** — prefer
|
|
3
|
+
* `convexPresence()` to name that intent explicitly. Pass `{ authority: "server" }` for a shared,
|
|
4
|
+
* host-authoritative world — see `examples/HOSTED.md`.
|
|
5
|
+
*/
|
|
1
6
|
export function convex(config) {
|
|
2
7
|
return { kind: "convex", topology: config?.topology ?? "shared", authority: config?.authority };
|
|
3
8
|
}
|
|
9
|
+
/** Presence-only Convex transport — each client runs its own `onTick`; only presence/feeds/chat sync. Sugar for `convex({ ...config, authority: "client" })`. */
|
|
10
|
+
export function convexPresence(config) {
|
|
11
|
+
return { kind: "convex", topology: config?.topology ?? "shared", authority: "client" };
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* WebSocket transport. Omitting `authority` (or passing `"client"`) is **presence-only** — prefer
|
|
15
|
+
* `wsPresence()` to name that intent explicitly. Pass `{ authority: "server" }` for a shared,
|
|
16
|
+
* host-authoritative world — see `examples/HOSTED.md`.
|
|
17
|
+
*
|
|
18
|
+
* @capability multiplayer-ws server-hosted shared world over WebSocket — `multiplayer: ws({ authority: "server" })`
|
|
19
|
+
*/
|
|
4
20
|
export function ws(config) {
|
|
5
21
|
return { kind: "ws", topology: config?.topology ?? "shared", url: config?.url, authority: config?.authority };
|
|
6
22
|
}
|
|
23
|
+
/** Presence-only WebSocket transport — each client runs its own `onTick`; only presence/feeds/chat sync. Sugar for `ws({ ...config, authority: "client" })`. */
|
|
24
|
+
export function wsPresence(config) {
|
|
25
|
+
return { kind: "ws", topology: config?.topology ?? "shared", url: config?.url, authority: "client" };
|
|
26
|
+
}
|
|
7
27
|
export function fly(config) {
|
|
8
28
|
return {
|
|
9
29
|
kind: "ws",
|
|
@@ -15,6 +35,11 @@ export function fly(config) {
|
|
|
15
35
|
export function socketIo(config) {
|
|
16
36
|
return { kind: "socketio", topology: config?.topology ?? "shared", url: config?.url, authority: config?.authority };
|
|
17
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Serverless peer-to-peer (WebRTC) session — one peer hosts, friends join by room code.
|
|
40
|
+
*
|
|
41
|
+
* @capability multiplayer-p2p serverless co-op over WebRTC — `multiplayer: p2p({ room })`
|
|
42
|
+
*/
|
|
18
43
|
export function p2p(config) {
|
|
19
44
|
return { kind: "p2p", topology: config?.topology ?? "private", room: config?.room, authority: config?.authority };
|
|
20
45
|
}
|
|
@@ -23,9 +48,40 @@ export function lan(config) {
|
|
|
23
48
|
}
|
|
24
49
|
/** True when the adapter opts into host-authoritative world replication (`authority: "server"`). */
|
|
25
50
|
export function isServerAuthoritative(multiplayer) {
|
|
51
|
+
return resolveAuthority(multiplayer) === "server";
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolved authority for a multiplayer config.
|
|
55
|
+
* - `offline` / missing adapter → `null` (single-player; not multiplayer authority).
|
|
56
|
+
* - unset or `"client"` → `"client"` (presence-only; each client ticks).
|
|
57
|
+
* - `"server"` → host-authoritative shared sim.
|
|
58
|
+
*/
|
|
59
|
+
export function resolveAuthority(multiplayer) {
|
|
60
|
+
const adapter = adapterOf(multiplayer);
|
|
61
|
+
if (adapter === null || adapter.kind === "offline")
|
|
62
|
+
return null;
|
|
63
|
+
if ("authority" in adapter && adapter.authority === "server")
|
|
64
|
+
return "server";
|
|
65
|
+
return "client";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* True when multiplayer is on but the world sim is not host-authoritative — presence/feeds/chat only.
|
|
69
|
+
* Equivalent to `resolveAuthority(m) === "client"`.
|
|
70
|
+
*/
|
|
71
|
+
export function isPresenceOnly(multiplayer) {
|
|
72
|
+
return resolveAuthority(multiplayer) === "client";
|
|
73
|
+
}
|
|
74
|
+
/** True for a single-player world — no adapter, or an explicit `offline()` one. Gates offline-only wiring like local whole-world save. */
|
|
75
|
+
export function isOffline(multiplayer) {
|
|
26
76
|
const adapter = adapterOf(multiplayer);
|
|
27
|
-
return adapter
|
|
77
|
+
return adapter === null || adapter.kind === "offline";
|
|
28
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Explicit single-player adapter. Solo games never need this — omitting `multiplayer` in the shell
|
|
81
|
+
* `defineGame` already defaults to offline; pass it only where an adapter value is structurally required.
|
|
82
|
+
*
|
|
83
|
+
* @capability multiplayer-offline explicit solo adapter — omit `multiplayer` instead; offline is the shell default
|
|
84
|
+
*/
|
|
29
85
|
export function offline() {
|
|
30
86
|
return { kind: "offline" };
|
|
31
87
|
}
|
|
@@ -12,4 +12,5 @@ export type RunCommandResult = {
|
|
|
12
12
|
ok: false;
|
|
13
13
|
reason: string;
|
|
14
14
|
};
|
|
15
|
+
/** @internal */
|
|
15
16
|
export declare function runCommand<TInput>(snapshot: import("./snapshot.js").GameRuntimeSnapshot, commands: Record<string, CommandDef<TInput>>, commandName: string, input: TInput, actorUserId: string): RunCommandResult;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type DeathSystem } from "../../combat/death.js";
|
|
2
|
+
import { type CombatSpatialDeps, type EffectSystem } from "../../combat/effects.js";
|
|
3
|
+
import { type ProjectileSystem } from "../../combat/projectiles.js";
|
|
4
|
+
import type { PhysicsConfig } from "../../game/defineGame.js";
|
|
5
|
+
import type { GameEvents } from "../../game/events.js";
|
|
6
|
+
import { type VfxInstanceStore } from "../../game/vfxInstance.js";
|
|
7
|
+
import type { LootRegistry } from "../../game/lootTable.js";
|
|
8
|
+
import type { EntityColliderSet } from "../../scene/colliders.js";
|
|
9
|
+
import type { EntityStore } from "../../scene/entityStore.js";
|
|
10
|
+
import type { ObjectStore } from "../../scene/objectStore.js";
|
|
11
|
+
import type { SceneRaycastApi } from "../../scene/sceneRaycast.js";
|
|
12
|
+
import type { WeaponStats } from "../../item/weapon.js";
|
|
13
|
+
import type { SimClock } from "../../time/simClock.js";
|
|
14
|
+
import type { WorldItemRecord, WorldItemSpawnInput } from "../../game/worldItem.js";
|
|
15
|
+
import type { GameContextContent, GameContextEntityEntry, GameContextLoot } from "../gameContext.js";
|
|
16
|
+
import { type CombatFx } from "./combatFx.js";
|
|
17
|
+
/** @internal Wiring combat needs from the live scene, loot, and command seams. */
|
|
18
|
+
export interface CombatSubsystemDeps {
|
|
19
|
+
content: GameContextContent;
|
|
20
|
+
signalNotify: () => void;
|
|
21
|
+
now: () => number;
|
|
22
|
+
events: GameEvents;
|
|
23
|
+
time: SimClock;
|
|
24
|
+
entities: EntityStore;
|
|
25
|
+
objects: ObjectStore;
|
|
26
|
+
combatSpatial: CombatSpatialDeps;
|
|
27
|
+
sceneRaycast: SceneRaycastApi;
|
|
28
|
+
entityCollidersOf: (instanceId: string) => EntityColliderSet | null;
|
|
29
|
+
objectCollidersOf: (instanceId: string) => EntityColliderSet | null;
|
|
30
|
+
catalogEntry: (instanceId: string) => GameContextEntityEntry | null | undefined;
|
|
31
|
+
statsByInstance: Map<string, import("../../scene/entityStats.js").StatValueMap>;
|
|
32
|
+
weapon: WeaponStats;
|
|
33
|
+
loot: GameContextLoot;
|
|
34
|
+
lootRegistry: LootRegistry;
|
|
35
|
+
spawnWorldItem: (input: WorldItemSpawnInput) => WorldItemRecord;
|
|
36
|
+
despawnEntity: (instanceId: string) => boolean;
|
|
37
|
+
runCommand: (name: string, args: unknown) => void;
|
|
38
|
+
localUserId: string;
|
|
39
|
+
physics?: PhysicsConfig;
|
|
40
|
+
}
|
|
41
|
+
/** @internal Effects, projectiles, death, and combat presentation surface. */
|
|
42
|
+
export interface CombatSubsystem {
|
|
43
|
+
death: DeathSystem;
|
|
44
|
+
effects: EffectSystem;
|
|
45
|
+
floatingEffects: EffectSystem;
|
|
46
|
+
projectiles: ProjectileSystem;
|
|
47
|
+
combatFx: CombatFx;
|
|
48
|
+
vfxInstances: VfxInstanceStore;
|
|
49
|
+
}
|
|
50
|
+
/** @internal */
|
|
51
|
+
export declare function createCombatSubsystem(d: CombatSubsystemDeps): CombatSubsystem;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { createDeathSystem, deathReasonFromEffect } from "../../combat/death.js";
|
|
2
|
+
import { createEffectSystem, } from "../../combat/effects.js";
|
|
3
|
+
import { createProjectileSystem } from "../../combat/projectiles.js";
|
|
4
|
+
import { createVfxInstanceStore } from "../../game/vfxInstance.js";
|
|
5
|
+
import { notifyAfter } from "../../store/changeSignal.js";
|
|
6
|
+
import { createCombatFx } from "./combatFx.js";
|
|
7
|
+
import { applyLethalLoot, isLocalPlayerKill } from "./deathLoot.js";
|
|
8
|
+
/** @internal */
|
|
9
|
+
export function createCombatSubsystem(d) {
|
|
10
|
+
const { content, signalNotify, now, events, time, entities, objects, combatSpatial, sceneRaycast, entityCollidersOf, objectCollidersOf, catalogEntry, statsByInstance, weapon, loot, lootRegistry, spawnWorldItem, despawnEntity, runCommand, localUserId, } = d;
|
|
11
|
+
const death = createDeathSystem({
|
|
12
|
+
resolveOnDeath: (instanceId) => catalogEntry(instanceId)?.onDeath,
|
|
13
|
+
resolveIdentity(instanceId) {
|
|
14
|
+
const entity = entities.get(instanceId);
|
|
15
|
+
if (entity === null)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
catalogId: entity.name,
|
|
19
|
+
position: [entity.position[0], entity.position[1], entity.position[2]],
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
loot: { roll: (tableId) => (lootRegistry.has(tableId) ? lootRegistry.roll(tableId) : []) },
|
|
23
|
+
events,
|
|
24
|
+
runCommand(name, args) {
|
|
25
|
+
runCommand(name, args);
|
|
26
|
+
},
|
|
27
|
+
despawn(instanceId) {
|
|
28
|
+
despawnEntity(instanceId);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const effects = notifyAfter(createEffectSystem({
|
|
32
|
+
resolveReceive: (instanceId) => catalogEntry(instanceId)?.receive,
|
|
33
|
+
resolveStats: (instanceId) => statsByInstance.get(instanceId),
|
|
34
|
+
getStat: weapon.getStat,
|
|
35
|
+
spatial: combatSpatial,
|
|
36
|
+
onLethal(instanceId, lethalCtx) {
|
|
37
|
+
// Capture identity + onDeath *before* resolveDeath despawns the entity.
|
|
38
|
+
const dyingEntity = entities.get(instanceId);
|
|
39
|
+
const catalogId = dyingEntity?.name;
|
|
40
|
+
const position = dyingEntity?.position;
|
|
41
|
+
const onDeath = catalogEntry(instanceId)?.onDeath;
|
|
42
|
+
const reason = deathReasonFromEffect({
|
|
43
|
+
...lethalCtx,
|
|
44
|
+
userIdOf: (id) => (id === localUserId ? localUserId : undefined),
|
|
45
|
+
});
|
|
46
|
+
const resolution = death.resolveDeath(instanceId, reason);
|
|
47
|
+
if (resolution.status !== "resolved")
|
|
48
|
+
return;
|
|
49
|
+
applyLethalLoot({
|
|
50
|
+
drops: resolution.drops,
|
|
51
|
+
grantToLocalPlayer: isLocalPlayerKill(lethalCtx, localUserId),
|
|
52
|
+
onDeath,
|
|
53
|
+
position,
|
|
54
|
+
catalogId,
|
|
55
|
+
content,
|
|
56
|
+
spawnWorldItem,
|
|
57
|
+
grantToPlayer: loot.grantToPlayer,
|
|
58
|
+
localUserId,
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
}), ["applyEffect"], signalNotify);
|
|
62
|
+
const combatFx = createCombatFx({
|
|
63
|
+
entities,
|
|
64
|
+
events,
|
|
65
|
+
time,
|
|
66
|
+
applyEffect: (input) => effects.applyEffect(input),
|
|
67
|
+
});
|
|
68
|
+
const vfxInstances = createVfxInstanceStore({
|
|
69
|
+
onOp: (op) => events.emit("combat.vfxInstance", op),
|
|
70
|
+
now: () => time.now() * 1000,
|
|
71
|
+
});
|
|
72
|
+
const floatingEffects = {
|
|
73
|
+
canReceive: effects.canReceive,
|
|
74
|
+
preview: effects.preview,
|
|
75
|
+
applyEffect: combatFx.applyEffectAndFloat,
|
|
76
|
+
};
|
|
77
|
+
const projectileObstacles = d.physics?.projectileObstacles === true;
|
|
78
|
+
const projectileFilterFor = (filter) => ({
|
|
79
|
+
entities: true,
|
|
80
|
+
objects: projectileObstacles,
|
|
81
|
+
terrain: false,
|
|
82
|
+
walls: projectileObstacles,
|
|
83
|
+
...filter,
|
|
84
|
+
});
|
|
85
|
+
const projectileSceneRaycast = {
|
|
86
|
+
raycast(input) {
|
|
87
|
+
return sceneRaycast.raycast({ ...input, filter: projectileFilterFor(input.filter) });
|
|
88
|
+
},
|
|
89
|
+
raycastAll(input) {
|
|
90
|
+
return sceneRaycast.raycastAll({ ...input, filter: projectileFilterFor(input.filter) });
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const projectiles = notifyAfter(createProjectileSystem({
|
|
94
|
+
effects: floatingEffects,
|
|
95
|
+
spatial: combatSpatial,
|
|
96
|
+
getStat: weapon.getStat,
|
|
97
|
+
sceneRaycast: projectileSceneRaycast,
|
|
98
|
+
objects: projectileObstacles
|
|
99
|
+
? {
|
|
100
|
+
list: () => objects.list(),
|
|
101
|
+
inBox: (min, max) => objects.inBox(min, max),
|
|
102
|
+
halfExtents: (catalogId) => {
|
|
103
|
+
const half = content.objectById?.(catalogId)?.halfExtents;
|
|
104
|
+
return half === undefined ? null : [half[0], half[1], half[2]];
|
|
105
|
+
},
|
|
106
|
+
collidersOf: objectCollidersOf,
|
|
107
|
+
}
|
|
108
|
+
: undefined,
|
|
109
|
+
entityCollidersOf,
|
|
110
|
+
rotationYOf: (instanceId) => entities.get(instanceId)?.rotationY,
|
|
111
|
+
now,
|
|
112
|
+
onSettle(report) {
|
|
113
|
+
events.emit("projectile.settled", {
|
|
114
|
+
from: report.from,
|
|
115
|
+
origin: [report.origin[0], report.origin[1], report.origin[2]],
|
|
116
|
+
at: [report.at[0], report.at[1], report.at[2]],
|
|
117
|
+
effect: report.effect,
|
|
118
|
+
hit: report.hit,
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
}), ["fireProjectile", "settleProjectile"], signalNotify);
|
|
122
|
+
return {
|
|
123
|
+
death,
|
|
124
|
+
effects,
|
|
125
|
+
floatingEffects,
|
|
126
|
+
projectiles,
|
|
127
|
+
combatFx,
|
|
128
|
+
vfxInstances,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EffectInput, EffectResult } from "../../combat/effects.js";
|
|
2
|
+
import { type HitReaction } from "../../combat/hitReaction.js";
|
|
3
|
+
import type { GameEvents } from "../../game/events.js";
|
|
4
|
+
import type { EntityStore } from "../../scene/entityStore.js";
|
|
5
|
+
import type { SimClock } from "../../time/simClock.js";
|
|
6
|
+
import type { FloatTextInput, HitReactionInput, TelegraphInput, VfxInput } from "../gameContext.js";
|
|
7
|
+
/** @internal What the combat-presentation helpers need from the live context: entity poses, the event bus, the sim clock (telegraph windups), and the raw effect application. */
|
|
8
|
+
export interface CombatFxDeps {
|
|
9
|
+
entities: EntityStore;
|
|
10
|
+
events: GameEvents;
|
|
11
|
+
time: SimClock;
|
|
12
|
+
applyEffect: (input: EffectInput) => EffectResult[];
|
|
13
|
+
}
|
|
14
|
+
/** @internal Combat presentation surface registered under `ctx.scene.entity`: float text, VFX bursts, telegraphs, hit reactions, and the effect wrapper that emits damage/heal float text. */
|
|
15
|
+
export interface CombatFx {
|
|
16
|
+
emitFloatText(input: FloatTextInput): void;
|
|
17
|
+
emitVfx(input: VfxInput): void;
|
|
18
|
+
fireTelegraph(input: TelegraphInput): () => void;
|
|
19
|
+
applyHitReaction(input: HitReactionInput): HitReaction | null;
|
|
20
|
+
applyEffectAndFloat(input: EffectInput): EffectResult[];
|
|
21
|
+
}
|
|
22
|
+
/** @internal */
|
|
23
|
+
export declare function createCombatFx(d: CombatFxDeps): CombatFx;
|