@jgengine/core 0.18.1 → 0.21.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 (404) hide show
  1. package/CHANGELOG.md +504 -7
  2. package/dist/ai/decisionGraph.d.ts +50 -4
  3. package/dist/ai/decisionGraph.js +159 -23
  4. package/dist/ai/flock.d.ts +1 -1
  5. package/dist/ai/flock.js +7 -4
  6. package/dist/ai/groupAssist.d.ts +10 -0
  7. package/dist/ai/groupAssist.js +11 -0
  8. package/dist/ai/pursuit.d.ts +1 -1
  9. package/dist/ai/pursuit.js +1 -1
  10. package/dist/ai/threat.d.ts +8 -0
  11. package/dist/ai/threat.js +10 -0
  12. package/dist/anim/animGraph.d.ts +43 -1
  13. package/dist/anim/animGraph.js +326 -10
  14. package/dist/anim/boneTexture.d.ts +55 -0
  15. package/dist/anim/boneTexture.js +43 -0
  16. package/dist/anim/footPlacement.d.ts +57 -0
  17. package/dist/anim/footPlacement.js +67 -0
  18. package/dist/anim/locomotionGraph.d.ts +18 -1
  19. package/dist/anim/locomotionGraph.js +42 -3
  20. package/dist/audio/audioFalloff.d.ts +6 -0
  21. package/dist/audio/doppler.d.ts +21 -0
  22. package/dist/audio/doppler.js +32 -0
  23. package/dist/audio/engineLayers.d.ts +83 -0
  24. package/dist/audio/engineLayers.js +115 -0
  25. package/dist/audio/voiceAllocator.d.ts +46 -0
  26. package/dist/audio/voiceAllocator.js +76 -0
  27. package/dist/combat/abilityKit.d.ts +20 -0
  28. package/dist/combat/abilityKit.js +41 -4
  29. package/dist/combat/death.d.ts +11 -3
  30. package/dist/combat/death.js +3 -3
  31. package/dist/combat/magazine.d.ts +9 -0
  32. package/dist/combat/magazine.js +24 -2
  33. package/dist/combat/projectiles.d.ts +94 -2
  34. package/dist/combat/projectiles.js +282 -61
  35. package/dist/combat/regenShield.d.ts +14 -0
  36. package/dist/combat/regenShield.js +23 -7
  37. package/dist/combat/shotOrigin.d.ts +6 -0
  38. package/dist/combat/shotOrigin.js +6 -0
  39. package/dist/combat/weaponFeedback.d.ts +36 -0
  40. package/dist/combat/weaponFeedback.js +42 -0
  41. package/dist/combat/weaponHandling.d.ts +161 -0
  42. package/dist/combat/weaponHandling.js +202 -0
  43. package/dist/combat/weaponPresentation.d.ts +115 -0
  44. package/dist/combat/weaponPresentation.js +96 -0
  45. package/dist/crafting/recipeCatalog.d.ts +16 -0
  46. package/dist/crafting/recipeCatalog.js +55 -0
  47. package/dist/devtools/warnOnce.d.ts +8 -0
  48. package/dist/devtools/warnOnce.js +18 -0
  49. package/dist/economy/auctionBook.d.ts +1 -1
  50. package/dist/economy/auctionBook.js +11 -1
  51. package/dist/economy/listingBook.d.ts +1 -1
  52. package/dist/economy/listingBook.js +11 -1
  53. package/dist/economy/resourceLedger.js +3 -3
  54. package/dist/economy/shopStock.js +7 -6
  55. package/dist/economy/techTree.js +7 -6
  56. package/dist/economy/unlockPoints.js +3 -6
  57. package/dist/editor/commandApply.js +89 -16
  58. package/dist/editor/commands.d.ts +38 -1
  59. package/dist/editor/commands.js +320 -3
  60. package/dist/editor/creatorStorage.d.ts +59 -0
  61. package/dist/editor/creatorStorage.js +164 -0
  62. package/dist/editor/document.d.ts +4 -0
  63. package/dist/editor/document.js +119 -18
  64. package/dist/editor/environment.js +8 -0
  65. package/dist/editor/index.d.ts +2 -0
  66. package/dist/editor/liveSync.d.ts +4 -1
  67. package/dist/editor/liveSync.js +26 -10
  68. package/dist/editor/materialAuthoring.d.ts +14 -0
  69. package/dist/editor/materialAuthoring.js +38 -0
  70. package/dist/editor/modelNodeVisibility.d.ts +11 -0
  71. package/dist/editor/modelNodeVisibility.js +29 -0
  72. package/dist/editor/movementCatalog.d.ts +90 -0
  73. package/dist/editor/movementCatalog.js +144 -0
  74. package/dist/editor/simulation.d.ts +60 -0
  75. package/dist/editor/simulation.js +202 -0
  76. package/dist/editor/staticPrefab.d.ts +17 -0
  77. package/dist/editor/staticPrefab.js +51 -0
  78. package/dist/editor/types.d.ts +15 -0
  79. package/dist/faction/reputation.d.ts +6 -0
  80. package/dist/faction/reputation.js +11 -0
  81. package/dist/game/cameraConfig.d.ts +54 -2
  82. package/dist/game/clipRoles.d.ts +2 -1
  83. package/dist/game/clipRoles.js +7 -3
  84. package/dist/game/contentValidation.d.ts +69 -0
  85. package/dist/game/contentValidation.js +118 -0
  86. package/dist/game/controlGate.d.ts +8 -0
  87. package/dist/game/controlGate.js +43 -6
  88. package/dist/game/defineGame.d.ts +32 -3
  89. package/dist/game/dialogueGraph.d.ts +20 -0
  90. package/dist/game/dialogueGraph.js +107 -0
  91. package/dist/game/events.d.ts +11 -0
  92. package/dist/game/keyValueStore.d.ts +17 -4
  93. package/dist/game/keyValueStore.js +35 -23
  94. package/dist/game/lootModifiers.d.ts +17 -0
  95. package/dist/game/lootModifiers.js +26 -0
  96. package/dist/game/lootTable.d.ts +4 -0
  97. package/dist/game/lootTable.js +16 -0
  98. package/dist/game/narrativeAuthoring.d.ts +67 -0
  99. package/dist/game/narrativeAuthoring.js +122 -0
  100. package/dist/game/playableGame.d.ts +134 -35
  101. package/dist/game/quest.d.ts +15 -0
  102. package/dist/game/quest.js +209 -63
  103. package/dist/game/questCatalog.d.ts +50 -0
  104. package/dist/game/questCatalog.js +205 -0
  105. package/dist/game/saveStore.d.ts +6 -5
  106. package/dist/game/saveStore.js +57 -57
  107. package/dist/game/systemRuntime.d.ts +2 -2
  108. package/dist/game/systemRuntime.js +84 -33
  109. package/dist/game/toasts.d.ts +8 -0
  110. package/dist/game/toasts.js +7 -0
  111. package/dist/game/vfxInstance.d.ts +9 -0
  112. package/dist/game/vfxInstance.js +12 -1
  113. package/dist/game/viewports.d.ts +43 -0
  114. package/dist/game/viewports.js +46 -0
  115. package/dist/game/worldItem.d.ts +5 -1
  116. package/dist/game/worldItem.js +0 -1
  117. package/dist/gameplay.d.ts +3 -0
  118. package/dist/gameplay.js +3 -0
  119. package/dist/input/actionBindings.d.ts +15 -1
  120. package/dist/input/actionBindings.js +14 -3
  121. package/dist/input/actionContexts.d.ts +25 -1
  122. package/dist/input/actionContexts.js +82 -25
  123. package/dist/input/axisInput.d.ts +4 -0
  124. package/dist/input/axisInput.js +4 -0
  125. package/dist/input/axisShaper.d.ts +73 -0
  126. package/dist/input/axisShaper.js +105 -0
  127. package/dist/input/gamepadModel.d.ts +36 -2
  128. package/dist/input/gamepadModel.js +69 -30
  129. package/dist/input/haptics.d.ts +50 -0
  130. package/dist/input/haptics.js +74 -0
  131. package/dist/input/inputBuffer.d.ts +40 -0
  132. package/dist/input/inputBuffer.js +59 -0
  133. package/dist/input/lookChannel.d.ts +10 -0
  134. package/dist/input/lookChannel.js +6 -0
  135. package/dist/input/pointer.d.ts +2 -0
  136. package/dist/input/pointer.js +4 -0
  137. package/dist/interaction/promptRegistry.d.ts +5 -4
  138. package/dist/interaction/promptRegistry.js +8 -2
  139. package/dist/inventory/inventoryModel.js +9 -6
  140. package/dist/inventory/shapedGrid.d.ts +48 -9
  141. package/dist/inventory/shapedGrid.js +69 -10
  142. package/dist/item/affix.d.ts +6 -0
  143. package/dist/item/affix.js +6 -0
  144. package/dist/item/durability.js +4 -0
  145. package/dist/item/itemInstanceRegistry.d.ts +32 -1
  146. package/dist/item/itemInstanceRegistry.js +111 -7
  147. package/dist/item/itemgen.d.ts +1 -1
  148. package/dist/item/itemgen.js +1 -1
  149. package/dist/item/modularItem.js +7 -1
  150. package/dist/material/appearanceSignals.d.ts +53 -0
  151. package/dist/material/appearanceSignals.js +47 -0
  152. package/dist/material/hairCards.d.ts +47 -0
  153. package/dist/material/hairCards.js +136 -0
  154. package/dist/material/materialAsset.d.ts +162 -0
  155. package/dist/material/materialAsset.js +382 -0
  156. package/dist/meta/changelog.d.ts +1 -1
  157. package/dist/meta/changelog.js +444 -1
  158. package/dist/movement/characterController.d.ts +5 -2
  159. package/dist/movement/characterController.js +50 -23
  160. package/dist/movement/freeFlight.d.ts +2 -2
  161. package/dist/movement/freeFlight.js +3 -3
  162. package/dist/movement/glideModel.d.ts +3 -0
  163. package/dist/movement/glideModel.js +6 -0
  164. package/dist/movement/grappleSwing.d.ts +2 -0
  165. package/dist/movement/grappleSwing.js +5 -1
  166. package/dist/movement/movementModel.d.ts +63 -1
  167. package/dist/movement/movementModel.js +136 -26
  168. package/dist/movement/movementProbe.d.ts +51 -0
  169. package/dist/movement/movementProbe.js +119 -0
  170. package/dist/movement/playerMovement.d.ts +48 -2
  171. package/dist/movement/playerMovement.js +493 -87
  172. package/dist/movement/poseState.d.ts +2 -0
  173. package/dist/movement/poseState.js +29 -1
  174. package/dist/movement/solidObstacles.d.ts +11 -1
  175. package/dist/movement/solidObstacles.js +48 -3
  176. package/dist/movement/terrainGrade.d.ts +13 -0
  177. package/dist/movement/terrainGrade.js +33 -0
  178. package/dist/movement/voxelController.d.ts +2 -2
  179. package/dist/movement/voxelController.js +10 -10
  180. package/dist/nav/navFromEnvironment.d.ts +9 -3
  181. package/dist/nav/navFromEnvironment.js +18 -12
  182. package/dist/nav/navGrid.d.ts +19 -1
  183. package/dist/nav/navGrid.js +26 -10
  184. package/dist/nav/navMesh.d.ts +43 -2
  185. package/dist/nav/navMesh.js +534 -128
  186. package/dist/nav/solidRoute.d.ts +50 -0
  187. package/dist/nav/solidRoute.js +144 -0
  188. package/dist/physics/aircraftDynamics.d.ts +390 -0
  189. package/dist/physics/aircraftDynamics.js +704 -0
  190. package/dist/physics/ballisticSweep.d.ts +10 -3
  191. package/dist/physics/ballisticSweep.js +53 -29
  192. package/dist/physics/boatDynamics.d.ts +116 -0
  193. package/dist/physics/boatDynamics.js +160 -0
  194. package/dist/physics/drivableVehicle.d.ts +22 -8
  195. package/dist/physics/drivableVehicle.js +4 -2
  196. package/dist/physics/flightDynamics.d.ts +21 -4
  197. package/dist/physics/flightDynamics.js +28 -5
  198. package/dist/physics/forceVolume.d.ts +41 -0
  199. package/dist/physics/forceVolume.js +88 -0
  200. package/dist/physics/handlingProbe.d.ts +249 -0
  201. package/dist/physics/handlingProbe.js +606 -0
  202. package/dist/physics/kinematicVehicle.d.ts +40 -5
  203. package/dist/physics/kinematicVehicle.js +17 -2
  204. package/dist/physics/physicsBackend.d.ts +12 -0
  205. package/dist/physics/physicsBackendConformance.js +34 -0
  206. package/dist/physics/physicsWorldBackend.d.ts +1 -0
  207. package/dist/physics/physicsWorldBackend.js +52 -3
  208. package/dist/physics/spatialGrid.d.ts +1 -1
  209. package/dist/physics/spatialGrid.js +8 -9
  210. package/dist/physics/vehicleBackendLink.d.ts +49 -0
  211. package/dist/physics/vehicleBackendLink.js +102 -0
  212. package/dist/physics/vehicleDynamics.d.ts +375 -0
  213. package/dist/physics/vehicleDynamics.js +737 -0
  214. package/dist/physics/vehicleObstacles.d.ts +3 -2
  215. package/dist/physics/vehicleObstacles.js +29 -5
  216. package/dist/physics/worldColliders.d.ts +1 -1
  217. package/dist/physics/worldColliders.js +35 -3
  218. package/dist/puzzle/cellGrid.d.ts +15 -9
  219. package/dist/puzzle/cellGrid.js +13 -9
  220. package/dist/render/lookPreset.d.ts +9 -2
  221. package/dist/render/lookPreset.js +29 -2
  222. package/dist/render/postProcessing.d.ts +30 -0
  223. package/dist/render/postProcessing.js +1 -1
  224. package/dist/runtime/cameraDirector.d.ts +54 -3
  225. package/dist/runtime/cameraDirector.js +187 -0
  226. package/dist/runtime/commandDispatch.d.ts +14 -0
  227. package/dist/runtime/commandDispatch.js +19 -0
  228. package/dist/runtime/commandInput.d.ts +37 -0
  229. package/dist/runtime/commandInput.js +58 -0
  230. package/dist/runtime/commandRunner.d.ts +27 -0
  231. package/dist/runtime/commandRunner.js +31 -3
  232. package/dist/runtime/context/combat.d.ts +12 -4
  233. package/dist/runtime/context/combat.js +179 -11
  234. package/dist/runtime/context/deathLoot.d.ts +11 -8
  235. package/dist/runtime/context/deathLoot.js +17 -16
  236. package/dist/runtime/context/scene.d.ts +2 -0
  237. package/dist/runtime/context/scene.js +13 -21
  238. package/dist/runtime/descriptors/baseline.js +34 -3
  239. package/dist/runtime/descriptors/features.d.ts +2 -1
  240. package/dist/runtime/descriptors/features.js +18 -0
  241. package/dist/runtime/gameContext.js +86 -13
  242. package/dist/runtime/gameContextTypes.d.ts +33 -3
  243. package/dist/runtime/gameRuntime.d.ts +3 -1
  244. package/dist/runtime/gameRuntime.js +4 -0
  245. package/dist/runtime/headlessRunner.d.ts +3 -1
  246. package/dist/runtime/headlessRunner.js +11 -11
  247. package/dist/runtime/hostedGameRunner.d.ts +24 -1
  248. package/dist/runtime/hostedGameRunner.js +156 -10
  249. package/dist/runtime/hostedWorldSession.d.ts +17 -5
  250. package/dist/runtime/hostedWorldSession.js +154 -16
  251. package/dist/runtime/hostedWorldStore.d.ts +2 -2
  252. package/dist/runtime/inputRecorder.d.ts +1 -1
  253. package/dist/runtime/inputRecorder.js +21 -1
  254. package/dist/runtime/inputSnapshot.d.ts +22 -4
  255. package/dist/runtime/inputSnapshot.js +41 -3
  256. package/dist/runtime/localPlayers.d.ts +73 -0
  257. package/dist/runtime/localPlayers.js +119 -0
  258. package/dist/runtime/runtimeSave.d.ts +10 -6
  259. package/dist/runtime/runtimeSave.js +11 -5
  260. package/dist/runtime/simContext.d.ts +8 -3
  261. package/dist/runtime/simContext.js +7 -3
  262. package/dist/runtime/simSnapshot.js +2 -0
  263. package/dist/runtime/transport.d.ts +9 -0
  264. package/dist/runtime/transport.js +7 -1
  265. package/dist/runtime/worldReplication.d.ts +2 -0
  266. package/dist/runtime/worldReplication.js +1 -1
  267. package/dist/scene/assetCatalog.d.ts +2 -0
  268. package/dist/scene/behaviorRuntime.d.ts +38 -7
  269. package/dist/scene/behaviorRuntime.js +293 -30
  270. package/dist/scene/behaviors.d.ts +35 -2
  271. package/dist/scene/behaviors.js +29 -0
  272. package/dist/scene/entityStore.d.ts +14 -3
  273. package/dist/scene/entityStore.js +45 -9
  274. package/dist/scene/mount.d.ts +9 -0
  275. package/dist/scene/mount.js +35 -0
  276. package/dist/scene/possession.d.ts +2 -0
  277. package/dist/scene/possession.js +21 -1
  278. package/dist/scene/sceneKinds.d.ts +9 -0
  279. package/dist/scene/sceneRaycast.d.ts +7 -0
  280. package/dist/scene/sceneRaycast.js +55 -0
  281. package/dist/scene/spatial.d.ts +20 -1
  282. package/dist/scene/spatial.js +94 -2
  283. package/dist/scene/vehicleSeat.d.ts +41 -3
  284. package/dist/scene/vehicleSeat.js +94 -3
  285. package/dist/sensor/concealment.d.ts +6 -0
  286. package/dist/sensor/concealment.js +8 -0
  287. package/dist/sensor/freezeMonitor.d.ts +6 -0
  288. package/dist/sensor/freezeMonitor.js +8 -0
  289. package/dist/sensor/perception.d.ts +11 -1
  290. package/dist/sensor/perception.js +57 -10
  291. package/dist/sensor/recordingBuffer.d.ts +3 -0
  292. package/dist/sensor/recordingBuffer.js +8 -0
  293. package/dist/session/roundState.d.ts +4 -0
  294. package/dist/session/roundState.js +11 -0
  295. package/dist/settings/frameRateLimit.d.ts +16 -0
  296. package/dist/settings/frameRateLimit.js +37 -0
  297. package/dist/settings/graphicsProfile.d.ts +2 -0
  298. package/dist/settings/graphicsProfile.js +12 -0
  299. package/dist/settings/graphicsSettings.d.ts +40 -0
  300. package/dist/settings/graphicsSettings.js +81 -0
  301. package/dist/settings/settingsModel.d.ts +9 -1
  302. package/dist/settings/settingsModel.js +10 -0
  303. package/dist/stats/accumulatorMeter.d.ts +10 -0
  304. package/dist/stats/accumulatorMeter.js +6 -0
  305. package/dist/stats/eventMeter.d.ts +10 -3
  306. package/dist/stats/eventMeter.js +6 -3
  307. package/dist/store/defineStore.d.ts +3 -1
  308. package/dist/store/defineStore.js +3 -1
  309. package/dist/store/observableKeyedStore.d.ts +1 -1
  310. package/dist/store/observableKeyedStore.js +8 -6
  311. package/dist/time/simClock.d.ts +6 -2
  312. package/dist/time/simClock.js +5 -0
  313. package/dist/vfx/feedbackMixer.d.ts +61 -0
  314. package/dist/vfx/feedbackMixer.js +106 -0
  315. package/dist/vfx/particleDirector.d.ts +58 -6
  316. package/dist/vfx/particleDirector.js +113 -22
  317. package/dist/vfx/particles.d.ts +68 -5
  318. package/dist/vfx/particles.js +284 -32
  319. package/dist/visibility/assetStreaming.d.ts +21 -3
  320. package/dist/visibility/assetStreaming.js +108 -24
  321. package/dist/visibility/settings.d.ts +8 -2
  322. package/dist/visibility/settings.js +3 -0
  323. package/dist/visibility/simulationCulling.d.ts +8 -1
  324. package/dist/visibility/simulationCulling.js +7 -0
  325. package/dist/visibility/spatialIndex.d.ts +21 -0
  326. package/dist/visibility/spatialIndex.js +16 -0
  327. package/dist/visibility/visibilitySystem.js +1 -0
  328. package/dist/work/expedition.d.ts +110 -0
  329. package/dist/work/expedition.js +195 -0
  330. package/dist/work/staffedStation.d.ts +29 -0
  331. package/dist/work/staffedStation.js +27 -0
  332. package/dist/world/authoredAnimation.d.ts +38 -0
  333. package/dist/world/authoredAnimation.js +99 -0
  334. package/dist/world/authoredObjects.d.ts +24 -4
  335. package/dist/world/authoredObjects.js +43 -16
  336. package/dist/world/authoredSimulation.d.ts +74 -0
  337. package/dist/world/authoredSimulation.js +302 -0
  338. package/dist/world/authoredSolids.d.ts +46 -0
  339. package/dist/world/authoredSolids.js +75 -0
  340. package/dist/world/authoredWeather.d.ts +120 -0
  341. package/dist/world/authoredWeather.js +314 -0
  342. package/dist/world/buildingGenerator.js +2 -2
  343. package/dist/world/buildingKit.d.ts +11 -4
  344. package/dist/world/buildingKit.js +21 -8
  345. package/dist/world/buildings.d.ts +34 -2
  346. package/dist/world/buildings.js +11 -1
  347. package/dist/world/cityKind.d.ts +7 -0
  348. package/dist/world/cityKind.js +52 -1
  349. package/dist/world/environmentForces.d.ts +21 -0
  350. package/dist/world/environmentForces.js +42 -0
  351. package/dist/world/features.d.ts +32 -5
  352. package/dist/world/features.js +6 -0
  353. package/dist/world/footprintGrid.d.ts +62 -0
  354. package/dist/world/footprintGrid.js +217 -0
  355. package/dist/world/interiors.d.ts +1 -0
  356. package/dist/world/interiors.js +5 -3
  357. package/dist/world/lod.d.ts +6 -0
  358. package/dist/world/lod.js +8 -0
  359. package/dist/world/pathTerrain.d.ts +1 -1
  360. package/dist/world/terraform.d.ts +9 -1
  361. package/dist/world/terraform.js +53 -18
  362. package/dist/world/walls.d.ts +7 -0
  363. package/dist/world/walls.js +7 -0
  364. package/dist/world/weather.d.ts +17 -0
  365. package/dist/world/weather.js +116 -20
  366. package/dist/world/worldSolids.d.ts +95 -0
  367. package/dist/world/worldSolids.js +351 -0
  368. package/dist/world.d.ts +6 -6
  369. package/dist/world.js +5 -5
  370. package/package.json +1 -1
  371. package/skills/ce-handoff/SKILL.md +2 -2
  372. package/skills/game-design/SKILL.md +2 -2
  373. package/skills/jgengine/SKILL.md +28 -6
  374. package/skills/jgengine/api.md +139 -99
  375. package/skills/jgengine/capabilities.md +28 -0
  376. package/skills/jgengine/recipes/minimal-game.md +10 -2
  377. package/skills/jgengine-combat/SKILL.md +13 -2
  378. package/skills/jgengine-combat/api.md +150 -103
  379. package/skills/jgengine-combat/capabilities.md +29 -1
  380. package/skills/jgengine-combat/recipes/portable-runtime-state.md +60 -6
  381. package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +37 -3
  382. package/skills/jgengine-combat/recipes/weapon-feel.md +50 -0
  383. package/skills/jgengine-combat/reference.md +24 -2
  384. package/skills/jgengine-gameplay/SKILL.md +63 -0
  385. package/skills/jgengine-gameplay/api.md +583 -463
  386. package/skills/jgengine-gameplay/capabilities.md +92 -0
  387. package/skills/jgengine-gameplay/recipes/device-save-status.md +46 -0
  388. package/skills/jgengine-gameplay/recipes/expeditions.md +108 -0
  389. package/skills/jgengine-gameplay/recipes/narrative-authoring.md +76 -0
  390. package/skills/jgengine-gameplay/recipes/paged-item-storage.md +101 -0
  391. package/skills/jgengine-gameplay/recipes/quest-authoring.md +63 -0
  392. package/skills/jgengine-gameplay/recipes/shaped-inventory.md +50 -0
  393. package/skills/jgengine-gameplay/reference-content-validation.md +74 -0
  394. package/skills/jgengine-gameplay/reference-systems.md +123 -0
  395. package/skills/jgengine-world/SKILL.md +25 -4
  396. package/skills/jgengine-world/api.md +1045 -655
  397. package/skills/jgengine-world/capabilities.md +246 -9
  398. package/skills/jgengine-world/recipes/character-animation.md +62 -0
  399. package/skills/jgengine-world/recipes/controls.md +48 -0
  400. package/skills/jgengine-world/recipes/flight-feel.md +76 -0
  401. package/skills/jgengine-world/recipes/npc-senses.md +55 -0
  402. package/skills/jgengine-world/recipes/vehicle-feel.md +87 -0
  403. package/skills/jgengine-world/reference.md +180 -4
  404. package/skills/jgengine-world/visibility.md +139 -0
