@woosh/meep-engine 2.145.0 → 2.147.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 (99) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +33 -3
  3. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  4. package/src/core/geom/3d/shape/HeightMapShape3D.js +486 -451
  5. package/src/engine/control/first-person/DESIGN_COLLISION.md +365 -352
  6. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +1 -14
  7. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  8. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +20 -8
  9. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  10. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +552 -546
  11. package/src/engine/control/first-person/TODO.md +13 -11
  12. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +8 -3
  13. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -1
  14. package/src/engine/control/first-person/abilities/LedgeGrab.js +213 -199
  15. package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -1
  16. package/src/engine/control/first-person/abilities/Mantle.js +195 -188
  17. package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -1
  18. package/src/engine/control/first-person/abilities/WallJump.js +11 -3
  19. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -1
  20. package/src/engine/control/first-person/abilities/WallRun.js +183 -163
  21. package/src/engine/control/first-person/collision/KinematicMover.d.ts.map +1 -1
  22. package/src/engine/control/first-person/collision/KinematicMover.js +634 -592
  23. package/src/engine/control/first-person/prototype_first_person_controller.js +1003 -901
  24. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +9 -0
  25. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -1
  26. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +87 -77
  27. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +8 -0
  28. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
  29. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +229 -196
  30. package/src/engine/ecs/EntityManager.d.ts +34 -11
  31. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  32. package/src/engine/ecs/EntityManager.js +71 -42
  33. package/src/engine/interpolation/BinaryInterpolationAdapter.d.ts.map +1 -0
  34. package/src/engine/interpolation/Interpoland.d.ts +48 -0
  35. package/src/engine/interpolation/Interpoland.d.ts.map +1 -0
  36. package/src/engine/interpolation/Interpoland.js +49 -0
  37. package/src/engine/interpolation/Interpolated.d.ts +101 -0
  38. package/src/engine/interpolation/Interpolated.d.ts.map +1 -0
  39. package/src/engine/interpolation/Interpolated.js +149 -0
  40. package/src/engine/{network/sim → interpolation}/InterpolationLog.d.ts +1 -1
  41. package/src/engine/interpolation/InterpolationLog.d.ts.map +1 -0
  42. package/src/engine/{network/sim → interpolation}/InterpolationLog.js +2 -2
  43. package/src/engine/interpolation/InterpolationSystem.d.ts +116 -0
  44. package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -0
  45. package/src/engine/interpolation/InterpolationSystem.js +233 -0
  46. package/src/engine/interpolation/PoseInterpolationAdapter.d.ts +17 -0
  47. package/src/engine/interpolation/PoseInterpolationAdapter.d.ts.map +1 -0
  48. package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -0
  49. package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts +35 -0
  50. package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts.map +1 -0
  51. package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -0
  52. package/src/engine/interpolation/pose_interpoland.d.ts +18 -0
  53. package/src/engine/interpolation/pose_interpoland.d.ts.map +1 -0
  54. package/src/engine/interpolation/pose_interpoland.js +27 -0
  55. package/src/engine/network/NetworkSession.d.ts +2 -2
  56. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  57. package/src/engine/network/NetworkSession.js +2 -2
  58. package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts +1 -1
  59. package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts.map +1 -1
  60. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +1 -1
  61. package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts +1 -1
  62. package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts.map +1 -1
  63. package/src/engine/network/adapters/TransformInterpolationAdapter.js +1 -1
  64. package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts +1 -1
  65. package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts.map +1 -1
  66. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +1 -1
  67. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -0
  68. package/src/engine/physics/PLAN.md +944 -809
  69. package/src/engine/physics/body/BodyStorage.d.ts +9 -0
  70. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
  71. package/src/engine/physics/body/BodyStorage.js +23 -0
  72. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  73. package/src/engine/physics/broadphase/generate_pairs.js +7 -0
  74. package/src/engine/physics/ccd/linear_sweep.d.ts +97 -0
  75. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -0
  76. package/src/engine/physics/ccd/linear_sweep.js +238 -0
  77. package/src/engine/physics/ecs/PhysicsSystem.d.ts +82 -3
  78. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  79. package/src/engine/physics/ecs/PhysicsSystem.js +227 -8
  80. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +6 -0
  81. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -1
  82. package/src/engine/physics/ecs/RigidBodyFlags.js +6 -0
  83. package/src/engine/physics/narrowphase/box_triangle_contact.js +814 -811
  84. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
  85. package/src/engine/physics/narrowphase/compute_penetration.js +325 -323
  86. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +27 -8
  87. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -1
  88. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +235 -204
  89. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  90. package/src/engine/physics/narrowphase/narrowphase_step.js +97 -13
  91. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
  92. package/src/engine/physics/queries/overlap_shape.js +185 -183
  93. package/src/engine/simulation/Ticker.d.ts +14 -0
  94. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  95. package/src/engine/simulation/Ticker.js +136 -1
  96. package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts.map +0 -1
  97. package/src/engine/network/sim/InterpolationLog.d.ts.map +0 -1
  98. /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.d.ts +0 -0
  99. /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.js +0 -0
