@woosh/meep-engine 2.138.19 → 2.139.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 (496) hide show
  1. package/package.json +2 -1
  2. package/src/core/collection/PairUint32Map.d.ts +100 -0
  3. package/src/core/collection/PairUint32Map.d.ts.map +1 -0
  4. package/src/core/collection/PairUint32Map.js +321 -0
  5. package/src/core/collection/Uint32Map.d.ts +119 -0
  6. package/src/core/collection/Uint32Map.d.ts.map +1 -0
  7. package/src/core/collection/Uint32Map.js +345 -0
  8. package/src/core/collection/array/array_shuffle.d.ts +10 -3
  9. package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
  10. package/src/core/collection/array/array_shuffle.js +27 -22
  11. package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
  12. package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
  13. package/src/core/collection/heap/FibonacciHeap.js +586 -0
  14. package/src/core/collection/heap/Uint32Heap.js +1 -1
  15. package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
  16. package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
  17. package/src/core/collection/heap/Uint32Heap4.js +490 -0
  18. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
  19. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
  20. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
  21. package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
  22. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
  23. package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
  24. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
  25. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  26. package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
  27. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
  28. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  29. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
  30. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
  31. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  32. package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
  33. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
  34. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
  35. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
  36. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
  37. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
  38. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
  39. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
  40. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
  41. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
  42. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
  43. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
  44. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +673 -0
  45. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
  46. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
  47. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
  48. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
  49. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
  50. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
  51. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
  52. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
  53. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
  54. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
  55. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
  56. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
  57. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
  58. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
  59. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +365 -0
  60. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +31 -0
  61. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
  62. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +112 -0
  63. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +22 -0
  64. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
  65. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +55 -0
  66. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
  67. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
  68. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
  69. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +22 -0
  70. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
  71. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +49 -0
  72. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
  73. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
  74. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
  75. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
  76. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
  77. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
  78. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
  79. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
  80. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
  81. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
  82. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
  83. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  84. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
  85. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
  86. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
  87. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
  88. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
  89. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
  90. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
  91. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
  92. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
  93. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
  94. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
  95. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
  96. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
  97. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
  98. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
  99. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
  100. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
  101. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
  102. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
  103. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
  104. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
  105. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
  106. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
  108. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
  109. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
  110. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
  111. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
  112. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
  113. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
  114. package/src/core/graph/csr/CSRGraph.d.ts +168 -0
  115. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
  116. package/src/core/graph/csr/CSRGraph.js +319 -0
  117. package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
  118. package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
  119. package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
  120. package/src/core/graph/metis/metis.d.ts +19 -0
  121. package/src/core/graph/metis/metis.d.ts.map +1 -1
  122. package/src/core/graph/metis/metis.js +20 -0
  123. package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
  124. package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
  125. package/src/core/graph/metis/metis_cluster_bs.js +11 -0
  126. package/src/core/graph/metis/metis_options.d.ts +17 -2
  127. package/src/core/graph/metis/metis_options.d.ts.map +1 -1
  128. package/src/core/graph/metis/metis_options.js +17 -2
  129. package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
  130. package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
  131. package/src/core/graph/metis/native/MetisGraph.js +212 -0
  132. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
  133. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
  134. package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
  135. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
  136. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
  137. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
  138. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
  139. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
  140. package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
  141. package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
  142. package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
  143. package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
  144. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
  145. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
  146. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
  147. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
  148. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
  149. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
  150. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
  151. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
  152. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
  153. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
  154. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
  155. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
  156. package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
  157. package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
  158. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
  159. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
  160. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
  161. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
  162. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
  163. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
  164. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
  165. package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
  166. package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
  167. package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
  168. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
  169. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
  170. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
  171. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
  172. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
  173. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
  174. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
  175. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
  176. package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
  177. package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
  178. package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
  179. package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
  180. package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
  181. package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
  182. package/src/core/graph/metis/native/refine/project_kway.js +43 -0
  183. package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
  184. package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
  185. package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
  186. package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
  187. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
  188. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
  189. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
  190. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
  191. package/src/engine/EngineHarness.d.ts +3 -1
  192. package/src/engine/EngineHarness.d.ts.map +1 -1
  193. package/src/engine/EngineHarness.js +6 -4
  194. package/src/engine/control/first-person/DESIGN.md +30 -6
  195. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
  196. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +102 -9
  197. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  198. package/src/engine/control/first-person/FirstPersonPlayerController.js +38 -3
  199. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +533 -4
  200. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  201. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +315 -6
  202. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +220 -22
  203. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  204. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +858 -241
  205. package/src/engine/control/first-person/TODO.md +127 -0
  206. package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
  207. package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
  208. package/src/engine/control/first-person/abilities/Ability.js +119 -0
  209. package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
  210. package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
  211. package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
  212. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
  213. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
  214. package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
  215. package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
  216. package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
  217. package/src/engine/control/first-person/abilities/Mantle.js +188 -0
  218. package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
  219. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
  220. package/src/engine/control/first-person/abilities/Slide.js +158 -0
  221. package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
  222. package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
  223. package/src/engine/control/first-person/abilities/WallJump.js +131 -0
  224. package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
  225. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
  226. package/src/engine/control/first-person/abilities/WallRun.js +180 -0
  227. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
  228. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
  229. package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
  230. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
  231. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
  232. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
  233. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
  234. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
  235. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
  236. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
  237. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
  238. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
  239. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
  240. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
  241. package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
  242. package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
  243. package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
  244. package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
  245. package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
  246. package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
  247. package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
  248. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
  249. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
  250. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
  251. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
  252. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
  253. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
  254. package/src/engine/control/first-person/math/Spring.d.ts +56 -0
  255. package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
  256. package/src/engine/control/first-person/math/Spring.js +71 -0
  257. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
  258. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
  259. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
  260. package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
  261. package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
  262. package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
  263. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
  264. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
  265. package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
  266. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
  267. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
  268. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
  269. package/src/engine/control/first-person/prototype_first_person_controller.js +550 -119
  270. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
  271. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
  272. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
  273. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
  274. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
  275. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
  276. package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
  277. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
  278. package/src/engine/control/first-person/test/buildTestPlayer.js +28 -0
  279. package/src/engine/ecs/EntityManager.d.ts +2 -2
  280. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  281. package/src/engine/ecs/EntityManager.js +13 -8
  282. package/src/engine/ecs/System.d.ts.map +1 -1
  283. package/src/engine/ecs/System.js +2 -2
  284. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
  285. package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
  286. package/src/engine/graphics/ecs/light/Light.js +27 -0
  287. package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
  288. package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
  289. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
  290. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
  291. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
  292. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
  293. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
  294. package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
  295. package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
  296. package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
  297. package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
  298. package/src/engine/physics/PLAN.md +236 -0
  299. package/src/engine/physics/body/BodyStorage.d.ts +187 -0
  300. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
  301. package/src/engine/physics/body/BodyStorage.js +427 -0
  302. package/src/engine/physics/broadphase/PairList.d.ts +62 -0
  303. package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
  304. package/src/engine/physics/broadphase/PairList.js +97 -0
  305. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts +30 -0
  306. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +1 -0
  307. package/src/engine/physics/broadphase/aabb_transform_oriented.js +93 -0
  308. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
  309. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
  310. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
  311. package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
  312. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
  313. package/src/engine/physics/broadphase/generate_pairs.js +101 -0
  314. package/src/engine/physics/contact/ManifoldStore.d.ts +226 -0
  315. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
  316. package/src/engine/physics/contact/ManifoldStore.js +499 -0
  317. package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
  318. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
  319. package/src/engine/physics/ecs/BodyKind.js +24 -0
  320. package/src/engine/physics/ecs/Collider.d.ts +98 -0
  321. package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
  322. package/src/engine/physics/ecs/Collider.js +136 -0
  323. package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
  324. package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
  325. package/src/engine/physics/ecs/ColliderFlags.js +15 -0
  326. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
  327. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
  328. package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
  329. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
  330. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
  331. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
  332. package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
  333. package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
  334. package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
  335. package/src/engine/physics/ecs/PhysicsSystem.d.ts +520 -0
  336. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
  337. package/src/engine/physics/ecs/PhysicsSystem.js +1159 -0
  338. package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
  339. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
  340. package/src/engine/physics/ecs/RigidBody.js +240 -0
  341. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
  342. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
  343. package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
  344. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
  345. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
  346. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
  347. package/src/engine/physics/ecs/SleepState.d.ts +11 -0
  348. package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
  349. package/src/engine/physics/ecs/SleepState.js +12 -0
  350. package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
  351. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
  352. package/src/engine/physics/events/ContactEventBuffer.js +83 -0
  353. package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
  354. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
  355. package/src/engine/physics/events/diff_manifolds.js +50 -0
  356. package/src/engine/physics/fluid/FluidField.d.ts +294 -16
  357. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  358. package/src/engine/physics/fluid/FluidField.js +510 -66
  359. package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
  360. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  361. package/src/engine/physics/fluid/FluidSimulator.js +455 -95
  362. package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
  363. package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
  364. package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
  365. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
  366. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
  367. package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
  368. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
  369. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
  370. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
  371. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
  372. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
  373. package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
  374. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
  375. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
  376. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
  377. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
  378. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  379. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
  380. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
  381. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
  382. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
  383. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
  384. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  385. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
  386. package/src/engine/physics/fluid/prototype.js +102 -91
  387. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
  388. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
  389. package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
  390. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
  391. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  392. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +60 -38
  393. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
  394. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  395. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +93 -73
  396. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
  397. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
  398. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
  399. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
  400. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
  401. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
  402. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
  403. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
  404. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
  405. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
  406. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
  407. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
  408. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
  409. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
  410. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
  411. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
  412. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
  413. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
  414. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
  415. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
  416. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
  417. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +20 -0
  418. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +1 -0
  419. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +83 -0
  420. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +26 -0
  421. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
  422. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +70 -0
  423. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
  424. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +8 -10
  425. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +29 -0
  426. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
  427. package/src/engine/physics/inertia/world_inverse_inertia.js +79 -0
  428. package/src/engine/physics/integration/integrate_position.d.ts +16 -0
  429. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
  430. package/src/engine/physics/integration/integrate_position.js +48 -0
  431. package/src/engine/physics/integration/integrate_velocity.d.ts +25 -0
  432. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
  433. package/src/engine/physics/integration/integrate_velocity.js +79 -0
  434. package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
  435. package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
  436. package/src/engine/physics/integration/quat_integrate.js +62 -0
  437. package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
  438. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
  439. package/src/engine/physics/island/IslandBuilder.js +411 -0
  440. package/src/engine/physics/island/union_find.d.ts +51 -0
  441. package/src/engine/physics/island/union_find.d.ts.map +1 -0
  442. package/src/engine/physics/island/union_find.js +76 -0
  443. package/src/engine/physics/narrowphase/PosedShape.d.ts +59 -0
  444. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
  445. package/src/engine/physics/narrowphase/PosedShape.js +110 -0
  446. package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
  447. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
  448. package/src/engine/physics/narrowphase/box_box_manifold.js +543 -0
  449. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
  450. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
  451. package/src/engine/physics/narrowphase/capsule_contacts.js +508 -0
  452. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +11 -0
  453. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
  454. package/src/engine/physics/narrowphase/narrowphase_step.js +382 -0
  455. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
  456. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
  457. package/src/engine/physics/narrowphase/sphere_box_contact.js +130 -0
  458. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
  459. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
  460. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
  461. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
  462. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
  463. package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
  464. package/src/engine/physics/queries/raycast.d.ts +20 -0
  465. package/src/engine/physics/queries/raycast.d.ts.map +1 -0
  466. package/src/engine/physics/queries/raycast.js +249 -0
  467. package/src/engine/physics/solver/friction_cone.d.ts +16 -0
  468. package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
  469. package/src/engine/physics/solver/friction_cone.js +37 -0
  470. package/src/engine/physics/solver/solve_contacts.d.ts +36 -0
  471. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
  472. package/src/engine/physics/solver/solve_contacts.js +598 -0
  473. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
  474. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
  475. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
  476. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
  477. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
  478. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
  479. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
  480. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
  481. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
  482. package/src/engine/ecs/components/Motion.d.ts +0 -21
  483. package/src/engine/ecs/components/Motion.d.ts.map +0 -1
  484. package/src/engine/ecs/components/Motion.js +0 -27
  485. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
  486. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
  487. package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
  488. package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
  489. package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
  490. package/src/engine/ecs/systems/MotionSystem.js +0 -29
  491. package/src/engine/physics/fluid/Fluid.d.ts +0 -26
  492. package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
  493. package/src/engine/physics/fluid/Fluid.js +0 -221
  494. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
  495. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
  496. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.js +0 -8
