@woosh/meep-engine 2.138.20 → 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.
- package/package.json +1 -1
- package/src/core/collection/PairUint32Map.d.ts +100 -0
- package/src/core/collection/PairUint32Map.d.ts.map +1 -0
- package/src/core/collection/PairUint32Map.js +321 -0
- package/src/core/collection/Uint32Map.d.ts +119 -0
- package/src/core/collection/Uint32Map.d.ts.map +1 -0
- package/src/core/collection/Uint32Map.js +345 -0
- package/src/core/collection/array/array_shuffle.d.ts +10 -3
- package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
- package/src/core/collection/array/array_shuffle.js +27 -22
- package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
- package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
- package/src/core/collection/heap/FibonacciHeap.js +586 -0
- package/src/core/collection/heap/Uint32Heap.js +1 -1
- package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
- package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
- package/src/core/collection/heap/Uint32Heap4.js +490 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
- package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
- package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
- package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
- package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
- package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
- package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +673 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +365 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +31 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +112 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +22 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +55 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +49 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
- package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
- package/src/core/graph/csr/CSRGraph.d.ts +168 -0
- package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
- package/src/core/graph/csr/CSRGraph.js +319 -0
- package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
- package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
- package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
- package/src/core/graph/metis/metis.d.ts +19 -0
- package/src/core/graph/metis/metis.d.ts.map +1 -1
- package/src/core/graph/metis/metis.js +20 -0
- package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
- package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
- package/src/core/graph/metis/metis_cluster_bs.js +11 -0
- package/src/core/graph/metis/metis_options.d.ts +17 -2
- package/src/core/graph/metis/metis_options.d.ts.map +1 -1
- package/src/core/graph/metis/metis_options.js +17 -2
- package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
- package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
- package/src/core/graph/metis/native/MetisGraph.js +212 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
- package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
- package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
- package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
- package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
- package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
- package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
- package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
- package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
- package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
- package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
- package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
- package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
- package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
- package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/project_kway.js +43 -0
- package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
- package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
- package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
- package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
- package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
- package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
- package/src/engine/EngineHarness.d.ts +3 -1
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +3 -0
- package/src/engine/control/first-person/DESIGN.md +30 -6
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +102 -9
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerController.js +38 -3
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +533 -4
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +315 -6
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +220 -22
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +858 -241
- package/src/engine/control/first-person/TODO.md +127 -0
- package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
- package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Ability.js +119 -0
- package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
- package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
- package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Mantle.js +188 -0
- package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
- package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/Slide.js +158 -0
- package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
- package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/WallJump.js +131 -0
- package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
- package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
- package/src/engine/control/first-person/abilities/WallRun.js +180 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
- package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
- package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
- package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
- package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
- package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
- package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
- package/src/engine/control/first-person/math/Spring.d.ts +56 -0
- package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
- package/src/engine/control/first-person/math/Spring.js +71 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
- package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
- package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
- package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
- package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
- package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
- package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
- package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
- package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
- package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
- package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +550 -119
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
- package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
- package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
- package/src/engine/control/first-person/test/buildTestPlayer.js +28 -0
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
- package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
- package/src/engine/graphics/ecs/light/Light.js +27 -0
- package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
- package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
- package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
- package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
- package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
- package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
- package/src/engine/physics/PLAN.md +236 -0
- package/src/engine/physics/body/BodyStorage.d.ts +187 -0
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
- package/src/engine/physics/body/BodyStorage.js +427 -0
- package/src/engine/physics/broadphase/PairList.d.ts +62 -0
- package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
- package/src/engine/physics/broadphase/PairList.js +97 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts +30 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +1 -0
- package/src/engine/physics/broadphase/aabb_transform_oriented.js +93 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
- package/src/engine/physics/broadphase/generate_pairs.js +101 -0
- package/src/engine/physics/contact/ManifoldStore.d.ts +226 -0
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
- package/src/engine/physics/contact/ManifoldStore.js +499 -0
- package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
- package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
- package/src/engine/physics/ecs/BodyKind.js +24 -0
- package/src/engine/physics/ecs/Collider.d.ts +98 -0
- package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
- package/src/engine/physics/ecs/Collider.js +136 -0
- package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
- package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderFlags.js +15 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
- package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
- package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
- package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +520 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/PhysicsSystem.js +1159 -0
- package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
- package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBody.js +240 -0
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
- package/src/engine/physics/ecs/SleepState.d.ts +11 -0
- package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
- package/src/engine/physics/ecs/SleepState.js +12 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
- package/src/engine/physics/events/ContactEventBuffer.js +83 -0
- package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
- package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
- package/src/engine/physics/events/diff_manifolds.js +50 -0
- package/src/engine/physics/fluid/FluidField.d.ts +294 -16
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +510 -66
- package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +455 -95
- package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
- package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
- package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
- package/src/engine/physics/fluid/prototype.js +102 -91
- package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
- package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +60 -38
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +93 -73
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +20 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +83 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +26 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +70 -0
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
- package/src/engine/physics/gjk/expanding_polytope_algorithm.js +8 -10
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +29 -0
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
- package/src/engine/physics/inertia/world_inverse_inertia.js +79 -0
- package/src/engine/physics/integration/integrate_position.d.ts +16 -0
- package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
- package/src/engine/physics/integration/integrate_position.js +48 -0
- package/src/engine/physics/integration/integrate_velocity.d.ts +25 -0
- package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
- package/src/engine/physics/integration/integrate_velocity.js +79 -0
- package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
- package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
- package/src/engine/physics/integration/quat_integrate.js +62 -0
- package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
- package/src/engine/physics/island/IslandBuilder.js +411 -0
- package/src/engine/physics/island/union_find.d.ts +51 -0
- package/src/engine/physics/island/union_find.d.ts.map +1 -0
- package/src/engine/physics/island/union_find.js +76 -0
- package/src/engine/physics/narrowphase/PosedShape.d.ts +59 -0
- package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/PosedShape.js +110 -0
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/box_box_manifold.js +543 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/capsule_contacts.js +508 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts +11 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/narrowphase_step.js +382 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/sphere_box_contact.js +130 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
- package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
- package/src/engine/physics/queries/raycast.d.ts +20 -0
- package/src/engine/physics/queries/raycast.d.ts.map +1 -0
- package/src/engine/physics/queries/raycast.js +249 -0
- package/src/engine/physics/solver/friction_cone.d.ts +16 -0
- package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
- package/src/engine/physics/solver/friction_cone.js +37 -0
- package/src/engine/physics/solver/solve_contacts.d.ts +36 -0
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
- package/src/engine/physics/solver/solve_contacts.js +598 -0
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
- package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
- package/src/engine/ecs/components/Motion.d.ts +0 -21
- package/src/engine/ecs/components/Motion.d.ts.map +0 -1
- package/src/engine/ecs/components/Motion.js +0 -27
- package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
- package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
- package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
- package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
- package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
- package/src/engine/ecs/systems/MotionSystem.js +0 -29
- package/src/engine/physics/fluid/Fluid.d.ts +0 -26
- package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
- package/src/engine/physics/fluid/Fluid.js +0 -221
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
- package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
- 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
|