@@ -1,188 +1,195 @@
1
- import { FirstPersonPosture } from "../pose/FirstPersonPosture.js";
2
- import { Ability } from "./Ability.js";
3
-
4
- /**
5
- * Smoothstep-style horizontal interpolation: slow-fast-slow.
6
- * @param {number} t [0..1]
7
- */
8
- function easeInOutCubic(t) {
9
- return t < 0.5
10
- ? 4 * t * t * t
11
- : 1 - Math.pow(-2 * t + 2, 3) / 2;
12
- }
13
-
14
- /**
15
- * Front-loaded ease — fast rise then gentle settle. Used for the vertical
16
- * curve so the body lifts off the ground quickly (matching the hand-grip
17
- * pull-up dynamic) and decelerates as it approaches the surface top.
18
- * @param {number} t [0..1]
19
- */
20
- function easeOutCubic(t) {
21
- return 1 - Math.pow(1 - t, 3);
22
- }
23
-
24
- /**
25
- * Mantle ability — auto-triggers when the player walks/runs into a
26
- * reachable obstacle with forward intent. The body follows a scripted
27
- * parametric path (horizontal lerp on an ease-in-out, vertical lerp on
28
- * an ease-out) for {@link cfg.mantle.duration} seconds, landing on top
29
- * of the surface.
30
- *
31
- * Activation requires both `sensors.obstacleAhead.hit` (something in
32
- * front to climb) AND `sensors.ledgeAhead.hit` (there's a top surface
33
- * to land on). Heights between `cfg.mantle.minHeight` and `maxHeight`
34
- * are accepted; below is "just step over", above is "out of reach".
35
- *
36
- * The ability is FULLY non-interruptible once committed — `canInterrupt`
37
- * returns false throughout. This prevents the body from teleporting
38
- * mid-mantle if a higher-priority ability fires; the trade-off is the
39
- * player has limited control during the short window. Player input
40
- * for THIS frame is effectively suspended.
41
- *
42
- * Priority 30: above Slide (10) so an obstacle vault-into preempts a
43
- * slide; below Wall-run / Wall-jump so those high-air abilities still
44
- * win if their conditions are simultaneously met (which would be
45
- * unusual — typically you mantle from the ground).
46
- *
47
- * @author Alex Goldring
48
- * @copyright Company Named Limited (c) 2026
49
- */
50
- export class Mantle extends Ability {
51
- constructor() {
52
- super();
53
- this.name = "Mantle";
54
- this.priority = 30;
55
-
56
- // -- per-instance scripted-path state --
57
- /** @private Elapsed fraction of duration. */
58
- this._t = 0;
59
- /** @private Captured at activation. */
60
- this._duration = 0.5;
61
- this._startX = 0;
62
- this._startY = 0;
63
- this._startZ = 0;
64
- this._endX = 0;
65
- this._endY = 0;
66
- this._endZ = 0;
67
- }
68
-
69
- canActivate(controller, runtime, sensors) {
70
- const cfg = controller.config.mantle;
71
- if (!cfg) return false;
72
- if (sensors === undefined || sensors === null) return false;
73
-
74
- // Must have BOTH the face probe (obstacleAhead) AND the top probe
75
- // (ledgeAhead) — otherwise we don't know if there's anywhere to
76
- // land. obstacleAhead alone could be a wall too tall to climb.
77
- if (!sensors.obstacleAhead.hit) return false;
78
- if (!sensors.ledgeAhead.hit) return false;
79
-
80
- // Forward intent is required the player must be committing
81
- // into the obstacle, otherwise we don't want to grab them.
82
- if (controller.intent.move.y < 0.1) return false;
83
-
84
- // Height check: the target surface must be within the reachable
85
- // band.
86
- const surfaceTopY = sensors.ledgeAhead.point.y;
87
- const playerFootY = controller.pose.rootPosition.y;
88
- const heightDiff = surfaceTopY - playerFootY;
89
- if (heightDiff < cfg.minHeight) return false;
90
- if (heightDiff > cfg.maxHeight) return false;
91
-
92
- return true;
93
- }
94
-
95
- onActivate(controller, runtime) {
96
- const cfg = controller.config.mantle;
97
- const sensors = runtime.sensors;
98
-
99
- this._t = 0;
100
- this._duration = cfg.duration;
101
-
102
- // Capture start position (body's current world position).
103
- const startPos = controller.pose.rootPosition;
104
- this._startX = startPos.x;
105
- this._startY = startPos.y;
106
- this._startZ = startPos.z;
107
-
108
- // Compute end position: above the ledge surface, displaced
109
- // forward by `forwardOffsetOnLand` so the player ends standing
110
- // on the surface (not balancing on the edge).
111
- const yaw = runtime.bodyYaw;
112
- const fx = Math.sin(yaw);
113
- const fz = Math.cos(yaw);
114
- this._endX = sensors.ledgeAhead.point.x + fx * cfg.forwardOffsetOnLand;
115
- this._endY = sensors.ledgeAhead.point.y;
116
- this._endZ = sensors.ledgeAhead.point.z + fz * cfg.forwardOffsetOnLand;
117
-
118
- // Zero velocity — the body is on a path, not under integration.
119
- runtime.velocityX = 0;
120
- runtime.velocityY = 0;
121
- runtime.velocityZ = 0;
122
-
123
- // Clear airborne/jump state the scripted path supersedes them.
124
- runtime.midJump = false;
125
- runtime.apexFired = false;
126
- controller.state.isVariableJumpCut = false;
127
- controller.state.isAscending = false;
128
-
129
- // Body is climbing — upright posture (not Hang, even if we got
130
- // here from ledge-grab). Animators read posture for the rig
131
- // blend; this signals "switch from the hang clip to the climb /
132
- // upright clip".
133
- controller.state.posture = FirstPersonPosture.Stand;
134
-
135
- controller.signals.onLeaveGround.send1({ reason: "mantle" });
136
- }
137
-
138
- canInterrupt() {
139
- // Non-interruptible. Mantle commits.
140
- return false;
141
- }
142
-
143
- tick(controller, runtime, bodyTransform, dt, _system) {
144
- // Body is on a scripted path — no lat-accel-driven lean. Hold
145
- // the camera level for the duration of the mantle.
146
- runtime.leanTargetRad = 0;
147
- // Re-assert posture in case anything reset it. Mantle is a
148
- // committed climb; we want the rig in the climb/stand blend
149
- // until release.
150
- controller.state.posture = FirstPersonPosture.Stand;
151
-
152
- this._t += dt / this._duration;
153
-
154
- if (this._t >= 1.0) {
155
- // Completed: snap to end, mark grounded, release.
156
- bodyTransform.position.set(this._endX, this._endY, this._endZ);
157
- runtime.velocityX = 0;
158
- runtime.velocityY = 0;
159
- runtime.velocityZ = 0;
160
- controller.state.grounded = true;
161
- controller.state.verticalSpeed = 0;
162
- controller.state.airborneTime = 0;
163
- controller.state.timeSinceGrounded = 0;
164
- controller.signals.onLand.send1({ verticalSpeed: 0, kind: "soft" });
165
- return false;
166
- }
167
-
168
- // Sample the parametric path.
169
- const horizT = easeInOutCubic(this._t);
170
- const vertT = easeOutCubic(this._t);
171
- bodyTransform.position.set(
172
- this._startX + (this._endX - this._startX) * horizT,
173
- this._startY + (this._endY - this._startY) * vertT,
174
- this._startZ + (this._endZ - this._startZ) * horizT,
175
- );
176
-
177
- // Body is on a path — no integration this tick. Velocity stays 0.
178
- runtime.velocityX = 0;
179
- runtime.velocityY = 0;
180
- runtime.velocityZ = 0;
181
-
182
- return true;
183
- }
184
-
185
- onDeactivate(_controller, _runtime) {
186
- this._t = 0;
187
- }
188
- }
1
+ import { FirstPersonPosture } from "../pose/FirstPersonPosture.js";
2
+ import { Ability } from "./Ability.js";
3
+
4
+ /**
5
+ * Smoothstep-style horizontal interpolation: slow-fast-slow.
6
+ * @param {number} t [0..1]
7
+ */
8
+ function easeInOutCubic(t) {
9
+ return t < 0.5
10
+ ? 4 * t * t * t
11
+ : 1 - Math.pow(-2 * t + 2, 3) / 2;
12
+ }
13
+
14
+ /**
15
+ * Front-loaded ease — fast rise then gentle settle. Used for the vertical
16
+ * curve so the body lifts off the ground quickly (matching the hand-grip
17
+ * pull-up dynamic) and decelerates as it approaches the surface top.
18
+ * @param {number} t [0..1]
19
+ */
20
+ function easeOutCubic(t) {
21
+ return 1 - Math.pow(1 - t, 3);
22
+ }
23
+
24
+ /**
25
+ * Mantle ability — auto-triggers when the player walks/runs into a
26
+ * reachable obstacle with forward intent. The body follows a scripted
27
+ * parametric path (horizontal lerp on an ease-in-out, vertical lerp on
28
+ * an ease-out) for {@link cfg.mantle.duration} seconds, landing on top
29
+ * of the surface.
30
+ *
31
+ * Activation requires both `sensors.obstacleAhead.hit` (something in
32
+ * front to climb) AND `sensors.ledgeAhead.hit` (there's a top surface
33
+ * to land on). Heights between `cfg.mantle.minHeight` and `maxHeight`
34
+ * are accepted; below is "just step over", above is "out of reach".
35
+ *
36
+ * The ability is FULLY non-interruptible once committed — `canInterrupt`
37
+ * returns false throughout. This prevents the body from teleporting
38
+ * mid-mantle if a higher-priority ability fires; the trade-off is the
39
+ * player has limited control during the short window. Player input
40
+ * for THIS frame is effectively suspended.
41
+ *
42
+ * Priority 30: above Slide (10) so an obstacle vault-into preempts a
43
+ * slide; below Wall-run / Wall-jump so those high-air abilities still
44
+ * win if their conditions are simultaneously met (which would be
45
+ * unusual — typically you mantle from the ground).
46
+ *
47
+ * @author Alex Goldring
48
+ * @copyright Company Named Limited (c) 2026
49
+ */
50
+ export class Mantle extends Ability {
51
+ constructor() {
52
+ super();
53
+ this.name = "Mantle";
54
+ this.priority = 30;
55
+
56
+ // -- per-instance scripted-path state --
57
+ /** @private Elapsed fraction of duration. */
58
+ this._t = 0;
59
+ /** @private Captured at activation. */
60
+ this._duration = 0.5;
61
+ this._startX = 0;
62
+ this._startY = 0;
63
+ this._startZ = 0;
64
+ this._endX = 0;
65
+ this._endY = 0;
66
+ this._endZ = 0;
67
+ }
68
+
69
+ canActivate(controller, runtime, sensors) {
70
+ const cfg = controller.config.mantle;
71
+ if (!cfg) return false;
72
+ if (sensors === undefined || sensors === null) return false;
73
+
74
+ // Must have BOTH the face probe (obstacleAhead) AND the top probe
75
+ // (ledgeAhead) — otherwise we don't know if there's anywhere to
76
+ // land. obstacleAhead alone could be a wall too tall to climb.
77
+ if (!sensors.obstacleAhead.hit) return false;
78
+ if (!sensors.ledgeAhead.hit) return false;
79
+
80
+ // Only vault onto a top we can actually STAND on. A too-thin wall /
81
+ // knife-edge isn't a mantle target the body would land overhanging
82
+ // and fall right back off (on a wall-run wall this is the reported
83
+ // violent snap-then-drop). Ledge-grab, which can hang from a thin
84
+ // edge, takes those instead.
85
+ if (!sensors.ledgeStandable) return false;
86
+
87
+ // Forward intent is required — the player must be committing
88
+ // into the obstacle, otherwise we don't want to grab them.
89
+ if (controller.intent.move.y < 0.1) return false;
90
+
91
+ // Height check: the target surface must be within the reachable
92
+ // band.
93
+ const surfaceTopY = sensors.ledgeAhead.point.y;
94
+ const playerFootY = controller.pose.rootPosition.y;
95
+ const heightDiff = surfaceTopY - playerFootY;
96
+ if (heightDiff < cfg.minHeight) return false;
97
+ if (heightDiff > cfg.maxHeight) return false;
98
+
99
+ return true;
100
+ }
101
+
102
+ onActivate(controller, runtime) {
103
+ const cfg = controller.config.mantle;
104
+ const sensors = runtime.sensors;
105
+
106
+ this._t = 0;
107
+ this._duration = cfg.duration;
108
+
109
+ // Capture start position (body's current world position).
110
+ const startPos = controller.pose.rootPosition;
111
+ this._startX = startPos.x;
112
+ this._startY = startPos.y;
113
+ this._startZ = startPos.z;
114
+
115
+ // Compute end position: above the ledge surface, displaced
116
+ // forward by `forwardOffsetOnLand` so the player ends standing
117
+ // on the surface (not balancing on the edge).
118
+ const yaw = runtime.bodyYaw;
119
+ const fx = Math.sin(yaw);
120
+ const fz = Math.cos(yaw);
121
+ this._endX = sensors.ledgeAhead.point.x + fx * cfg.forwardOffsetOnLand;
122
+ this._endY = sensors.ledgeAhead.point.y;
123
+ this._endZ = sensors.ledgeAhead.point.z + fz * cfg.forwardOffsetOnLand;
124
+
125
+ // Zero velocity — the body is on a path, not under integration.
126
+ runtime.velocityX = 0;
127
+ runtime.velocityY = 0;
128
+ runtime.velocityZ = 0;
129
+
130
+ // Clear airborne/jump state the scripted path supersedes them.
131
+ runtime.midJump = false;
132
+ runtime.apexFired = false;
133
+ controller.state.isVariableJumpCut = false;
134
+ controller.state.isAscending = false;
135
+
136
+ // Body is climbing — upright posture (not Hang, even if we got
137
+ // here from ledge-grab). Animators read posture for the rig
138
+ // blend; this signals "switch from the hang clip to the climb /
139
+ // upright clip".
140
+ controller.state.posture = FirstPersonPosture.Stand;
141
+
142
+ controller.signals.onLeaveGround.send1({ reason: "mantle" });
143
+ }
144
+
145
+ canInterrupt() {
146
+ // Non-interruptible. Mantle commits.
147
+ return false;
148
+ }
149
+
150
+ tick(controller, runtime, bodyTransform, dt, _system) {
151
+ // Body is on a scripted path — no lat-accel-driven lean. Hold
152
+ // the camera level for the duration of the mantle.
153
+ runtime.leanTargetRad = 0;
154
+ // Re-assert posture in case anything reset it. Mantle is a
155
+ // committed climb; we want the rig in the climb/stand blend
156
+ // until release.
157
+ controller.state.posture = FirstPersonPosture.Stand;
158
+
159
+ this._t += dt / this._duration;
160
+
161
+ if (this._t >= 1.0) {
162
+ // Completed: snap to end, mark grounded, release.
163
+ bodyTransform.position.set(this._endX, this._endY, this._endZ);
164
+ runtime.velocityX = 0;
165
+ runtime.velocityY = 0;
166
+ runtime.velocityZ = 0;
167
+ controller.state.grounded = true;
168
+ controller.state.verticalSpeed = 0;
169
+ controller.state.airborneTime = 0;
170
+ controller.state.timeSinceGrounded = 0;
171
+ controller.signals.onLand.send1({ verticalSpeed: 0, kind: "soft" });
172
+ return false;
173
+ }
174
+
175
+ // Sample the parametric path.
176
+ const horizT = easeInOutCubic(this._t);
177
+ const vertT = easeOutCubic(this._t);
178
+ bodyTransform.position.set(
179
+ this._startX + (this._endX - this._startX) * horizT,
180
+ this._startY + (this._endY - this._startY) * vertT,
181
+ this._startZ + (this._endZ - this._startZ) * horizT,
182
+ );
183
+
184
+ // Body is on a path — no integration this tick. Velocity stays 0.
185
+ runtime.velocityX = 0;
186
+ runtime.velocityY = 0;
187
+ runtime.velocityZ = 0;
188
+
189
+ return true;
190
+ }
191
+
192
+ onDeactivate(_controller, _runtime) {
193
+ this._t = 0;
194
+ }
195
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"WallJump.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/WallJump.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH;IAOI,kEAoBC;IAED,gDAgDC;IAED;;;;;OAKG;IACH,wBAEC;IAED,4FAKC;CACJ;wBAhIuB,cAAc"}
1
+ {"version":3,"file":"WallJump.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/WallJump.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH;IAOI,kEA4BC;IAED,gDAgDC;IAED;;;;;OAKG;IACH,wBAEC;IAED,4FAKC;CACJ;wBAxIuB,cAAc"}
@@ -52,11 +52,19 @@ export class WallJump extends Ability {
52
52
  // Must be airborne — wall-jump from the ground is just a jump.
53
53
  if (controller.state.grounded) return false;
54
54
 
55
- // At least one side wall within the near-wall distance.
55
+ // At least one side wall within reach. From an ACTIVE wall-run the
56
+ // wall is right there by definition — allow the kick regardless of
57
+ // distance (the wall-run pins the player at the sensor's edge, which
58
+ // is beyond nearWallMaxDistance, so gating the canonical wall-run →
59
+ // wall-jump chain on the near distance would make it misfire).
60
+ // Otherwise (near-wall airborne, not committed) require the closer
61
+ // distance so a stray nearby wall doesn't grant a free jump.
62
+ const onWallRun = controller.abilities.active !== null
63
+ && controller.abilities.active.name === "WallRun";
56
64
  const left = sensors.wallLeft;
57
65
  const right = sensors.wallRight;
58
- const leftClose = left.hit && left.distance <= cfg.nearWallMaxDistance;
59
- const rightClose = right.hit && right.distance <= cfg.nearWallMaxDistance;
66
+ const leftClose = left.hit && (onWallRun || left.distance <= cfg.nearWallMaxDistance);
67
+ const rightClose = right.hit && (onWallRun || right.distance <= cfg.nearWallMaxDistance);
60
68
  if (!leftClose && !rightClose) return false;
61
69
 
62
70
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"WallRun.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/WallRun.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAMQ,qDAAqD;IACrD,iBAAiB;IACjB,yDAAyD;IACzD,cAAgB;IAGpB,kEAiBC;IAED,gDAqBC;IAED;;;;OAIG;IACH,wBAEC;IAED,uFAgEC;CAKJ;wBAjKuB,cAAc"}
1
+ {"version":3,"file":"WallRun.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/WallRun.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAMQ,qDAAqD;IACrD,iBAAiB;IACjB,yDAAyD;IACzD,cAAgB;IAGpB,kEAqCC;IAED,gDAqBC;IAED;;;;OAIG;IACH,wBAEC;IAED,uFAgEC;CAKJ;wBArLuB,cAAc"}