@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.
Files changed (631) hide show
  1. package/CHANGELOG.md +34 -3
  2. package/LICENSE +203 -661
  3. package/README.md +1 -1
  4. package/dist/ai/crowd.d.ts +55 -0
  5. package/dist/ai/crowd.js +114 -0
  6. package/dist/ai/flock.d.ts +5 -2
  7. package/dist/ai/flock.js +5 -2
  8. package/dist/ai/groupAssist.d.ts +1 -0
  9. package/dist/ai/groupAssist.js +1 -0
  10. package/dist/ai/heatSystem.d.ts +76 -0
  11. package/dist/ai/heatSystem.js +97 -0
  12. package/dist/ai/interestScheduler.d.ts +107 -0
  13. package/dist/ai/interestScheduler.js +118 -0
  14. package/dist/ai/jobBoard.d.ts +1 -0
  15. package/dist/ai/jobBoard.js +1 -0
  16. package/dist/ai/laneSelect.d.ts +5 -2
  17. package/dist/ai/laneSelect.js +5 -2
  18. package/dist/ai/mobBrain.d.ts +1 -0
  19. package/dist/ai/mobBrain.js +1 -0
  20. package/dist/ai/spawnDirector.d.ts +19 -1
  21. package/dist/ai/spawnDirector.js +53 -26
  22. package/dist/ai/spawnPoint.d.ts +7 -0
  23. package/dist/ai/spawnPoint.js +7 -0
  24. package/dist/ai/targetAcquisition.d.ts +84 -0
  25. package/dist/ai/targetAcquisition.js +92 -0
  26. package/dist/anim/easing.d.ts +19 -0
  27. package/dist/anim/easing.js +19 -0
  28. package/dist/anim/oscillator.d.ts +12 -0
  29. package/dist/anim/oscillator.js +25 -0
  30. package/dist/area/areaEffectField.d.ts +127 -0
  31. package/dist/area/areaEffectField.js +175 -0
  32. package/dist/area/stackPolicy.d.ts +47 -0
  33. package/dist/area/stackPolicy.js +99 -0
  34. package/dist/audio/audioFalloff.d.ts +5 -2
  35. package/dist/audio/music.d.ts +53 -0
  36. package/dist/audio/music.js +34 -0
  37. package/dist/audio/synth.d.ts +60 -0
  38. package/dist/audio/synth.js +8 -0
  39. package/dist/authoring.d.ts +15 -0
  40. package/dist/authoring.js +15 -0
  41. package/dist/board/laneBoard.d.ts +13 -0
  42. package/dist/board/laneBoard.js +13 -0
  43. package/dist/board/timelineBoard.d.ts +10 -0
  44. package/dist/board/timelineBoard.js +10 -0
  45. package/dist/combat/abilityKit.d.ts +18 -0
  46. package/dist/combat/abilityKit.js +24 -9
  47. package/dist/combat/animationState.d.ts +5 -0
  48. package/dist/combat/animationState.js +5 -0
  49. package/dist/combat/breakMeters.d.ts +10 -0
  50. package/dist/combat/breakMeters.js +10 -0
  51. package/dist/combat/castRunner.d.ts +5 -0
  52. package/dist/combat/castRunner.js +5 -0
  53. package/dist/combat/comboPoints.d.ts +5 -0
  54. package/dist/combat/comboPoints.js +5 -0
  55. package/dist/combat/comboString.d.ts +5 -0
  56. package/dist/combat/comboString.js +5 -0
  57. package/dist/combat/damageInterceptors.d.ts +192 -0
  58. package/dist/combat/damageInterceptors.js +251 -0
  59. package/dist/combat/damageMatchup.d.ts +68 -0
  60. package/dist/combat/damageMatchup.js +42 -0
  61. package/dist/combat/damageResolution.d.ts +63 -0
  62. package/dist/combat/damageResolution.js +50 -0
  63. package/dist/combat/death.d.ts +7 -1
  64. package/dist/combat/death.js +5 -0
  65. package/dist/combat/deathReason.d.ts +14 -0
  66. package/dist/combat/deathReason.js +1 -0
  67. package/dist/combat/defensiveWindow.d.ts +5 -0
  68. package/dist/combat/defensiveWindow.js +5 -0
  69. package/dist/combat/dotField.d.ts +47 -0
  70. package/dist/combat/dotField.js +52 -0
  71. package/dist/combat/downed.d.ts +5 -0
  72. package/dist/combat/downed.js +5 -0
  73. package/dist/combat/effects.d.ts +5 -0
  74. package/dist/combat/effects.js +5 -0
  75. package/dist/combat/encounterSequence.d.ts +258 -0
  76. package/dist/combat/encounterSequence.js +426 -0
  77. package/dist/combat/hitReaction.d.ts +57 -1
  78. package/dist/combat/hitReaction.js +45 -5
  79. package/dist/combat/magazine.d.ts +54 -0
  80. package/dist/combat/magazine.js +96 -0
  81. package/dist/combat/projectiles.d.ts +7 -2
  82. package/dist/combat/projectiles.js +48 -17
  83. package/dist/combat/receivedDamage.d.ts +117 -0
  84. package/dist/combat/receivedDamage.js +92 -0
  85. package/dist/combat/regenShield.d.ts +39 -0
  86. package/dist/combat/regenShield.js +49 -0
  87. package/dist/combat/renderCues.d.ts +51 -0
  88. package/dist/combat/renderCues.js +44 -0
  89. package/dist/combat/resourcePool.d.ts +5 -0
  90. package/dist/combat/resourcePool.js +5 -0
  91. package/dist/combat/rewardAllocation.d.ts +121 -0
  92. package/dist/combat/rewardAllocation.js +251 -0
  93. package/dist/combat/shotOrigin.d.ts +30 -1
  94. package/dist/combat/shotOrigin.js +70 -2
  95. package/dist/combat/statusApplication.d.ts +96 -0
  96. package/dist/combat/statusApplication.js +81 -0
  97. package/dist/combat/telegraph.d.ts +11 -2
  98. package/dist/combat/telegraph.js +11 -2
  99. package/dist/combat/thresholdCrossings.d.ts +85 -0
  100. package/dist/combat/thresholdCrossings.js +116 -0
  101. package/dist/combat.d.ts +34 -0
  102. package/dist/combat.js +34 -0
  103. package/dist/commands/commandRegistry.d.ts +11 -0
  104. package/dist/commands/commandRegistry.js +9 -2
  105. package/dist/crafting/crop.d.ts +18 -0
  106. package/dist/crafting/crop.js +18 -0
  107. package/dist/crafting/production.d.ts +5 -0
  108. package/dist/crafting/production.js +5 -0
  109. package/dist/devtools/rewriteTunables.d.ts +17 -0
  110. package/dist/devtools/rewriteTunables.js +276 -0
  111. package/dist/devtools/saveEndpoint.d.ts +46 -0
  112. package/dist/devtools/saveEndpoint.js +48 -0
  113. package/dist/devtools/transformTunables.d.ts +3 -0
  114. package/dist/devtools/transformTunables.js +3 -0
  115. package/dist/devtools/tunableSchema.d.ts +31 -0
  116. package/dist/devtools/tunableSchema.js +31 -0
  117. package/dist/economy/currency.d.ts +12 -1
  118. package/dist/economy/currency.js +12 -1
  119. package/dist/economy/listingBook.d.ts +91 -0
  120. package/dist/economy/listingBook.js +144 -0
  121. package/dist/economy/resourceLedger.d.ts +222 -0
  122. package/dist/economy/resourceLedger.js +353 -0
  123. package/dist/economy/sharedWallet.d.ts +14 -0
  124. package/dist/economy/sharedWallet.js +14 -0
  125. package/dist/economy/techTree.d.ts +12 -0
  126. package/dist/economy/techTree.js +12 -0
  127. package/dist/economy/wallet.d.ts +26 -2
  128. package/dist/economy/wallet.js +35 -6
  129. package/dist/editor/commands.d.ts +248 -0
  130. package/dist/editor/commands.js +865 -0
  131. package/dist/editor/document.d.ts +186 -0
  132. package/dist/editor/document.js +884 -0
  133. package/dist/editor/grid.d.ts +229 -0
  134. package/dist/editor/grid.js +366 -0
  135. package/dist/editor/gridAdapters.d.ts +80 -0
  136. package/dist/editor/gridAdapters.js +134 -0
  137. package/dist/editor/index.d.ts +97 -0
  138. package/dist/editor/index.js +10 -0
  139. package/dist/editor/liveSync.d.ts +127 -0
  140. package/dist/editor/liveSync.js +249 -0
  141. package/dist/editor/runtimeInspector.d.ts +88 -0
  142. package/dist/editor/runtimeInspector.js +239 -0
  143. package/dist/editor/types.d.ts +175 -0
  144. package/dist/editor/types.js +29 -0
  145. package/dist/faction/reputation.d.ts +5 -0
  146. package/dist/faction/reputation.js +5 -0
  147. package/dist/format/distance.d.ts +17 -0
  148. package/dist/format/distance.js +18 -0
  149. package/dist/format/duration.d.ts +27 -0
  150. package/dist/format/duration.js +45 -0
  151. package/dist/format/speed.d.ts +17 -0
  152. package/dist/format/speed.js +25 -0
  153. package/dist/game/connectedPlayers.d.ts +30 -0
  154. package/dist/game/connectedPlayers.js +21 -0
  155. package/dist/game/cosmetics.d.ts +9 -0
  156. package/dist/game/cosmetics.js +16 -0
  157. package/dist/game/defineGame.d.ts +141 -2
  158. package/dist/game/defineGame.js +39 -1
  159. package/dist/game/defineSystem.d.ts +88 -0
  160. package/dist/game/defineSystem.js +45 -0
  161. package/dist/game/dialogue.d.ts +33 -0
  162. package/dist/game/dialogue.js +21 -0
  163. package/dist/game/events.d.ts +50 -13
  164. package/dist/game/events.js +5 -0
  165. package/dist/game/feed.d.ts +33 -0
  166. package/dist/game/feed.js +35 -2
  167. package/dist/game/gamePhase.d.ts +11 -0
  168. package/dist/game/gamePhase.js +16 -0
  169. package/dist/game/keyValueStore.d.ts +25 -0
  170. package/dist/game/keyValueStore.js +61 -0
  171. package/dist/game/leaderboard.d.ts +5 -0
  172. package/dist/game/leaderboard.js +5 -0
  173. package/dist/game/levelSequence.d.ts +24 -2
  174. package/dist/game/levelSequence.js +51 -2
  175. package/dist/game/loadout.d.ts +5 -0
  176. package/dist/game/loadout.js +5 -0
  177. package/dist/game/lootFilter.d.ts +2 -0
  178. package/dist/game/lootFilter.js +2 -0
  179. package/dist/game/lootPipeline.d.ts +164 -0
  180. package/dist/game/lootPipeline.js +216 -0
  181. package/dist/game/lootTable.d.ts +21 -0
  182. package/dist/game/lootTable.js +15 -4
  183. package/dist/game/modelAnimation.d.ts +8 -0
  184. package/dist/game/modelAnimation.js +18 -0
  185. package/dist/game/objectives.d.ts +43 -0
  186. package/dist/game/objectives.js +36 -0
  187. package/dist/game/paramLayers.d.ts +148 -0
  188. package/dist/game/paramLayers.js +185 -0
  189. package/dist/game/ping.d.ts +5 -0
  190. package/dist/game/ping.js +5 -0
  191. package/dist/game/playableGame.d.ts +160 -12
  192. package/dist/game/quest.d.ts +8 -0
  193. package/dist/game/quest.js +29 -0
  194. package/dist/game/race.d.ts +141 -0
  195. package/dist/game/race.js +169 -0
  196. package/dist/game/recordBook.d.ts +5 -5
  197. package/dist/game/recordBook.js +4 -1
  198. package/dist/game/ruleSelection.d.ts +75 -0
  199. package/dist/game/ruleSelection.js +127 -0
  200. package/dist/game/runDraft.d.ts +5 -0
  201. package/dist/game/runDraft.js +5 -0
  202. package/dist/game/saveStore.d.ts +111 -0
  203. package/dist/game/saveStore.js +312 -0
  204. package/dist/game/snapshotHistory.d.ts +67 -0
  205. package/dist/game/snapshotHistory.js +95 -0
  206. package/dist/game/social.d.ts +38 -1
  207. package/dist/game/social.js +71 -0
  208. package/dist/game/spawnPoints.d.ts +5 -0
  209. package/dist/game/spawnPoints.js +5 -0
  210. package/dist/game/systemRuntime.d.ts +50 -0
  211. package/dist/game/systemRuntime.js +157 -0
  212. package/dist/game/systemSchedule.d.ts +72 -0
  213. package/dist/game/systemSchedule.js +242 -0
  214. package/dist/game/toasts.d.ts +43 -0
  215. package/dist/game/toasts.js +44 -0
  216. package/dist/game/trade.d.ts +10 -0
  217. package/dist/game/trade.js +10 -0
  218. package/dist/game/unlocks.d.ts +8 -0
  219. package/dist/game/unlocks.js +16 -0
  220. package/dist/game/vfxInstance.d.ts +138 -0
  221. package/dist/game/vfxInstance.js +96 -0
  222. package/dist/game/worldItem.d.ts +17 -4
  223. package/dist/game/worldItem.js +17 -4
  224. package/dist/gameplay.d.ts +91 -0
  225. package/dist/gameplay.js +91 -0
  226. package/dist/index.d.ts +5 -7
  227. package/dist/index.js +5 -7
  228. package/dist/input/actionBindings.d.ts +24 -5
  229. package/dist/input/actionBindings.js +23 -5
  230. package/dist/input/axisInput.d.ts +13 -1
  231. package/dist/input/axisInput.js +22 -1
  232. package/dist/input/controlGroups.d.ts +67 -0
  233. package/dist/input/controlGroups.js +41 -0
  234. package/dist/input/touchScheme.d.ts +82 -6
  235. package/dist/input/touchScheme.js +123 -10
  236. package/dist/interaction/contextMenu.d.ts +1 -0
  237. package/dist/interaction/contextMenu.js +1 -0
  238. package/dist/interaction/lockpick.d.ts +61 -0
  239. package/dist/interaction/lockpick.js +168 -0
  240. package/dist/interaction/proximityPrompt.d.ts +5 -1
  241. package/dist/interaction/proximityPrompt.js +5 -3
  242. package/dist/interaction/qte.d.ts +5 -0
  243. package/dist/interaction/qte.js +5 -0
  244. package/dist/interaction/skillCheck.d.ts +5 -0
  245. package/dist/interaction/skillCheck.js +5 -0
  246. package/dist/inventory/inventoryModel.d.ts +12 -0
  247. package/dist/inventory/inventoryModel.js +12 -0
  248. package/dist/inventory/shapedGrid.d.ts +16 -0
  249. package/dist/inventory/shapedGrid.js +16 -0
  250. package/dist/inventory/slotModel.d.ts +10 -0
  251. package/dist/inventory/slotModel.js +10 -0
  252. package/dist/item/durability.d.ts +5 -0
  253. package/dist/item/durability.js +5 -0
  254. package/dist/item/itemIdentity.d.ts +171 -0
  255. package/dist/item/itemIdentity.js +138 -0
  256. package/dist/item/itemInstanceRegistry.d.ts +32 -0
  257. package/dist/item/itemInstanceRegistry.js +34 -0
  258. package/dist/item/itemgen.d.ts +163 -0
  259. package/dist/item/itemgen.js +151 -0
  260. package/dist/item/modularItem.d.ts +5 -0
  261. package/dist/item/modularItem.js +5 -0
  262. package/dist/item/use.d.ts +5 -0
  263. package/dist/item/use.js +5 -0
  264. package/dist/item/useBehavior.d.ts +142 -0
  265. package/dist/item/useBehavior.js +105 -0
  266. package/dist/item/weapon.d.ts +5 -0
  267. package/dist/item/weapon.js +5 -0
  268. package/dist/math/scalar.d.ts +25 -0
  269. package/dist/math/scalar.js +47 -0
  270. package/dist/meta/changelog.d.ts +4 -1
  271. package/dist/meta/changelog.js +36 -1
  272. package/dist/movement/avoidance.d.ts +45 -0
  273. package/dist/movement/avoidance.js +123 -0
  274. package/dist/movement/cameraRig.d.ts +8 -0
  275. package/dist/movement/cameraRig.js +8 -0
  276. package/dist/movement/dash.d.ts +11 -0
  277. package/dist/movement/dash.js +11 -0
  278. package/dist/movement/formation.d.ts +135 -0
  279. package/dist/movement/formation.js +194 -0
  280. package/dist/movement/glideModel.d.ts +5 -0
  281. package/dist/movement/glideModel.js +5 -0
  282. package/dist/movement/grappleSwing.d.ts +5 -0
  283. package/dist/movement/grappleSwing.js +5 -0
  284. package/dist/movement/leaderTrail.d.ts +5 -0
  285. package/dist/movement/leaderTrail.js +5 -0
  286. package/dist/movement/movementModel.d.ts +38 -7
  287. package/dist/movement/movementModel.js +54 -13
  288. package/dist/movement/playerMovement.d.ts +41 -0
  289. package/dist/movement/playerMovement.js +236 -0
  290. package/dist/movement/poseState.d.ts +13 -0
  291. package/dist/movement/poseState.js +16 -0
  292. package/dist/movement/steering.d.ts +8 -0
  293. package/dist/movement/steering.js +18 -0
  294. package/dist/multiplayer/combatSnapshot.d.ts +3 -0
  295. package/dist/multiplayer/combatSnapshot.js +3 -0
  296. package/dist/multiplayer/lagCompensation.d.ts +5 -0
  297. package/dist/multiplayer/lagCompensation.js +5 -0
  298. package/dist/multiplayer/presenceModel.d.ts +9 -1
  299. package/dist/multiplayer/presenceModel.js +9 -1
  300. package/dist/multiplayer/simultaneousCommit.d.ts +3 -0
  301. package/dist/multiplayer/simultaneousCommit.js +3 -0
  302. package/dist/multiplayer.d.ts +11 -0
  303. package/dist/multiplayer.js +11 -0
  304. package/dist/nav/pathFollow.d.ts +57 -0
  305. package/dist/nav/pathFollow.js +109 -0
  306. package/dist/orders/orderKinds.d.ts +156 -0
  307. package/dist/orders/orderKinds.js +197 -0
  308. package/dist/orders/orderQueue.d.ts +208 -0
  309. package/dist/orders/orderQueue.js +211 -0
  310. package/dist/physics/drivableVehicle.d.ts +29 -0
  311. package/dist/physics/drivableVehicle.js +16 -0
  312. package/dist/physics/kinematicVehicle.d.ts +21 -1
  313. package/dist/physics/kinematicVehicle.js +23 -8
  314. package/dist/physics/physicsWorld.d.ts +24 -12
  315. package/dist/physics/physicsWorld.js +11 -5
  316. package/dist/physics/radialImpulse.d.ts +25 -0
  317. package/dist/physics/radialImpulse.js +27 -0
  318. package/dist/procedural.d.ts +3 -0
  319. package/dist/procedural.js +3 -0
  320. package/dist/progression/statGraph.d.ts +116 -0
  321. package/dist/progression/statGraph.js +318 -0
  322. package/dist/puzzle/cellGrid.d.ts +9 -0
  323. package/dist/puzzle/cellGrid.js +9 -0
  324. package/dist/puzzle/fallingPiece.d.ts +9 -0
  325. package/dist/puzzle/fallingPiece.js +9 -0
  326. package/dist/puzzle/nonogram.d.ts +39 -0
  327. package/dist/puzzle/nonogram.js +136 -0
  328. package/dist/random/nameGen.d.ts +5 -0
  329. package/dist/random/nameGen.js +5 -0
  330. package/dist/random/pick.d.ts +8 -0
  331. package/dist/random/pick.js +31 -0
  332. package/dist/random/rng.d.ts +24 -0
  333. package/dist/random/rng.js +30 -8
  334. package/dist/random/seedLink.d.ts +4 -0
  335. package/dist/random/seedLink.js +4 -0
  336. package/dist/relation/keyedValues.d.ts +54 -0
  337. package/dist/relation/keyedValues.js +115 -0
  338. package/dist/relation/thresholds.d.ts +62 -0
  339. package/dist/relation/thresholds.js +62 -0
  340. package/dist/render/color.d.ts +12 -0
  341. package/dist/render/color.js +26 -0
  342. package/dist/render/lookPreset.d.ts +41 -0
  343. package/dist/render/lookPreset.js +29 -0
  344. package/dist/render/postProcessing.d.ts +76 -0
  345. package/dist/render/postProcessing.js +21 -0
  346. package/dist/rules/predicate.d.ts +53 -0
  347. package/dist/rules/predicate.js +64 -0
  348. package/dist/rules/ruleEffects.d.ts +38 -0
  349. package/dist/rules/ruleEffects.js +37 -0
  350. package/dist/rules/triggeredRules.d.ts +160 -0
  351. package/dist/rules/triggeredRules.js +241 -0
  352. package/dist/runtime/adapter.d.ts +58 -0
  353. package/dist/runtime/adapter.js +54 -5
  354. package/dist/runtime/cameraDirector.d.ts +1 -0
  355. package/dist/runtime/cameraDirector.js +1 -0
  356. package/dist/runtime/commandRunner.d.ts +1 -0
  357. package/dist/runtime/commandRunner.js +1 -0
  358. package/dist/runtime/context/combatFx.d.ts +23 -0
  359. package/dist/runtime/context/combatFx.js +161 -0
  360. package/dist/runtime/context/registries.d.ts +13 -0
  361. package/dist/runtime/context/registries.js +84 -0
  362. package/dist/runtime/context/worldItems.d.ts +21 -0
  363. package/dist/runtime/context/worldItems.js +37 -0
  364. package/dist/runtime/descriptors/baseline.d.ts +48 -0
  365. package/dist/runtime/descriptors/baseline.js +134 -0
  366. package/dist/runtime/descriptors/features.d.ts +74 -0
  367. package/dist/runtime/descriptors/features.js +281 -0
  368. package/dist/runtime/gameContext.d.ts +163 -19
  369. package/dist/runtime/gameContext.js +385 -339
  370. package/dist/runtime/gameRuntime.d.ts +1 -0
  371. package/dist/runtime/gameRuntime.js +1 -0
  372. package/dist/runtime/headlessRunner.d.ts +60 -0
  373. package/dist/runtime/headlessRunner.js +44 -0
  374. package/dist/runtime/hostPersistence.d.ts +12 -0
  375. package/dist/runtime/hostPersistence.js +12 -0
  376. package/dist/runtime/hostedGameRunner.d.ts +54 -0
  377. package/dist/runtime/hostedGameRunner.js +85 -0
  378. package/dist/runtime/hostedWorldSession.d.ts +73 -0
  379. package/dist/runtime/hostedWorldSession.js +64 -0
  380. package/dist/runtime/inputSnapshot.d.ts +21 -3
  381. package/dist/runtime/inputSnapshot.js +8 -2
  382. package/dist/runtime/motionIntents.d.ts +12 -1
  383. package/dist/runtime/motionIntents.js +26 -1
  384. package/dist/runtime/perContext.d.ts +15 -0
  385. package/dist/runtime/perContext.js +21 -0
  386. package/dist/runtime/runtimeSave.d.ts +79 -0
  387. package/dist/runtime/runtimeSave.js +105 -0
  388. package/dist/runtime/save.d.ts +4 -0
  389. package/dist/runtime/save.js +4 -0
  390. package/dist/runtime/snapshot.d.ts +7 -0
  391. package/dist/runtime/snapshot.js +7 -0
  392. package/dist/runtime/visibility.d.ts +2 -1
  393. package/dist/runtime/visibility.js +2 -1
  394. package/dist/runtime/worldChannel.d.ts +62 -0
  395. package/dist/runtime/worldChannel.js +114 -0
  396. package/dist/runtime/worldMirror.d.ts +36 -0
  397. package/dist/runtime/worldMirror.js +44 -0
  398. package/dist/runtime/worldProjection.d.ts +47 -0
  399. package/dist/runtime/worldProjection.js +52 -0
  400. package/dist/runtime/worldReplication.d.ts +69 -0
  401. package/dist/runtime/worldReplication.js +217 -0
  402. package/dist/runtime/worldSnapshot.d.ts +44 -0
  403. package/dist/runtime/worldSnapshot.js +30 -0
  404. package/dist/scene/assetCatalog.d.ts +22 -0
  405. package/dist/scene/assetCatalog.js +4 -0
  406. package/dist/scene/assetDiagnostics.d.ts +69 -0
  407. package/dist/scene/assetDiagnostics.js +110 -0
  408. package/dist/scene/assetGenerator.d.ts +65 -0
  409. package/dist/scene/assetGenerator.js +64 -0
  410. package/dist/scene/assetSpace.d.ts +137 -0
  411. package/dist/scene/assetSpace.js +259 -0
  412. package/dist/scene/authoredTriggers.d.ts +169 -0
  413. package/dist/scene/authoredTriggers.js +340 -0
  414. package/dist/scene/behaviorRuntime.d.ts +75 -0
  415. package/dist/scene/behaviorRuntime.js +217 -0
  416. package/dist/scene/behaviors.d.ts +14 -2
  417. package/dist/scene/behaviors.js +7 -2
  418. package/dist/scene/bodyBind.d.ts +60 -0
  419. package/dist/scene/bodyBind.js +51 -0
  420. package/dist/scene/builtinSceneKinds.d.ts +5 -0
  421. package/dist/scene/builtinSceneKinds.js +62 -0
  422. package/dist/scene/colliders.d.ts +18 -0
  423. package/dist/scene/colliders.js +61 -1
  424. package/dist/scene/entityStats.d.ts +13 -0
  425. package/dist/scene/entityStats.js +30 -0
  426. package/dist/scene/entityStore.d.ts +41 -1
  427. package/dist/scene/entityStore.js +75 -0
  428. package/dist/scene/facing.d.ts +18 -0
  429. package/dist/scene/facing.js +26 -0
  430. package/dist/scene/modelSockets.d.ts +33 -0
  431. package/dist/scene/modelSockets.js +29 -0
  432. package/dist/scene/objectQuery.d.ts +2 -0
  433. package/dist/scene/objectQuery.js +2 -0
  434. package/dist/scene/objectStore.d.ts +4 -0
  435. package/dist/scene/objectStore.js +6 -0
  436. package/dist/scene/possession.d.ts +8 -0
  437. package/dist/scene/possession.js +14 -0
  438. package/dist/scene/roster.d.ts +3 -0
  439. package/dist/scene/roster.js +12 -0
  440. package/dist/scene/sceneKinds.d.ts +240 -0
  441. package/dist/scene/sceneKinds.js +214 -0
  442. package/dist/scene/sceneOwnership.d.ts +169 -0
  443. package/dist/scene/sceneOwnership.js +179 -0
  444. package/dist/scene/selectionBookmarks.d.ts +93 -0
  445. package/dist/scene/selectionBookmarks.js +122 -0
  446. package/dist/scene/vehicleSeat.d.ts +68 -0
  447. package/dist/scene/vehicleSeat.js +59 -0
  448. package/dist/sensor/concealment.d.ts +3 -0
  449. package/dist/sensor/concealment.js +3 -0
  450. package/dist/sensor/freezeMonitor.d.ts +1 -0
  451. package/dist/sensor/freezeMonitor.js +1 -0
  452. package/dist/sensor/frustumSensor.d.ts +7 -3
  453. package/dist/sensor/frustumSensor.js +7 -3
  454. package/dist/sensor/hiddenStateProbe.d.ts +5 -2
  455. package/dist/sensor/hiddenStateProbe.js +5 -2
  456. package/dist/sensor/recordingBuffer.d.ts +2 -1
  457. package/dist/sensor/recordingBuffer.js +2 -1
  458. package/dist/sensor/replayLoop.d.ts +6 -2
  459. package/dist/sensor/replayLoop.js +6 -2
  460. package/dist/sensor/revealQuery.d.ts +2 -1
  461. package/dist/sensor/revealQuery.js +2 -1
  462. package/dist/sensor/visionCone.d.ts +10 -3
  463. package/dist/sensor/visionCone.js +10 -3
  464. package/dist/session/contestedChannel.d.ts +1 -0
  465. package/dist/session/contestedChannel.js +1 -0
  466. package/dist/session/extraction.d.ts +1 -0
  467. package/dist/session/extraction.js +1 -0
  468. package/dist/session/roles.d.ts +6 -0
  469. package/dist/session/roles.js +6 -0
  470. package/dist/session/roundState.d.ts +8 -0
  471. package/dist/session/roundState.js +2 -0
  472. package/dist/settings/settingsModel.d.ts +1 -0
  473. package/dist/settings/settingsModel.js +1 -0
  474. package/dist/stats/accumulatorMeter.d.ts +6 -0
  475. package/dist/stats/accumulatorMeter.js +6 -0
  476. package/dist/stats/eventMeter.d.ts +5 -0
  477. package/dist/stats/eventMeter.js +5 -0
  478. package/dist/stats/rollCheck.d.ts +5 -0
  479. package/dist/stats/rollCheck.js +5 -0
  480. package/dist/stats/statModifiers.d.ts +5 -0
  481. package/dist/stats/statModifiers.js +5 -0
  482. package/dist/store/defineKeyedStore.d.ts +38 -0
  483. package/dist/store/defineKeyedStore.js +42 -0
  484. package/dist/store/defineStore.d.ts +33 -0
  485. package/dist/store/defineStore.js +35 -0
  486. package/dist/store/observableKeyedStore.d.ts +9 -0
  487. package/dist/store/observableKeyedStore.js +43 -2
  488. package/dist/survival/decayMeter.d.ts +55 -0
  489. package/dist/survival/decayMeter.js +130 -55
  490. package/dist/survival/moodle.d.ts +2 -0
  491. package/dist/survival/regionHealth.d.ts +6 -0
  492. package/dist/survival/regionHealth.js +5 -0
  493. package/dist/tactics/fallingGrid.d.ts +6 -4
  494. package/dist/tactics/fallingGrid.js +6 -4
  495. package/dist/tactics/predictiveQuery.d.ts +3 -0
  496. package/dist/tactics/predictiveQuery.js +3 -0
  497. package/dist/tactics/snapshot.d.ts +2 -0
  498. package/dist/tactics/snapshot.js +2 -0
  499. package/dist/tactics/surface.d.ts +1 -0
  500. package/dist/tactics/surface.js +1 -0
  501. package/dist/tactics/tacticalGrid.d.ts +1 -0
  502. package/dist/tactics/tacticalGrid.js +1 -0
  503. package/dist/time/beatClock.d.ts +14 -4
  504. package/dist/time/beatClock.js +14 -4
  505. package/dist/time/calendarClock.d.ts +3 -0
  506. package/dist/time/calendarClock.js +3 -0
  507. package/dist/time/idleProgress.d.ts +4 -0
  508. package/dist/time/idleProgress.js +4 -0
  509. package/dist/time/simClock.d.ts +2 -0
  510. package/dist/time/simClock.js +20 -5
  511. package/dist/ui/actionModel.d.ts +110 -0
  512. package/dist/ui/actionModel.js +159 -0
  513. package/dist/ui/gameLayout.d.ts +144 -0
  514. package/dist/ui/gameLayout.js +148 -0
  515. package/dist/ui/hudDocument.d.ts +114 -0
  516. package/dist/ui/hudDocument.js +220 -0
  517. package/dist/ui/hudLayout.d.ts +33 -1
  518. package/dist/ui/hudLayout.js +204 -17
  519. package/dist/ui/orientation.d.ts +39 -0
  520. package/dist/ui/orientation.js +49 -0
  521. package/dist/ui/selectionModel.d.ts +92 -0
  522. package/dist/ui/selectionModel.js +88 -0
  523. package/dist/ui/swingTimer.d.ts +42 -0
  524. package/dist/ui/swingTimer.js +38 -0
  525. package/dist/ui/tooltipModel.d.ts +63 -0
  526. package/dist/ui/tooltipModel.js +82 -0
  527. package/dist/ui.d.ts +15 -0
  528. package/dist/ui.js +15 -0
  529. package/dist/visibility/bounds.d.ts +8 -1
  530. package/dist/visibility/bounds.js +8 -1
  531. package/dist/visibility/frustum.d.ts +12 -3
  532. package/dist/visibility/frustum.js +12 -3
  533. package/dist/visibility/spatialIndex.js +34 -20
  534. package/dist/work/jobQueue.d.ts +201 -0
  535. package/dist/work/jobQueue.js +253 -0
  536. package/dist/work/unitTraining.d.ts +58 -0
  537. package/dist/work/unitTraining.js +52 -0
  538. package/dist/world/authoredObjects.d.ts +58 -0
  539. package/dist/world/authoredObjects.js +69 -0
  540. package/dist/world/buildingGenerator.d.ts +18 -0
  541. package/dist/world/buildingGenerator.js +62 -0
  542. package/dist/world/buildings.d.ts +5 -0
  543. package/dist/world/buildings.js +5 -0
  544. package/dist/world/catenary.d.ts +22 -0
  545. package/dist/world/catenary.js +69 -0
  546. package/dist/world/environmentSummary.d.ts +11 -2
  547. package/dist/world/environmentSummary.js +11 -1
  548. package/dist/world/features.d.ts +244 -7
  549. package/dist/world/features.js +92 -4
  550. package/dist/world/footprintGrid.d.ts +59 -0
  551. package/dist/world/footprintGrid.js +141 -0
  552. package/dist/world/geometry.d.ts +64 -0
  553. package/dist/world/geometry.js +94 -0
  554. package/dist/world/grassKind.d.ts +51 -0
  555. package/dist/world/grassKind.js +101 -0
  556. package/dist/world/pathInstances.d.ts +27 -0
  557. package/dist/world/pathInstances.js +27 -0
  558. package/dist/world/pathTerrain.d.ts +80 -0
  559. package/dist/world/pathTerrain.js +142 -0
  560. package/dist/world/placeAsset.d.ts +81 -0
  561. package/dist/world/placeAsset.js +77 -0
  562. package/dist/world/placement.d.ts +4 -0
  563. package/dist/world/placement.js +4 -0
  564. package/dist/world/placementController.d.ts +6 -0
  565. package/dist/world/placementController.js +6 -0
  566. package/dist/world/polyline.d.ts +34 -0
  567. package/dist/world/polyline.js +81 -0
  568. package/dist/world/roads.d.ts +55 -0
  569. package/dist/world/roads.js +184 -0
  570. package/dist/world/scatterRegion.d.ts +164 -0
  571. package/dist/world/scatterRegion.js +409 -0
  572. package/dist/world/sceneShapes.d.ts +43 -0
  573. package/dist/world/sceneShapes.js +1 -0
  574. package/dist/world/segment.d.ts +27 -0
  575. package/dist/world/segment.js +43 -0
  576. package/dist/world/soilKind.d.ts +48 -0
  577. package/dist/world/soilKind.js +92 -0
  578. package/dist/world/spatialSample.d.ts +241 -0
  579. package/dist/world/spatialSample.js +465 -0
  580. package/dist/world/streets.d.ts +80 -0
  581. package/dist/world/streets.js +144 -0
  582. package/dist/world/terraform.d.ts +213 -1
  583. package/dist/world/terraform.js +655 -20
  584. package/dist/world/terrain.d.ts +138 -12
  585. package/dist/world/terrain.js +346 -28
  586. package/dist/world/terrainGuides.d.ts +182 -0
  587. package/dist/world/terrainGuides.js +343 -0
  588. package/dist/world/vec2.d.ts +81 -0
  589. package/dist/world/vec2.js +128 -0
  590. package/dist/world/vec3.d.ts +49 -0
  591. package/dist/world/vec3.js +76 -0
  592. package/dist/world/vegetation.d.ts +71 -0
  593. package/dist/world/vegetation.js +151 -0
  594. package/dist/world/visibilityField.d.ts +154 -0
  595. package/dist/world/visibilityField.js +271 -0
  596. package/dist/world/volumetricClouds.d.ts +52 -0
  597. package/dist/world/volumetricClouds.js +43 -0
  598. package/dist/world/walls.d.ts +9 -0
  599. package/dist/world/walls.js +9 -0
  600. package/dist/world/waterKind.d.ts +55 -0
  601. package/dist/world/waterKind.js +99 -0
  602. package/dist/world.d.ts +132 -0
  603. package/dist/world.js +132 -0
  604. package/package.json +32 -8
  605. package/skills/jgengine/SKILL.md +51 -0
  606. package/skills/jgengine/api.md +434 -0
  607. package/skills/jgengine/capabilities.md +29 -0
  608. package/skills/jgengine/reference-cartridge.md +72 -0
  609. package/skills/jgengine-combat/SKILL.md +34 -0
  610. package/skills/jgengine-combat/api.md +549 -0
  611. package/skills/jgengine-combat/capabilities.md +169 -0
  612. package/skills/jgengine-combat/reference.md +98 -0
  613. package/skills/jgengine-gameplay/SKILL.md +39 -0
  614. package/skills/jgengine-gameplay/api.md +1794 -0
  615. package/skills/jgengine-gameplay/capabilities.md +378 -0
  616. package/skills/jgengine-gameplay/reference-systems.md +60 -0
  617. package/skills/jgengine-world/SKILL.md +38 -0
  618. package/skills/jgengine-world/api.md +2652 -0
  619. package/skills/jgengine-world/capabilities.md +370 -0
  620. package/skills/jgengine-world/reference.md +222 -0
  621. package/dist/cartridge/runtime.d.ts +0 -15
  622. package/dist/cartridge/runtime.js +0 -556
  623. package/dist/cartridge/spec.d.ts +0 -188
  624. package/dist/cartridge/spec.js +0 -19
  625. package/dist/cartridge/validate.d.ts +0 -2
  626. package/dist/cartridge/validate.js +0 -78
  627. package/dist/store/engineStore.d.ts +0 -22
  628. package/dist/store/engineStore.js +0 -50
  629. package/dist/store/features.d.ts +0 -10
  630. package/dist/store/features.js +0 -23
  631. package/llms.txt +0 -4983