@@ -0,0 +1,133 @@
1
+ import { AnimationCurve } from "../../../animation/curve/AnimationCurve.js";
2
+ import { Keyframe } from "../../../animation/curve/Keyframe.js";
3
+ import { DecisionPoint } from "./DecisionPoint.js";
4
+ import { MasteryEvaluator } from "./MasteryEvaluator.js";
5
+
6
+ /**
7
+ * Symmetric curve over breath phase ∈ [0, 1):
8
+ * 0.00 → neutral (mid-inhale-to-exhale transition)
9
+ * 0.25 → trough: inhaling (small penalty)
10
+ * 0.50 → neutral
11
+ * 0.75 → peak: exhaling (small bonus)
12
+ *
13
+ * Physically motivated. Power-output research (weightlifting, sports
14
+ * biomechanics) consistently finds that peak force output happens during
15
+ * controlled exhalation. Holding breath produces a brief assist but
16
+ * inhaling during exertion is measurably worse. Bonus magnitude > penalty
17
+ * magnitude per the project design rule (asymmetric in magnitude).
18
+ *
19
+ * The curve is parameterizable so the same evaluator can serve multiple
20
+ * roles: large peak/trough for "action" decisions (jump, slide, wall-
21
+ * jump), small peak/trough for "continuous" decisions (ground accel
22
+ * during running in-sync with breath).
23
+ */
24
+ export function makeBreathRhythmCurve(peakBonus, troughPenalty) {
25
+ return AnimationCurve.from([
26
+ Keyframe.from(0.00, 1.0),
27
+ Keyframe.from(0.25, 1.0 - troughPenalty),
28
+ Keyframe.from(0.50, 1.0),
29
+ Keyframe.from(0.75, 1.0 + peakBonus),
30
+ Keyframe.from(1.00, 1.0),
31
+ ]);
32
+ }
33
+
34
+ /**
35
+ * Mastery evaluator: scales the queried quantity by breath-phase timing.
36
+ * Multi-decision-point — same instance fires on whatever decision points
37
+ * are configured. Two canonical use cases:
38
+ *
39
+ * 1. **Action evaluators** (jump, slide-start, wall-jump, mantle-exit):
40
+ * Default magnitudes (+3% peak / −1% trough). Fires once per event;
41
+ * players naturally hold or release breath when committing to an
42
+ * action.
43
+ *
44
+ * 2. **Sustained-action evaluator** (ground accel during in-sync run):
45
+ * Smaller magnitudes (+1.5% / −0.5%) and gated by exertion (only
46
+ * meaningful when the player is actually breathing heavily; matches
47
+ * the locomotor-respiratory-coupling principle — coupling-bonus
48
+ * kicks in at high exertion).
49
+ *
50
+ * The "smallest bonus in the system" rule applies here: this evaluator's
51
+ * defaults are tiny on purpose. Compounded across a long run with many
52
+ * actions, a breath-aware player gets a noticeable lift; a casual player
53
+ * who never notices the rhythm pays barely anything.
54
+ *
55
+ * Example usage:
56
+ *
57
+ * // Action bonuses — fires on jump/slide-entry/wall-jump
58
+ * controller.mastery.add(new BreathRhythmEvaluator());
59
+ *
60
+ * // Speed bonus during sustained heavy breathing
61
+ * controller.mastery.add(new BreathRhythmEvaluator({
62
+ * decisionPoints: [DecisionPoint.GroundAccel],
63
+ * peakBonus: 0.015,
64
+ * troughPenalty: 0.005,
65
+ * requireExertionAbove: 0.3,
66
+ * }));
67
+ *
68
+ * @author Alex Goldring
69
+ * @copyright Company Named Limited (c) 2026
70
+ */
71
+ export class BreathRhythmEvaluator extends MasteryEvaluator {
72
+ /**
73
+ * @param {object} [opts]
74
+ * @param {number[]} [opts.decisionPoints] Defaults to action points
75
+ * (jump, slide entry, wall-jump). Pass [GroundAccel] for the
76
+ * "running in sync" speed bonus.
77
+ * @param {number} [opts.peakBonus] Default 0.03 = +3% at exhale.
78
+ * @param {number} [opts.troughPenalty] Default 0.01 = −1% at inhale.
79
+ * @param {number} [opts.requireExertionAbove] Below this exertion
80
+ * level (default 0) the evaluator returns identity. Use ~0.3 for
81
+ * "only when breathing heavily" semantics.
82
+ */
83
+ constructor({
84
+ decisionPoints,
85
+ peakBonus = 0.03,
86
+ troughPenalty = 0.01,
87
+ requireExertionAbove = 0.0,
88
+ } = {}) {
89
+ super();
90
+ this.name = "BreathRhythm";
91
+
92
+ /**
93
+ * Set of decision points this evaluator answers. Default: the
94
+ * three classic "action" points.
95
+ * @type {Set<number>}
96
+ */
97
+ this.decisionPoints = new Set(decisionPoints || [
98
+ DecisionPoint.JumpImpulse,
99
+ DecisionPoint.SlideEntryVelocity,
100
+ DecisionPoint.WallJumpImpulse,
101
+ ]);
102
+
103
+ /** @type {number} */
104
+ this.peakBonus = peakBonus;
105
+ /** @type {number} */
106
+ this.troughPenalty = troughPenalty;
107
+ /** @type {number} */
108
+ this.requireExertionAbove = requireExertionAbove;
109
+
110
+ /** Magnitude exponent — scales the deviation around 1.0. */
111
+ this.flatBoost = 1.0;
112
+
113
+ /** @private */
114
+ this._curve = makeBreathRhythmCurve(peakBonus, troughPenalty);
115
+ }
116
+
117
+ /**
118
+ * Rebuild the curve from current peakBonus/troughPenalty. Call after
119
+ * mutating those fields if you want the change to take effect.
120
+ */
121
+ rebuildCurve() {
122
+ this._curve = makeBreathRhythmCurve(this.peakBonus, this.troughPenalty);
123
+ }
124
+
125
+ evaluate(decisionPoint, controller, _runtime) {
126
+ if (!this.decisionPoints.has(decisionPoint)) return 1.0;
127
+ if (controller.state.exertion < this.requireExertionAbove) return 1.0;
128
+
129
+ const phase = controller.state.breathPhase;
130
+ const raw = this._curve.evaluate(phase);
131
+ return 1.0 + (raw - 1.0) * this.flatBoost;
132
+ }
133
+ }
@@ -0,0 +1,10 @@
1
+ export namespace DecisionPoint {
2
+ let JumpImpulse: number;
3
+ let GroundAccel: number;
4
+ let SlideEntryVelocity: number;
5
+ let WallJumpImpulse: number;
6
+ let MantleExitSpeed: number;
7
+ let WallRunGravity: number;
8
+ let _Count: number;
9
+ }
10
+ //# sourceMappingURL=DecisionPoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionPoint.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/mastery/DecisionPoint.js"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Discrete moments in the controller's update where mastery evaluators get
3
+ * to weigh in on a single numeric quantity.
4
+ *
5
+ * Each decision point has an associated meaning for its multiplier:
6
+ * - `1.0` → no opinion (use base value)
7
+ * - `> 1.0` → bonus (apply a percentage scaling up)
8
+ * - `< 1.0` → penalty (apply a percentage scaling down)
9
+ *
10
+ * Evaluator contributions compose multiplicatively per decision point. See
11
+ * {@link MasterySet}.
12
+ *
13
+ * @readonly enum
14
+ */
15
+ export const DecisionPoint = {
16
+ /** Multiplier applied to jump initial vertical velocity at impulse fire. */
17
+ JumpImpulse: 0,
18
+ /** Multiplier applied to ground acceleration each fixed step. */
19
+ GroundAccel: 1,
20
+ /** Multiplier applied to slide-entry velocity preservation. */
21
+ SlideEntryVelocity: 2,
22
+ /** Multiplier applied to wall-jump impulse magnitude. */
23
+ WallJumpImpulse: 3,
24
+ /** Multiplier applied to mantle exit horizontal speed. */
25
+ MantleExitSpeed: 4,
26
+ /** Multiplier applied to wall-run effective gravity (lower → longer hang). */
27
+ WallRunGravity: 5,
28
+ /** Sentinel — total count; useful for fixed-size arrays keyed by point. */
29
+ _Count: 6,
30
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Default symmetric foot-asymmetry curve. Input is signed alignment
3
+ * ∈ [-1, +1]:
4
+ * +1 = optimal (turn direction matches the standing-foot's push-off side)
5
+ * 0 = no turn, or no relevant standing foot
6
+ * −1 = anti-optimal (turning AWAY from the push-off direction)
7
+ *
8
+ * Asymmetric magnitude per the design rule: +5% peak bonus vs −2% trough.
9
+ */
10
+ export function makeDefaultFootAsymmetryTurnCurve(): AnimationCurve;
11
+ /**
12
+ * Mastery evaluator: ground acceleration is modulated by which foot is
13
+ * standing relative to which way you're turning.
14
+ *
15
+ * Physically motivated: when you turn while running, you push off the
16
+ * grounded foot to redirect momentum. The most powerful push-off comes
17
+ * from the LEFT foot when turning right, and the RIGHT foot when
18
+ * turning left. (Think of how runners plant on the outside leg before
19
+ * cutting in the opposite direction.) Players who time their turns to
20
+ * align with the right foot's swing/stance phase carry more momentum
21
+ * through the turn.
22
+ *
23
+ * The bonus is small (max ~5%) by design — it's mastery, not magic.
24
+ * Compounded over a long turn under sprint, it accumulates into
25
+ * meaningfully more distance covered.
26
+ *
27
+ * Engineering note: we read `runtime.yawRateRadPerSec` (computed during
28
+ * look consumption) rather than recomputing from yaw deltas. That keeps
29
+ * the evaluator simple and avoids assumptions about controller internals.
30
+ *
31
+ * @author Alex Goldring
32
+ * @copyright Company Named Limited (c) 2026
33
+ */
34
+ export class FootAsymmetryTurnEvaluator extends MasteryEvaluator {
35
+ /**
36
+ * Alignment ∈ [-1, +1] → multiplier curve. Symmetric in behaviour
37
+ * (both sides exist) and asymmetric in magnitude (bonus side
38
+ * larger than penalty side).
39
+ * @type {AnimationCurve}
40
+ */
41
+ curve: AnimationCurve;
42
+ /**
43
+ * Exponent applied to (curve - 1.0). Scales overall magnitude
44
+ * while preserving symmetry around 1.0. Default 1.0 = use curve
45
+ * as authored.
46
+ * @type {number}
47
+ */
48
+ flatBoost: number;
49
+ /**
50
+ * Yaw rate magnitude (rad/s) at which alignment saturates to ±1.
51
+ * Slow turns produce weaker alignment; fast turns saturate. ~1.5
52
+ * rad/s ≈ 86°/s — a brisk but not-flicky turn. Sub-second
53
+ * 180° turns saturate.
54
+ * @type {number}
55
+ */
56
+ saturationYawRate: number;
57
+ evaluate(decisionPoint: any, controller: any, runtime: any): number;
58
+ }
59
+ import { AnimationCurve } from "../../../animation/curve/AnimationCurve.js";
60
+ import { MasteryEvaluator } from "./MasteryEvaluator.js";
61
+ //# sourceMappingURL=FootAsymmetryTurnEvaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FootAsymmetryTurnEvaluator.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,oEAMC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAKQ;;;;;OAKG;IACH,OAFU,cAAc,CAEwB;IAEhD;;;;;OAKG;IACH,WAFU,MAAM,CAEI;IAEpB;;;;;;OAMG;IACH,mBAFU,MAAM,CAEY;IAGhC,oEA8BC;CACJ;+BA3G8B,4CAA4C;iCAG1C,uBAAuB"}
@@ -0,0 +1,109 @@
1
+ import { clamp } from "../../../../core/math/clamp.js";
2
+ import { AnimationCurve } from "../../../animation/curve/AnimationCurve.js";
3
+ import { Keyframe } from "../../../animation/curve/Keyframe.js";
4
+ import { DecisionPoint } from "./DecisionPoint.js";
5
+ import { MasteryEvaluator } from "./MasteryEvaluator.js";
6
+
7
+ /**
8
+ * Default symmetric foot-asymmetry curve. Input is signed alignment
9
+ * ∈ [-1, +1]:
10
+ * +1 = optimal (turn direction matches the standing-foot's push-off side)
11
+ * 0 = no turn, or no relevant standing foot
12
+ * −1 = anti-optimal (turning AWAY from the push-off direction)
13
+ *
14
+ * Asymmetric magnitude per the design rule: +5% peak bonus vs −2% trough.
15
+ */
16
+ export function makeDefaultFootAsymmetryTurnCurve() {
17
+ return AnimationCurve.from([
18
+ Keyframe.from(-1.0, 0.98), // anti-aligned: −2% accel
19
+ Keyframe.from(0.0, 1.00),
20
+ Keyframe.from(1.0, 1.05), // aligned: +5% accel
21
+ ]);
22
+ }
23
+
24
+ /**
25
+ * Mastery evaluator: ground acceleration is modulated by which foot is
26
+ * standing relative to which way you're turning.
27
+ *
28
+ * Physically motivated: when you turn while running, you push off the
29
+ * grounded foot to redirect momentum. The most powerful push-off comes
30
+ * from the LEFT foot when turning right, and the RIGHT foot when
31
+ * turning left. (Think of how runners plant on the outside leg before
32
+ * cutting in the opposite direction.) Players who time their turns to
33
+ * align with the right foot's swing/stance phase carry more momentum
34
+ * through the turn.
35
+ *
36
+ * The bonus is small (max ~5%) by design — it's mastery, not magic.
37
+ * Compounded over a long turn under sprint, it accumulates into
38
+ * meaningfully more distance covered.
39
+ *
40
+ * Engineering note: we read `runtime.yawRateRadPerSec` (computed during
41
+ * look consumption) rather than recomputing from yaw deltas. That keeps
42
+ * the evaluator simple and avoids assumptions about controller internals.
43
+ *
44
+ * @author Alex Goldring
45
+ * @copyright Company Named Limited (c) 2026
46
+ */
47
+ export class FootAsymmetryTurnEvaluator extends MasteryEvaluator {
48
+ constructor() {
49
+ super();
50
+ this.name = "FootAsymmetryTurn";
51
+
52
+ /**
53
+ * Alignment ∈ [-1, +1] → multiplier curve. Symmetric in behaviour
54
+ * (both sides exist) and asymmetric in magnitude (bonus side
55
+ * larger than penalty side).
56
+ * @type {AnimationCurve}
57
+ */
58
+ this.curve = makeDefaultFootAsymmetryTurnCurve();
59
+
60
+ /**
61
+ * Exponent applied to (curve - 1.0). Scales overall magnitude
62
+ * while preserving symmetry around 1.0. Default 1.0 = use curve
63
+ * as authored.
64
+ * @type {number}
65
+ */
66
+ this.flatBoost = 1.0;
67
+
68
+ /**
69
+ * Yaw rate magnitude (rad/s) at which alignment saturates to ±1.
70
+ * Slow turns produce weaker alignment; fast turns saturate. ~1.5
71
+ * rad/s ≈ 86°/s — a brisk but not-flicky turn. Sub-second
72
+ * 180° turns saturate.
73
+ * @type {number}
74
+ */
75
+ this.saturationYawRate = 1.5;
76
+ }
77
+
78
+ evaluate(decisionPoint, controller, runtime) {
79
+ if (decisionPoint !== DecisionPoint.GroundAccel) return 1.0;
80
+ // Only meaningful when grounded and actually moving.
81
+ if (!controller.state.grounded) return 1.0;
82
+ if (controller.state.speed < 0.5) return 1.0;
83
+
84
+ const yawRate = runtime.yawRateRadPerSec;
85
+ if (!yawRate || Math.abs(yawRate) < 1e-4) return 1.0; // not turning
86
+
87
+ // Sign convention: in our engine, yawRate < 0 means turning RIGHT
88
+ // (mouse-right decreases bodyYaw). Encode turn direction as +1
89
+ // for right, -1 for left.
90
+ const turnSign = yawRate < 0 ? 1 : -1;
91
+
92
+ // Optimal-foot encoding: standing on the LEFT foot is good for
93
+ // RIGHT turns (you push off the left to swing right); standing on
94
+ // the RIGHT foot is good for LEFT turns.
95
+ const footSign = runtime.standingFoot === "L" ? 1 : -1;
96
+
97
+ // Yaw intensity: 0 (no turn) to 1 (saturated). Smooth ramp.
98
+ const intensity = clamp(
99
+ Math.abs(yawRate) / Math.max(this.saturationYawRate, 1e-4),
100
+ 0, 1,
101
+ );
102
+
103
+ // Alignment ∈ [-1, +1]. Aligned when turnSign × footSign > 0.
104
+ const alignment = turnSign * footSign * intensity;
105
+
106
+ const raw = this.curve.evaluate(alignment);
107
+ return 1.0 + (raw - 1.0) * this.flatBoost;
108
+ }
109
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Base class for mastery evaluators. Each evaluator observes the
3
+ * controller's state at a given {@link DecisionPoint} and returns a
4
+ * multiplier:
5
+ *
6
+ * `1.0` → no opinion (identity)
7
+ * `> 1.0` → bonus (e.g. 1.10 = +10%)
8
+ * `< 1.0` → penalty (e.g. 0.95 = −5%)
9
+ *
10
+ * Multiple evaluators registered against the same point compose
11
+ * multiplicatively. The composition pattern is intentionally symmetric:
12
+ * the same curve drives both bonus and penalty regions — well-timed
13
+ * inputs land in the bonus half, poorly-timed in the penalty half. Per the
14
+ * project design convention the bonus side is bigger than the penalty
15
+ * side (e.g. ±5% penalty for ~+12% bonus) — that's handled at the
16
+ * curve-authoring level by asymmetric peak/trough heights.
17
+ *
18
+ * Subclasses override {@link evaluate}. They typically own an
19
+ * `AnimationCurve` and a `flatBoost` exponent — see
20
+ * `StrideTimingJumpEvaluator` for the canonical pattern.
21
+ *
22
+ * @author Alex Goldring
23
+ * @copyright Company Named Limited (c) 2026
24
+ */
25
+ export class MasteryEvaluator {
26
+ /**
27
+ * Human-readable identifier for telemetry (mastery score keying,
28
+ * debugging overlays). Subclasses should set a stable string.
29
+ * @type {string}
30
+ */
31
+ name: string;
32
+ /**
33
+ * @param {number} decisionPoint one of {@link DecisionPoint}
34
+ * @param {*} controller the FirstPersonPlayerController
35
+ * @param {*} runtime per-entity runtime state
36
+ * @returns {number} multiplier; 1.0 = no opinion
37
+ */
38
+ evaluate(decisionPoint: number, controller: any, runtime: any): number;
39
+ }
40
+ //# sourceMappingURL=MasteryEvaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MasteryEvaluator.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/mastery/MasteryEvaluator.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IAEQ;;;;OAIG;IACH,MAFU,MAAM,CAEc;IAGlC;;;;;OAKG;IAEH,wBANW,MAAM,kCAGJ,MAAM,CAKlB;CACJ"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Base class for mastery evaluators. Each evaluator observes the
3
+ * controller's state at a given {@link DecisionPoint} and returns a
4
+ * multiplier:
5
+ *
6
+ * `1.0` → no opinion (identity)
7
+ * `> 1.0` → bonus (e.g. 1.10 = +10%)
8
+ * `< 1.0` → penalty (e.g. 0.95 = −5%)
9
+ *
10
+ * Multiple evaluators registered against the same point compose
11
+ * multiplicatively. The composition pattern is intentionally symmetric:
12
+ * the same curve drives both bonus and penalty regions — well-timed
13
+ * inputs land in the bonus half, poorly-timed in the penalty half. Per the
14
+ * project design convention the bonus side is bigger than the penalty
15
+ * side (e.g. ±5% penalty for ~+12% bonus) — that's handled at the
16
+ * curve-authoring level by asymmetric peak/trough heights.
17
+ *
18
+ * Subclasses override {@link evaluate}. They typically own an
19
+ * `AnimationCurve` and a `flatBoost` exponent — see
20
+ * `StrideTimingJumpEvaluator` for the canonical pattern.
21
+ *
22
+ * @author Alex Goldring
23
+ * @copyright Company Named Limited (c) 2026
24
+ */
25
+ export class MasteryEvaluator {
26
+ constructor() {
27
+ /**
28
+ * Human-readable identifier for telemetry (mastery score keying,
29
+ * debugging overlays). Subclasses should set a stable string.
30
+ * @type {string}
31
+ */
32
+ this.name = "MasteryEvaluator";
33
+ }
34
+
35
+ /**
36
+ * @param {number} decisionPoint one of {@link DecisionPoint}
37
+ * @param {*} controller the FirstPersonPlayerController
38
+ * @param {*} runtime per-entity runtime state
39
+ * @returns {number} multiplier; 1.0 = no opinion
40
+ */
41
+ // eslint-disable-next-line no-unused-vars
42
+ evaluate(decisionPoint, controller, runtime) {
43
+ return 1.0;
44
+ }
45
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Exponential moving average of mastery contributions. Provides a per-
3
+ * decision-point and a global aggregate score, both centred at 0:
4
+ *
5
+ * `score === 0` → on average, evaluators returned 1.0 (neutral)
6
+ * `score > 0` → trending bonus (player is consistently timing well)
7
+ * `score < 0` → trending penalty (player is consistently mistiming)
8
+ *
9
+ * The controller does NOT consume this score itself. It's a side-channel
10
+ * for downstream systems (HUDs, post-match summaries, training-mode
11
+ * coaching, achievement triggers, leaderboards) to expose mastery
12
+ * progress however they see fit, without forcing any visual treatment on
13
+ * the controller.
14
+ *
15
+ * Samples are added by {@link MasterySet} as evaluators fire. Time-based
16
+ * decay (so old samples wash out) is applied via {@link tick}.
17
+ *
18
+ * @author Alex Goldring
19
+ * @copyright Company Named Limited (c) 2026
20
+ */
21
+ export class MasteryScore {
22
+ /**
23
+ * @param {number} [halfLife] seconds for any sample's contribution to halve
24
+ */
25
+ constructor(halfLife?: number);
26
+ /**
27
+ * Time-half-life of the EMA. A score sample 1×halfLife ago counts ½
28
+ * as much as a fresh one. Tune for "how recent should mastery feel".
29
+ * @type {number}
30
+ */
31
+ halfLife: number;
32
+ /**
33
+ * EMA of (multiplier − 1.0) across ALL evaluator contributions.
34
+ * Useful as a single-number "how skilled has the player been
35
+ * recently" indicator.
36
+ * @type {number}
37
+ */
38
+ aggregate: number;
39
+ /**
40
+ * EMA per decision point — same metric, sliced by which interaction
41
+ * the contribution came from. Index space matches DecisionPoint.
42
+ * Useful for telemetry like "you're nailing jump timing but poor at
43
+ * slide initiation".
44
+ * @type {number[]}
45
+ */
46
+ byPoint: number[];
47
+ /**
48
+ * Record a contribution from an evaluator. Call once per evaluator per
49
+ * decision-point evaluation. The multiplier is converted to a signed
50
+ * deviation from neutral (1.0) for EMA accumulation.
51
+ *
52
+ * @param {number} decisionPoint
53
+ * @param {number} multiplier raw evaluator output (1.0 = neutral)
54
+ */
55
+ record(decisionPoint: number, multiplier: number): void;
56
+ /**
57
+ * Apply time-based decay so stale samples wash out. Call once per
58
+ * fixed step; the system handles this for you.
59
+ *
60
+ * @param {number} dt seconds
61
+ */
62
+ decay(dt: number): void;
63
+ /**
64
+ * Reset to neutral. Useful on respawn / scene change.
65
+ */
66
+ reset(): void;
67
+ }
68
+ //# sourceMappingURL=MasteryScore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MasteryScore.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/mastery/MasteryScore.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IACI;;OAEG;IACH,uBAFW,MAAM,EA0BhB;IAvBG;;;;OAIG;IACH,UAFU,MAAM,CAEQ;IAExB;;;;;OAKG;IACH,WAFU,MAAM,CAEE;IAElB;;;;;;OAMG;IACH,SAFU,MAAM,EAAE,CAEoC;IAG1D;;;;;;;OAOG;IACH,sBAHW,MAAM,cACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,UAFW,MAAM,QAUhB;IAED;;OAEG;IACH,cAKC;CACJ"}
@@ -0,0 +1,100 @@
1
+ import { DecisionPoint } from "./DecisionPoint.js";
2
+
3
+ const LN2 = Math.log(2);
4
+
5
+ /**
6
+ * Exponential moving average of mastery contributions. Provides a per-
7
+ * decision-point and a global aggregate score, both centred at 0:
8
+ *
9
+ * `score === 0` → on average, evaluators returned 1.0 (neutral)
10
+ * `score > 0` → trending bonus (player is consistently timing well)
11
+ * `score < 0` → trending penalty (player is consistently mistiming)
12
+ *
13
+ * The controller does NOT consume this score itself. It's a side-channel
14
+ * for downstream systems (HUDs, post-match summaries, training-mode
15
+ * coaching, achievement triggers, leaderboards) to expose mastery
16
+ * progress however they see fit, without forcing any visual treatment on
17
+ * the controller.
18
+ *
19
+ * Samples are added by {@link MasterySet} as evaluators fire. Time-based
20
+ * decay (so old samples wash out) is applied via {@link tick}.
21
+ *
22
+ * @author Alex Goldring
23
+ * @copyright Company Named Limited (c) 2026
24
+ */
25
+ export class MasteryScore {
26
+ /**
27
+ * @param {number} [halfLife] seconds for any sample's contribution to halve
28
+ */
29
+ constructor(halfLife = 8.0) {
30
+ /**
31
+ * Time-half-life of the EMA. A score sample 1×halfLife ago counts ½
32
+ * as much as a fresh one. Tune for "how recent should mastery feel".
33
+ * @type {number}
34
+ */
35
+ this.halfLife = halfLife;
36
+
37
+ /**
38
+ * EMA of (multiplier − 1.0) across ALL evaluator contributions.
39
+ * Useful as a single-number "how skilled has the player been
40
+ * recently" indicator.
41
+ * @type {number}
42
+ */
43
+ this.aggregate = 0;
44
+
45
+ /**
46
+ * EMA per decision point — same metric, sliced by which interaction
47
+ * the contribution came from. Index space matches DecisionPoint.
48
+ * Useful for telemetry like "you're nailing jump timing but poor at
49
+ * slide initiation".
50
+ * @type {number[]}
51
+ */
52
+ this.byPoint = new Array(DecisionPoint._Count).fill(0);
53
+ }
54
+
55
+ /**
56
+ * Record a contribution from an evaluator. Call once per evaluator per
57
+ * decision-point evaluation. The multiplier is converted to a signed
58
+ * deviation from neutral (1.0) for EMA accumulation.
59
+ *
60
+ * @param {number} decisionPoint
61
+ * @param {number} multiplier raw evaluator output (1.0 = neutral)
62
+ */
63
+ record(decisionPoint, multiplier) {
64
+ const dev = multiplier - 1.0;
65
+ // Light blend on each sample; the per-tick time decay (apply()) is
66
+ // what actually carries the EMA character.
67
+ const blend = 0.1;
68
+ this.aggregate = (1 - blend) * this.aggregate + blend * dev;
69
+ const pi = decisionPoint;
70
+ if (pi >= 0 && pi < this.byPoint.length) {
71
+ this.byPoint[pi] = (1 - blend) * this.byPoint[pi] + blend * dev;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Apply time-based decay so stale samples wash out. Call once per
77
+ * fixed step; the system handles this for you.
78
+ *
79
+ * @param {number} dt seconds
80
+ */
81
+ decay(dt) {
82
+ if (this.halfLife <= 0 || dt <= 0) return;
83
+ // Multiplicative decay toward 0 with the given half-life.
84
+ const alpha = Math.exp(-LN2 * dt / this.halfLife);
85
+ this.aggregate *= alpha;
86
+ for (let i = 0; i < this.byPoint.length; i++) {
87
+ this.byPoint[i] *= alpha;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Reset to neutral. Useful on respawn / scene change.
93
+ */
94
+ reset() {
95
+ this.aggregate = 0;
96
+ for (let i = 0; i < this.byPoint.length; i++) {
97
+ this.byPoint[i] = 0;
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Aggregates {@link MasteryEvaluator} instances and exposes a single
3
+ * `evaluate(decisionPoint, ...)` entry point that composes all evaluators
4
+ * for that point multiplicatively.
5
+ *
6
+ * Identity behaviour: with zero evaluators registered, every query returns
7
+ * `1.0`, leaving the base controller behaviour untouched. This is the
8
+ * default state — mastery is opt-in.
9
+ *
10
+ * Composition: contributions multiply, NOT sum. So a +10% and a +5% give
11
+ * +15.5% (1.10 × 1.05 = 1.155). And a +10% with a −5% gives +4.5% (1.10
12
+ * × 0.95 = 1.045). Mistiming partially offsets bonuses from other
13
+ * evaluators — exactly what we want for honest "your timing matters
14
+ * everywhere" feel.
15
+ *
16
+ * @author Alex Goldring
17
+ * @copyright Company Named Limited (c) 2026
18
+ */
19
+ export class MasterySet {
20
+ /**
21
+ * Registered evaluators, in insertion order.
22
+ * @type {MasteryEvaluator[]}
23
+ */
24
+ evaluators: MasteryEvaluator[];
25
+ /**
26
+ * Telemetry EMA. The controller doesn't consume it; downstream
27
+ * systems read it for player-facing mastery feedback.
28
+ * @type {MasteryScore}
29
+ */
30
+ score: MasteryScore;
31
+ /**
32
+ * Add an evaluator. Order does not affect the final result
33
+ * (multiplication is commutative).
34
+ * @param {MasteryEvaluator} evaluator
35
+ */
36
+ add(evaluator: MasteryEvaluator): void;
37
+ /**
38
+ * Remove an evaluator if present.
39
+ * @param {MasteryEvaluator} evaluator
40
+ */
41
+ remove(evaluator: MasteryEvaluator): void;
42
+ /**
43
+ * Compose all registered evaluators against `decisionPoint`. Each
44
+ * evaluator's contribution is recorded into the score for telemetry,
45
+ * then multiplied into the running product.
46
+ *
47
+ * @param {number} decisionPoint
48
+ * @param {*} controller
49
+ * @param {*} runtime
50
+ * @returns {number} composed multiplier; 1.0 if no evaluators care
51
+ */
52
+ evaluate(decisionPoint: number, controller: any, runtime: any): number;
53
+ /**
54
+ * Advance the score's time-based decay. Call once per fixed step.
55
+ * @param {number} dt
56
+ */
57
+ tick(dt: number): void;
58
+ }
59
+ import { MasteryScore } from "./MasteryScore.js";
60
+ //# sourceMappingURL=MasterySet.d.ts.map