@jgengine/core 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -3
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/ai/crowd.d.ts +55 -0
- package/dist/ai/crowd.js +114 -0
- package/dist/ai/flock.d.ts +5 -2
- package/dist/ai/flock.js +5 -2
- package/dist/ai/groupAssist.d.ts +1 -0
- package/dist/ai/groupAssist.js +1 -0
- package/dist/ai/heatSystem.d.ts +76 -0
- package/dist/ai/heatSystem.js +97 -0
- package/dist/ai/interestScheduler.d.ts +107 -0
- package/dist/ai/interestScheduler.js +118 -0
- package/dist/ai/jobBoard.d.ts +1 -0
- package/dist/ai/jobBoard.js +1 -0
- package/dist/ai/laneSelect.d.ts +5 -2
- package/dist/ai/laneSelect.js +5 -2
- package/dist/ai/mobBrain.d.ts +1 -0
- package/dist/ai/mobBrain.js +1 -0
- package/dist/ai/spawnDirector.d.ts +19 -1
- package/dist/ai/spawnDirector.js +53 -26
- package/dist/ai/spawnPoint.d.ts +7 -0
- package/dist/ai/spawnPoint.js +7 -0
- package/dist/ai/targetAcquisition.d.ts +84 -0
- package/dist/ai/targetAcquisition.js +92 -0
- package/dist/anim/easing.d.ts +19 -0
- package/dist/anim/easing.js +19 -0
- package/dist/anim/oscillator.d.ts +12 -0
- package/dist/anim/oscillator.js +25 -0
- package/dist/area/areaEffectField.d.ts +127 -0
- package/dist/area/areaEffectField.js +175 -0
- package/dist/area/stackPolicy.d.ts +47 -0
- package/dist/area/stackPolicy.js +99 -0
- package/dist/audio/audioFalloff.d.ts +5 -2
- package/dist/audio/music.d.ts +53 -0
- package/dist/audio/music.js +34 -0
- package/dist/audio/synth.d.ts +60 -0
- package/dist/audio/synth.js +8 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +15 -0
- package/dist/board/laneBoard.d.ts +13 -0
- package/dist/board/laneBoard.js +13 -0
- package/dist/board/timelineBoard.d.ts +10 -0
- package/dist/board/timelineBoard.js +10 -0
- package/dist/combat/abilityKit.d.ts +18 -0
- package/dist/combat/abilityKit.js +24 -9
- package/dist/combat/animationState.d.ts +5 -0
- package/dist/combat/animationState.js +5 -0
- package/dist/combat/breakMeters.d.ts +10 -0
- package/dist/combat/breakMeters.js +10 -0
- package/dist/combat/castRunner.d.ts +5 -0
- package/dist/combat/castRunner.js +5 -0
- package/dist/combat/comboPoints.d.ts +5 -0
- package/dist/combat/comboPoints.js +5 -0
- package/dist/combat/comboString.d.ts +5 -0
- package/dist/combat/comboString.js +5 -0
- package/dist/combat/damageInterceptors.d.ts +192 -0
- package/dist/combat/damageInterceptors.js +251 -0
- package/dist/combat/damageMatchup.d.ts +68 -0
- package/dist/combat/damageMatchup.js +42 -0
- package/dist/combat/damageResolution.d.ts +63 -0
- package/dist/combat/damageResolution.js +50 -0
- package/dist/combat/death.d.ts +7 -1
- package/dist/combat/death.js +5 -0
- package/dist/combat/deathReason.d.ts +14 -0
- package/dist/combat/deathReason.js +1 -0
- package/dist/combat/defensiveWindow.d.ts +5 -0
- package/dist/combat/defensiveWindow.js +5 -0
- package/dist/combat/dotField.d.ts +47 -0
- package/dist/combat/dotField.js +52 -0
- package/dist/combat/downed.d.ts +5 -0
- package/dist/combat/downed.js +5 -0
- package/dist/combat/effects.d.ts +5 -0
- package/dist/combat/effects.js +5 -0
- package/dist/combat/encounterSequence.d.ts +258 -0
- package/dist/combat/encounterSequence.js +426 -0
- package/dist/combat/hitReaction.d.ts +57 -1
- package/dist/combat/hitReaction.js +45 -5
- package/dist/combat/magazine.d.ts +54 -0
- package/dist/combat/magazine.js +96 -0
- package/dist/combat/projectiles.d.ts +7 -2
- package/dist/combat/projectiles.js +48 -17
- package/dist/combat/receivedDamage.d.ts +117 -0
- package/dist/combat/receivedDamage.js +92 -0
- package/dist/combat/regenShield.d.ts +39 -0
- package/dist/combat/regenShield.js +49 -0
- package/dist/combat/renderCues.d.ts +51 -0
- package/dist/combat/renderCues.js +44 -0
- package/dist/combat/resourcePool.d.ts +5 -0
- package/dist/combat/resourcePool.js +5 -0
- package/dist/combat/rewardAllocation.d.ts +121 -0
- package/dist/combat/rewardAllocation.js +251 -0
- package/dist/combat/shotOrigin.d.ts +30 -1
- package/dist/combat/shotOrigin.js +70 -2
- package/dist/combat/statusApplication.d.ts +96 -0
- package/dist/combat/statusApplication.js +81 -0
- package/dist/combat/telegraph.d.ts +11 -2
- package/dist/combat/telegraph.js +11 -2
- package/dist/combat/thresholdCrossings.d.ts +85 -0
- package/dist/combat/thresholdCrossings.js +116 -0
- package/dist/combat.d.ts +34 -0
- package/dist/combat.js +34 -0
- package/dist/commands/commandRegistry.d.ts +11 -0
- package/dist/commands/commandRegistry.js +9 -2
- package/dist/crafting/crop.d.ts +18 -0
- package/dist/crafting/crop.js +18 -0
- package/dist/crafting/production.d.ts +5 -0
- package/dist/crafting/production.js +5 -0
- package/dist/devtools/rewriteTunables.d.ts +17 -0
- package/dist/devtools/rewriteTunables.js +276 -0
- package/dist/devtools/saveEndpoint.d.ts +46 -0
- package/dist/devtools/saveEndpoint.js +48 -0
- package/dist/devtools/transformTunables.d.ts +3 -0
- package/dist/devtools/transformTunables.js +3 -0
- package/dist/devtools/tunableSchema.d.ts +31 -0
- package/dist/devtools/tunableSchema.js +31 -0
- package/dist/economy/currency.d.ts +12 -1
- package/dist/economy/currency.js +12 -1
- package/dist/economy/listingBook.d.ts +91 -0
- package/dist/economy/listingBook.js +144 -0
- package/dist/economy/resourceLedger.d.ts +222 -0
- package/dist/economy/resourceLedger.js +353 -0
- package/dist/economy/sharedWallet.d.ts +14 -0
- package/dist/economy/sharedWallet.js +14 -0
- package/dist/economy/techTree.d.ts +12 -0
- package/dist/economy/techTree.js +12 -0
- package/dist/economy/wallet.d.ts +26 -2
- package/dist/economy/wallet.js +35 -6
- package/dist/editor/commands.d.ts +248 -0
- package/dist/editor/commands.js +865 -0
- package/dist/editor/document.d.ts +186 -0
- package/dist/editor/document.js +884 -0
- package/dist/editor/grid.d.ts +229 -0
- package/dist/editor/grid.js +366 -0
- package/dist/editor/gridAdapters.d.ts +80 -0
- package/dist/editor/gridAdapters.js +134 -0
- package/dist/editor/index.d.ts +97 -0
- package/dist/editor/index.js +10 -0
- package/dist/editor/liveSync.d.ts +127 -0
- package/dist/editor/liveSync.js +249 -0
- package/dist/editor/runtimeInspector.d.ts +88 -0
- package/dist/editor/runtimeInspector.js +239 -0
- package/dist/editor/types.d.ts +175 -0
- package/dist/editor/types.js +29 -0
- package/dist/faction/reputation.d.ts +5 -0
- package/dist/faction/reputation.js +5 -0
- package/dist/format/distance.d.ts +17 -0
- package/dist/format/distance.js +18 -0
- package/dist/format/duration.d.ts +27 -0
- package/dist/format/duration.js +45 -0
- package/dist/format/speed.d.ts +17 -0
- package/dist/format/speed.js +25 -0
- package/dist/game/connectedPlayers.d.ts +30 -0
- package/dist/game/connectedPlayers.js +21 -0
- package/dist/game/cosmetics.d.ts +9 -0
- package/dist/game/cosmetics.js +16 -0
- package/dist/game/defineGame.d.ts +141 -2
- package/dist/game/defineGame.js +39 -1
- package/dist/game/defineSystem.d.ts +88 -0
- package/dist/game/defineSystem.js +45 -0
- package/dist/game/dialogue.d.ts +33 -0
- package/dist/game/dialogue.js +21 -0
- package/dist/game/events.d.ts +50 -13
- package/dist/game/events.js +5 -0
- package/dist/game/feed.d.ts +33 -0
- package/dist/game/feed.js +35 -2
- package/dist/game/gamePhase.d.ts +11 -0
- package/dist/game/gamePhase.js +16 -0
- package/dist/game/keyValueStore.d.ts +25 -0
- package/dist/game/keyValueStore.js +61 -0
- package/dist/game/leaderboard.d.ts +5 -0
- package/dist/game/leaderboard.js +5 -0
- package/dist/game/levelSequence.d.ts +24 -2
- package/dist/game/levelSequence.js +51 -2
- package/dist/game/loadout.d.ts +5 -0
- package/dist/game/loadout.js +5 -0
- package/dist/game/lootFilter.d.ts +2 -0
- package/dist/game/lootFilter.js +2 -0
- package/dist/game/lootPipeline.d.ts +164 -0
- package/dist/game/lootPipeline.js +216 -0
- package/dist/game/lootTable.d.ts +21 -0
- package/dist/game/lootTable.js +15 -4
- package/dist/game/modelAnimation.d.ts +8 -0
- package/dist/game/modelAnimation.js +18 -0
- package/dist/game/objectives.d.ts +43 -0
- package/dist/game/objectives.js +36 -0
- package/dist/game/paramLayers.d.ts +148 -0
- package/dist/game/paramLayers.js +185 -0
- package/dist/game/ping.d.ts +5 -0
- package/dist/game/ping.js +5 -0
- package/dist/game/playableGame.d.ts +160 -12
- package/dist/game/quest.d.ts +8 -0
- package/dist/game/quest.js +29 -0
- package/dist/game/race.d.ts +141 -0
- package/dist/game/race.js +169 -0
- package/dist/game/recordBook.d.ts +5 -5
- package/dist/game/recordBook.js +4 -1
- package/dist/game/ruleSelection.d.ts +75 -0
- package/dist/game/ruleSelection.js +127 -0
- package/dist/game/runDraft.d.ts +5 -0
- package/dist/game/runDraft.js +5 -0
- package/dist/game/saveStore.d.ts +111 -0
- package/dist/game/saveStore.js +312 -0
- package/dist/game/snapshotHistory.d.ts +67 -0
- package/dist/game/snapshotHistory.js +95 -0
- package/dist/game/social.d.ts +38 -1
- package/dist/game/social.js +71 -0
- package/dist/game/spawnPoints.d.ts +5 -0
- package/dist/game/spawnPoints.js +5 -0
- package/dist/game/systemRuntime.d.ts +50 -0
- package/dist/game/systemRuntime.js +157 -0
- package/dist/game/systemSchedule.d.ts +72 -0
- package/dist/game/systemSchedule.js +242 -0
- package/dist/game/toasts.d.ts +43 -0
- package/dist/game/toasts.js +44 -0
- package/dist/game/trade.d.ts +10 -0
- package/dist/game/trade.js +10 -0
- package/dist/game/unlocks.d.ts +8 -0
- package/dist/game/unlocks.js +16 -0
- package/dist/game/vfxInstance.d.ts +138 -0
- package/dist/game/vfxInstance.js +96 -0
- package/dist/game/worldItem.d.ts +17 -4
- package/dist/game/worldItem.js +17 -4
- package/dist/gameplay.d.ts +91 -0
- package/dist/gameplay.js +91 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -7
- package/dist/input/actionBindings.d.ts +24 -5
- package/dist/input/actionBindings.js +23 -5
- package/dist/input/axisInput.d.ts +13 -1
- package/dist/input/axisInput.js +22 -1
- package/dist/input/controlGroups.d.ts +67 -0
- package/dist/input/controlGroups.js +41 -0
- package/dist/input/touchScheme.d.ts +82 -6
- package/dist/input/touchScheme.js +123 -10
- package/dist/interaction/contextMenu.d.ts +1 -0
- package/dist/interaction/contextMenu.js +1 -0
- package/dist/interaction/lockpick.d.ts +61 -0
- package/dist/interaction/lockpick.js +168 -0
- package/dist/interaction/proximityPrompt.d.ts +5 -1
- package/dist/interaction/proximityPrompt.js +5 -3
- package/dist/interaction/qte.d.ts +5 -0
- package/dist/interaction/qte.js +5 -0
- package/dist/interaction/skillCheck.d.ts +5 -0
- package/dist/interaction/skillCheck.js +5 -0
- package/dist/inventory/inventoryModel.d.ts +12 -0
- package/dist/inventory/inventoryModel.js +12 -0
- package/dist/inventory/shapedGrid.d.ts +16 -0
- package/dist/inventory/shapedGrid.js +16 -0
- package/dist/inventory/slotModel.d.ts +10 -0
- package/dist/inventory/slotModel.js +10 -0
- package/dist/item/durability.d.ts +5 -0
- package/dist/item/durability.js +5 -0
- package/dist/item/itemIdentity.d.ts +171 -0
- package/dist/item/itemIdentity.js +138 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -0
- package/dist/item/itemInstanceRegistry.js +34 -0
- package/dist/item/itemgen.d.ts +163 -0
- package/dist/item/itemgen.js +151 -0
- package/dist/item/modularItem.d.ts +5 -0
- package/dist/item/modularItem.js +5 -0
- package/dist/item/use.d.ts +5 -0
- package/dist/item/use.js +5 -0
- package/dist/item/useBehavior.d.ts +142 -0
- package/dist/item/useBehavior.js +105 -0
- package/dist/item/weapon.d.ts +5 -0
- package/dist/item/weapon.js +5 -0
- package/dist/math/scalar.d.ts +25 -0
- package/dist/math/scalar.js +47 -0
- package/dist/meta/changelog.d.ts +4 -1
- package/dist/meta/changelog.js +36 -1
- package/dist/movement/avoidance.d.ts +45 -0
- package/dist/movement/avoidance.js +123 -0
- package/dist/movement/cameraRig.d.ts +8 -0
- package/dist/movement/cameraRig.js +8 -0
- package/dist/movement/dash.d.ts +11 -0
- package/dist/movement/dash.js +11 -0
- package/dist/movement/formation.d.ts +135 -0
- package/dist/movement/formation.js +194 -0
- package/dist/movement/glideModel.d.ts +5 -0
- package/dist/movement/glideModel.js +5 -0
- package/dist/movement/grappleSwing.d.ts +5 -0
- package/dist/movement/grappleSwing.js +5 -0
- package/dist/movement/leaderTrail.d.ts +5 -0
- package/dist/movement/leaderTrail.js +5 -0
- package/dist/movement/movementModel.d.ts +38 -7
- package/dist/movement/movementModel.js +54 -13
- package/dist/movement/playerMovement.d.ts +41 -0
- package/dist/movement/playerMovement.js +236 -0
- package/dist/movement/poseState.d.ts +13 -0
- package/dist/movement/poseState.js +16 -0
- package/dist/movement/steering.d.ts +8 -0
- package/dist/movement/steering.js +18 -0
- package/dist/multiplayer/combatSnapshot.d.ts +3 -0
- package/dist/multiplayer/combatSnapshot.js +3 -0
- package/dist/multiplayer/lagCompensation.d.ts +5 -0
- package/dist/multiplayer/lagCompensation.js +5 -0
- package/dist/multiplayer/presenceModel.d.ts +9 -1
- package/dist/multiplayer/presenceModel.js +9 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
- package/dist/multiplayer/simultaneousCommit.js +3 -0
- package/dist/multiplayer.d.ts +11 -0
- package/dist/multiplayer.js +11 -0
- package/dist/nav/pathFollow.d.ts +57 -0
- package/dist/nav/pathFollow.js +109 -0
- package/dist/orders/orderKinds.d.ts +156 -0
- package/dist/orders/orderKinds.js +197 -0
- package/dist/orders/orderQueue.d.ts +208 -0
- package/dist/orders/orderQueue.js +211 -0
- package/dist/physics/drivableVehicle.d.ts +29 -0
- package/dist/physics/drivableVehicle.js +16 -0
- package/dist/physics/kinematicVehicle.d.ts +21 -1
- package/dist/physics/kinematicVehicle.js +23 -8
- package/dist/physics/physicsWorld.d.ts +24 -12
- package/dist/physics/physicsWorld.js +11 -5
- package/dist/physics/radialImpulse.d.ts +25 -0
- package/dist/physics/radialImpulse.js +27 -0
- package/dist/procedural.d.ts +3 -0
- package/dist/procedural.js +3 -0
- package/dist/progression/statGraph.d.ts +116 -0
- package/dist/progression/statGraph.js +318 -0
- package/dist/puzzle/cellGrid.d.ts +9 -0
- package/dist/puzzle/cellGrid.js +9 -0
- package/dist/puzzle/fallingPiece.d.ts +9 -0
- package/dist/puzzle/fallingPiece.js +9 -0
- package/dist/puzzle/nonogram.d.ts +39 -0
- package/dist/puzzle/nonogram.js +136 -0
- package/dist/random/nameGen.d.ts +5 -0
- package/dist/random/nameGen.js +5 -0
- package/dist/random/pick.d.ts +8 -0
- package/dist/random/pick.js +31 -0
- package/dist/random/rng.d.ts +24 -0
- package/dist/random/rng.js +30 -8
- package/dist/random/seedLink.d.ts +4 -0
- package/dist/random/seedLink.js +4 -0
- package/dist/relation/keyedValues.d.ts +54 -0
- package/dist/relation/keyedValues.js +115 -0
- package/dist/relation/thresholds.d.ts +62 -0
- package/dist/relation/thresholds.js +62 -0
- package/dist/render/color.d.ts +12 -0
- package/dist/render/color.js +26 -0
- package/dist/render/lookPreset.d.ts +41 -0
- package/dist/render/lookPreset.js +29 -0
- package/dist/render/postProcessing.d.ts +76 -0
- package/dist/render/postProcessing.js +21 -0
- package/dist/rules/predicate.d.ts +53 -0
- package/dist/rules/predicate.js +64 -0
- package/dist/rules/ruleEffects.d.ts +38 -0
- package/dist/rules/ruleEffects.js +37 -0
- package/dist/rules/triggeredRules.d.ts +160 -0
- package/dist/rules/triggeredRules.js +241 -0
- package/dist/runtime/adapter.d.ts +58 -0
- package/dist/runtime/adapter.js +54 -5
- package/dist/runtime/cameraDirector.d.ts +1 -0
- package/dist/runtime/cameraDirector.js +1 -0
- package/dist/runtime/commandRunner.d.ts +1 -0
- package/dist/runtime/commandRunner.js +1 -0
- package/dist/runtime/context/combatFx.d.ts +23 -0
- package/dist/runtime/context/combatFx.js +161 -0
- package/dist/runtime/context/registries.d.ts +13 -0
- package/dist/runtime/context/registries.js +84 -0
- package/dist/runtime/context/worldItems.d.ts +21 -0
- package/dist/runtime/context/worldItems.js +37 -0
- package/dist/runtime/descriptors/baseline.d.ts +48 -0
- package/dist/runtime/descriptors/baseline.js +134 -0
- package/dist/runtime/descriptors/features.d.ts +74 -0
- package/dist/runtime/descriptors/features.js +281 -0
- package/dist/runtime/gameContext.d.ts +163 -19
- package/dist/runtime/gameContext.js +385 -339
- package/dist/runtime/gameRuntime.d.ts +1 -0
- package/dist/runtime/gameRuntime.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +60 -0
- package/dist/runtime/headlessRunner.js +44 -0
- package/dist/runtime/hostPersistence.d.ts +12 -0
- package/dist/runtime/hostPersistence.js +12 -0
- package/dist/runtime/hostedGameRunner.d.ts +54 -0
- package/dist/runtime/hostedGameRunner.js +85 -0
- package/dist/runtime/hostedWorldSession.d.ts +73 -0
- package/dist/runtime/hostedWorldSession.js +64 -0
- package/dist/runtime/inputSnapshot.d.ts +21 -3
- package/dist/runtime/inputSnapshot.js +8 -2
- package/dist/runtime/motionIntents.d.ts +12 -1
- package/dist/runtime/motionIntents.js +26 -1
- package/dist/runtime/perContext.d.ts +15 -0
- package/dist/runtime/perContext.js +21 -0
- package/dist/runtime/runtimeSave.d.ts +79 -0
- package/dist/runtime/runtimeSave.js +105 -0
- package/dist/runtime/save.d.ts +4 -0
- package/dist/runtime/save.js +4 -0
- package/dist/runtime/snapshot.d.ts +7 -0
- package/dist/runtime/snapshot.js +7 -0
- package/dist/runtime/visibility.d.ts +2 -1
- package/dist/runtime/visibility.js +2 -1
- package/dist/runtime/worldChannel.d.ts +62 -0
- package/dist/runtime/worldChannel.js +114 -0
- package/dist/runtime/worldMirror.d.ts +36 -0
- package/dist/runtime/worldMirror.js +44 -0
- package/dist/runtime/worldProjection.d.ts +47 -0
- package/dist/runtime/worldProjection.js +52 -0
- package/dist/runtime/worldReplication.d.ts +69 -0
- package/dist/runtime/worldReplication.js +217 -0
- package/dist/runtime/worldSnapshot.d.ts +44 -0
- package/dist/runtime/worldSnapshot.js +30 -0
- package/dist/scene/assetCatalog.d.ts +22 -0
- package/dist/scene/assetCatalog.js +4 -0
- package/dist/scene/assetDiagnostics.d.ts +69 -0
- package/dist/scene/assetDiagnostics.js +110 -0
- package/dist/scene/assetGenerator.d.ts +65 -0
- package/dist/scene/assetGenerator.js +64 -0
- package/dist/scene/assetSpace.d.ts +137 -0
- package/dist/scene/assetSpace.js +259 -0
- package/dist/scene/authoredTriggers.d.ts +169 -0
- package/dist/scene/authoredTriggers.js +340 -0
- package/dist/scene/behaviorRuntime.d.ts +75 -0
- package/dist/scene/behaviorRuntime.js +217 -0
- package/dist/scene/behaviors.d.ts +14 -2
- package/dist/scene/behaviors.js +7 -2
- package/dist/scene/bodyBind.d.ts +60 -0
- package/dist/scene/bodyBind.js +51 -0
- package/dist/scene/builtinSceneKinds.d.ts +5 -0
- package/dist/scene/builtinSceneKinds.js +62 -0
- package/dist/scene/colliders.d.ts +18 -0
- package/dist/scene/colliders.js +61 -1
- package/dist/scene/entityStats.d.ts +13 -0
- package/dist/scene/entityStats.js +30 -0
- package/dist/scene/entityStore.d.ts +41 -1
- package/dist/scene/entityStore.js +75 -0
- package/dist/scene/facing.d.ts +18 -0
- package/dist/scene/facing.js +26 -0
- package/dist/scene/modelSockets.d.ts +33 -0
- package/dist/scene/modelSockets.js +29 -0
- package/dist/scene/objectQuery.d.ts +2 -0
- package/dist/scene/objectQuery.js +2 -0
- package/dist/scene/objectStore.d.ts +4 -0
- package/dist/scene/objectStore.js +6 -0
- package/dist/scene/possession.d.ts +8 -0
- package/dist/scene/possession.js +14 -0
- package/dist/scene/roster.d.ts +3 -0
- package/dist/scene/roster.js +12 -0
- package/dist/scene/sceneKinds.d.ts +240 -0
- package/dist/scene/sceneKinds.js +214 -0
- package/dist/scene/sceneOwnership.d.ts +169 -0
- package/dist/scene/sceneOwnership.js +179 -0
- package/dist/scene/selectionBookmarks.d.ts +93 -0
- package/dist/scene/selectionBookmarks.js +122 -0
- package/dist/scene/vehicleSeat.d.ts +68 -0
- package/dist/scene/vehicleSeat.js +59 -0
- package/dist/sensor/concealment.d.ts +3 -0
- package/dist/sensor/concealment.js +3 -0
- package/dist/sensor/freezeMonitor.d.ts +1 -0
- package/dist/sensor/freezeMonitor.js +1 -0
- package/dist/sensor/frustumSensor.d.ts +7 -3
- package/dist/sensor/frustumSensor.js +7 -3
- package/dist/sensor/hiddenStateProbe.d.ts +5 -2
- package/dist/sensor/hiddenStateProbe.js +5 -2
- package/dist/sensor/recordingBuffer.d.ts +2 -1
- package/dist/sensor/recordingBuffer.js +2 -1
- package/dist/sensor/replayLoop.d.ts +6 -2
- package/dist/sensor/replayLoop.js +6 -2
- package/dist/sensor/revealQuery.d.ts +2 -1
- package/dist/sensor/revealQuery.js +2 -1
- package/dist/sensor/visionCone.d.ts +10 -3
- package/dist/sensor/visionCone.js +10 -3
- package/dist/session/contestedChannel.d.ts +1 -0
- package/dist/session/contestedChannel.js +1 -0
- package/dist/session/extraction.d.ts +1 -0
- package/dist/session/extraction.js +1 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +6 -0
- package/dist/session/roundState.d.ts +8 -0
- package/dist/session/roundState.js +2 -0
- package/dist/settings/settingsModel.d.ts +1 -0
- package/dist/settings/settingsModel.js +1 -0
- package/dist/stats/accumulatorMeter.d.ts +6 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +5 -0
- package/dist/stats/eventMeter.js +5 -0
- package/dist/stats/rollCheck.d.ts +5 -0
- package/dist/stats/rollCheck.js +5 -0
- package/dist/stats/statModifiers.d.ts +5 -0
- package/dist/stats/statModifiers.js +5 -0
- package/dist/store/defineKeyedStore.d.ts +38 -0
- package/dist/store/defineKeyedStore.js +42 -0
- package/dist/store/defineStore.d.ts +33 -0
- package/dist/store/defineStore.js +35 -0
- package/dist/store/observableKeyedStore.d.ts +9 -0
- package/dist/store/observableKeyedStore.js +43 -2
- package/dist/survival/decayMeter.d.ts +55 -0
- package/dist/survival/decayMeter.js +130 -55
- package/dist/survival/moodle.d.ts +2 -0
- package/dist/survival/regionHealth.d.ts +6 -0
- package/dist/survival/regionHealth.js +5 -0
- package/dist/tactics/fallingGrid.d.ts +6 -4
- package/dist/tactics/fallingGrid.js +6 -4
- package/dist/tactics/predictiveQuery.d.ts +3 -0
- package/dist/tactics/predictiveQuery.js +3 -0
- package/dist/tactics/snapshot.d.ts +2 -0
- package/dist/tactics/snapshot.js +2 -0
- package/dist/tactics/surface.d.ts +1 -0
- package/dist/tactics/surface.js +1 -0
- package/dist/tactics/tacticalGrid.d.ts +1 -0
- package/dist/tactics/tacticalGrid.js +1 -0
- package/dist/time/beatClock.d.ts +14 -4
- package/dist/time/beatClock.js +14 -4
- package/dist/time/calendarClock.d.ts +3 -0
- package/dist/time/calendarClock.js +3 -0
- package/dist/time/idleProgress.d.ts +4 -0
- package/dist/time/idleProgress.js +4 -0
- package/dist/time/simClock.d.ts +2 -0
- package/dist/time/simClock.js +20 -5
- package/dist/ui/actionModel.d.ts +110 -0
- package/dist/ui/actionModel.js +159 -0
- package/dist/ui/gameLayout.d.ts +144 -0
- package/dist/ui/gameLayout.js +148 -0
- package/dist/ui/hudDocument.d.ts +114 -0
- package/dist/ui/hudDocument.js +220 -0
- package/dist/ui/hudLayout.d.ts +33 -1
- package/dist/ui/hudLayout.js +204 -17
- package/dist/ui/orientation.d.ts +39 -0
- package/dist/ui/orientation.js +49 -0
- package/dist/ui/selectionModel.d.ts +92 -0
- package/dist/ui/selectionModel.js +88 -0
- package/dist/ui/swingTimer.d.ts +42 -0
- package/dist/ui/swingTimer.js +38 -0
- package/dist/ui/tooltipModel.d.ts +63 -0
- package/dist/ui/tooltipModel.js +82 -0
- package/dist/ui.d.ts +15 -0
- package/dist/ui.js +15 -0
- package/dist/visibility/bounds.d.ts +8 -1
- package/dist/visibility/bounds.js +8 -1
- package/dist/visibility/frustum.d.ts +12 -3
- package/dist/visibility/frustum.js +12 -3
- package/dist/visibility/spatialIndex.js +34 -20
- package/dist/work/jobQueue.d.ts +201 -0
- package/dist/work/jobQueue.js +253 -0
- package/dist/work/unitTraining.d.ts +58 -0
- package/dist/work/unitTraining.js +52 -0
- package/dist/world/authoredObjects.d.ts +58 -0
- package/dist/world/authoredObjects.js +69 -0
- package/dist/world/buildingGenerator.d.ts +18 -0
- package/dist/world/buildingGenerator.js +62 -0
- package/dist/world/buildings.d.ts +5 -0
- package/dist/world/buildings.js +5 -0
- package/dist/world/catenary.d.ts +22 -0
- package/dist/world/catenary.js +69 -0
- package/dist/world/environmentSummary.d.ts +11 -2
- package/dist/world/environmentSummary.js +11 -1
- package/dist/world/features.d.ts +244 -7
- package/dist/world/features.js +92 -4
- package/dist/world/footprintGrid.d.ts +59 -0
- package/dist/world/footprintGrid.js +141 -0
- package/dist/world/geometry.d.ts +64 -0
- package/dist/world/geometry.js +94 -0
- package/dist/world/grassKind.d.ts +51 -0
- package/dist/world/grassKind.js +101 -0
- package/dist/world/pathInstances.d.ts +27 -0
- package/dist/world/pathInstances.js +27 -0
- package/dist/world/pathTerrain.d.ts +80 -0
- package/dist/world/pathTerrain.js +142 -0
- package/dist/world/placeAsset.d.ts +81 -0
- package/dist/world/placeAsset.js +77 -0
- package/dist/world/placement.d.ts +4 -0
- package/dist/world/placement.js +4 -0
- package/dist/world/placementController.d.ts +6 -0
- package/dist/world/placementController.js +6 -0
- package/dist/world/polyline.d.ts +34 -0
- package/dist/world/polyline.js +81 -0
- package/dist/world/roads.d.ts +55 -0
- package/dist/world/roads.js +184 -0
- package/dist/world/scatterRegion.d.ts +164 -0
- package/dist/world/scatterRegion.js +409 -0
- package/dist/world/sceneShapes.d.ts +43 -0
- package/dist/world/sceneShapes.js +1 -0
- package/dist/world/segment.d.ts +27 -0
- package/dist/world/segment.js +43 -0
- package/dist/world/soilKind.d.ts +48 -0
- package/dist/world/soilKind.js +92 -0
- package/dist/world/spatialSample.d.ts +241 -0
- package/dist/world/spatialSample.js +465 -0
- package/dist/world/streets.d.ts +80 -0
- package/dist/world/streets.js +144 -0
- package/dist/world/terraform.d.ts +213 -1
- package/dist/world/terraform.js +655 -20
- package/dist/world/terrain.d.ts +138 -12
- package/dist/world/terrain.js +346 -28
- package/dist/world/terrainGuides.d.ts +182 -0
- package/dist/world/terrainGuides.js +343 -0
- package/dist/world/vec2.d.ts +81 -0
- package/dist/world/vec2.js +128 -0
- package/dist/world/vec3.d.ts +49 -0
- package/dist/world/vec3.js +76 -0
- package/dist/world/vegetation.d.ts +71 -0
- package/dist/world/vegetation.js +151 -0
- package/dist/world/visibilityField.d.ts +154 -0
- package/dist/world/visibilityField.js +271 -0
- package/dist/world/volumetricClouds.d.ts +52 -0
- package/dist/world/volumetricClouds.js +43 -0
- package/dist/world/walls.d.ts +9 -0
- package/dist/world/walls.js +9 -0
- package/dist/world/waterKind.d.ts +55 -0
- package/dist/world/waterKind.js +99 -0
- package/dist/world.d.ts +132 -0
- package/dist/world.js +132 -0
- package/package.json +32 -8
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-combat/SKILL.md +34 -0
- package/skills/jgengine-combat/api.md +549 -0
- package/skills/jgengine-combat/capabilities.md +169 -0
- package/skills/jgengine-combat/reference.md +98 -0
- package/skills/jgengine-gameplay/SKILL.md +39 -0
- package/skills/jgengine-gameplay/api.md +1794 -0
- package/skills/jgengine-gameplay/capabilities.md +378 -0
- package/skills/jgengine-gameplay/reference-systems.md +60 -0
- package/skills/jgengine-world/SKILL.md +38 -0
- package/skills/jgengine-world/api.md +2652 -0
- package/skills/jgengine-world/capabilities.md +370 -0
- package/skills/jgengine-world/reference.md +222 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/store/engineStore.d.ts +0 -22
- package/dist/store/engineStore.js +0 -50
- package/dist/store/features.d.ts +0 -10
- package/dist/store/features.js +0 -23
- package/llms.txt +0 -4983
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
function cellKey(cell) {
|
|
2
|
+
return `${cell.col}:${cell.row}`;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Multi-cell footprint occupancy/reservation on a shared build grid — `world/placementController`
|
|
6
|
+
* only owns the ghost preview; this is the persistent claim a committed placement holds so the next
|
|
7
|
+
* hover's `isFree` check (or another player's, in a shared world) sees it. Bridge into
|
|
8
|
+
* `world/placement`'s `PlacementRules.obstacles` with {@link footprintObstacles} instead of
|
|
9
|
+
* hand-rolling an occupancy map per game.
|
|
10
|
+
*
|
|
11
|
+
* @capability footprint-grid multi-cell footprint occupancy/reservation on a shared build grid
|
|
12
|
+
*/
|
|
13
|
+
export function createFootprintGrid(options = {}) {
|
|
14
|
+
const cellSize = options.cellSize ?? 1;
|
|
15
|
+
const occupied = new Map();
|
|
16
|
+
const reservations = new Map();
|
|
17
|
+
return {
|
|
18
|
+
cellSize,
|
|
19
|
+
cellsFor(origin, footprint, quarterTurns = 0) {
|
|
20
|
+
const turned = ((quarterTurns % 2) + 2) % 2 === 1;
|
|
21
|
+
const cols = Math.max(1, Math.round((turned ? footprint.d : footprint.w) / cellSize));
|
|
22
|
+
const rows = Math.max(1, Math.round((turned ? footprint.w : footprint.d) / cellSize));
|
|
23
|
+
const originCol = Math.round(origin[0] / cellSize - cols / 2);
|
|
24
|
+
const originRow = Math.round(origin[1] / cellSize - rows / 2);
|
|
25
|
+
const cells = [];
|
|
26
|
+
for (let row = 0; row < rows; row += 1) {
|
|
27
|
+
for (let col = 0; col < cols; col += 1)
|
|
28
|
+
cells.push({ col: originCol + col, row: originRow + row });
|
|
29
|
+
}
|
|
30
|
+
return cells;
|
|
31
|
+
},
|
|
32
|
+
isFree(cells) {
|
|
33
|
+
return cells.every((cell) => !occupied.has(cellKey(cell)));
|
|
34
|
+
},
|
|
35
|
+
reserve(id, kind, cells) {
|
|
36
|
+
if (reservations.has(id))
|
|
37
|
+
return false;
|
|
38
|
+
if (!cells.every((cell) => !occupied.has(cellKey(cell))))
|
|
39
|
+
return false;
|
|
40
|
+
for (const cell of cells)
|
|
41
|
+
occupied.set(cellKey(cell), id);
|
|
42
|
+
reservations.set(id, { id, kind, cells: cells.slice() });
|
|
43
|
+
return true;
|
|
44
|
+
},
|
|
45
|
+
release(id) {
|
|
46
|
+
const reservation = reservations.get(id);
|
|
47
|
+
if (reservation === undefined)
|
|
48
|
+
return false;
|
|
49
|
+
for (const cell of reservation.cells)
|
|
50
|
+
occupied.delete(cellKey(cell));
|
|
51
|
+
reservations.delete(id);
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
occupantAt(cell) {
|
|
55
|
+
return occupied.get(cellKey(cell)) ?? null;
|
|
56
|
+
},
|
|
57
|
+
kindAt(cell) {
|
|
58
|
+
const id = occupied.get(cellKey(cell));
|
|
59
|
+
if (id === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
return reservations.get(id)?.kind ?? null;
|
|
62
|
+
},
|
|
63
|
+
reservationOf(id) {
|
|
64
|
+
return reservations.get(id) ?? null;
|
|
65
|
+
},
|
|
66
|
+
list() {
|
|
67
|
+
return Array.from(reservations.values());
|
|
68
|
+
},
|
|
69
|
+
clear() {
|
|
70
|
+
occupied.clear();
|
|
71
|
+
reservations.clear();
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const CARDINAL_OFFSETS = [
|
|
76
|
+
{ col: 0, row: -1 },
|
|
77
|
+
{ col: 1, row: 0 },
|
|
78
|
+
{ col: 0, row: 1 },
|
|
79
|
+
{ col: -1, row: 0 },
|
|
80
|
+
];
|
|
81
|
+
/** Every occupied cell orthogonally touching `cells` but outside them — the connective-piece neighbor set. */
|
|
82
|
+
export function boundaryNeighbors(grid, cells) {
|
|
83
|
+
const own = new Set(cells.map(cellKey));
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const cell of cells) {
|
|
87
|
+
for (const offset of CARDINAL_OFFSETS) {
|
|
88
|
+
const neighbor = { col: cell.col + offset.col, row: cell.row + offset.row };
|
|
89
|
+
const key = cellKey(neighbor);
|
|
90
|
+
if (own.has(key) || seen.has(key))
|
|
91
|
+
continue;
|
|
92
|
+
seen.add(key);
|
|
93
|
+
const kind = grid.kindAt(neighbor);
|
|
94
|
+
if (kind !== null)
|
|
95
|
+
out.push({ cell: neighbor, kind });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Connective-piece adjacency validity: every occupied neighbor of `cells` must satisfy `accepts`
|
|
102
|
+
* (no incompatible piece touching), and when `requireConnection` is true at least one neighbor must
|
|
103
|
+
* (a road/pipe/belt segment placed with nothing to connect to is invalid). An empty-bordered footprint
|
|
104
|
+
* (no occupied neighbors at all) passes unless `requireConnection` demands one.
|
|
105
|
+
*/
|
|
106
|
+
export function hasValidAdjacency(grid, cells, accepts, requireConnection = false) {
|
|
107
|
+
const neighbors = boundaryNeighbors(grid, cells);
|
|
108
|
+
if (requireConnection && neighbors.length === 0)
|
|
109
|
+
return false;
|
|
110
|
+
if (!neighbors.every((neighbor) => accepts(neighbor.kind)))
|
|
111
|
+
return false;
|
|
112
|
+
return !requireConnection || neighbors.some((neighbor) => accepts(neighbor.kind));
|
|
113
|
+
}
|
|
114
|
+
/** Bridges live reservations into `world/placement`'s `PlacementRules.obstacles` so `validatePlacement`/`createPlacementController` see the grid's committed footprints unchanged. */
|
|
115
|
+
export function footprintObstacles(grid) {
|
|
116
|
+
return grid.list().map((reservation) => {
|
|
117
|
+
let minCol = Infinity;
|
|
118
|
+
let minRow = Infinity;
|
|
119
|
+
let maxCol = -Infinity;
|
|
120
|
+
let maxRow = -Infinity;
|
|
121
|
+
for (const cell of reservation.cells) {
|
|
122
|
+
if (cell.col < minCol)
|
|
123
|
+
minCol = cell.col;
|
|
124
|
+
if (cell.col > maxCol)
|
|
125
|
+
maxCol = cell.col;
|
|
126
|
+
if (cell.row < minRow)
|
|
127
|
+
minRow = cell.row;
|
|
128
|
+
if (cell.row > maxRow)
|
|
129
|
+
maxRow = cell.row;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
id: reservation.id,
|
|
133
|
+
aabb: {
|
|
134
|
+
minX: minCol * grid.cellSize,
|
|
135
|
+
maxX: (maxCol + 1) * grid.cellSize,
|
|
136
|
+
minZ: minRow * grid.cellSize,
|
|
137
|
+
maxZ: (maxRow + 1) * grid.cellSize,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
}
|
package/dist/world/geometry.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export type Vec2 = readonly [number, number];
|
|
2
|
+
/** A 3D point/vector as an `[x, y, z]` tuple — the engine's zero-allocation spatial primitive. */
|
|
3
|
+
export type Vec3 = readonly [number, number, number];
|
|
2
4
|
export interface Footprint {
|
|
3
5
|
w: number;
|
|
4
6
|
d: number;
|
|
@@ -13,11 +15,73 @@ export interface MoveOptions {
|
|
|
13
15
|
bounds?: Aabb;
|
|
14
16
|
radius?: number;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A circular clearance around a gameplay spot (spawn, plot, path point, POI): scatter is repelled
|
|
20
|
+
* from it and terrain is flattened toward its center. `feather` (meters) is the soft outer band —
|
|
21
|
+
* full effect within `radius - feather`, ramping to zero at `radius`.
|
|
22
|
+
*/
|
|
23
|
+
export interface AvoidZone {
|
|
24
|
+
x: number;
|
|
25
|
+
z: number;
|
|
26
|
+
radius: number;
|
|
27
|
+
feather?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A clearance *corridor* along a polyline (a path/road): scatter is repelled within `halfWidth` of
|
|
31
|
+
* the centerline, feathered over the outer band. Clean straight edges — unlike approximating a
|
|
32
|
+
* corridor with a scalloped chain of discs.
|
|
33
|
+
*/
|
|
34
|
+
export interface AvoidCorridor {
|
|
35
|
+
points: readonly Vec2[];
|
|
36
|
+
halfWidth: number;
|
|
37
|
+
feather?: number;
|
|
38
|
+
}
|
|
39
|
+
/** A clearance region: point discs (spawns/plots) plus centerline corridors (paths). */
|
|
40
|
+
export interface AvoidMasks {
|
|
41
|
+
discs: readonly AvoidZone[];
|
|
42
|
+
corridors: readonly AvoidCorridor[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* How strongly a point falls inside a clearance zone: 1 at/inside the solid core, ramping to 0 at
|
|
46
|
+
* the zone's outer `radius` across its `feather` band, 0 outside. The max over all zones.
|
|
47
|
+
* @internal — the falloff math behind scatter avoid and terrain flatten.
|
|
48
|
+
*/
|
|
49
|
+
export declare function zoneInfluence(x: number, z: number, zones: readonly AvoidZone[]): number;
|
|
50
|
+
/** Clearance influence of a corridor: nearest-segment distance vs `halfWidth`, feathered. @internal */
|
|
51
|
+
export declare function corridorInfluence(x: number, z: number, corridor: AvoidCorridor): number;
|
|
52
|
+
/** Combined clearance influence of discs + corridors — the max over every mask. @internal */
|
|
53
|
+
export declare function masksInfluence(x: number, z: number, masks: AvoidMasks): number;
|
|
54
|
+
/** @internal */
|
|
16
55
|
export declare function snapToGrid(point: Vec2, size: number): Vec2;
|
|
56
|
+
/** @internal */
|
|
17
57
|
export declare function footprintAabb(center: Vec2, footprint: Footprint, quarterTurns?: number): Aabb;
|
|
58
|
+
/** @internal */
|
|
18
59
|
export declare function expandAabb(aabb: Aabb, margin: number): Aabb;
|
|
60
|
+
/** @internal */
|
|
19
61
|
export declare function aabbOverlap(a: Aabb, b: Aabb): boolean;
|
|
62
|
+
/** @internal */
|
|
20
63
|
export declare function aabbContains(outer: Aabb, inner: Aabb): boolean;
|
|
64
|
+
/** @internal */
|
|
21
65
|
export declare function pointInAabb(point: Vec2, aabb: Aabb): boolean;
|
|
66
|
+
/** @internal */
|
|
22
67
|
export declare function clampToAabb(point: Vec2, aabb: Aabb): Vec2;
|
|
68
|
+
/** @internal */
|
|
23
69
|
export declare function resolveMove(from: Vec2, delta: Vec2, blockers: readonly Aabb[], options?: MoveOptions): Vec2;
|
|
70
|
+
/** An axis-aligned ellipse: `center` with semi-axes `radiusX` and `radiusY`. */
|
|
71
|
+
export interface Ellipse {
|
|
72
|
+
center: Vec2;
|
|
73
|
+
radiusX: number;
|
|
74
|
+
radiusY: number;
|
|
75
|
+
}
|
|
76
|
+
/** True when `point` sits inside (or on) the ellipse — the oval-arena containment test.
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
|
+
export declare function pointInEllipse(point: Vec2, ellipse: Ellipse): boolean;
|
|
80
|
+
/** Clamp `point` to the ellipse boundary when it strays outside, else return it unchanged.
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export declare function clampToEllipse(point: Vec2, ellipse: Ellipse): Vec2;
|
|
84
|
+
/** Outward unit normal of the ellipse at the point nearest `point` — the boundary bounce direction.
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
export declare function ellipseNormal(point: Vec2, ellipse: Ellipse): Vec2;
|
package/dist/world/geometry.js
CHANGED
|
@@ -1,8 +1,61 @@
|
|
|
1
|
+
function bandInfluence(dist, radius, feather) {
|
|
2
|
+
if (dist >= radius)
|
|
3
|
+
return 0;
|
|
4
|
+
const inner = radius - Math.max(0, feather);
|
|
5
|
+
return dist <= inner || feather <= 0 ? 1 : (radius - dist) / feather;
|
|
6
|
+
}
|
|
7
|
+
/** Perpendicular distance from a point to a polyline segment [a,b] on the XZ plane. */
|
|
8
|
+
function distanceToSegment(px, pz, a, b) {
|
|
9
|
+
const dx = b[0] - a[0];
|
|
10
|
+
const dz = b[1] - a[1];
|
|
11
|
+
const lenSq = dx * dx + dz * dz || 1;
|
|
12
|
+
let t = ((px - a[0]) * dx + (pz - a[1]) * dz) / lenSq;
|
|
13
|
+
t = t < 0 ? 0 : t > 1 ? 1 : t;
|
|
14
|
+
return Math.hypot(px - (a[0] + dx * t), pz - (a[1] + dz * t));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* How strongly a point falls inside a clearance zone: 1 at/inside the solid core, ramping to 0 at
|
|
18
|
+
* the zone's outer `radius` across its `feather` band, 0 outside. The max over all zones.
|
|
19
|
+
* @internal — the falloff math behind scatter avoid and terrain flatten.
|
|
20
|
+
*/
|
|
21
|
+
export function zoneInfluence(x, z, zones) {
|
|
22
|
+
let best = 0;
|
|
23
|
+
for (const zone of zones) {
|
|
24
|
+
const t = bandInfluence(Math.hypot(x - zone.x, z - zone.z), zone.radius, zone.feather ?? 0);
|
|
25
|
+
if (t > best)
|
|
26
|
+
best = t;
|
|
27
|
+
}
|
|
28
|
+
return best;
|
|
29
|
+
}
|
|
30
|
+
/** Clearance influence of a corridor: nearest-segment distance vs `halfWidth`, feathered. @internal */
|
|
31
|
+
export function corridorInfluence(x, z, corridor) {
|
|
32
|
+
const { points, halfWidth } = corridor;
|
|
33
|
+
const feather = corridor.feather ?? 0;
|
|
34
|
+
let best = 0;
|
|
35
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
36
|
+
const t = bandInfluence(distanceToSegment(x, z, points[i - 1], points[i]), halfWidth, feather);
|
|
37
|
+
if (t > best)
|
|
38
|
+
best = t;
|
|
39
|
+
}
|
|
40
|
+
return best;
|
|
41
|
+
}
|
|
42
|
+
/** Combined clearance influence of discs + corridors — the max over every mask. @internal */
|
|
43
|
+
export function masksInfluence(x, z, masks) {
|
|
44
|
+
let best = zoneInfluence(x, z, masks.discs);
|
|
45
|
+
for (const corridor of masks.corridors) {
|
|
46
|
+
const t = corridorInfluence(x, z, corridor);
|
|
47
|
+
if (t > best)
|
|
48
|
+
best = t;
|
|
49
|
+
}
|
|
50
|
+
return best;
|
|
51
|
+
}
|
|
52
|
+
/** @internal */
|
|
1
53
|
export function snapToGrid(point, size) {
|
|
2
54
|
if (!(size > 0))
|
|
3
55
|
return point;
|
|
4
56
|
return [Math.round(point[0] / size) * size, Math.round(point[1] / size) * size];
|
|
5
57
|
}
|
|
58
|
+
/** @internal */
|
|
6
59
|
export function footprintAabb(center, footprint, quarterTurns = 0) {
|
|
7
60
|
const turned = ((quarterTurns % 2) + 2) % 2 === 1;
|
|
8
61
|
const halfW = (turned ? footprint.d : footprint.w) / 2;
|
|
@@ -14,6 +67,7 @@ export function footprintAabb(center, footprint, quarterTurns = 0) {
|
|
|
14
67
|
maxZ: center[1] + halfD,
|
|
15
68
|
};
|
|
16
69
|
}
|
|
70
|
+
/** @internal */
|
|
17
71
|
export function expandAabb(aabb, margin) {
|
|
18
72
|
return {
|
|
19
73
|
minX: aabb.minX - margin,
|
|
@@ -22,18 +76,22 @@ export function expandAabb(aabb, margin) {
|
|
|
22
76
|
maxZ: aabb.maxZ + margin,
|
|
23
77
|
};
|
|
24
78
|
}
|
|
79
|
+
/** @internal */
|
|
25
80
|
export function aabbOverlap(a, b) {
|
|
26
81
|
return a.minX < b.maxX && a.maxX > b.minX && a.minZ < b.maxZ && a.maxZ > b.minZ;
|
|
27
82
|
}
|
|
83
|
+
/** @internal */
|
|
28
84
|
export function aabbContains(outer, inner) {
|
|
29
85
|
return (inner.minX >= outer.minX &&
|
|
30
86
|
inner.maxX <= outer.maxX &&
|
|
31
87
|
inner.minZ >= outer.minZ &&
|
|
32
88
|
inner.maxZ <= outer.maxZ);
|
|
33
89
|
}
|
|
90
|
+
/** @internal */
|
|
34
91
|
export function pointInAabb(point, aabb) {
|
|
35
92
|
return point[0] >= aabb.minX && point[0] <= aabb.maxX && point[1] >= aabb.minZ && point[1] <= aabb.maxZ;
|
|
36
93
|
}
|
|
94
|
+
/** @internal */
|
|
37
95
|
export function clampToAabb(point, aabb) {
|
|
38
96
|
return [
|
|
39
97
|
Math.min(Math.max(point[0], aabb.minX), aabb.maxX),
|
|
@@ -62,6 +120,7 @@ function resolveAxis(main, cross, delta, blockers, axisX) {
|
|
|
62
120
|
}
|
|
63
121
|
return next;
|
|
64
122
|
}
|
|
123
|
+
/** @internal */
|
|
65
124
|
export function resolveMove(from, delta, blockers, options = {}) {
|
|
66
125
|
const radius = options.radius ?? 0;
|
|
67
126
|
const expanded = radius === 0 ? blockers : blockers.map((blocker) => expandAabb(blocker, radius));
|
|
@@ -73,3 +132,38 @@ export function resolveMove(from, delta, blockers, options = {}) {
|
|
|
73
132
|
z = Math.min(Math.max(z, options.bounds.minZ + radius), options.bounds.maxZ - radius);
|
|
74
133
|
return [x, z];
|
|
75
134
|
}
|
|
135
|
+
function normalizedRadius2(point, ellipse) {
|
|
136
|
+
const nx = ellipse.radiusX > 0 ? (point[0] - ellipse.center[0]) / ellipse.radiusX : 0;
|
|
137
|
+
const ny = ellipse.radiusY > 0 ? (point[1] - ellipse.center[1]) / ellipse.radiusY : 0;
|
|
138
|
+
return nx * nx + ny * ny;
|
|
139
|
+
}
|
|
140
|
+
/** True when `point` sits inside (or on) the ellipse — the oval-arena containment test.
|
|
141
|
+
* @internal
|
|
142
|
+
*/
|
|
143
|
+
export function pointInEllipse(point, ellipse) {
|
|
144
|
+
return normalizedRadius2(point, ellipse) <= 1;
|
|
145
|
+
}
|
|
146
|
+
/** Clamp `point` to the ellipse boundary when it strays outside, else return it unchanged.
|
|
147
|
+
* @internal
|
|
148
|
+
*/
|
|
149
|
+
export function clampToEllipse(point, ellipse) {
|
|
150
|
+
const r2 = normalizedRadius2(point, ellipse);
|
|
151
|
+
if (r2 <= 1)
|
|
152
|
+
return point;
|
|
153
|
+
const scale = 1 / Math.sqrt(r2);
|
|
154
|
+
return [
|
|
155
|
+
ellipse.center[0] + (point[0] - ellipse.center[0]) * scale,
|
|
156
|
+
ellipse.center[1] + (point[1] - ellipse.center[1]) * scale,
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
/** Outward unit normal of the ellipse at the point nearest `point` — the boundary bounce direction.
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
export function ellipseNormal(point, ellipse) {
|
|
163
|
+
const nx = ellipse.radiusX > 0 ? (point[0] - ellipse.center[0]) / (ellipse.radiusX * ellipse.radiusX) : 0;
|
|
164
|
+
const ny = ellipse.radiusY > 0 ? (point[1] - ellipse.center[1]) / (ellipse.radiusY * ellipse.radiusY) : 0;
|
|
165
|
+
const len = Math.hypot(nx, ny);
|
|
166
|
+
if (len < 1e-6)
|
|
167
|
+
return [1, 0];
|
|
168
|
+
return [nx / len, ny / len];
|
|
169
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `grass_field` studio: a GPU grass patch authored as a box volume — its XZ footprint is the grass
|
|
3
|
+
* area, its top the ground height. Pure config here (blade/wind/color params + a footprint resolver);
|
|
4
|
+
* the instanced vertex-wind grass mesh lives in the `shell` renderer, which drives the existing
|
|
5
|
+
* `GrassField`. An engine environment kind (like water/scatter) so grass wind and colours are
|
|
6
|
+
* slider-authorable in the editor and persisted in `editor.scene.json` — the #813 grass studio.
|
|
7
|
+
*
|
|
8
|
+
* @capability grass-field editor-authorable GPU grass patch
|
|
9
|
+
*/
|
|
10
|
+
import { type ParamSchema, type SceneKindObject } from "../scene/sceneKinds.js";
|
|
11
|
+
/** The editor volume kind marking a box as a GPU grass patch. */
|
|
12
|
+
export declare const GRASS_FIELD_KIND = "grass_field";
|
|
13
|
+
/** Fully-defaulted grass params parsed from a volume's `meta`. */
|
|
14
|
+
export interface GrassRules {
|
|
15
|
+
/** Blades per square meter (the shell caps by an instance budget). */
|
|
16
|
+
density: number;
|
|
17
|
+
/** Blade height in meters. */
|
|
18
|
+
bladeHeight: number;
|
|
19
|
+
/** Base (root) color, hex. */
|
|
20
|
+
colorBase: string;
|
|
21
|
+
/** Tip color, hex. */
|
|
22
|
+
colorTip: string;
|
|
23
|
+
/** Per-blade color jitter, 0..1. */
|
|
24
|
+
colorVariation: number;
|
|
25
|
+
/** Vertex-wind sway strength, 0..1. */
|
|
26
|
+
windStrength: number;
|
|
27
|
+
/** Wind animation speed. */
|
|
28
|
+
windSpeed: number;
|
|
29
|
+
/** Gust patch scale (spatial frequency of gusts). */
|
|
30
|
+
windGust: number;
|
|
31
|
+
/** Blade material roughness, 0..1. */
|
|
32
|
+
roughness: number;
|
|
33
|
+
/** Seed string; same seed reproduces the same blade layout. */
|
|
34
|
+
seed: string;
|
|
35
|
+
}
|
|
36
|
+
/** Grass defaults: a lush, lightly-swaying meadow. */
|
|
37
|
+
export declare const GRASS_DEFAULTS: GrassRules;
|
|
38
|
+
/** The grass parameter schema — drives the inspector and `meta` parse via the studio seam. */
|
|
39
|
+
export declare const GRASS_SCHEMA: ParamSchema;
|
|
40
|
+
/** Parse a volume's `meta` into fully-defaulted grass rules. @internal */
|
|
41
|
+
export declare function readGrassRules(meta: Record<string, unknown> | undefined): GrassRules;
|
|
42
|
+
/** A resolved grass patch: world-space area center at ground height, footprint size (XZ), and rules. */
|
|
43
|
+
export interface ResolvedGrass {
|
|
44
|
+
center: readonly [number, number, number];
|
|
45
|
+
size: readonly [number, number];
|
|
46
|
+
rules: GrassRules;
|
|
47
|
+
}
|
|
48
|
+
/** Resolve a grass volume into an area footprint (from box half-extents / radius) at the box base. @internal */
|
|
49
|
+
export declare function resolveGrassObject(object: SceneKindObject): ResolvedGrass | null;
|
|
50
|
+
/** Registers the `grass_field` scene kind (schema + resolver). Called by {@link registerBuiltinSceneKinds}. @internal */
|
|
51
|
+
export declare function registerGrassKind(): void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `grass_field` studio: a GPU grass patch authored as a box volume — its XZ footprint is the grass
|
|
3
|
+
* area, its top the ground height. Pure config here (blade/wind/color params + a footprint resolver);
|
|
4
|
+
* the instanced vertex-wind grass mesh lives in the `shell` renderer, which drives the existing
|
|
5
|
+
* `GrassField`. An engine environment kind (like water/scatter) so grass wind and colours are
|
|
6
|
+
* slider-authorable in the editor and persisted in `editor.scene.json` — the #813 grass studio.
|
|
7
|
+
*
|
|
8
|
+
* @capability grass-field editor-authorable GPU grass patch
|
|
9
|
+
*/
|
|
10
|
+
import { registerSceneKind } from "../scene/sceneKinds.js";
|
|
11
|
+
/** The editor volume kind marking a box as a GPU grass patch. */
|
|
12
|
+
export const GRASS_FIELD_KIND = "grass_field";
|
|
13
|
+
/** Grass defaults: a lush, lightly-swaying meadow. */
|
|
14
|
+
export const GRASS_DEFAULTS = {
|
|
15
|
+
density: 4,
|
|
16
|
+
bladeHeight: 0.6,
|
|
17
|
+
colorBase: "#3f6f37",
|
|
18
|
+
colorTip: "#9ac25a",
|
|
19
|
+
colorVariation: 0.35,
|
|
20
|
+
windStrength: 0.22,
|
|
21
|
+
windSpeed: 1.6,
|
|
22
|
+
windGust: 0.16,
|
|
23
|
+
roughness: 0.85,
|
|
24
|
+
seed: "",
|
|
25
|
+
};
|
|
26
|
+
/** The grass parameter schema — drives the inspector and `meta` parse via the studio seam. */
|
|
27
|
+
export const GRASS_SCHEMA = {
|
|
28
|
+
fields: [
|
|
29
|
+
{ type: "range", key: "density", label: "density", min: 0.5, max: 16, step: 0.5, default: GRASS_DEFAULTS.density, unit: "/m²" },
|
|
30
|
+
{ type: "range", key: "bladeHeight", label: "blade height", min: 0.1, max: 2, step: 0.05, default: GRASS_DEFAULTS.bladeHeight, unit: "m" },
|
|
31
|
+
{ type: "color", key: "colorBase", label: "base color", default: GRASS_DEFAULTS.colorBase },
|
|
32
|
+
{ type: "color", key: "colorTip", label: "tip color", default: GRASS_DEFAULTS.colorTip },
|
|
33
|
+
{ type: "range", key: "colorVariation", label: "color variation", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.colorVariation },
|
|
34
|
+
{ type: "range", key: "windStrength", label: "wind strength", min: 0, max: 1, step: 0.01, default: GRASS_DEFAULTS.windStrength },
|
|
35
|
+
{ type: "range", key: "windSpeed", label: "wind speed", min: 0, max: 4, step: 0.05, default: GRASS_DEFAULTS.windSpeed },
|
|
36
|
+
{ type: "range", key: "windGust", label: "gust scale", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.windGust },
|
|
37
|
+
{ type: "range", key: "roughness", label: "roughness", min: 0, max: 1, step: 0.02, default: GRASS_DEFAULTS.roughness },
|
|
38
|
+
{ type: "seed", key: "seed", label: "seed", default: "" },
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
function metaNumber(meta, key, fallback) {
|
|
42
|
+
const value = meta?.[key];
|
|
43
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
44
|
+
}
|
|
45
|
+
function metaString(meta, key, fallback) {
|
|
46
|
+
const value = meta?.[key];
|
|
47
|
+
return typeof value === "string" ? value : fallback;
|
|
48
|
+
}
|
|
49
|
+
/** Parse a volume's `meta` into fully-defaulted grass rules. @internal */
|
|
50
|
+
export function readGrassRules(meta) {
|
|
51
|
+
return {
|
|
52
|
+
density: Math.max(0, metaNumber(meta, "density", GRASS_DEFAULTS.density)),
|
|
53
|
+
bladeHeight: Math.max(0.05, metaNumber(meta, "bladeHeight", GRASS_DEFAULTS.bladeHeight)),
|
|
54
|
+
colorBase: metaString(meta, "colorBase", GRASS_DEFAULTS.colorBase),
|
|
55
|
+
colorTip: metaString(meta, "colorTip", GRASS_DEFAULTS.colorTip),
|
|
56
|
+
colorVariation: metaNumber(meta, "colorVariation", GRASS_DEFAULTS.colorVariation),
|
|
57
|
+
windStrength: metaNumber(meta, "windStrength", GRASS_DEFAULTS.windStrength),
|
|
58
|
+
windSpeed: metaNumber(meta, "windSpeed", GRASS_DEFAULTS.windSpeed),
|
|
59
|
+
windGust: metaNumber(meta, "windGust", GRASS_DEFAULTS.windGust),
|
|
60
|
+
roughness: metaNumber(meta, "roughness", GRASS_DEFAULTS.roughness),
|
|
61
|
+
seed: metaString(meta, "seed", GRASS_DEFAULTS.seed),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function axis(value) {
|
|
65
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
66
|
+
}
|
|
67
|
+
/** Resolve a grass volume into an area footprint (from box half-extents / radius) at the box base. @internal */
|
|
68
|
+
export function resolveGrassObject(object) {
|
|
69
|
+
const center = object.center ?? object.position;
|
|
70
|
+
if (center === undefined)
|
|
71
|
+
return null;
|
|
72
|
+
const he = object.halfExtents;
|
|
73
|
+
const radius = object.radius;
|
|
74
|
+
const halfX = axis(he?.x) ?? radius ?? 10;
|
|
75
|
+
const halfZ = axis(he?.z) ?? radius ?? 10;
|
|
76
|
+
const halfY = axis(he?.y) ?? 0;
|
|
77
|
+
return {
|
|
78
|
+
center: [center.x, center.y - halfY, center.z],
|
|
79
|
+
size: [Math.max(0.5, halfX * 2), Math.max(0.5, halfZ * 2)],
|
|
80
|
+
rules: readGrassRules(object.meta),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Registers the `grass_field` scene kind (schema + resolver). Called by {@link registerBuiltinSceneKinds}. @internal */
|
|
84
|
+
export function registerGrassKind() {
|
|
85
|
+
registerSceneKind({
|
|
86
|
+
kind: GRASS_FIELD_KIND,
|
|
87
|
+
target: "volume",
|
|
88
|
+
label: "Grass field",
|
|
89
|
+
addCategory: "Studios",
|
|
90
|
+
accent: "#7fbf4d",
|
|
91
|
+
schema: GRASS_SCHEMA,
|
|
92
|
+
resolve: (object) => resolveGrassObject(object),
|
|
93
|
+
note: (object) => {
|
|
94
|
+
const resolved = resolveGrassObject(object);
|
|
95
|
+
if (resolved === null)
|
|
96
|
+
return "Give the volume a box footprint.";
|
|
97
|
+
const area = resolved.size[0] * resolved.size[1];
|
|
98
|
+
return `${Math.round(resolved.size[0])}×${Math.round(resolved.size[1])} m · ≈${Math.round(area * resolved.rules.density).toLocaleString()} blades`;
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** One placed transform along a path: grounded position, facing yaw, and its ordinal + arc distance. */
|
|
2
|
+
export interface PathInstance {
|
|
3
|
+
index: number;
|
|
4
|
+
/** Arc-length distance from the path start, meters. */
|
|
5
|
+
distance: number;
|
|
6
|
+
position: readonly [number, number, number];
|
|
7
|
+
/** Yaw (radians) facing along the direction of travel. */
|
|
8
|
+
yaw: number;
|
|
9
|
+
}
|
|
10
|
+
/** Options for {@link placeAlongPath}. */
|
|
11
|
+
export interface PlaceAlongPathOptions {
|
|
12
|
+
/** Target meters between instances. The run is divided into equal spans nearest this spacing. */
|
|
13
|
+
spacing: number;
|
|
14
|
+
/** Ground each instance to this height sampler (else y = 0). */
|
|
15
|
+
sampleHeight?: (x: number, z: number) => number;
|
|
16
|
+
/** Force at least this many instances regardless of length. Default 1 (endpoints only when short). */
|
|
17
|
+
minCount?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Evenly place transforms along `points` (XZ polyline). The run length is divided into the whole
|
|
21
|
+
* number of equal spans closest to `spacing`, so instances always land on both endpoints and stay
|
|
22
|
+
* evenly distributed. Returns `spans + 1` instances. Empty for fewer than 2 points.
|
|
23
|
+
*/
|
|
24
|
+
export declare function placeAlongPath(points: readonly {
|
|
25
|
+
x: number;
|
|
26
|
+
z: number;
|
|
27
|
+
}[], options: PlaceAlongPathOptions): PathInstance[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { pointAtDistance, polyline, tangentAtDistance } from "./polyline.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evenly place transforms along `points` (XZ polyline). The run length is divided into the whole
|
|
4
|
+
* number of equal spans closest to `spacing`, so instances always land on both endpoints and stay
|
|
5
|
+
* evenly distributed. Returns `spans + 1` instances. Empty for fewer than 2 points.
|
|
6
|
+
*/
|
|
7
|
+
export function placeAlongPath(points, options) {
|
|
8
|
+
if (points.length < 2)
|
|
9
|
+
return [];
|
|
10
|
+
const line = polyline(points.map((point) => [point.x, point.z]));
|
|
11
|
+
const total = line.length;
|
|
12
|
+
if (total <= 0)
|
|
13
|
+
return [];
|
|
14
|
+
const spacing = Math.max(0.01, options.spacing);
|
|
15
|
+
const minSpans = Math.max(1, (options.minCount ?? 1) - 1);
|
|
16
|
+
const spans = Math.max(minSpans, Math.round(total / spacing), 1);
|
|
17
|
+
const step = total / spans;
|
|
18
|
+
const out = [];
|
|
19
|
+
for (let i = 0; i <= spans; i += 1) {
|
|
20
|
+
const distance = i * step;
|
|
21
|
+
const [x, z] = pointAtDistance(line, distance);
|
|
22
|
+
const [tx, tz] = tangentAtDistance(line, Math.min(distance, total - 1e-4));
|
|
23
|
+
const y = options.sampleHeight?.(x, z) ?? 0;
|
|
24
|
+
out.push({ index: i, distance, position: [x, y, z], yaw: Math.atan2(tx, tz) });
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path-driven terrain modifiers: one authored centerline reshapes a heightfield across a corridor —
|
|
3
|
+
* flatten a roadbed, grade a constant-slope ramp, carve a river/trench, and hold retaining walls where
|
|
4
|
+
* the corridor cuts or fills into the surrounding ground. Genre-agnostic: roads, rails, rivers,
|
|
5
|
+
* trenches, runways, and accessibility ramps are all the same profile with different numbers, so no game
|
|
6
|
+
* hand-rolls its own flatten-mask generator. Pure XZ math over a polyline — deterministic, bounded
|
|
7
|
+
* (O(points) per sample), and serializable; it composes onto any height sampler and pairs with
|
|
8
|
+
* `resolveTerrainField` so the same authored path drives both the rendered mesh and player collision.
|
|
9
|
+
* @capability path-terrain flatten / grade / carve a heightfield from an authored path with retaining profiles
|
|
10
|
+
* @consumer packages/core/src/world/terrain.ts (resolveTerrainField), Games/the-robots roads
|
|
11
|
+
*/
|
|
12
|
+
import type { Vec2 } from "./geometry.js";
|
|
13
|
+
/**
|
|
14
|
+
* Where a path corridor drives its centerline height:
|
|
15
|
+
* - `sample` — follow the base terrain under the centerline, so the corridor drapes level across its
|
|
16
|
+
* width while still tracking the hills the path crosses (the natural policy for a road or trail).
|
|
17
|
+
* - `fixed` — hold one constant height for the whole corridor (a level causeway, runway, or dam crest).
|
|
18
|
+
* - `grade` — interpolate linearly from `start` to `end` height along the path's arc length, a
|
|
19
|
+
* constant-slope ramp between two anchors (a switchback, a graded rail bed, an accessibility ramp).
|
|
20
|
+
*/
|
|
21
|
+
export type PathHeightPolicy = {
|
|
22
|
+
readonly kind: "sample";
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: "fixed";
|
|
25
|
+
readonly height: number;
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: "grade";
|
|
28
|
+
readonly start: number;
|
|
29
|
+
readonly end: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Retaining behavior for a path corridor's shoulders. A wall rises only where the corridor already cuts or
|
|
33
|
+
* fills into the surrounding ground by at least `threshold` — gentle stretches stay open — so a road
|
|
34
|
+
* through a canyon gets held banks while the same profile on flat ground does not. The wall fades in
|
|
35
|
+
* smoothly across `taper` above the threshold so it never steps on or off between adjacent samples.
|
|
36
|
+
*/
|
|
37
|
+
export interface PathRetaining {
|
|
38
|
+
/** Crest height raised above the corridor edge on both shoulders (canyon walls, road berms, levee banks). */
|
|
39
|
+
readonly wallHeight: number;
|
|
40
|
+
/** Minimum cut/fill (world units) between corridor and surrounding ground before a wall rises. Default 0 (wall the whole path). */
|
|
41
|
+
readonly threshold?: number;
|
|
42
|
+
/** Cut/fill band above `threshold` over which the wall fades from none to full height. Default equal to `threshold`. */
|
|
43
|
+
readonly taper?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A serializable path-driven terrain modifier. The `points` centerline reshapes the heightfield across a
|
|
47
|
+
* corridor of `width`, feathering back to the surrounding ground across `shoulder`. `height` sets the
|
|
48
|
+
* centerline target (sample / fixed / grade); `depth` carves a channel below it (deepest at the
|
|
49
|
+
* centerline, easing to zero at the core edge — rivers and trenches); `retaining` raises walls where the
|
|
50
|
+
* cut/fill exceeds a threshold; `maxCut`/`maxFill` cap how far the ground may move from its base height.
|
|
51
|
+
* All fields are plain data (numbers, string enums, point arrays) so a profile round-trips through the
|
|
52
|
+
* scene document and evaluates identically at author time and runtime.
|
|
53
|
+
*/
|
|
54
|
+
export interface TerrainPathProfile {
|
|
55
|
+
/** Centerline vertices in world XZ; needs at least two points. Repeat the first point as the last for a closed loop. */
|
|
56
|
+
readonly points: readonly Vec2[];
|
|
57
|
+
/** Full corridor width; the reshaped core extends `width / 2` either side of the centerline. */
|
|
58
|
+
readonly width: number;
|
|
59
|
+
/** Blend-ring width outside the core where the corridor height smoothsteps back to the surrounding ground. Default `width * 0.5`. */
|
|
60
|
+
readonly shoulder?: number;
|
|
61
|
+
/** Centerline target-height policy. Default `{ kind: "sample" }` (drape level across the base terrain). */
|
|
62
|
+
readonly height?: PathHeightPolicy;
|
|
63
|
+
/** Carve depth below the target height, deepest at the centerline and easing to zero at the core edge (0 = flat corridor). Default 0. */
|
|
64
|
+
readonly depth?: number;
|
|
65
|
+
/** Never cut the ground more than this far below its base height. Omit for unlimited cut. */
|
|
66
|
+
readonly maxCut?: number;
|
|
67
|
+
/** Never fill the ground more than this far above its base height. Omit for unlimited fill. */
|
|
68
|
+
readonly maxFill?: number;
|
|
69
|
+
/** Raise retaining walls along the shoulders where the corridor cuts/fills into the surrounding ground. */
|
|
70
|
+
readonly retaining?: PathRetaining;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Wraps a height sampler so each authored `TerrainPathProfile` reshapes it. Profiles apply in list order
|
|
74
|
+
* (later profiles compose over earlier ones, so an intersection's last profile wins its core); each reads
|
|
75
|
+
* the running height as its surrounding ground and the original `base` for `sample` centerline heights.
|
|
76
|
+
* The returned sampler is pure and deterministic. Degenerate profiles (fewer than two points, non-positive
|
|
77
|
+
* width or length) are skipped; with no usable profile the original `base` is returned unchanged.
|
|
78
|
+
* @capability path-terrain compose flatten/grade/carve/retaining path profiles onto a height sampler
|
|
79
|
+
*/
|
|
80
|
+
export declare function withPathProfiles(base: (x: number, z: number) => number, profiles: readonly TerrainPathProfile[]): (x: number, z: number) => number;
|