@@ -0,0 +1,426 @@
1
+ function clone(phase) {
2
+ const copy = { id: phase.id };
3
+ if (phase.data !== undefined)
4
+ copy.data = phase.data;
5
+ if (phase.completion !== undefined)
6
+ copy.completion = phase.completion;
7
+ if (phase.spawn !== undefined)
8
+ copy.spawn = phase.spawn;
9
+ if (phase.repeat !== undefined)
10
+ copy.repeat = phase.repeat;
11
+ if (phase.children !== undefined)
12
+ copy.children = phase.children.map(clone);
13
+ return copy;
14
+ }
15
+ function readNumber(params, key, fallback) {
16
+ const value = params[key];
17
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
18
+ }
19
+ function readString(params, key) {
20
+ const value = params[key];
21
+ return typeof value === "string" ? value : null;
22
+ }
23
+ /**
24
+ * Built-in completion predicates covering the common encounter gates: `immediate` (leaf
25
+ * marker), `manual`/`flag` (external event via a caller flag), `timer` (phase seconds),
26
+ * `cleared` (tagged entity count drained), `metric` (threshold on a live value), `event`
27
+ * (cumulative event count), and `quorum` (at least N of nested predicates met). Merge your
28
+ * own over these through {@link EncounterConfig.predicates}.
29
+ *
30
+ * @capability encounter-predicates gate encounter phase completion on timers, cleared spawns, metrics, events, or a quorum of conditions
31
+ */
32
+ export const BUILTIN_COMPLETION_PREDICATES = {
33
+ immediate: () => true,
34
+ manual: (params, ctx) => {
35
+ const flag = readString(params, "flag") ?? ctx.phaseId;
36
+ return ctx.signals.flags?.[flag] === true;
37
+ },
38
+ flag: (params, ctx) => {
39
+ const flag = readString(params, "flag") ?? ctx.phaseId;
40
+ return ctx.signals.flags?.[flag] === true;
41
+ },
42
+ timer: (params, ctx) => ctx.phaseElapsed >= readNumber(params, "seconds", 0),
43
+ cleared: (params, ctx) => {
44
+ const tag = readString(params, "tag");
45
+ if (tag === null)
46
+ return false;
47
+ const remaining = readNumber(params, "remaining", 0);
48
+ return (ctx.signals.counts?.[tag] ?? 0) <= remaining;
49
+ },
50
+ metric: (params, ctx) => {
51
+ const name = readString(params, "name");
52
+ if (name === null)
53
+ return false;
54
+ const value = ctx.signals.metrics?.[name] ?? 0;
55
+ const target = readNumber(params, "target", 0);
56
+ return readString(params, "direction") === "atMost" ? value <= target : value >= target;
57
+ },
58
+ event: (params, ctx) => {
59
+ const name = readString(params, "name");
60
+ if (name === null)
61
+ return false;
62
+ return (ctx.signals.events?.[name] ?? 0) >= readNumber(params, "count", 1);
63
+ },
64
+ quorum: (params, ctx) => {
65
+ const refs = params["predicates"];
66
+ if (!Array.isArray(refs))
67
+ return false;
68
+ const need = readNumber(params, "count", refs.length);
69
+ let met = 0;
70
+ for (const raw of refs) {
71
+ const ref = raw;
72
+ const predicate = BUILTIN_COMPLETION_PREDICATES[ref.kind];
73
+ if (predicate !== undefined && predicate(ref.params ?? {}, ctx))
74
+ met += 1;
75
+ if (met >= need)
76
+ return true;
77
+ }
78
+ return false;
79
+ },
80
+ };
81
+ /**
82
+ * Built-in spawn providers. `points` reads a named authored scene point list from context
83
+ * and cycles it to emit `count` requests, keeping coordinates in the scene rather than the
84
+ * sequence. `list` echoes literal requests authored in `params.requests`. Merge your own
85
+ * catalog- or director-backed providers through {@link EncounterConfig.spawnProviders}.
86
+ *
87
+ * @capability encounter-spawn-providers turn an entered encounter phase into spawn requests from authored scene points or an inline list
88
+ */
89
+ export const BUILTIN_SPAWN_PROVIDERS = {
90
+ points: (params, ctx) => {
91
+ const ref = readString(params, "ref");
92
+ if (ref === null)
93
+ return [];
94
+ const points = ctx.spawnPoints[ref] ?? [];
95
+ if (points.length === 0)
96
+ return [];
97
+ const count = Math.max(0, Math.floor(readNumber(params, "count", points.length)));
98
+ const entityRef = readString(params, "entity") ?? ref;
99
+ const requests = [];
100
+ for (let index = 0; index < count; index += 1) {
101
+ requests.push({ ref: entityRef, point: points[index % points.length] });
102
+ }
103
+ return requests;
104
+ },
105
+ list: (params) => {
106
+ const raw = params["requests"];
107
+ return Array.isArray(raw) ? raw : [];
108
+ },
109
+ };
110
+ function collectIds(phases, out) {
111
+ for (const phase of phases) {
112
+ if (out.has(phase.id))
113
+ throw new Error(`encounter phase id "${phase.id}" is not unique`);
114
+ out.add(phase.id);
115
+ if (phase.children !== undefined)
116
+ collectIds(phase.children, out);
117
+ }
118
+ }
119
+ function indexTree(phases, parent, index) {
120
+ for (const phase of phases) {
121
+ index.set(phase.id, { phase, parent });
122
+ if (phase.children !== undefined)
123
+ indexTree(phase.children, phase, index);
124
+ }
125
+ }
126
+ function ensureRuntime(state, id) {
127
+ let runtime = state.nodes[id];
128
+ if (runtime === undefined) {
129
+ runtime = { status: "pending", iteration: 0, enteredAt: state.elapsed };
130
+ state.nodes[id] = runtime;
131
+ }
132
+ return runtime;
133
+ }
134
+ /**
135
+ * Build the initial, serializable state for an encounter from its config. Deep-copies the
136
+ * authored phase tree (so later injection never mutates the config), verifies phase ids are
137
+ * unique, and leaves every node pending. Does not enter the first phase — call
138
+ * {@link startEncounter} for that.
139
+ *
140
+ * @capability encounter-state create the serializable starting state of a hierarchical encounter sequence
141
+ */
142
+ export function createEncounterState(config) {
143
+ const ids = new Set();
144
+ collectIds(config.phases, ids);
145
+ const roots = config.phases.map(clone);
146
+ const nodes = {};
147
+ for (const id of ids)
148
+ nodes[id] = { status: "pending", iteration: 0, enteredAt: 0 };
149
+ return { roots, nodes, activePath: [], elapsed: 0, started: false, done: false };
150
+ }
151
+ function access(state) {
152
+ const index = new Map();
153
+ indexTree(state.roots, null, index);
154
+ return {
155
+ index,
156
+ siblingsOf(id) {
157
+ const parent = index.get(id)?.parent;
158
+ return parent?.children ?? state.roots;
159
+ },
160
+ };
161
+ }
162
+ function resetSubtree(state, phase) {
163
+ const runtime = ensureRuntime(state, phase.id);
164
+ runtime.status = "pending";
165
+ if (phase.children !== undefined)
166
+ for (const child of phase.children)
167
+ resetSubtree(state, child);
168
+ }
169
+ /**
170
+ * Enter a node and, if it is a group, descend to its first child, pushing every entered id
171
+ * onto the active path and emitting enter + spawn events. Leaves the deepest entered node
172
+ * as the new cursor. Bounded by tree depth.
173
+ */
174
+ function enterChain(config, state, tree, startId, ctx, events, spawned) {
175
+ let currentId = startId;
176
+ const providers = { ...BUILTIN_SPAWN_PROVIDERS, ...config.spawnProviders };
177
+ let guard = tree.index.size + 1;
178
+ while (currentId !== undefined && guard > 0) {
179
+ guard -= 1;
180
+ const entry = tree.index.get(currentId);
181
+ if (entry === undefined)
182
+ return;
183
+ const phase = entry.phase;
184
+ const runtime = ensureRuntime(state, currentId);
185
+ runtime.status = "active";
186
+ runtime.enteredAt = state.elapsed;
187
+ state.activePath.push(currentId);
188
+ events.push({ type: "enter", phaseId: currentId, iteration: runtime.iteration });
189
+ if (phase.spawn !== undefined) {
190
+ // A phase that introduces spawns cannot complete on the same tick it enters — the
191
+ // caller has not observed the spawn yet — so defer its evaluation to the next update.
192
+ spawned.add(currentId);
193
+ const provider = providers[phase.spawn.kind];
194
+ if (provider !== undefined) {
195
+ const requests = provider(phase.spawn.params ?? {}, {
196
+ phaseId: currentId,
197
+ iteration: runtime.iteration,
198
+ elapsed: state.elapsed,
199
+ spawnPoints: ctx.spawnPoints ?? {},
200
+ });
201
+ if (requests.length > 0)
202
+ events.push({ type: "spawn", phaseId: currentId, provider: phase.spawn.kind, requests });
203
+ }
204
+ }
205
+ const firstChild = phase.children?.[0];
206
+ currentId = firstChild?.id;
207
+ }
208
+ }
209
+ /**
210
+ * Start a created encounter: enter the first root phase, descending to its first leaf, and
211
+ * return the initial enter/spawn events. A no-op (with no events) on an already-started or
212
+ * empty encounter. Mutates and returns `state`.
213
+ *
214
+ * @capability encounter-start enter the first phase of a hierarchical encounter and emit its opening spawn events
215
+ */
216
+ export function startEncounter(config, state, ctx = {}) {
217
+ const events = [];
218
+ if (state.started || state.done || state.roots.length === 0)
219
+ return { state, events };
220
+ state.started = true;
221
+ const tree = access(state);
222
+ enterChain(config, state, tree, state.roots[0].id, ctx, events, new Set());
223
+ return { state, events };
224
+ }
225
+ function predicateMet(config, phase, runtime, state, ctx) {
226
+ const completion = phase.completion;
227
+ if (completion === undefined)
228
+ return { met: true, reason: phase.children === undefined ? "immediate" : "children" };
229
+ const predicates = { ...BUILTIN_COMPLETION_PREDICATES, ...config.predicates };
230
+ const predicate = predicates[completion.kind];
231
+ if (predicate === undefined)
232
+ return { met: false, reason: completion.kind };
233
+ const met = predicate(completion.params ?? {}, {
234
+ phaseId: phase.id,
235
+ iteration: runtime.iteration,
236
+ elapsed: state.elapsed,
237
+ phaseElapsed: state.elapsed - runtime.enteredAt,
238
+ signals: ctx.signals ?? {},
239
+ });
240
+ return { met, reason: completion.kind };
241
+ }
242
+ /**
243
+ * Advance an encounter by `dt` seconds against the caller `ctx`. Accumulates time, then
244
+ * repeatedly: evaluates the cursor node's completion predicate; on completion, either
245
+ * re-runs its subtree (`repeat`) or marks it complete and advances to the next sibling —
246
+ * bubbling up to parent groups whose children are exhausted — entering the next chain and
247
+ * emitting enter/spawn/complete events. Emits a final `done` event when the last phase
248
+ * completes. Bounded per call by node count; mutates and returns `state`.
249
+ *
250
+ * @capability encounter-advance step a hierarchical encounter, resolving predicate-gated completion, repeats, and nested advance with lifecycle events
251
+ */
252
+ export function updateEncounter(config, state, dt, ctx = {}) {
253
+ const events = [];
254
+ if (!state.started || state.done || state.activePath.length === 0)
255
+ return { state, events };
256
+ if (dt > 0)
257
+ state.elapsed += dt;
258
+ const tree = access(state);
259
+ const justSpawned = new Set();
260
+ let guard = tree.index.size * 2 + 2;
261
+ while (guard > 0 && state.activePath.length > 0) {
262
+ guard -= 1;
263
+ const cursorId = state.activePath[state.activePath.length - 1];
264
+ // A phase that spawned earlier in this same step defers its completion to the next update.
265
+ if (justSpawned.has(cursorId))
266
+ break;
267
+ const entry = tree.index.get(cursorId);
268
+ if (entry === undefined) {
269
+ state.activePath.pop();
270
+ continue;
271
+ }
272
+ const phase = entry.phase;
273
+ const runtime = ensureRuntime(state, cursorId);
274
+ const { met, reason } = predicateMet(config, phase, runtime, state, ctx);
275
+ if (!met)
276
+ break;
277
+ if (runtime.iteration < Math.max(0, Math.floor(phase.repeat ?? 0))) {
278
+ runtime.iteration += 1;
279
+ if (phase.children !== undefined)
280
+ for (const child of phase.children)
281
+ resetSubtree(state, child);
282
+ state.activePath.pop();
283
+ enterChain(config, state, tree, cursorId, ctx, events, justSpawned);
284
+ continue;
285
+ }
286
+ runtime.status = "complete";
287
+ events.push({ type: "complete", phaseId: cursorId, iteration: runtime.iteration, reason });
288
+ state.activePath.pop();
289
+ const siblings = tree.siblingsOf(cursorId);
290
+ const position = siblings.findIndex((sibling) => sibling.id === cursorId);
291
+ const nextSibling = position >= 0 ? siblings[position + 1] : undefined;
292
+ if (nextSibling !== undefined) {
293
+ enterChain(config, state, tree, nextSibling.id, ctx, events, justSpawned);
294
+ }
295
+ else if (state.activePath.length === 0) {
296
+ state.done = true;
297
+ events.push({ type: "done" });
298
+ break;
299
+ }
300
+ }
301
+ return { state, events };
302
+ }
303
+ /**
304
+ * Force the deepest active phase (or a named active phase) to complete now, regardless of
305
+ * its predicate — the escape hatch for external/scripted completion and failure/retry flows.
306
+ * Advances into the next phase and emits the same lifecycle events as a natural completion.
307
+ * Returns no events if the phase is not currently active. Mutates and returns `state`.
308
+ *
309
+ * @capability encounter-force-complete externally complete an active encounter phase to drive scripted or failure-retry transitions
310
+ */
311
+ export function forceCompletePhase(config, state, ctx = {}, phaseId) {
312
+ const events = [];
313
+ if (!state.started || state.done || state.activePath.length === 0)
314
+ return { state, events };
315
+ const targetId = phaseId ?? state.activePath[state.activePath.length - 1];
316
+ if (!state.activePath.includes(targetId))
317
+ return { state, events };
318
+ // Collapse the active path down to the target so update resolves it as the cursor, then
319
+ // advance it via an always-true synthetic predicate scoped to this single phase.
320
+ while (state.activePath.length > 0 && state.activePath[state.activePath.length - 1] !== targetId) {
321
+ state.activePath.pop();
322
+ }
323
+ const tree = access(state);
324
+ const entry = tree.index.get(targetId);
325
+ if (entry === undefined)
326
+ return { state, events };
327
+ const originalCompletion = entry.phase.completion;
328
+ entry.phase.completion = { kind: "__forced__" };
329
+ const forcedConfig = {
330
+ ...config,
331
+ predicates: { ...config.predicates, __forced__: () => true },
332
+ };
333
+ const step = updateEncounter(forcedConfig, state, 0, ctx);
334
+ // Restore the authored predicate on the (possibly repeating) phase for future runs.
335
+ if (originalCompletion === undefined)
336
+ delete entry.phase.completion;
337
+ else
338
+ entry.phase.completion = originalCompletion;
339
+ return step;
340
+ }
341
+ /**
342
+ * Insert a phase into the working tree at runtime — before/after a sibling, or as a child of
343
+ * a group — without disturbing already-completed or active nodes. The injected subtree
344
+ * becomes part of the serializable state (so a mid-encounter save preserves it) and is
345
+ * reached in normal order if it sits ahead of the cursor. Ids must stay tree-unique. Mutates
346
+ * and returns `state`.
347
+ *
348
+ * @capability encounter-inject-phase dynamically insert a phase or branch into a running encounter, e.g. a boss on the final wave
349
+ */
350
+ export function injectPhase(state, phase, at) {
351
+ const existing = new Set();
352
+ collectIds(state.roots, existing);
353
+ const incoming = new Set();
354
+ collectIds([phase], incoming);
355
+ for (const id of incoming)
356
+ if (existing.has(id))
357
+ throw new Error(`encounter phase id "${id}" is not unique`);
358
+ const copy = clone(phase);
359
+ const tree = access(state);
360
+ if ("childOf" in at) {
361
+ const parentEntry = tree.index.get(at.childOf);
362
+ if (parentEntry === undefined)
363
+ throw new Error(`inject target "${at.childOf}" not found`);
364
+ const parent = parentEntry.phase;
365
+ const children = parent.children !== undefined ? [...parent.children] : [];
366
+ const index = at.index === undefined ? children.length : Math.max(0, Math.min(children.length, at.index));
367
+ children.splice(index, 0, copy);
368
+ parent.children = children;
369
+ }
370
+ else {
371
+ const targetId = "before" in at ? at.before : at.after;
372
+ const targetEntry = tree.index.get(targetId);
373
+ if (targetEntry === undefined)
374
+ throw new Error(`inject target "${targetId}" not found`);
375
+ const siblings = targetEntry.parent?.children ?? state.roots;
376
+ const list = [...siblings];
377
+ const position = list.findIndex((sibling) => sibling.id === targetId);
378
+ const insertAt = "before" in at ? position : position + 1;
379
+ list.splice(insertAt, 0, copy);
380
+ if (targetEntry.parent === null)
381
+ state.roots = list;
382
+ else
383
+ targetEntry.parent.children = list;
384
+ }
385
+ resetSubtree(state, copy);
386
+ return state;
387
+ }
388
+ /**
389
+ * The deepest active phase id — the completion cursor a HUD reads to label the current
390
+ * wave/phase — or null before start and once done.
391
+ *
392
+ * @capability encounter-active-phase read the id of the phase an encounter is currently waiting on
393
+ */
394
+ export function activePhaseId(state) {
395
+ return state.activePath.length > 0 ? state.activePath[state.activePath.length - 1] : null;
396
+ }
397
+ /**
398
+ * The runtime status of a phase by id (pending/active/complete), or null if the id is
399
+ * unknown — for driving per-phase HUD ticks and objective checklists.
400
+ *
401
+ * @capability encounter-phase-status read whether a specific encounter phase is pending, active, or complete
402
+ */
403
+ export function phaseStatus(state, id) {
404
+ return state.nodes[id]?.status ?? null;
405
+ }
406
+ /**
407
+ * Progress across the whole tree: how many phases have completed out of the total node
408
+ * count, plus whether the encounter has finished. Counts injected phases.
409
+ *
410
+ * @capability encounter-progress read completed-vs-total progress across a hierarchical encounter for HUD or objective display
411
+ */
412
+ export function encounterProgress(state) {
413
+ let total = 0;
414
+ let completed = 0;
415
+ const walk = (phases) => {
416
+ for (const phase of phases) {
417
+ total += 1;
418
+ if (state.nodes[phase.id]?.status === "complete")
419
+ completed += 1;
420
+ if (phase.children !== undefined)
421
+ walk(phase.children);
422
+ }
423
+ };
424
+ walk(state.roots);
425
+ return { completed, total, done: state.done };
426
+ }
@@ -8,6 +8,10 @@ export interface HitReactionConfig {
8
8
  knockback: number;
9
9
  vertical?: number;
10
10
  shake?: CameraShake;
11
+ /** Trauma (0..1) fed to a trauma² camera-shake channel — the calibrated alternative to `shake`. */
12
+ trauma?: number;
13
+ /** Slow-mo factor during hitstop (e.g. 0.05 = 5% speed); read by the game's own time-scale system, not applied here. */
14
+ timescale?: number;
11
15
  }