@@ -4,26 +4,26 @@
4
4
 
5
5
  ## @jgengine/core/combat
6
6
 
7
- - `AbilityKit` (interface): interface AbilityKit — ⚠ undocumented
8
- - `AbilitySlotSnapshot` (interface): interface AbilitySlotSnapshot — ⚠ undocumented
7
+ - `AbilityKit` (interface): interface AbilityKit { slots(): readonly string[]; config(slotId: string): AbilitySlotConfig | null; state(): AbilityKitState; state(slotId: string, resourceAvailable?: number): AbilitySlotSnapshot | null; snapshot(resourceAvailable?: number): AbilitySlotSnapsh… — ⚠ undocumented · used by `createAbilityKit`: A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
8
+ - `AbilitySlotSnapshot` (interface): interface AbilitySlotSnapshot { id: string; state: AbilitySlotState; castType: AbilityCastType; resourceCost: number; charges: number; chargesMax: number; cooldownRemainingMs: number; cooldownFraction: number; groupRemainingMs: number; justCast: boolean; ready: boolean … — ⚠ undocumented · used by `actionFromAbilitySlot` (@jgengine/react): Composable React renderers over the headless action view model (`@jgengine/core/ui/actionModel`) — the data/renderer/chrome split for an RTS…
9
9
  - `AbilitySlotState` (type): type AbilitySlotState = "ready" | "cooldown" | "no-resource" | "just-cast" — ⚠ undocumented
10
10
  - `AllocationOutcome` (interface): interface AllocationOutcome — The serializable result of an allocation pass — immediate `grants` plus any deferred `pools`.
11
11
  - `AllocationRequest` (interface): interface AllocationRequest — The inputs one allocation pass consumes. `allocationSeed` governs distribution decisions (ordering, round-robin rotation, remainder splits, reservation) while the separate optional `generationSeed` seeds per-recipient `instanced` generation — keeping join order from perturbing other players' rolls. Provide `results` for pre-rolled policies, `generate` for `instanced`, `assignment` for `assigned`, and `claim` for `claimed`.
12
- - `AnimationClip` (interface): interface AnimationClip — ⚠ undocumented
12
+ - `AnimationClip` (interface): interface AnimationClip { id: string; frames: number; fps: number; ranges: readonly FrameRange[]; loop?: boolean } — ⚠ undocumented · used by `createGraphPose` (@jgengine/shell/render/useModelAnimation): Binds a graph's clips to a rig exactly as `useModelAnimation` does (masked layers get filtered clips, additive layers additive ones) so a ho…
13
13
  - `AntiOneShotConfig` (interface): interface AntiOneShotConfig — Caller data for the anti-one-shot composition: "cannot cross lethal while above X, leave Y, then recover for Z".
14
14
  - `AntiOneShotPolicy` (interface): interface AntiOneShotPolicy — The anti-one-shot policy: an interceptor plus its serializable recovery-immunity state.
15
15
  - `BUILTIN_COMPLETION_PREDICATES` (const): const BUILTIN_COMPLETION_PREDICATES: Readonly<Record<string, CompletionPredicate>> — Built-in completion predicates covering the common encounter gates: `immediate` (leaf marker), `manual`/`flag` (external event via a caller flag), `timer` (phase seconds), `cleared` (tagged entity count drained), `metric` (threshold on a live value), `event` (cumulative event count), and `quorum` (at least N of nested predicates met). Merge your own over these through {@link EncounterConfig.predicates}.
16
16
  - `BUILTIN_SPAWN_PROVIDERS` (const): const BUILTIN_SPAWN_PROVIDERS: Readonly<Record<string, SpawnProvider>> — Built-in spawn providers. `points` reads a named authored scene point list from context and cycles it to emit `count` requests, keeping coordinates in the scene rather than the sequence. `list` echoes literal requests authored in `params.requests`. Merge your own catalog- or director-backed providers through {@link EncounterConfig.spawnProviders}.
17
- - `BuildupProc` (interface): interface BuildupProc — ⚠ undocumented
17
+ - `BuildupProc` (interface): interface BuildupProc { status: string; durationMs: number } — ⚠ undocumented
18
18
  - `CheckAdvantage` (type): type CheckAdvantage = "advantage" | "disadvantage" | "normal" — ⚠ undocumented
19
- - `CheckResult` (interface): interface CheckResult — ⚠ undocumented
19
+ - `CheckResult` (interface): interface CheckResult { rolls: readonly number[]; roll: number; total: number; success: boolean; critical: "success" | "failure" | null } — ⚠ undocumented · used by `rollCheck`: Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
20
20
  - `ClaimOutcome` (interface): interface ClaimOutcome — The outcome of a claim attempt — the updated pool and the grants owed (empty when the claim is refused).
21
21
  - `ClaimablePool` (interface): interface ClaimablePool — A serializable pool of results left open for later claiming — first-come contested drops or a `reservedFor` personal reward. Tracks `eligible` claimants, optional `expiresAtMs`, and the authoritative `claimedBy` winner so reconnect and duplicate-claim attempts resolve idempotently.
22
22
  - `ComboMeter` (interface): interface ComboMeter — A live, observable combo/multiplier meter — an integer hit chain with a decay window, free-string tier thresholds, a derived multiplier, and peak tracking.
23
23
  - `ComboMeterConfig` (interface): interface ComboMeterConfig — Options for {@link createComboMeter}.
24
24
  - `ComboMeterSnapshot` (interface): interface ComboMeterSnapshot — Serializable state for save/restore — clock-agnostic (stores time left, not an absolute deadline).
25
25
  - `ComboMeterView` (interface): interface ComboMeterView — A pooled, read-only snapshot of the live meter for a renderer to draw each frame. Reused across {@link ComboMeter.view} calls and overwritten on the next one — read it, do not retain it. For a save, use {@link ComboMeter.snapshot}.
26
- - `ComboStep` (interface): interface ComboStep — ⚠ undocumented
26
+ - `ComboStep` (interface): interface ComboStep { id: string; clip: string; cancelInto?: readonly string[]; cancelPhases?: readonly FramePhase[]; stance?: string } — ⚠ undocumented
27
27
  - `ComboTier` (interface): interface ComboTier — One tier threshold in a {@link ComboMeter}. Tiers gate on the integer combo `count` (not a filled fraction), and `id` is a free string the game owns and styles ("good", "great", "savage", …) — the model never interprets it.
28
28
  - `CompletionPredicate` (type): type CompletionPredicate = ( params: Readonly<Record<string, unknown>>, ctx: PredicateContext, ) => boolean — A completion predicate: pure and deterministic, returns true when the node it gates is finished. Registered under a `kind` and reused across phases with different `params`.
29
29
  - `CrossingDirection` (type): type CrossingDirection = "falling" | "rising" — The direction a crossing moved: `falling` = value decreased past the mark, `rising` = increased past it.
@@ -55,12 +55,12 @@
55
55
  - `EncounterState` (interface): interface EncounterState<TData = unknown> — Full serializable encounter state: the working phase tree (including any injected phases), a per-node runtime map, the active path from root to the deepest open node, accumulated time, and whether the sequence has finished. Round-trips through JSON with no behavioral change; the registries live in {@link EncounterConfig}, not here.
56
56
  - `EncounterStep` (interface): interface EncounterStep<TData = unknown> — Result of a step: the (mutated, returned) state and the events emitted this step.
57
57
  - `EntityRenderCues` (interface): interface EntityRenderCues — Per-entity render cues: the motion/animation signal a custom `renderEntity` or first-person viewmodel component needs to drive gait, muzzle flash, reload poses, and hit reactions — without diffing the parent group's position itself or reading a game-side module map for attack timing.
58
- - `EventMeter` (interface): interface EventMeter — ⚠ undocumented
59
- - `EventMeterFeedResult` (interface): interface EventMeterFeedResult — ⚠ undocumented
58
+ - `EventMeter` (interface): interface EventMeter { state(): EventMeterState; restore(next: EventMeterState): void; value(): number; fraction(): number; tier(): string | null; ready(): boolean; feed(tag: string, scale?: number): EventMeterFeedResult; consume(): boolean; drain(amount: numbe… — ⚠ undocumented · used by `createEventMeter`: A heat/hype gauge that rises as tagged events land and cools between them, firing when it fills or breaks — the streak/overdrive meter shoot…
59
+ - `EventMeterFeedResult` (interface): interface EventMeterFeedResult { tag: string; reset: boolean; amount: number; value: number; fraction: number; fired: boolean; ready: boolean; overflow: number; tier: string | null; tierChanged: boolean } — ⚠ undocumented
60
60
  - `FireCadence` (interface): interface FireCadence — A minimal minimum-interval rate gate for a repeated action — weapon fire, ability spam, any "no faster than N per second" rule. Deterministic and serializable: its whole state is the elapsed time since the last action, exposed via {@link FireCadence.elapsedMs}.
61
61
  - `FireCadenceConfig` (interface): interface FireCadenceConfig — Tuning for {@link createFireCadence}: the minimum interval between actions and whether it starts ready.
62
- - `FrameRange` (interface): interface FrameRange — ⚠ undocumented
63
- - `HitReactionConfig` (interface): interface HitReactionConfig — ⚠ undocumented
62
+ - `FrameRange` (interface): interface FrameRange { phase: FramePhase; from: number; to: number } — ⚠ undocumented
63
+ - `HitReactionConfig` (interface): interface HitReactionConfig { hitstopMs: number; knockback: number; vertical?: number; shake?: CameraShake; trauma?: number; timescale?: number } — ⚠ undocumented · used by `resolveHitReaction`: Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
64
64
  - `ImmunityWindow` (interface): interface ImmunityWindow — A per-target timed immunity policy: an interceptor plus grant/query/serialize controls, toggled by transitions.
65
65
  - `InterceptContext` (interface): interface InterceptContext — Read-only context an interceptor may consult — deterministic clock and optional health lookup for HP-relative policies.
66
66
  - `InterceptDecision` (type): type InterceptDecision = | { kind: "pass" } | { kind: "transform"; amount: number; note?: string } | { kind: "clamp"; max: number; note?: string } | { kind: "redirect"; target: string; note?: string } | { kind: "split"; parts: readonly PendingDamage[]; note?: string } | { kind: "defer"; note?: strin… — What an interceptor decides to do with the pending application it was handed. `split` parts continue at the NEXT interceptor (never re-entering the splitter), which is what keeps the pipeline bounded and recursion-free.
@@ -71,9 +71,9 @@
71
71
  - `MagazineReserve` (interface): interface MagazineReserve — Draws ammo for a `Magazine`'s reload from wherever the reserve pool actually lives.
72
72
  - `MagazineSnapshot` (interface): interface MagazineSnapshot — Complete serializable state for a {@link Magazine}; `reserve: null` means infinite reserve.
73
73
  - `MatchupOutputs` (interface): interface MatchupOutputs — The independent, typed outputs a channel-vs-trait matchup can scale. Every field is an optional multiplier that defaults to `1` (identity), so a matchup entry names only the axes it bends. `impact` scales the direct hit, `applyChance` the odds a status lands, `magnitude` and `duration` the applied status itself, and `extra` carries any further caller-defined scalar (knockback, stagger, heat) the engine forwards without interpreting.
74
- - `MeterAddResult` (interface): interface MeterAddResult — ⚠ undocumented
74
+ - `MeterAddResult` (interface): interface MeterAddResult { value: number; fired: boolean; overflow: number; tier: string | null; tierChanged: boolean } — ⚠ undocumented
75
75
  - `ObjectRaycastHit` (interface): interface ObjectRaycastHit — ⚠ undocumented
76
- - `OnDeathSpec` (interface): interface OnDeathSpec — ⚠ undocumented
76
+ - `OnDeathSpec` (interface): interface OnDeathSpec — Catalog `onDeath` for an entity: loot tables to roll, `dropMode: "world"` to scatter drops on the ground (rendered with loot beams) instead of granting them into the killer's bag, and commands to run. Fires only when the entity dies through `ctx.scene.entity.effect`, not a raw `stats.delta`.
77
77
  - `PendingDamage` (interface): interface PendingDamage — Ordered, inspectable damage-resolution interception (#931).
78
78
  - `PhaseCompletionRef` (interface): interface PhaseCompletionRef — Reference to a registered completion predicate: a `kind` naming the evaluator plus opaque `params` the evaluator reads. The sequence core never interprets `params`; the predicate registered under `kind` does.
79
79
  - `PhaseInjectAt` (type): type PhaseInjectAt = | { before: string } | { after: string } | { childOf: string; index?: number } — Where to insert an injected phase, relative to an existing node by id.
@@ -81,7 +81,7 @@
81
81
  - `PhaseSpawnRef` (interface): interface PhaseSpawnRef — Reference to a registered spawn provider invoked when a phase is entered: a `kind` naming the provider plus opaque `params`. Spawning is one optional node adapter — a phase without `spawn` simply emits no spawn requests.
82
82
  - `PhaseStatus` (type): type PhaseStatus = "pending" | "active" | "complete" — Lifecycle status of one phase in an encounter sequence: waiting to run, currently running, or finished. Groups and leaves share the same three states.
83
83
  - `PredicateContext` (interface): interface PredicateContext — Evaluation context a completion predicate receives for the node under test.
84
- - `ProjectileSystemDeps` (interface): interface ProjectileSystemDeps — ⚠ undocumented
84
+ - `ProjectileSystemDeps` (interface): interface ProjectileSystemDeps { effects: EffectSystem; spatial: CombatSpatialDeps; getStat(itemId: string, stat: string): number | null; raycast?: Raycast; sceneRaycast?: SceneRaycastApi; objects?: ProjectileObjectsDeps; entityCollidersOf?(instanceId: string): EntityCol… — ⚠ undocumented · used by `createProjectileSystem`: Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
85
85
  - `RaycastHit` (type): type RaycastHit = EntityRaycastHit | ObjectRaycastHit — ⚠ undocumented
86
86
  - `ReceiveMap` (type): type ReceiveMap = Record<string, ReceiveRule> — ⚠ undocumented
87
87
  - `ReceivedDamageResult` (interface): interface ReceivedDamageResult — The full, provenance-rich outcome of running received modifiers over one hit.
@@ -90,7 +90,7 @@
90
90
  - `RenderCueTuning` (interface): interface RenderCueTuning — Tuning knobs for `advanceMotionCues` / `useEntityRenderCues`; every field has a default, override only what a weapon/rig's feel needs to differ.
91
91
  - `ResolvedMatchup` (interface): interface ResolvedMatchup — Fully-resolved matchup outputs (every axis populated) plus the contributions that produced them.
92
92
  - `ResolvedShot` (interface): interface ResolvedShot — A shot's resolved firing geometry in world space: `origin` is the point the projectile/ray starts from and `direction` is its normalized aim vector, both computed by {@link resolveShot} from the shooter's position, facing, and the chosen origin policy.
93
- - `ResourcePool` (interface): interface ResourcePool — ⚠ undocumented
93
+ - `ResourcePool` (interface): interface ResourcePool { current(): number; max(): number; setMax(value: number): void; fraction(): number; canSpend(amount: number): boolean; spend(amount: number): boolean; gain(amount: number): number; set(value: number): void; tick(dtSeconds: number): void; i… — ⚠ undocumented · used by `createResourcePool`: A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
94
94
  - `RewardClaimSpec` (interface): interface RewardClaimSpec — How a `claimed` allocation exposes its pool: open first-come (`first`) or `reserved` to one recipient.
95
95
  - `RewardGrant` (interface): interface RewardGrant — An authoritative, serializable award of one result stack to one recipient — carries `via` (the policy that produced it) and `private` (replication scope) so provenance and visibility survive save/load and viewer projection. Applying a grant twice with the same identity is the caller's idempotency contract; this seam only decides who is owed what.
96
96
  - `RewardPolicyKind` (type): type RewardPolicyKind = "instanced" | "shared" | "copy" | "roundRobin" | "assigned" | "claimed" — The distribution policies allocation ships — each a distinct answer to "who gets this result".
@@ -106,7 +106,7 @@
106
106
  - `StatPoolChange` (interface): interface StatPoolChange — Inspectable result of a bounded pool change.
107
107
  - `StatPoolInput` (interface): interface StatPoolInput — Input used to create a normalized pool. `current` defaults to `max`; `min` defaults to zero.
108
108
  - `StatPoolPatch` (interface): interface StatPoolPatch — Partial update applied without mutating the previous pool.
109
- - `Stats` (interface): interface Stats<TStat extends string> — ⚠ undocumented
109
+ - `Stats` (interface): interface Stats<TStat extends string> { setBase(stat: TStat, value: number): void; getBase(stat: TStat): number; addSource(sourceId: string, modifiers: StatModifierSet<TStat>, options?: {expiresAtMs?: number}): void; removeSource(sourceId: string): void; hasSource(sourceId: str… — ⚠ undocumented · used by `createStats`: A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
110
110
  - `StatsSnapshot` (interface): interface StatsSnapshot<TStat extends string> — Complete plain-data state for a {@link Stats} runtime.
111
111
  - `StatusApplicationOutcome` (interface): interface StatusApplicationOutcome — The result of one status application: the outcome, the resulting instance (if any), and the roll.
112
112
  - `StatusApplicationSpec` (interface): interface StatusApplicationSpec — A serializable, effect-agnostic description of a status a hit tries to apply: an opaque `status` id the game routes to its own effect/DoT pipeline, a base landing `chance`, and the duration/ticks/magnitude/attribution/stacking data the resolver needs. The engine never interprets `status` — it is a reference, not a built-in condition.
@@ -116,7 +116,7 @@
116
116
  - `StatusInstance` (interface): interface StatusInstance — A live status carried by a target — the serializable, replicable state a status application mutates.
117
117
  - `StatusStackPolicy` (type): type StatusStackPolicy = | { kind: "refresh" } | { kind: "stack"; max?: number; add?: number } | { kind: "replace" } | { kind: "ignore" } — How a fresh application behaves when the target already carries the status. - `refresh` — reset duration, hold the existing stack count. - `stack` — add `add` stacks (default 1) up to `max`, and refresh duration. - `replace` — overwrite duration and magnitude, stacks reset to 1. - `ignore` — leave the existing instance untouched (first application wins).
118
118
  - `TargetTraitId` (type): type TargetTraitId = string — Caller-owned id for a target trait — `"armored"`, `"fleshy"`, `"wet"`, `"boss"`. Traits are the receiver-side facets a matchup scores a channel against.
119
- - `TelegraphConfig` (interface): interface TelegraphConfig — ⚠ undocumented
119
+ - `TelegraphConfig` (interface): interface TelegraphConfig { shape: TelegraphShape; at: EntityPosition; dir?: number; windupMs?: number; turns?: number; kind?: string } — ⚠ undocumented
120
120
  - `TelegraphShape` (type): type TelegraphShape = | { kind: "circle"; radius: number } | { kind: "ring"; radius: number; innerRadius: number } | { kind: "cone"; radius: number; angle: number } | { kind: "line"; length: number; width: number } — ⚠ undocumented
121
121
  - `ThresholdCrossing` (interface): interface ThresholdCrossing — One emitted crossing: which threshold, which way, and the value span that produced it.
122
122
  - `ThresholdCrossingConfig` (interface): interface ThresholdCrossingConfig — Caller configuration for a threshold tracker.
@@ -189,7 +189,7 @@
189
189
  - `resolveMatchup` (function): function resolveMatchup<TChannel extends string = DamageChannelId, TTrait extends string = TargetTraitId>(matchup: DamageMatchup<TChannel, TTrait>, channel: TChannel | string, targetTraits: readonly (TTrait | string)[]): ResolvedMatchup — Resolve a channel against a target's traits into independent, multiplied outputs. Pure and order-independent: every trait the channel has an entry for contributes, its axes multiplying into the running product; unmatched traits are skipped, and when nothing matches the table's `default` (or identity) is used. Bounded by the trait count — no world scan.
190
190
  - `resolveReceivedDamage` (function): function resolveReceivedDamage(input: ReceivedDamageInput): ReceivedDamageResult — Run receiver-side modifiers over an incoming hit, in ascending `order`, recording every step. Amplification, reduction, caps, conversion, redirection, and immunity are all data — the engine applies whichever policies the target's modifiers declare and never branches on channel names. Pure over serializable data with bounded work (one pass over the modifier list); an `immune` policy short-circuits the remaining modifiers.
191
191
  - `resolveResistance` (function): function resolveResistance<TCategory extends string = string, TProperty extends string = string>(matrix: ResistanceMatrix<TCategory, TProperty>, category: TCategory | string, targetProperties: readonly (TProperty | string)[]): ResistanceResult — ⚠ undocumented
192
- - `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — ⚠ undocumented
192
+ - `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — Resolves a shot's world origin and direction from the shooter's eye or muzzle and an {@link Aim}, ready for `ctx.scene.raycast` — the aim half of a hitscan weapon.
193
193
  - `resolveStatusApplication` (function): function resolveStatusApplication(input: StatusApplicationInput): StatusApplicationOutcome — Resolve one status application: reject on immunity, roll landing chance against injected RNG, scale magnitude/duration by the matchup, then fold into any existing instance per the stacking policy. Deterministic given a seeded `rng`; pure over serializable data, so authority can run it and replicate only the returned `instance`.
194
194
  - `resolveVfxPreset` (function): function resolveVfxPreset(name: string | undefined, overrides?: Partial<VfxPreset>): VfxPreset — Resolve a named visual flavor into a concrete `{ kind, color, durationMs?, radius? }`, with any provided `overrides` winning field by field. An unknown name resolves to {@link DEFAULT_VFX_PRESET} rather than throwing, so a flavor typo degrades to a visible spark. Used by `ctx.scene.entity.vfx({ preset })`; call it directly when you need the raw numbers (e.g. to seed a retained `vfxInstance` from the same vocabulary).
195
195
  - `rollCheck` (function): function rollCheck(input: CheckInput, rng?: () => number): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
@@ -207,28 +207,29 @@
207
207
  - `AbilityCastResult` (type): type AbilityCastResult = | { ok: true; slot: AbilitySlotSnapshot } | { ok: false; reason: AbilityCastReason; slot: AbilitySlotSnapshot | null } — ⚠ undocumented
208
208
  - `AbilityCastType` (type): type AbilityCastType = "instant" | "projectile" | "channel" | "targeted" — ⚠ undocumented
209
209
  - `AbilityCooldownGroup` (interface): interface AbilityCooldownGroup — A cooldown shared across every member slot: casting any member starts it, and no member can cast while it runs. One group that every slot joins is an MMO global cooldown.
210
- - `AbilityKit` (interface): interface AbilityKit — ⚠ undocumented
211
- - `AbilityKitOptions` (interface): interface AbilityKitOptions — ⚠ undocumented
210
+ - `AbilityKit` (interface): interface AbilityKit { slots(): readonly string[]; config(slotId: string): AbilitySlotConfig | null; state(): AbilityKitState; state(slotId: string, resourceAvailable?: number): AbilitySlotSnapshot | null; snapshot(resourceAvailable?: number): AbilitySlotSnapsh… — ⚠ undocumented · used by `createAbilityKit`: A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
211
+ - `AbilityKitOptions` (interface): interface AbilityKitOptions { groups?: readonly AbilityCooldownGroup[]; resource?: AbilityResource } — ⚠ undocumented · used by `createAbilityKit`: A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
212
+ - `AbilityKitState` (interface): interface AbilityKitState — Mutable kit state; slot/group definitions and any bound resource are saved by the caller.
212
213
  - `AbilityResource` (interface): interface AbilityResource — A spendable resource pool (mana, energy, rage) bound to an ability kit. When bound, `cast` deducts a slot's `resourceCost` on success and `state`/`snapshot`/`canCast` reflect affordability without a per-call `resourceAvailable` argument — the cast path actually spends instead of only gating (#357).
213
- - `AbilitySlotConfig` (interface): interface AbilitySlotConfig — ⚠ undocumented
214
- - `AbilitySlotRetune` (interface): interface AbilitySlotRetune — ⚠ undocumented
215
- - `AbilitySlotSnapshot` (interface): interface AbilitySlotSnapshot — ⚠ undocumented
214
+ - `AbilitySlotConfig` (interface): interface AbilitySlotConfig { id: string; cooldownMs: number; chargesMax?: number; resourceCost?: number; castType?: AbilityCastType; flashMs?: number; groups?: readonly string[] } — ⚠ undocumented · used by `createAbilityKit`: A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
215
+ - `AbilitySlotRetune` (interface): interface AbilitySlotRetune { cooldownMs?: number; resourceCost?: number } — ⚠ undocumented
216
+ - `AbilitySlotSnapshot` (interface): interface AbilitySlotSnapshot { id: string; state: AbilitySlotState; castType: AbilityCastType; resourceCost: number; charges: number; chargesMax: number; cooldownRemainingMs: number; cooldownFraction: number; groupRemainingMs: number; justCast: boolean; ready: boolean … — ⚠ undocumented · used by `actionFromAbilitySlot` (@jgengine/react): Composable React renderers over the headless action view model (`@jgengine/core/ui/actionModel`) — the data/renderer/chrome split for an RTS…
216
217
  - `AbilitySlotState` (type): type AbilitySlotState = "ready" | "cooldown" | "no-resource" | "just-cast" — ⚠ undocumented
217
218
  - `createAbilityKit` (function): function createAbilityKit(configs: readonly AbilitySlotConfig[], options: AbilityKitOptions = {}): AbilityKit — A bar of cooldown-gated abilities the player fires by slot, tracking readiness and cooldown per ability.
218
219
 
219
220
  ## @jgengine/core/combat/animationState
220
221
 
221
- - `AnimationClip` (interface): interface AnimationClip — ⚠ undocumented
222
- - `AnimationSnapshot` (interface): interface AnimationSnapshot — ⚠ undocumented
223
- - `AnimationState` (interface): interface AnimationState — ⚠ undocumented
224
- - `AnimationStateConfig` (interface): interface AnimationStateConfig — ⚠ undocumented
225
- - `AnimationTickResult` (interface): interface AnimationTickResult — ⚠ undocumented
222
+ - `AnimationClip` (interface): interface AnimationClip { id: string; frames: number; fps: number; ranges: readonly FrameRange[]; loop?: boolean } — ⚠ undocumented · used by `createGraphPose` (@jgengine/shell/render/useModelAnimation): Binds a graph's clips to a rig exactly as `useModelAnimation` does (masked layers get filtered clips, additive layers additive ones) so a ho…
223
+ - `AnimationSnapshot` (interface): interface AnimationSnapshot { clipId: string; frame: number; elapsedMs: number } — ⚠ undocumented
224
+ - `AnimationState` (interface): interface AnimationState { play(clipId: string): void; stop(): void; tick(dtSeconds: number): AnimationTickResult; current(): AnimationSnapshot | null; phases(): readonly FramePhase[]; inPhase(phase: FramePhase): boolean; isActive(): boolean; canCancel(): boolean; … — ⚠ undocumented · used by `createComboRunner` (@jgengine/core/combat): Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
225
+ - `AnimationStateConfig` (interface): interface AnimationStateConfig { clips: readonly AnimationClip[] } — ⚠ undocumented
226
+ - `AnimationTickResult` (interface): interface AnimationTickResult { clipId: string | null; frame: number; entered: readonly FramePhase[]; exited: readonly FramePhase[]; completed: boolean } — ⚠ undocumented
226
227
  - `FramePhase` (type): type FramePhase = "windup" | "active" | "recovery" | "cancel" — ⚠ undocumented
227
- - `FrameRange` (interface): interface FrameRange — ⚠ undocumented
228
+ - `FrameRange` (interface): interface FrameRange { phase: FramePhase; from: number; to: number } — ⚠ undocumented
228
229
 
229
230
  ## @jgengine/core/combat/attackTags
230
231
 
231
- - `AttackMeta` (interface): interface AttackMeta — ⚠ undocumented
232
+ - `AttackMeta` (interface): interface AttackMeta { tags: readonly AttackTag[]; effect?: string; power?: number } — ⚠ undocumented
232
233
  - `AttackTag` (type): type AttackTag = | "unblockable" | "thrust" | "sweep" | "grab" | "overhead" | "ranged" | "aerial" — ⚠ undocumented
233
234
  - `CounterMove` (type): type CounterMove = "mikiri" | "deflect" | "sidestep" — ⚠ undocumented
234
235
  - `attackMeta` (function): function attackMeta(tags: readonly AttackTag[], extra?: Omit<AttackMeta, "tags">): AttackMeta — ⚠ undocumented
@@ -241,18 +242,18 @@
241
242
 
242
243
  ## @jgengine/core/combat/breakMeters
243
244
 
244
- - `BuildupMeter` (interface): interface BuildupMeter — ⚠ undocumented
245
- - `BuildupMeterConfig` (interface): interface BuildupMeterConfig — ⚠ undocumented
246
- - `BuildupProc` (interface): interface BuildupProc — ⚠ undocumented
247
- - `StaggerMeter` (interface): interface StaggerMeter — ⚠ undocumented
248
- - `StaggerMeterConfig` (interface): interface StaggerMeterConfig — ⚠ undocumented
245
+ - `BuildupMeter` (interface): interface BuildupMeter { add(amount: number): BuildupProc | null; value(): number; fraction(): number; tick(dtSeconds: number): void } — ⚠ undocumented · used by `createBuildupMeter`: Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
246
+ - `BuildupMeterConfig` (interface): interface BuildupMeterConfig { status: string; max: number; durationMs: number; decayPerSecond?: number; decayDelayMs?: number } — ⚠ undocumented · used by `createBuildupMeter`: Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
247
+ - `BuildupProc` (interface): interface BuildupProc { status: string; durationMs: number } — ⚠ undocumented
248
+ - `StaggerMeter` (interface): interface StaggerMeter { add(amount: number): boolean; broke(): boolean; value(): number; fraction(): number; recover(): void; tick(dtSeconds: number): void } — ⚠ undocumented · used by `createStaggerMeter`: Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
249
+ - `StaggerMeterConfig` (interface): interface StaggerMeterConfig { max: number; decayPerSecond?: number; decayDelayMs?: number } — ⚠ undocumented · used by `createStaggerMeter`: Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
249
250
  - `createBuildupMeter` (function): function createBuildupMeter(config: BuildupMeterConfig): BuildupMeter — Accumulate an ailment buildup — bleed, freeze, poison — that procs a status once it fills, then decays.
250
251
  - `createStaggerMeter` (function): function createStaggerMeter(config: StaggerMeterConfig): StaggerMeter — Build a stagger/poise gauge from landed hits toward a break threshold that staggers the target.
251
252
 
252
253
  ## @jgengine/core/combat/castRunner
253
254
 
254
- - `CastBarSnapshot` (interface): interface CastBarSnapshot — ⚠ undocumented
255
- - `CastConfig` (interface): interface CastConfig — ⚠ undocumented
255
+ - `CastBarSnapshot` (interface): interface CastBarSnapshot { abilityId: string; castTimeMs: number; elapsedMs: number; remainingMs: number; fraction: number } — ⚠ undocumented
256
+ - `CastConfig` (interface): interface CastConfig { abilityId: string; castTimeMs: number; moveTolerance?: number; moveDeadzone?: number } — ⚠ undocumented
256
257
  - `CastEvent` (type): type CastEvent = | { kind: "completed"; abilityId: string } | { kind: "interrupted"; abilityId: string; reason: CastInterruptReason } — ⚠ undocumented
257
258
  - `CastInterruptReason` (type): type CastInterruptReason = "moved" | "cancelled" | "replaced" — ⚠ undocumented
258
259
  - `CastRunner` (interface): interface CastRunner — Per-entity cast-time state machine — begin, tick with game-time `dt` plus how far the caster moved, and act on the returned event. The runner owns timing and move-interruption only; the caller spends resources, starts cooldowns, and executes the ability when `completed` fires (compose with `abilityKit` — check readiness before `begin`, `cast` on completion).
@@ -269,18 +270,18 @@
269
270
 
270
271
  ## @jgengine/core/combat/comboPoints
271
272
 
272
- - `ComboPoints` (interface): interface ComboPoints — ⚠ undocumented
273
- - `ComboPointsConfig` (interface): interface ComboPointsConfig — ⚠ undocumented
273
+ - `ComboPoints` (interface): interface ComboPoints { points(): number; gain(amount?: number): number; spend(amount: number): boolean; spendAll(): number; tick(dtSeconds: number): void; expiresIn(): number | null; clear(): void; snapshot(): ComboPointsSnapshot; restore(state: ComboPointsSnap… — ⚠ undocumented · used by `createComboPoints`: Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
274
+ - `ComboPointsConfig` (interface): interface ComboPointsConfig { max: number; expireAfterSeconds?: number } — ⚠ undocumented · used by `createComboPoints`: Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
274
275
  - `ComboPointsSnapshot` (interface): interface ComboPointsSnapshot — Complete serializable state for {@link ComboPoints}; `remaining: null` means no expiry is running.
275
276
  - `createComboPoints` (function): function createComboPoints(config: ComboPointsConfig): ComboPoints — Build and spend finisher points — the combo-point economy behind rogue-style builders and spenders.
276
277
 
277
278
  ## @jgengine/core/combat/comboString
278
279
 
279
- - `AdvanceComboInput` (interface): interface AdvanceComboInput — ⚠ undocumented
280
+ - `AdvanceComboInput` (interface): interface AdvanceComboInput { combo: ComboString; currentStepId: string | null; requestedStepId: string; phases: readonly FramePhase[]; stance?: string } — ⚠ undocumented
280
281
  - `AdvanceComboResult` (type): type AdvanceComboResult = | { accepted: true; step: ComboStep } | { accepted: false; reason: "unknown-step" | "not-chainable" | "wrong-stance" | "window-closed" } — ⚠ undocumented
281
- - `ComboRunner` (interface): interface ComboRunner — ⚠ undocumented
282
- - `ComboStep` (interface): interface ComboStep — ⚠ undocumented
283
- - `ComboString` (interface): interface ComboString — ⚠ undocumented
282
+ - `ComboRunner` (interface): interface ComboRunner { currentStep(): string | null; request(stepId: string, stance?: string): AdvanceComboResult; reset(): void } — ⚠ undocumented · used by `createComboRunner`: Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
283
+ - `ComboStep` (interface): interface ComboStep { id: string; clip: string; cancelInto?: readonly string[]; cancelPhases?: readonly FramePhase[]; stance?: string } — ⚠ undocumented
284
+ - `ComboString` (interface): interface ComboString { id: string; entry: string; steps: readonly ComboStep[] } — ⚠ undocumented · used by `createComboRunner`: Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
284
285
  - `advanceCombo` (function): function advanceCombo(input: AdvanceComboInput): AdvanceComboResult — ⚠ undocumented
285
286
  - `createComboRunner` (function): function createComboRunner(combo: ComboString, anim: AnimationState): ComboRunner — Advance a chained melee string from timed inputs, tracking the current step and its cancel/continue windows.
286
287
  - `stepById` (function): function stepById(combo: ComboString, stepId: string): ComboStep | null — ⚠ undocumented
@@ -323,17 +324,17 @@
323
324
 
324
325
  ## @jgengine/core/combat/death
325
326
 
326
- - `DeathIdentity` (interface): interface DeathIdentity — ⚠ undocumented
327
+ - `DeathIdentity` (interface): interface DeathIdentity { catalogId: string; userId?: string; displayName?: string; position: [number, number, number] } — ⚠ undocumented
327
328
  - `DeathReasonKind` (type): type DeathReasonKind = DeathReason["kind"] — ⚠ undocumented
328
329
  - `DeathResolution` (type): type DeathResolution = | { status: "resolved"; drops: Drop[]; ranCommand: string | null } | { status: "rejected"; reason: string } — ⚠ undocumented
329
- - `DeathSystem` (interface): interface DeathSystem — ⚠ undocumented
330
- - `DeathSystemDeps` (interface): interface DeathSystemDeps — ⚠ undocumented
330
+ - `DeathSystem` (interface): interface DeathSystem { resolveDeath(instanceId: string, reason: DeathReason): DeathResolution; revive(instanceId: string): boolean } — ⚠ undocumented · used by `createDeathSystem`: Resolve entity death and the on-death consequences — drops, respawn eligibility, kill credit.
331
+ - `DeathSystemDeps` (interface): interface DeathSystemDeps { resolveOnDeath(instanceId: string, reason?: DeathReason): OnDeathSpec | null | undefined; resolveIdentity(instanceId: string): DeathIdentity | null; loot: {roll(tableId: string): Drop[]}; events: GameEvents; runCommand?(name: string, args… — ⚠ undocumented · used by `createDeathSystem`: Resolve entity death and the on-death consequences — drops, respawn eligibility, kill credit.
331
332
  - `DropMode` (type): type DropMode = "grant" | "world" — ⚠ undocumented
332
- - `EffectDeathContext` (interface): interface EffectDeathContext — ⚠ undocumented
333
- - `NormalizedOnDeath` (interface): interface NormalizedOnDeath — ⚠ undocumented
334
- - `OnDeathCommandRule` (interface): interface OnDeathCommandRule — ⚠ undocumented
335
- - `OnDeathDropRule` (interface): interface OnDeathDropRule — ⚠ undocumented
336
- - `OnDeathSpec` (interface): interface OnDeathSpec — ⚠ undocumented
333
+ - `EffectDeathContext` (interface): interface EffectDeathContext { from: string; via?: EffectVia; userIdOf?(instanceId: string): string | undefined } — ⚠ undocumented
334
+ - `NormalizedOnDeath` (interface): interface NormalizedOnDeath { drops: OnDeathDropRule[]; command: OnDeathCommandRule | null; dropMode: DropMode; scatter?: ScatterOptions } — ⚠ undocumented
335
+ - `OnDeathCommandRule` (interface): interface OnDeathCommandRule { name: string; args?: unknown; when?: {reason: DeathReasonKind} } — ⚠ undocumented
336
+ - `OnDeathDropRule` (interface): interface OnDeathDropRule { table: string; when?: {reason: DeathReasonKind | "any"} } — ⚠ undocumented
337
+ - `OnDeathSpec` (interface): interface OnDeathSpec — Catalog `onDeath` for an entity: loot tables to roll, `dropMode: "world"` to scatter drops on the ground (rendered with loot beams) instead of granting them into the killer's bag, and commands to run. Fires only when the entity dies through `ctx.scene.entity.effect`, not a raw `stats.delta`.
337
338
  - `createDeathSystem` (function): function createDeathSystem(deps: DeathSystemDeps): DeathSystem — Resolve entity death and the on-death consequences — drops, respawn eligibility, kill credit.
338
339
  - `deathReasonFromEffect` (function): function deathReasonFromEffect(ctx: EffectDeathContext): DeathReason — ⚠ undocumented
339
340
  - `normalizeOnDeath` (function): function normalizeOnDeath(spec: OnDeathSpec | null | undefined): NormalizedOnDeath — ⚠ undocumented
@@ -347,9 +348,9 @@
347
348
  - `DefenseKind` (type): type DefenseKind = "parry" | "block" | "dodge" — ⚠ undocumented
348
349
  - `DefenseOutcome` (type): type DefenseOutcome = "parry" | "block" | "iframe" | "hit" — ⚠ undocumented
349
350
  - `DefenseResolution` (interface): interface DefenseResolution — Result of resolving an incoming hit against a defensive window: `outcome` is the graded defense (`"parry"`/`"block"`/`"iframe"`/`"hit"`) and `perfect` is true when the input landed inside the tight just-frame at the window's start rather than its wider active span.
350
- - `DefensiveWindow` (interface): interface DefensiveWindow — ⚠ undocumented
351
- - `DefensiveWindowConfig` (interface): interface DefensiveWindowConfig — ⚠ undocumented
352
- - `ResolveDefenseInput` (interface): interface ResolveDefenseInput — ⚠ undocumented
351
+ - `DefensiveWindow` (interface): interface DefensiveWindow { open(nowMs: number): void; close(): void; isOpen(nowMs: number): boolean; evaluate(nowMs: number, attack: AttackMeta): DefenseResolution; isInvulnerable(nowMs: number): boolean } — ⚠ undocumented · used by `createDefensiveWindow`: Open a timed defensive window — block, parry, or i-frames — and test incoming hits against it.
352
+ - `DefensiveWindowConfig` (interface): interface DefensiveWindowConfig { kind: DefenseKind; startupMs?: number; activeMs: number; recoveryMs?: number; iframes?: {fromMs: number; toMs: number} } — ⚠ undocumented · used by `createDefensiveWindow`: Open a timed defensive window — block, parry, or i-frames — and test incoming hits against it.
353
+ - `ResolveDefenseInput` (interface): interface ResolveDefenseInput { config: DefensiveWindowConfig; elapsedMs: number; attack: AttackMeta } — ⚠ undocumented
353
354
  - `createDefensiveWindow` (function): function createDefensiveWindow(config: DefensiveWindowConfig): DefensiveWindow — Open a timed defensive window — block, parry, or i-frames — and test incoming hits against it.
354
355
  - `iframeActiveAt` (function): function iframeActiveAt(config: DefensiveWindowConfig, elapsedMs: number): boolean — ⚠ undocumented
355
356
  - `resolveDefense` (function): function resolveDefense(input: ResolveDefenseInput): DefenseResolution — ⚠ undocumented
@@ -365,30 +366,30 @@
365
366
 
366
367
  ## @jgengine/core/combat/downed
367
368
 
368
- - `DownedConfig` (interface): interface DownedConfig — ⚠ undocumented
369
- - `DownedEntry` (interface): interface DownedEntry — ⚠ undocumented
370
- - `DownedEvent` (interface): interface DownedEvent — ⚠ undocumented
369
+ - `DownedConfig` (interface): interface DownedConfig { bleedoutSeconds: number; reviveSeconds?: number; reviveHealthFraction?: number; banner?: {expireSeconds: number} } — ⚠ undocumented · used by `createDownedState`: A downed/bleed-out state that ticks toward death and that teammates can revive before the timer runs out.
370
+ - `DownedEntry` (interface): interface DownedEntry { phase: DownedPhase; bleedoutRemaining: number; reviveProgress: number; bannerRemaining: number | null } — ⚠ undocumented
371
+ - `DownedEvent` (interface): interface DownedEvent { kind: DownedEventKind; instanceId: string; reason?: string; reviveHealthFraction?: number } — ⚠ undocumented
371
372
  - `DownedEventKind` (type): type DownedEventKind = | "downed" | "revived" | "reviving" | "died" | "banner.created" | "banner.expired" | "respawned" — ⚠ undocumented
372
373
  - `DownedPhase` (type): type DownedPhase = "alive" | "downed" | "dead" — ⚠ undocumented
373
- - `DownedState` (interface): interface DownedState — ⚠ undocumented
374
+ - `DownedState` (interface): interface DownedState { down(instanceId: string): DownedEvent | null; revive(instanceId: string, dt: number): DownedEvent | null; interruptRevive(instanceId: string): void; finish(instanceId: string, reason?: string): DownedEvent | null; tick(dt: number): Downed… — ⚠ undocumented · used by `createDownedState`: A downed/bleed-out state that ticks toward death and that teammates can revive before the timer runs out.
374
375
  - `createDownedState` (function): function createDownedState(config: DownedConfig): DownedState — A downed/bleed-out state that ticks toward death and that teammates can revive before the timer runs out.
375
376
 
376
377
  ## @jgengine/core/combat/effects
377
378
 
378
- - `AppliedPoolDelta` (interface): interface AppliedPoolDelta — ⚠ undocumented
379
- - `AreaEffectInput` (interface): interface AreaEffectInput — ⚠ undocumented
380
- - `AreaTarget` (interface): interface AreaTarget — ⚠ undocumented
381
- - `AreaTargetInput` (interface): interface AreaTargetInput — ⚠ undocumented
382
- - `CombatSpatialDeps` (interface): interface CombatSpatialDeps — ⚠ undocumented
379
+ - `AppliedPoolDelta` (interface): interface AppliedPoolDelta { statId: string; delta: number } — ⚠ undocumented
380
+ - `AreaEffectInput` (interface): interface AreaEffectInput { from: string; effect: string; via?: EffectVia; at: EntityPosition; radius: number; falloff?: "linear" | "none"; los?: boolean } — ⚠ undocumented
381
+ - `AreaTarget` (interface): interface AreaTarget { instanceId: string; scale: number } — ⚠ undocumented
382
+ - `AreaTargetInput` (interface): interface AreaTargetInput { at: EntityPosition; radius: number; falloff?: "linear" | "none"; los?: boolean } — ⚠ undocumented
383
+ - `CombatSpatialDeps` (interface): interface CombatSpatialDeps { inRadius(center: EntityPosition, radius: number): string[]; hasLineOfSight(from: EntityPosition | string, to: string): boolean; positionOf(instanceId: string): EntityPosition | undefined } — ⚠ undocumented
383
384
  - `EffectInput` (type): type EffectInput = SingleTargetEffectInput | AreaEffectInput — ⚠ undocumented
384
- - `EffectResult` (interface): interface EffectResult — ⚠ undocumented
385
- - `EffectSystem` (interface): interface EffectSystem — ⚠ undocumented
386
- - `EffectSystemDeps` (interface): interface EffectSystemDeps — ⚠ undocumented
387
- - `EffectVia` (interface): interface EffectVia — ⚠ undocumented
388
- - `LethalContext` (interface): interface LethalContext — ⚠ undocumented
385
+ - `EffectResult` (interface): interface EffectResult { instanceId: string; effect: string; applied: AppliedPoolDelta[]; lethal: boolean; slain?: SlainIdentity } — ⚠ undocumented
386
+ - `EffectSystem` (interface): interface EffectSystem { canReceive(instanceId: string, effect: string, magnitude?: number): string | null; preview(input: SingleTargetEffectInput): number; applyEffect(input: EffectInput): EffectResult[] } — ⚠ undocumented · used by `createEffectSystem`: Resolve direct or area resource effects through caller-owned stat pools, including ordered absorption, restoration, modifiers, and lethal co…
387
+ - `EffectSystemDeps` (interface): interface EffectSystemDeps { resolveReceive(instanceId: string): ReceiveMap | null | undefined; statPools?: StatPoolAccess; resolveStats?(instanceId: string): Record<string, StatPool> | undefined; getStat(itemId: string, stat: string): number | null; spatial: CombatS… — ⚠ undocumented · used by `createEffectSystem`: Resolve direct or area resource effects through caller-owned stat pools, including ordered absorption, restoration, modifiers, and lethal co…
388
+ - `EffectVia` (interface): interface EffectVia { item?: string; amount?: number } — ⚠ undocumented
389
+ - `LethalContext` (interface): interface LethalContext { from: string; via?: EffectVia; effect: string } — ⚠ undocumented
389
390
  - `ReceiveMap` (type): type ReceiveMap = Record<string, ReceiveRule> — ⚠ undocumented
390
- - `ReceiveRule` (interface): interface ReceiveRule — ⚠ undocumented
391
- - `SingleTargetEffectInput` (interface): interface SingleTargetEffectInput — ⚠ undocumented
391
+ - `ReceiveRule` (interface): interface ReceiveRule { order: string[]; modifiers?: Record<string, number> } — ⚠ undocumented
392
+ - `SingleTargetEffectInput` (interface): interface SingleTargetEffectInput { from: string; to: string; effect: string; via?: EffectVia } — ⚠ undocumented
392
393
  - `SlainIdentity` (interface): interface SlainIdentity — Identity of an entity slain by a lethal effect, captured before the death system despawns it. Serializable and genre-agnostic: `catalogId` is the slain entity's spawn kind/name (the same value the `entity.died` event carries), `name` an optional human-readable label for kill feeds, and `userId` the owning player when the slain unit was player-controlled. The slain entity's instance id is already {@link EffectResult.instanceId}.
393
394
  - `createEffectSystem` (function): function createEffectSystem(deps: EffectSystemDeps): EffectSystem — Resolve direct or area resource effects through caller-owned stat pools, including ordered absorption, restoration, modifiers, and lethal context.
394
395
  - `resolveAreaTargets` (function): function resolveAreaTargets(spatial: CombatSpatialDeps, input: AreaTargetInput, accept?: (instanceId: string) => boolean): AreaTarget[] — ⚠ undocumented
@@ -425,10 +426,10 @@
425
426
 
426
427
  ## @jgengine/core/combat/hitReaction
427
428
 
428
- - `CameraShake` (interface): interface CameraShake — ⚠ undocumented
429
- - `HitReaction` (interface): interface HitReaction — ⚠ undocumented
430
- - `HitReactionConfig` (interface): interface HitReactionConfig — ⚠ undocumented
431
- - `HitReactionInput` (interface): interface HitReactionInput — ⚠ undocumented
429
+ - `CameraShake` (interface): interface CameraShake { amplitude: number; decay: number } — ⚠ undocumented
430
+ - `HitReaction` (interface): interface HitReaction { hitstopMs: number; impulse: [number, number, number]; shake: CameraShake | null; trauma: number | null; timescale: number | null } — ⚠ undocumented · used by `resolveHitReaction`: Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
431
+ - `HitReactionConfig` (interface): interface HitReactionConfig { hitstopMs: number; knockback: number; vertical?: number; shake?: CameraShake; trauma?: number; timescale?: number } — ⚠ undocumented · used by `resolveHitReaction`: Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
432
+ - `HitReactionInput` (interface): interface HitReactionInput { attackerPos: EntityPosition; targetPos: EntityPosition; power?: number } — ⚠ undocumented · used by `resolveHitReaction`: Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
432
433
  - `ImpactPreset` (interface): interface ImpactPreset — A calibrated `resolveHitReaction` config for a named impact event — hitstop + trauma so feel works with zero tuning.
433
434
  - `ImpactPresetName` (type): type ImpactPresetName = keyof typeof impactPresets — A named key into {@link impactPresets} (`"pickup" | "jumpLand" | "enemyKilled" | "playerHit" | "explosion"`).
434
435
  - `applyImpulse` (function): function applyImpulse(position: EntityPosition, impulse: [number, number, number]): EntityPosition — ⚠ undocumented
@@ -441,19 +442,27 @@
441
442
  - `MagazineConfig` (interface): interface MagazineConfig — Tuning for `createMagazine`: mag capacity, reload delay, and where reserve ammo is drawn from.
442
443
  - `MagazineReserve` (interface): interface MagazineReserve — Draws ammo for a `Magazine`'s reload from wherever the reserve pool actually lives.
443
444
  - `MagazineSnapshot` (interface): interface MagazineSnapshot — Complete serializable state for a {@link Magazine}; `reserve: null` means infinite reserve.
445
+ - `MagazineTuning` (interface): interface MagazineTuning — Live magazine tuning; shrinking below loaded rounds rejects unless overflow is explicit.
444
446
  - `createMagazine` (function): function createMagazine(config: MagazineConfig): Magazine — Builds a {@link Magazine}: discrete loaded ammo, a timed reload, and reserve-pool interaction.
445
447
 
446
448
  ## @jgengine/core/combat/projectiles
447
449
 
448
- - `EntityRaycastHit` (interface): interface EntityRaycastHit — ⚠ undocumented
449
- - `ObjectRaycastHit` (interface): interface ObjectRaycastHit — ⚠ undocumented
450
+ - `EntityRaycastHit` (interface): interface EntityRaycastHit { kind: "entity"; instanceId: string; distance: number; at: EntityPosition; colliderName?: string; damageEligible?: boolean; blocks?: boolean } — ⚠ undocumented
451
+ - `LiveProjectile` (interface): interface LiveProjectile — Detached pose of one active projectile pellet for presentation.
452
+ - `ObjectRaycastHit` (interface): interface ObjectRaycastHit { kind: "object"; instanceId: string; catalogId: string; distance: number; at: EntityPosition; colliderName?: string; damageEligible?: boolean; blocks?: boolean } — ⚠ undocumented
453
+ - `ProjectileFlightState` (interface): interface ProjectileFlightState — Serializable motion state of one projectile pellet.
450
454
  - `ProjectileHit` (type): type ProjectileHit = | { kind: "entity"; instanceId: string; distance: number; colliderName?: string; damageEligible?: boolean; } | { kind: "object"; instanceId: string; catalogId: string; distance: number; colliderName?: string; damageEligible?: boolean; } — ⚠ undocumented
451
- - `ProjectileObjectsDeps` (interface): interface ProjectileObjectsDeps — ⚠ undocumented
452
- - `ProjectilePrediction` (interface): interface ProjectilePrediction — ⚠ undocumented
453
- - `ProjectileSettleReport` (interface): interface ProjectileSettleReport — ⚠ undocumented
454
- - `ProjectileShotInput` (interface): interface ProjectileShotInput — ⚠ undocumented
455
- - `ProjectileSystem` (interface): interface ProjectileSystem — ⚠ undocumented
456
- - `ProjectileSystemDeps` (interface): interface ProjectileSystemDeps — ⚠ undocumented
455
+ - `ProjectileObjectsDeps` (interface): interface ProjectileObjectsDeps { list(): readonly {instanceId: string; catalogId: string; position: readonly [number, number, number]; rotationY?: number;}[]; inBox?(min: EntityPosition, max: EntityPosition): readonly {instanceId: string; catalogId: string; position: rea… — ⚠ undocumented
456
+ - `ProjectilePrediction` (interface): interface ProjectilePrediction { hits: ProjectileHit[]; blocked?: boolean; origin?: EntityPosition; direction?: EntityPosition; firstImpact?: ProjectileHit | null } — ⚠ undocumented
457
+ - `ProjectileSettleReport` (interface): interface ProjectileSettleReport — Exactly-once settlement with launch identity and actual applied effects.
458
+ - `ProjectileShotInput` (interface): interface ProjectileShotInput { from: string; via: EffectVia; aim: Aim; effect: string; originPolicy?: ShotOriginPolicy; travel?: ProjectileTravelConfig } — ⚠ undocumented
459
+ - `ProjectileShotState` (interface): interface ProjectileShotState — Serializable captured launch and settlement state.
460
+ - `ProjectileSystem` (interface): interface ProjectileSystem { willHitProjectile(input: ProjectileShotInput): ProjectilePrediction; fireProjectile(input: ProjectileShotInput): string; settleProjectile(shotId: string): SettleResult; advanceProjectiles(dt: number, time: number): SettleResult[]; activeP… — ⚠ undocumented · used by `createProjectileSystem`: Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
461
+ - `ProjectileSystemDeps` (interface): interface ProjectileSystemDeps { effects: EffectSystem; spatial: CombatSpatialDeps; getStat(itemId: string, stat: string): number | null; raycast?: Raycast; sceneRaycast?: SceneRaycastApi; objects?: ProjectileObjectsDeps; entityCollidersOf?(instanceId: string): EntityCol… — ⚠ undocumented · used by `createProjectileSystem`: Spawn and advance projectiles each frame, resolving travel, lifetime, and hits.
462
+ - `ProjectileSystemState` (interface): interface ProjectileSystemState — Detached projectile owner state for replay and restore.
463
+ - `ProjectileTravelConfig` (interface): interface ProjectileTravelConfig — Captured launch settings for authoritative live travel.
464
+ - `ProjectileTravelDeps` (interface): interface ProjectileTravelDeps — Authoritative clock, collision and environmental acceleration providers.
465
+ - `ProjectileTravelImpact` (interface): interface ProjectileTravelImpact — Nearest contact returned by a live segment sweep.
457
466
  - `Raycast` (type): type Raycast = (from: string, aim: Aim, range: number, originPolicy?: ShotOriginPolicy) => RaycastHit[] — ⚠ undocumented
458
467
  - `RaycastHit` (type): type RaycastHit = EntityRaycastHit | ObjectRaycastHit — ⚠ undocumented
459
468
  - `SettleResult` (type): type SettleResult = | { status: "settled"; shotId: string; at: [number, number, number]; hits: EffectResult[]; origin?: [number, number, number]; } | { status: "rejected"; shotId: string; reason: string } — ⚠ undocumented
@@ -477,6 +486,7 @@
477
486
  - `RegenShieldConfig` (interface): interface RegenShieldConfig — Tuning for `createRegenShield`: pool size, refill rate, and the post-damage grace period.
478
487
  - `RegenShieldPool` (interface): interface RegenShieldPool — External storage a {@link RegenShield} reads and writes instead of keeping the value itself — an entity stat, a replicated store, a save record. This is the same port `Magazine` exposes as `MagazineReserve`, and it exists for the same reason: in most games the shield value is already owned by the stat system that damage, the HUD, and replication all read, so a primitive that insists on owning the number privately cannot be adopted without creating a second source of truth.
479
488
  - `RegenShieldRates` (interface): interface RegenShieldRates — Per-tick rate overrides, for games that derive regen from live state — a talent tree, a buff, an equipped mod — rather than a constant fixed when the shield was built. Omit to use the configured values; the grace period in effect is whichever `regenDelayMs` was last passed to `tick`.
489
+ - `RegenShieldState` (interface): interface RegenShieldState — Complete mutable shield state, including pending external damage detection.
480
490
  - `createRegenShield` (function): function createRegenShield(config: RegenShieldConfig): RegenShield — Builds a {@link RegenShield} that suppresses regen for `regenDelayMs` after each hit.
481
491
 
482
492
  ## @jgengine/core/combat/renderCues
@@ -496,8 +506,8 @@
496
506
  ## @jgengine/core/combat/resistance
497
507
 
498
508
  - `ResistVerdict` (type): type ResistVerdict = "immune" | "resist" | "normal" | "vulnerable" — ⚠ undocumented
499
- - `ResistanceMatrix` (interface): interface ResistanceMatrix<TCategory extends string = string, TProperty extends string = string> — ⚠ undocumented
500
- - `ResistanceResult` (interface): interface ResistanceResult — ⚠ undocumented
509
+ - `ResistanceMatrix` (interface): interface ResistanceMatrix<TCategory extends string = string, TProperty extends string = string> { categories: Partial<Record<TCategory, Partial<Record<TProperty, ResistVerdict>>>>; categoryIds?: readonly TCategory[]; propertyIds?: readonly TProperty[]; multipliers?: Partial<Record<ResistVerdict, number>>; default?: ResistVerdict; unkn… — ⚠ undocumented
510
+ - `ResistanceResult` (interface): interface ResistanceResult { verdict: ResistVerdict; multiplier: number; immune: boolean } — ⚠ undocumented
501
511
  - `UnknownResistanceCategoryError` (class): class UnknownResistanceCategoryError extends Error — ⚠ undocumented
502
512
  - `UnknownResistancePropertyError` (class): class UnknownResistancePropertyError extends Error — ⚠ undocumented
503
513
  - `resistanceScale` (function): function resistanceScale<TCategory extends string = string, TProperty extends string = string>(matrix: ResistanceMatrix<TCategory, TProperty>, category: TCategory | string, targetProperties: readonly (TProperty | string)[]): number — ⚠ undocumented
@@ -505,8 +515,8 @@
505
515
 
506
516
  ## @jgengine/core/combat/resourcePool
507
517
 
508
- - `ResourcePool` (interface): interface ResourcePool — ⚠ undocumented
509
- - `ResourcePoolConfig` (interface): interface ResourcePoolConfig — ⚠ undocumented
518
+ - `ResourcePool` (interface): interface ResourcePool { current(): number; max(): number; setMax(value: number): void; fraction(): number; canSpend(amount: number): boolean; spend(amount: number): boolean; gain(amount: number): number; set(value: number): void; tick(dtSeconds: number): void; i… — ⚠ undocumented · used by `createResourcePool`: A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
519
+ - `ResourcePoolConfig` (interface): interface ResourcePoolConfig { max: number; initial?: number; regenPerSecond?: number; decayPerSecond?: number } — ⚠ undocumented · used by `createResourcePool`: A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
510
520
  - `ResourcePoolRetune` (interface): interface ResourcePoolRetune — Runtime tuning patch for {@link ResourcePool.retune} — omitted fields keep their current value.
511
521
  - `ResourcePoolSnapshot` (interface): interface ResourcePoolSnapshot — Complete serializable state for a {@link ResourcePool}.
512
522
  - `createResourcePool` (function): function createResourcePool(config: ResourcePoolConfig): ResourcePool — A regenerating resource pool — mana, stamina, energy — that actions spend from and that refills over time.
@@ -531,13 +541,13 @@
531
541
 
532
542
  - `DEFAULT_EYE_HEIGHT` (const): const DEFAULT_EYE_HEIGHT: number — Shot-origin and first-person camera eye height above an entity's position: 90% of the default 1.8m hitbox top.
533
543
  - `ResolvedShot` (interface): interface ResolvedShot — A shot's resolved firing geometry in world space: `origin` is the point the projectile/ray starts from and `direction` is its normalized aim vector, both computed by {@link resolveShot} from the shooter's position, facing, and the chosen origin policy.
534
- - `ShotOriginDeps` (interface): interface ShotOriginDeps — ⚠ undocumented
544
+ - `ShotOriginDeps` (interface): interface ShotOriginDeps { positionOf(instanceId: string): EntityPosition | undefined; rotationYOf?(instanceId: string): number | undefined; collidersOf?(instanceId: string): EntityColliderSet | null | undefined } — ⚠ undocumented · used by `convergeShot`: Resolves a `converge` shot with scene knowledge: fires from the gun muzzle but bends the direction so the shot passes through the aim point …
535
545
  - `ShotOriginPolicy` (type): type ShotOriginPolicy = | { kind: "converge"; muzzle?: EntityPosition; height?: number } | { kind: "eye"; height?: number } | { kind: "legacy" } | { kind: "entity" } | { kind: "entityOffset"; offset: EntityPosition } | { kind: "muzzle"; offset?: EntityPosition } | { kind: "camera"; origin: EntityPos… — How a shot's world-space origin (and optional direction) is resolved before prediction/settlement. - `converge` — the shot leaves the gun `muzzle` yet still passes through whatever the shooter's sightline (crosshair) covers: origin is the muzzle offset, direction is bent from the muzzle to the eye ray's aim point. The projectile system's default for a free `{ yaw, pitch }` aim, so a bullet visibly comes from the barrel without missing the reticle. Needs a scene raycast to find the aim point (`convergeShot`); a bare `resolveShot` degrades to a straight muzzle ray. Passes an explicit `{ origin, direction }` aim through untouched. - `eye` — `aim.origin` when present, else the shooter's entity position raised to eye height; the shot traces the shooter's sightline, so what the crosshair covers is what gets hit. - `legacy` — `aim.origin` when present, else the shooter's raw entity position (feet). - `entity` — always the shooter's entity position. - `entityOffset` / `muzzle` — entity-local offset rotated by the shooter's yaw (muzzle on a weapon model). - `camera` — explicit camera/reticle world origin (and optional direction override). - `world` — absolute world origin.
536
546
  - `aimDirection` (function): function aimDirection(aim: Aim): EntityPosition | null — ⚠ undocumented
537
547
  - `aimSpreadDeg` (function): function aimSpreadDeg(aim: Aim): number — ⚠ undocumented
538
548
  - `convergeShot` (function): function convergeShot(deps: ShotOriginDeps, from: string, aim: Aim, range: number, sightHit: (origin: EntityPosition, direction: EntityPosition) => EntityPosition | null, muzzleOffset?: EntityPosition): ResolvedShot | null — Resolves a `converge` shot with scene knowledge: fires from the gun muzzle but bends the direction so the shot passes through the aim point the shooter's eye ray covers. `sightHit` casts the eye ray and returns where it lands (first impact), or `null` to fall back to a point `range` metres down the sightline. A `{ origin, direction }` aim is passed through unchanged (nothing to converge).
539
549
  - `eyeHeightFromColliders` (function): function eyeHeightFromColliders(set: EntityColliderSet | null | undefined): number — Eye height derived from a collider set: 90% of the tallest hitbox top, or the humanoid default when unknown.
540
- - `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — ⚠ undocumented
550
+ - `resolveShot` (function): function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy: ShotOriginPolicy = { kind: "eye" }): ResolvedShot | null — Resolves a shot's world origin and direction from the shooter's eye or muzzle and an {@link Aim}, ready for `ctx.scene.raycast` — the aim half of a hitscan weapon.
541
551
 
542
552
  ## @jgengine/core/combat/statusApplication
543
553
 
@@ -561,10 +571,10 @@
561
571
 
562
572
  ## @jgengine/core/combat/telegraph
563
573
 
564
- - `HazardCycleConfig` (interface): interface HazardCycleConfig — ⚠ undocumented
565
- - `HazardCycleSample` (interface): interface HazardCycleSample — ⚠ undocumented
574
+ - `HazardCycleConfig` (interface): interface HazardCycleConfig { windupMs: number; activeMs: number; cooldownMs?: number; offsetMs?: number } — ⚠ undocumented
575
+ - `HazardCycleSample` (interface): interface HazardCycleSample { phase: HazardPhase; fraction: number; remainingMs: number; cycleIndex: number } — ⚠ undocumented
566
576
  - `HazardPhase` (type): type HazardPhase = "windup" | "active" | "cooldown" — ⚠ undocumented
567
- - `TelegraphConfig` (interface): interface TelegraphConfig — ⚠ undocumented
577
+ - `TelegraphConfig` (interface): interface TelegraphConfig { shape: TelegraphShape; at: EntityPosition; dir?: number; windupMs?: number; turns?: number; kind?: string } — ⚠ undocumented
568
578
  - `TelegraphShape` (type): type TelegraphShape = | { kind: "circle"; radius: number } | { kind: "ring"; radius: number; innerRadius: number } | { kind: "cone"; radius: number; angle: number } | { kind: "line"; length: number; width: number } — ⚠ undocumented
569
579
 
570
580
  ## @jgengine/core/combat/thresholdCrossings
@@ -587,6 +597,13 @@
587
597
  - `resolveVfxPreset` (function): function resolveVfxPreset(name: string | undefined, overrides?: Partial<VfxPreset>): VfxPreset — Resolve a named visual flavor into a concrete `{ kind, color, durationMs?, radius? }`, with any provided `overrides` winning field by field. An unknown name resolves to {@link DEFAULT_VFX_PRESET} rather than throwing, so a flavor typo degrades to a visible spark. Used by `ctx.scene.entity.vfx({ preset })`; call it directly when you need the raw numbers (e.g. to seed a retained `vfxInstance` from the same vocabulary).
588
598
  - `vfxPresets` (const): const vfxPresets: { readonly arrow: { readonly kind: "projectile"; readonly color: 14207392; }; readonly bolt: { readonly kind: "projectile"; readonly color: 16777215; }; readonly fireball: { readonly kind: "projectile"; readonly color: 16738842; readonly durationMs: 460; }; readonly firebolt: { rea… — Ready-made visual flavors for the things players actually shoot, swing, and cast — so `ctx.scene.entity.vfx({ preset: "arrow", from, to })` renders a visible bolt with zero tuning, and `"lightning"`, `"web"`, `"slash"`, `"shield"`, `"heal"`, `"explosion"` likewise just work. Each entry only picks a `kind` (`projectile | beam | nova | glow | spark`), a color, and a lifetime; it is visual vocabulary (like named CSS colors), not a gameplay archetype — combat numbers stay in the caller's own effect/ability data. Any field passed to `vfx()` overrides the preset, and unknown names fall back to `spark` so a flavor typo still shows *something* rather than nothing.
589
599
 
600
+ ## @jgengine/core/combat/weaponFeedback
601
+
602
+ - `WeaponFeedbackSignal` (type): type WeaponFeedbackSignal = "shot" | "kick" | "impact" | "recoil" | "cameraKick" | "spread" | "ads" — Signals {@link createWeaponFeedbackSignals} reports each tick, named for `createFeedbackMixer` routes. `shot`, `kick` and `impact` are pulses that read non-zero only on the tick they happened; the rest follow the handling frame.
603
+ - `WeaponFeedbackSignals` (interface): interface WeaponFeedbackSignals — Collects weapon events between presentation ticks and hands them to a feedback mixer as one signal record.
604
+ - `WeaponFeedbackState` (interface): interface WeaponFeedbackState — Serializable pending pulses, so a snapshot taken between a shot and the next read loses nothing.
605
+ - `createWeaponFeedbackSignals` (function): function createWeaponFeedbackSignals(): WeaponFeedbackSignals — Creates {@link WeaponFeedbackSignals}: the bridge from shots, recoil kick and impacts to `createFeedbackMixer` routes (camera shake, audio, rumble). Route `kick` with no smoothing into camera-shake trauma, `impact` with a `release` into rumble, and `ads`/`spread` into continuous audio or FOV targets. Deterministic and allocation-free per read.
606
+
590
607
  ## @jgengine/core/combat/weaponFire
591
608
 
592
609
  - `FireCadence` (interface): interface FireCadence — A minimal minimum-interval rate gate for a repeated action — weapon fire, ability spam, any "no faster than N per second" rule. Deterministic and serializable: its whole state is the elapsed time since the last action, exposed via {@link FireCadence.elapsedMs}.
@@ -598,28 +615,58 @@
598
615
  - `createFireCadence` (function): function createFireCadence(config: FireCadenceConfig): FireCadence — Build a {@link FireCadence} rate gate. Reach for this instead of hand-tracking a `lastFiredAt` timestamp and comparing against a fire interval per game.
599
616
  - `createWeaponRuntime` (function): function createWeaponRuntime<TAim, THit>(config: WeaponRuntimeConfig<TAim, THit>): WeaponRuntime<TAim, THit> — Compose a portable weapon fire controller from the existing generic primitives — a {@link FireCadence} gate, an optional {@link Magazine}, a caller-provided raycast, and portable {@link resolveDamageHit} damage resolution. No `GameContext`, entity store, renderer, or default weapon is involved; the caller owns aiming, its raycaster, and all presentation, and the result carries full damage provenance for authority to apply and replicate.
600
617
 
618
+ ## @jgengine/core/combat/weaponHandling
619
+
620
+ - `WeaponHandling` (interface): interface WeaponHandling — The player-to-weapon relationship as state: recoil that climbs and recovers, spread that blooms and settles, and an aim-down-sights blend. Cadence, ammo and hits stay in `weaponFire`/`magazine`; this owns how the weapon feels between them. First-person, third-person and over-the-shoulder presentations read the same frame.
621
+ - `WeaponHandlingFrame` (interface): interface WeaponHandlingFrame — Live handling readout: the offsets to add to aim and camera, current spread and ADS blend.
622
+ - `WeaponHandlingState` (interface): interface WeaponHandlingState — Serializable handling state.
623
+ - `WeaponHandlingTuning` (interface): interface WeaponHandlingTuning — Tuning for {@link createWeaponHandling}. Every number is an angle in radians or a time in seconds, so two weapons differ by numbers a person can reason about: a controllable rifle climbs a little and recovers fast; a shotgun kicks hard and blooms wide.
624
+ - `WeaponProbeOptions` (interface): interface WeaponProbeOptions — Options for {@link measureWeapon}.
625
+ - `WeaponRecoilTuning` (interface): interface WeaponRecoilTuning — Recoil per shot, in radians of aim. `pitch > 0` climbs the muzzle, `yaw > 0` pulls right.
626
+ - `WeaponReport` (interface): interface WeaponReport — Deterministic weapon-feel metrics from {@link measureWeapon}.
627
+ - `WeaponShot` (interface): interface WeaponShot — What one shot did: the cone to sample and the kick it applied.
628
+ - `WeaponSpreadTuning` (interface): interface WeaponSpreadTuning — Cone of fire, as a half-angle in radians.
629
+ - `WeaponStance` (interface): interface WeaponStance — Stance and aim for one tick.
630
+ - `createWeaponHandling` (function): function createWeaponHandling(initial: WeaponHandlingTuning, options: { random?: () => number } = {}): WeaponHandling — Creates a {@link WeaponHandling}. Pass `random` (e.g. `ctx.rng` or `seededRng(seed)`) for the random recoil cone; without it the cone is skipped, so the result stays deterministic either way.
631
+ - `measureWeapon` (function): function measureWeapon(create: () => WeaponHandling, options: WeaponProbeOptions): WeaponReport — Fires a held burst through a fresh handling instance at a fixed interval and reports spread growth, climb, reset time, ADS time and time-to-kill. Time-to-kill counts expected damage: each projectile hits with the share of its spread cone the target covers at `range`, scaled by `damageAt(range)`, so a blooming rifle and a wide shotgun compare at the distance the game cares about.
632
+
633
+ ## @jgengine/core/combat/weaponPresentation
634
+
635
+ - `DEFAULT_VIEWMODEL_ADS` (const): const DEFAULT_VIEWMODEL_ADS: ViewmodelOffset — Default ADS anchor: the built-in viewmodel's top rail on the camera axis.
636
+ - `DEFAULT_VIEWMODEL_HIP` (const): const DEFAULT_VIEWMODEL_HIP: ViewmodelOffset — Default hip anchor, matching the shell's built-in viewmodel.
637
+ - `ViewmodelOffset` (type): type ViewmodelOffset = readonly [number, number, number] — Camera-space position `[x, y, z]` in metres: `+x` right, `+y` up, `-z` forward.
638
+ - `WeaponPose` (interface): interface WeaponPose — Where the viewmodel and camera go this frame. First person applies all of it; third person and over-the-shoulder read `lookPitch`/`lookYaw`, `aimPitch`/`aimYaw` and `adsProgress` from the same frame.
639
+ - `WeaponPresentation` (interface): interface WeaponPresentation — Turns a {@link WeaponHandlingFrame} plus look and movement into a viewmodel and camera pose.
640
+ - `WeaponPresentationInput` (interface): interface WeaponPresentationInput — One frame of inputs: look motion, the movement probe, and the weapon's handling readout.
641
+ - `WeaponPresentationState` (interface): interface WeaponPresentationState — Serializable presentation state: the current sway lag.
642
+ - `WeaponPresentationTuning` (interface): interface WeaponPresentationTuning — How one weapon sits in first person. Offsets are camera-space metres, angles are radians, FOVs are degrees. Every field is optional; two weapons differ by the ones they set.
643
+ - `createWeaponPresentation` (function): function createWeaponPresentation(initial: WeaponPresentationTuning = {}): WeaponPresentation — Creates a {@link WeaponPresentation}: per-weapon viewmodel offset, ADS pose and viewmodel FOV, sway and inertia from look speed, bob from the movement probe, and a recoil kick, all driven by the same handling frame third-person and over-the-shoulder rigs read. Deterministic and allocation-free per update.
644
+ - `viewmodelFovScale` (function): function viewmodelFovScale(worldFov: number, viewmodelFov: number): number — Scale for a viewmodel drawn at `viewmodelFov` through a camera at `worldFov` (both degrees): multiply the viewmodel's camera-space x and y by this and it projects as if rendered with its own FOV, without a second camera or render pass.
645
+
601
646
  ## @jgengine/core/stats/accumulatorMeter
602
647
 
603
- - `AccumulatorMeter` (interface): interface AccumulatorMeter — ⚠ undocumented
604
- - `AccumulatorMeterConfig` (interface): interface AccumulatorMeterConfig — ⚠ undocumented
605
- - `MeterAddResult` (interface): interface MeterAddResult — ⚠ undocumented
648
+ - `AccumulatorMeter` (interface): interface AccumulatorMeter { state(): AccumulatorMeterState; restore(next: AccumulatorMeterState): void; value(): number; fraction(): number; tier(): string | null; broke(): boolean; add(amount: number): MeterAddResult; drain(amount: number): void; reset(): void; tic… — ⚠ undocumented · used by `createAccumulatorMeter`: A raw accumulating gauge that crosses named tier thresholds as a value builds, with optional decay — the primitive under charge, rage, and c…
649
+ - `AccumulatorMeterConfig` (interface): interface AccumulatorMeterConfig { max: number; mode?: MeterMode; decayPerSecond?: number; decayDelayMs?: number; tiers?: readonly MeterTier[] } — ⚠ undocumented · used by `createAccumulatorMeter`: A raw accumulating gauge that crosses named tier thresholds as a value builds, with optional decay — the primitive under charge, rage, and c…
650
+ - `AccumulatorMeterState` (interface): interface AccumulatorMeterState — Mutable meter value, hold latch, and time since the last gain.
651
+ - `MeterAddResult` (interface): interface MeterAddResult { value: number; fired: boolean; overflow: number; tier: string | null; tierChanged: boolean } — ⚠ undocumented
606
652
  - `MeterMode` (type): type MeterMode = "hold" | "reset" — ⚠ undocumented
607
- - `MeterTier` (interface): interface MeterTier — ⚠ undocumented
653
+ - `MeterTier` (interface): interface MeterTier { id: string; at: number } — ⚠ undocumented · used by `tierAt`: The highest tier id whose `at` threshold `value` has reached, or `null` below every tier — the pure lookup `createAccumulatorMeter`/`createE…
608
654
  - `createAccumulatorMeter` (function): function createAccumulatorMeter(config: AccumulatorMeterConfig): AccumulatorMeter — A raw accumulating gauge that crosses named tier thresholds as a value builds, with optional decay — the primitive under charge, rage, and combo meters.
609
655
  - `tierAt` (function): function tierAt(value: number, tiers: readonly MeterTier[]): string | null — The highest tier id whose `at` threshold `value` has reached, or `null` below every tier — the pure lookup `createAccumulatorMeter`/`createEventMeter` call on every `add`/`tick`.
610
656
 
611
657
  ## @jgengine/core/stats/eventMeter
612
658
 
613
- - `EventMeter` (interface): interface EventMeter — ⚠ undocumented
614
- - `EventMeterConfig` (interface): interface EventMeterConfig — ⚠ undocumented
615
- - `EventMeterFeedResult` (interface): interface EventMeterFeedResult — ⚠ undocumented
659
+ - `EventMeter` (interface): interface EventMeter { state(): EventMeterState; restore(next: EventMeterState): void; value(): number; fraction(): number; tier(): string | null; ready(): boolean; feed(tag: string, scale?: number): EventMeterFeedResult; consume(): boolean; drain(amount: numbe… — ⚠ undocumented · used by `createEventMeter`: A heat/hype gauge that rises as tagged events land and cools between them, firing when it fills or breaks — the streak/overdrive meter shoot…
660
+ - `EventMeterConfig` (interface): interface EventMeterConfig { max: number; mode?: MeterMode; decayPerSecond?: number; decayDelayMs?: number; tiers?: readonly MeterTier[]; gains: Record<string, number>; resets?: readonly string[] } — ⚠ undocumented · used by `createEventMeter`: A heat/hype gauge that rises as tagged events land and cools between them, firing when it fills or breaks — the streak/overdrive meter shoot…
661
+ - `EventMeterFeedResult` (interface): interface EventMeterFeedResult { tag: string; reset: boolean; amount: number; value: number; fraction: number; fired: boolean; ready: boolean; overflow: number; tier: string | null; tierChanged: boolean } — ⚠ undocumented
662
+ - `EventMeterState` (type): type EventMeterState = AccumulatorMeterState — Event meter persistence uses the underlying accumulator's complete state.
616
663
  - `createEventMeter` (function): function createEventMeter(config: EventMeterConfig): EventMeter — A heat/hype gauge that rises as tagged events land and cools between them, firing when it fills or breaks — the streak/overdrive meter shooters and fighters hand-roll.
617
664
 
618
665
  ## @jgengine/core/stats/rollCheck
619
666
 
620
667
  - `CheckAdvantage` (type): type CheckAdvantage = "advantage" | "disadvantage" | "normal" — ⚠ undocumented
621
- - `CheckInput` (interface): interface CheckInput — ⚠ undocumented
622
- - `CheckResult` (interface): interface CheckResult — ⚠ undocumented
668
+ - `CheckInput` (interface): interface CheckInput { modifier: number; dc: number; advantage?: CheckAdvantage; diceSides?: number } — ⚠ undocumented · used by `rollCheck`: Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
669
+ - `CheckResult` (interface): interface CheckResult { rolls: readonly number[]; roll: number; total: number; success: boolean; critical: "success" | "failure" | null } — ⚠ undocumented · used by `rollCheck`: Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
623
670
  - `rollCheck` (function): function rollCheck(input: CheckInput, rng?: () => number): CheckResult — Resolve a tabletop-style pass/fail roll against a target number with modifiers and crit/fumble bands.
624
671
 
625
672
  ## @jgengine/core/stats/spawnLevelStats
@@ -637,10 +684,10 @@
637
684
 
638
685
  ## @jgengine/core/stats/statModifiers
639
686
 
640
- - `CreateStatsOptions` (interface): interface CreateStatsOptions — ⚠ undocumented
641
- - `StatModifier` (interface): interface StatModifier — ⚠ undocumented
642
- - `StatModifierSet` (type): type StatModifierSet<TStat extends string> = Partial<Record<TStat, StatModifier>> — ⚠ undocumented
643
- - `Stats` (interface): interface Stats<TStat extends string> — ⚠ undocumented
687
+ - `CreateStatsOptions` (interface): interface CreateStatsOptions { now?: () => number } — ⚠ undocumented · used by `createStats`: A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
688
+ - `StatModifier` (interface): interface StatModifier { add?: number; multiply?: number } — ⚠ undocumented
689
+ - `StatModifierSet` (type): type StatModifierSet<TStat extends string> = Partial<Record<TStat, StatModifier>> — ⚠ undocumented · used by `statModifierContributions` (@jgengine/core/gameplay): Bridge the shared {@link StatModifierSet} shape (add/multiply, used by talents, items, and buffs) into stat-graph contributions, so a ranked…
690
+ - `Stats` (interface): interface Stats<TStat extends string> { setBase(stat: TStat, value: number): void; getBase(stat: TStat): number; addSource(sourceId: string, modifiers: StatModifierSet<TStat>, options?: {expiresAtMs?: number}): void; removeSource(sourceId: string): void; hasSource(sourceId: str… — ⚠ undocumented · used by `createStats`: A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
644
691
  - `StatsSnapshot` (interface): interface StatsSnapshot<TStat extends string> — Complete plain-data state for a {@link Stats} runtime.
645
692
  - `createStats` (function): function createStats<TStat extends string>(base: Record<TStat, number>, options?: CreateStatsOptions): Stats<TStat> — A stat block whose base values take stacking, timed buffs and debuffs, resolving the modified value on read.
646
693