12
16
  export interface HitReactionInput {
13
17
  attackerPos: EntityPosition;
@@ -18,6 +22,58 @@ export interface HitReaction {
18
22
  hitstopMs: number;
19
23
  impulse: [number, number, number];
20
24
  shake: CameraShake | null;
25
+ trauma: number | null;
26
+ timescale: number | null;
21
27
  }
22
- export declare function resolveHitReaction(config: HitReactionConfig, input: HitReactionInput): HitReaction;
28
+ /** A calibrated `resolveHitReaction` config for a named impact event — hitstop + trauma so feel works with zero tuning. */
29
+ export interface ImpactPreset {
30
+ hitstopMs: number;
31
+ trauma: number;
32
+ timescale?: number;
33
+ knockback?: number;
34
+ vertical?: number;
35
+ }
36
+ /**
37
+ * Calibrated per-event impact feel — hitstop and trauma numbers harvested
38
+ * from a shipped game-feel reference, not hand-invented per game. `explosion`
39
+ * and `playerHit` are "heavy hit" events (60–90ms hitstop @ 0.05 timescale);
40
+ * `pickup`/`jumpLand` are light events with no hitstop. Trauma is later
41
+ * clamped to 1.0 by `resolveHitReaction`.
42
+ *
43
+ * @capability impact-feel calibrated hitstop + trauma preset for a named impact event
44
+ */
45
+ export declare const impactPresets: {
46
+ readonly pickup: {
47
+ readonly hitstopMs: 0;
48
+ readonly trauma: 0.15;
49
+ };
50
+ readonly jumpLand: {
51
+ readonly hitstopMs: 0;
52
+ readonly trauma: 0.2;
53
+ };
54
+ readonly enemyKilled: {
55
+ readonly hitstopMs: 40;
56
+ readonly trauma: 0.3;
57
+ };
58
+ readonly playerHit: {
59
+ readonly hitstopMs: 70;
60
+ readonly trauma: 0.4;
61
+ readonly timescale: 0.05;
62
+ };
63
+ readonly explosion: {
64
+ readonly hitstopMs: 90;
65
+ readonly trauma: 0.7;
66
+ readonly timescale: 0.05;
67
+ };
68
+ };
69
+ /** A named key into {@link impactPresets} (`"pickup" | "jumpLand" | "enemyKilled" | "playerHit" | "explosion"`). */
70
+ export type ImpactPresetName = keyof typeof impactPresets;
71
+ /**
72
+ * Resolves hit feel (hitstop, knockback impulse, camera shake) from either a
73
+ * named `impactPresets` event (`resolveHitReaction("explosion", input)`) or a
74
+ * raw `HitReactionConfig` override.
75
+ *
76
+ * @capability impact-feel resolve hitstop/knockback/shake feel from an impact preset or raw config
77
+ */
78
+ export declare function resolveHitReaction(config: HitReactionConfig | ImpactPresetName, input: HitReactionInput): HitReaction;
23
79
  export declare function applyImpulse(position: EntityPosition, impulse: [number, number, number]): EntityPosition;
@@ -1,18 +1,58 @@
1
+ /**
2
+ * Calibrated per-event impact feel — hitstop and trauma numbers harvested
3
+ * from a shipped game-feel reference, not hand-invented per game. `explosion`
4
+ * and `playerHit` are "heavy hit" events (60–90ms hitstop @ 0.05 timescale);
5
+ * `pickup`/`jumpLand` are light events with no hitstop. Trauma is later
6
+ * clamped to 1.0 by `resolveHitReaction`.
7
+ *
8
+ * @capability impact-feel calibrated hitstop + trauma preset for a named impact event
9
+ */
10
+ export const impactPresets = {
11
+ pickup: { hitstopMs: 0, trauma: 0.15 },
12
+ jumpLand: { hitstopMs: 0, trauma: 0.2 },
13
+ enemyKilled: { hitstopMs: 40, trauma: 0.3 },
14
+ playerHit: { hitstopMs: 70, trauma: 0.4, timescale: 0.05 },
15
+ explosion: { hitstopMs: 90, trauma: 0.7, timescale: 0.05 },
16
+ };
17
+ function clamp01(value) {
18
+ return value < 0 ? 0 : value > 1 ? 1 : value;
19
+ }
20
+ function configFromPreset(name) {
21
+ const preset = impactPresets[name];
22
+ return {
23
+ hitstopMs: preset.hitstopMs,
24
+ knockback: preset.knockback ?? 0,
25
+ trauma: preset.trauma,
26
+ ...(preset.vertical === undefined ? {} : { vertical: preset.vertical }),
27
+ ...(preset.timescale === undefined ? {} : { timescale: preset.timescale }),
28
+ };
29
+ }
30
+ /**
31
+ * Resolves hit feel (hitstop, knockback impulse, camera shake) from either a
32
+ * named `impactPresets` event (`resolveHitReaction("explosion", input)`) or a
33
+ * raw `HitReactionConfig` override.
34
+ *
35
+ * @capability impact-feel resolve hitstop/knockback/shake feel from an impact preset or raw config
36
+ */
1
37
  export function resolveHitReaction(config, input) {
38
+ const resolved = typeof config === "string" ? configFromPreset(config) : config;
2
39
  const power = input.power ?? 1;
3
40
  const dx = input.targetPos[0] - input.attackerPos[0];
4
41
  const dz = input.targetPos[2] - input.attackerPos[2];
5
42
  const planar = Math.hypot(dx, dz);
6
43
  const nx = planar === 0 ? 0 : dx / planar;
7
44
  const nz = planar === 0 ? 0 : dz / planar;
8
- const magnitude = config.knockback * power;
9
- const shake = config.shake === undefined
45
+ const magnitude = resolved.knockback * power;
46
+ const shake = resolved.shake === undefined
10
47
  ? null
11
- : { amplitude: config.shake.amplitude * power, decay: config.shake.decay };
48
+ : { amplitude: resolved.shake.amplitude * power, decay: resolved.shake.decay };
49
+ const trauma = resolved.trauma === undefined ? null : clamp01(resolved.trauma * power);
12
50
  return {
13
- hitstopMs: config.hitstopMs,
14
- impulse: [nx * magnitude, (config.vertical ?? 0) * power, nz * magnitude],
51
+ hitstopMs: resolved.hitstopMs,
52
+ impulse: [nx * magnitude, (resolved.vertical ?? 0) * power, nz * magnitude],
15
53
  shake,
54
+ trauma,
55
+ timescale: resolved.timescale ?? null,
16
56
  };
17
57
  }
18
58
  export function applyImpulse(position, impulse) {
@@ -0,0 +1,54 @@
1
+ /** Draws ammo for a `Magazine`'s reload from wherever the reserve pool actually lives. */
2
+ export interface MagazineReserve {
3
+ current(): number;
4
+ spend(amount: number): boolean;
5
+ gain?(amount: number): void;
6
+ }
7
+ /** Tuning for `createMagazine`: mag capacity, reload delay, and where reserve ammo is drawn from. */
8
+ export interface MagazineConfig {
9
+ capacity: number;
10
+ reloadMs: number;
11
+ /** Starting loaded count; defaults to `capacity` (a full mag). */
12
+ loaded?: number;
13
+ /**
14
+ * A plain number seeds a self-contained reserve pool; a `MagazineReserve` bridges reload draws
15
+ * into an externally-owned pool (a shared ammo-type stat, another `ResourcePool`); omitted means
16
+ * an infinite reserve (classic arcade shooter, never locked out of reloading).
17
+ */
18
+ reserve?: number | MagazineReserve;
19
+ }
20
+ /**
21
+ * A per-weapon magazine: discrete loaded rounds, a timed reload that refills from a reserve pool,
22
+ * and the reserve-pool interaction itself — the primitive that replaces hand-rolling mag size,
23
+ * reload delay, and reserve bookkeeping per game (#536.2).
24
+ */
25
+ export interface Magazine {
26
+ loaded(): number;
27
+ capacity(): number;
28
+ /** Reserve rounds available to reload from, or `null` when the reserve is infinite. */
29
+ reserve(): number | null;
30
+ isReloading(): boolean;
31
+ /** Reload progress in `[0, 1]`; 0 while idle. */
32
+ reloadFraction(): number;
33
+ isEmpty(): boolean;
34
+ isFull(): boolean;
35
+ canFire(rounds?: number): boolean;
36
+ /** Spend `rounds` (default 1) loaded ammo; returns false without effect when insufficient. */
37
+ fire(rounds?: number): boolean;
38
+ /** True when a reload could start: not already full, not already reloading, reserve has rounds. */
39
+ canReload(): boolean;
40
+ /** Begin the reload timer if `canReload()`; returns whether it started. */
41
+ startReload(): boolean;
42
+ /** Abort an in-progress reload; loaded/reserve are unchanged (only completion moves ammo). */
43
+ cancelReload(): void;
44
+ /** Add `amount` to a self-contained numeric reserve (a pickup); a no-op against an infinite or externally-owned reserve without a `gain`. */
45
+ addReserve(amount: number): void;
46
+ /** Advance the reload timer; completes the reload once `reloadMs` has elapsed. */
47
+ tick(dtSeconds: number): void;
48
+ }
49
+ /**
50
+ * Builds a {@link Magazine}: discrete loaded ammo, a timed reload, and reserve-pool interaction.
51
+ *
52
+ * @capability magazine a weapon magazine with capacity, timed reload, and reserve-pool interaction
53
+ */
54
+ export declare function createMagazine(config: MagazineConfig): Magazine;