@woosh/meep-engine 2.146.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.
- package/package.json +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +0 -11
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +8 -6
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +552 -551
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +8 -3
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/LedgeGrab.js +213 -199
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/Mantle.js +195 -188
- package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/WallRun.js +183 -175
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +9 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -1
- package/src/engine/control/first-person/sensors/FirstPersonSensors.js +87 -77
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +8 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +229 -196
- package/src/engine/ecs/EntityManager.d.ts +34 -11
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +71 -42
- package/src/engine/interpolation/BinaryInterpolationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/Interpoland.d.ts +48 -0
- package/src/engine/interpolation/Interpoland.d.ts.map +1 -0
- package/src/engine/interpolation/Interpoland.js +49 -0
- package/src/engine/interpolation/Interpolated.d.ts +101 -0
- package/src/engine/interpolation/Interpolated.d.ts.map +1 -0
- package/src/engine/interpolation/Interpolated.js +149 -0
- package/src/engine/{network/sim → interpolation}/InterpolationLog.d.ts +1 -1
- package/src/engine/interpolation/InterpolationLog.d.ts.map +1 -0
- package/src/engine/{network/sim → interpolation}/InterpolationLog.js +2 -2
- package/src/engine/interpolation/InterpolationSystem.d.ts +116 -0
- package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -0
- package/src/engine/interpolation/InterpolationSystem.js +233 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.d.ts +17 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts +35 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -0
- package/src/engine/interpolation/pose_interpoland.d.ts +18 -0
- package/src/engine/interpolation/pose_interpoland.d.ts.map +1 -0
- package/src/engine/interpolation/pose_interpoland.js +27 -0
- package/src/engine/network/NetworkSession.d.ts +2 -2
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +2 -2
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.js +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.js +1 -1
- package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -0
- package/src/engine/physics/PLAN.md +10 -9
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +64 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +168 -0
- package/src/engine/physics/narrowphase/box_triangle_contact.js +15 -12
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +28 -1
- package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts.map +0 -1
- package/src/engine/network/sim/InterpolationLog.d.ts.map +0 -1
- /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.d.ts +0 -0
- /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.js +0 -0
|
@@ -49,10 +49,15 @@
|
|
|
49
49
|
* @copyright Company Named Limited (c) 2026
|
|
50
50
|
*/
|
|
51
51
|
export class LedgeGrab extends Ability {
|
|
52
|
-
/** @private
|
|
53
|
-
|
|
52
|
+
/** @private Wall-face anchor (x,z), the face's outward normal (x,z),
|
|
53
|
+
* and the top-edge height (y) — captured at onActivate. The hang pose
|
|
54
|
+
* is built from the WALL, not from the (possibly oblique) body
|
|
55
|
+
* facing, so it stays just outside the wall at any approach angle. */
|
|
56
|
+
private _anchorX;
|
|
57
|
+
_anchorZ: number;
|
|
58
|
+
_nx: number;
|
|
59
|
+
_nz: number;
|
|
54
60
|
_edgeY: number;
|
|
55
|
-
_edgeZ: number;
|
|
56
61
|
canActivate(controller: any, runtime: any, sensors: any): boolean;
|
|
57
62
|
onActivate(controller: any, runtime: any): void;
|
|
58
63
|
canInterrupt(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LedgeGrab.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/LedgeGrab.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH;IAMQ
|
|
1
|
+
{"version":3,"file":"LedgeGrab.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/LedgeGrab.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH;IAMQ;;;2EAGuE;IACvE,iBAAiB;IACjB,iBAAiB;IACjB,YAAY;IACZ,YAAY;IACZ,eAAe;IAGnB,kEAkBC;IAED,gDAkCC;IAED,wBAKC;IAED,wFA6EC;CACJ;wBAlNuB,cAAc"}
|
|
@@ -1,199 +1,213 @@
|
|
|
1
|
-
import { clamp } from "../../../../core/math/clamp.js";
|
|
2
|
-
import { FirstPersonPosture } from "../pose/FirstPersonPosture.js";
|
|
3
|
-
import { Ability } from "./Ability.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Ledge-grab ability — snap to a forward ledge while descending and hang
|
|
7
|
-
* from it until the player chooses (or is forced) to release.
|
|
8
|
-
*
|
|
9
|
-
* Activation:
|
|
10
|
-
* - `sensors.ledgeAhead.hit` (a forward+up obstacle probe found a grab-
|
|
11
|
-
* able edge — typically the same probe mantle uses).
|
|
12
|
-
* - `runtime.velocityY <= 0` — the player is descending or static. We
|
|
13
|
-
* don't auto-catch ledges on the way UP — that would feel like the
|
|
14
|
-
* world is grabbing the player mid-jump.
|
|
15
|
-
* - `state.airborneTime >= minAirborneTime` — leaves a small window
|
|
16
|
-
* after takeoff where ledge-grab can't fire, even if the player is
|
|
17
|
-
* instantly at apex (which would otherwise satisfy `velocityY <= 0`).
|
|
18
|
-
* - Forward intent (`intent.move.y > 0.1`) — the player must be
|
|
19
|
-
* committing into the ledge. Walking backwards off an edge shouldn't
|
|
20
|
-
* auto-catch the lip.
|
|
21
|
-
*
|
|
22
|
-
* Behaviour:
|
|
23
|
-
* - Body position snaps to a "hang from edge" pose: at the ledge edge
|
|
24
|
-
* X/Z (with a small back-offset so the body is pulled against the
|
|
25
|
-
* wall below), and Y offset down by ~bodyHeight so the hands grip
|
|
26
|
-
* the edge with the body suspended below.
|
|
27
|
-
* - Velocity is zeroed each tick — the body is parked.
|
|
28
|
-
* - Exertion rises at `cfg.exertionRiseRate` per second, scaled by
|
|
29
|
-
* mass. Climbing fatigue: hang too long and the next exit is
|
|
30
|
-
* forced (a slip).
|
|
31
|
-
* - Grounded stays false (the player is hanging in air).
|
|
32
|
-
*
|
|
33
|
-
* Exit:
|
|
34
|
-
* - Jump pressed (rising edge) → mantle-up. Release with a small
|
|
35
|
-
* upward velocity so mantle's ledgeAhead probe still hits next
|
|
36
|
-
* tick; mantle (priority 30) then takes over and animates the
|
|
37
|
-
* climb-onto-surface path.
|
|
38
|
-
* - Back-intent (`intent.move.y < -0.1`) → drop. Release with zero
|
|
39
|
-
* velocity; the player falls under base gravity.
|
|
40
|
-
* - Crouch pressed → drop. Same as back-intent.
|
|
41
|
-
* - Exertion saturates (`>= 1`) → slip. Release with zero velocity.
|
|
42
|
-
* - `sensors.ledgeAhead.hit` becomes false → shuffled off the edge.
|
|
43
|
-
* Release with zero velocity.
|
|
44
|
-
*
|
|
45
|
-
* Priority 40 — above mantle (30), below wall-run (50). Mantle CAN'T
|
|
46
|
-
* preempt an active ledge-grab — that's the point of placing ledge
|
|
47
|
-
* higher. Otherwise mantle would fire mid-hang and snap the body away.
|
|
48
|
-
* Wall-run and wall-jump can preempt — but in practice they need lateral
|
|
49
|
-
* walls + speed (wall-run) or a jump press near a side wall (wall-jump),
|
|
50
|
-
* conditions which rarely hold while hanging.
|
|
51
|
-
*
|
|
52
|
-
* @author Alex Goldring
|
|
53
|
-
* @copyright Company Named Limited (c) 2026
|
|
54
|
-
*/
|
|
55
|
-
export class LedgeGrab extends Ability {
|
|
56
|
-
constructor() {
|
|
57
|
-
super();
|
|
58
|
-
this.name = "LedgeGrab";
|
|
59
|
-
this.priority = 40;
|
|
60
|
-
|
|
61
|
-
/** @private
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (controller.intent.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
controller.state.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
if (controller.
|
|
169
|
-
controller.signals.onLedgeRelease.send1({ reason: "
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// --
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
1
|
+
import { clamp } from "../../../../core/math/clamp.js";
|
|
2
|
+
import { FirstPersonPosture } from "../pose/FirstPersonPosture.js";
|
|
3
|
+
import { Ability } from "./Ability.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ledge-grab ability — snap to a forward ledge while descending and hang
|
|
7
|
+
* from it until the player chooses (or is forced) to release.
|
|
8
|
+
*
|
|
9
|
+
* Activation:
|
|
10
|
+
* - `sensors.ledgeAhead.hit` (a forward+up obstacle probe found a grab-
|
|
11
|
+
* able edge — typically the same probe mantle uses).
|
|
12
|
+
* - `runtime.velocityY <= 0` — the player is descending or static. We
|
|
13
|
+
* don't auto-catch ledges on the way UP — that would feel like the
|
|
14
|
+
* world is grabbing the player mid-jump.
|
|
15
|
+
* - `state.airborneTime >= minAirborneTime` — leaves a small window
|
|
16
|
+
* after takeoff where ledge-grab can't fire, even if the player is
|
|
17
|
+
* instantly at apex (which would otherwise satisfy `velocityY <= 0`).
|
|
18
|
+
* - Forward intent (`intent.move.y > 0.1`) — the player must be
|
|
19
|
+
* committing into the ledge. Walking backwards off an edge shouldn't
|
|
20
|
+
* auto-catch the lip.
|
|
21
|
+
*
|
|
22
|
+
* Behaviour:
|
|
23
|
+
* - Body position snaps to a "hang from edge" pose: at the ledge edge
|
|
24
|
+
* X/Z (with a small back-offset so the body is pulled against the
|
|
25
|
+
* wall below), and Y offset down by ~bodyHeight so the hands grip
|
|
26
|
+
* the edge with the body suspended below.
|
|
27
|
+
* - Velocity is zeroed each tick — the body is parked.
|
|
28
|
+
* - Exertion rises at `cfg.exertionRiseRate` per second, scaled by
|
|
29
|
+
* mass. Climbing fatigue: hang too long and the next exit is
|
|
30
|
+
* forced (a slip).
|
|
31
|
+
* - Grounded stays false (the player is hanging in air).
|
|
32
|
+
*
|
|
33
|
+
* Exit:
|
|
34
|
+
* - Jump pressed (rising edge) → mantle-up. Release with a small
|
|
35
|
+
* upward velocity so mantle's ledgeAhead probe still hits next
|
|
36
|
+
* tick; mantle (priority 30) then takes over and animates the
|
|
37
|
+
* climb-onto-surface path.
|
|
38
|
+
* - Back-intent (`intent.move.y < -0.1`) → drop. Release with zero
|
|
39
|
+
* velocity; the player falls under base gravity.
|
|
40
|
+
* - Crouch pressed → drop. Same as back-intent.
|
|
41
|
+
* - Exertion saturates (`>= 1`) → slip. Release with zero velocity.
|
|
42
|
+
* - `sensors.ledgeAhead.hit` becomes false → shuffled off the edge.
|
|
43
|
+
* Release with zero velocity.
|
|
44
|
+
*
|
|
45
|
+
* Priority 40 — above mantle (30), below wall-run (50). Mantle CAN'T
|
|
46
|
+
* preempt an active ledge-grab — that's the point of placing ledge
|
|
47
|
+
* higher. Otherwise mantle would fire mid-hang and snap the body away.
|
|
48
|
+
* Wall-run and wall-jump can preempt — but in practice they need lateral
|
|
49
|
+
* walls + speed (wall-run) or a jump press near a side wall (wall-jump),
|
|
50
|
+
* conditions which rarely hold while hanging.
|
|
51
|
+
*
|
|
52
|
+
* @author Alex Goldring
|
|
53
|
+
* @copyright Company Named Limited (c) 2026
|
|
54
|
+
*/
|
|
55
|
+
export class LedgeGrab extends Ability {
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
this.name = "LedgeGrab";
|
|
59
|
+
this.priority = 40;
|
|
60
|
+
|
|
61
|
+
/** @private Wall-face anchor (x,z), the face's outward normal (x,z),
|
|
62
|
+
* and the top-edge height (y) — captured at onActivate. The hang pose
|
|
63
|
+
* is built from the WALL, not from the (possibly oblique) body
|
|
64
|
+
* facing, so it stays just outside the wall at any approach angle. */
|
|
65
|
+
this._anchorX = 0;
|
|
66
|
+
this._anchorZ = 0;
|
|
67
|
+
this._nx = 0;
|
|
68
|
+
this._nz = 0;
|
|
69
|
+
this._edgeY = 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
canActivate(controller, runtime, sensors) {
|
|
73
|
+
const cfg = controller.config.ledgeGrab;
|
|
74
|
+
if (!cfg) return false;
|
|
75
|
+
if (sensors === undefined || sensors === null) return false;
|
|
76
|
+
|
|
77
|
+
if (!sensors.ledgeAhead.hit) return false;
|
|
78
|
+
if (runtime.velocityY > 0) return false; // not on the way up
|
|
79
|
+
if (controller.state.grounded) return false;
|
|
80
|
+
if (controller.state.airborneTime < cfg.minAirborneTime) return false;
|
|
81
|
+
if (controller.intent.move.y < 0.1) return false;
|
|
82
|
+
// Crouch or exhausted: don't re-grab. These are the same exit
|
|
83
|
+
// conditions that would IMMEDIATELY release after activation, so
|
|
84
|
+
// gating them here prevents a same-tick re-activation flicker
|
|
85
|
+
// after a crouch-release or slip.
|
|
86
|
+
if (controller.intent.crouch) return false;
|
|
87
|
+
if (controller.state.exertion >= 1.0) return false;
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
onActivate(controller, runtime) {
|
|
93
|
+
const sensors = runtime.sensors;
|
|
94
|
+
|
|
95
|
+
// Anchor on the wall face + its outward normal (ledgeAhead is only
|
|
96
|
+
// probed when obstacleAhead hits, so the face data is always present
|
|
97
|
+
// here). The top-edge height comes from the ledge probe.
|
|
98
|
+
this._anchorX = sensors.obstacleAhead.point.x;
|
|
99
|
+
this._anchorZ = sensors.obstacleAhead.point.z;
|
|
100
|
+
this._nx = sensors.obstacleAhead.normal.x;
|
|
101
|
+
this._nz = sensors.obstacleAhead.normal.z;
|
|
102
|
+
this._edgeY = sensors.ledgeAhead.point.y;
|
|
103
|
+
|
|
104
|
+
// Zero velocity — the body is now parked on the ledge.
|
|
105
|
+
runtime.velocityX = 0;
|
|
106
|
+
runtime.velocityY = 0;
|
|
107
|
+
runtime.velocityZ = 0;
|
|
108
|
+
|
|
109
|
+
// Clear any in-progress jump state — hanging supersedes them.
|
|
110
|
+
runtime.midJump = false;
|
|
111
|
+
runtime.apexFired = false;
|
|
112
|
+
controller.state.isVariableJumpCut = false;
|
|
113
|
+
controller.state.isAscending = false;
|
|
114
|
+
|
|
115
|
+
// The body is hanging — not on the ground.
|
|
116
|
+
controller.state.grounded = false;
|
|
117
|
+
|
|
118
|
+
// Body is suspended by the hands; no striding feet, head near
|
|
119
|
+
// the hands gripping the edge. L2 reads posture to gate gait
|
|
120
|
+
// and set eye height.
|
|
121
|
+
controller.state.posture = FirstPersonPosture.Hang;
|
|
122
|
+
|
|
123
|
+
controller.signals.onLedgeGrab.send1({
|
|
124
|
+
ledgeHeight: this._edgeY - controller.pose.rootPosition.y,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
canInterrupt() {
|
|
129
|
+
// Wall-run / wall-jump can preempt if their conditions
|
|
130
|
+
// somehow hold (unusual mid-hang). Higher-priority abilities
|
|
131
|
+
// shouldn't be blocked.
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
tick(controller, runtime, bodyTransform, dt, _system) {
|
|
136
|
+
const cfg = controller.config.ledgeGrab;
|
|
137
|
+
const sensors = runtime.sensors;
|
|
138
|
+
|
|
139
|
+
// Re-assert posture each tick (defence against any layer
|
|
140
|
+
// resetting it before L2 reads).
|
|
141
|
+
controller.state.posture = FirstPersonPosture.Hang;
|
|
142
|
+
// Body is parked against the wall under the ledge — no lean.
|
|
143
|
+
runtime.leanTargetRad = 0;
|
|
144
|
+
|
|
145
|
+
// -- Exit: lost the ledge (shuffled past the edge, ledge ended).
|
|
146
|
+
if (!sensors.ledgeAhead.hit) {
|
|
147
|
+
controller.signals.onLedgeRelease.send1({ reason: "shuffle-off" });
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// -- Exit: jump rising-edge → mantle-up. Apply small upward
|
|
152
|
+
// velocity so the next tick's mantle.canActivate finds an
|
|
153
|
+
// obstacleAhead + ledgeAhead at the right relative height.
|
|
154
|
+
// (On a top too thin to STAND on, mantle is gated, so this currently
|
|
155
|
+
// just bumps you up and re-grabs — a clean "pull up & OVER" there
|
|
156
|
+
// needs a scripted vault, tracked as a follow-up.)
|
|
157
|
+
if (controller.intent.jump && !runtime.prevJumpHeld) {
|
|
158
|
+
runtime.velocityY = runtime.jumpInitialVy * cfg.mantleUpUpFactor;
|
|
159
|
+
runtime.prevJumpHeld = true;
|
|
160
|
+
runtime.midJump = true;
|
|
161
|
+
controller.state.isAscending = true;
|
|
162
|
+
controller.signals.onLedgeRelease.send1({ reason: "mantle-up" });
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// -- Exit: back-intent → drop. Zero velocity (let gravity take over
|
|
167
|
+
// on the next tick).
|
|
168
|
+
if (controller.intent.move.y < -0.1) {
|
|
169
|
+
controller.signals.onLedgeRelease.send1({ reason: "drop" });
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// -- Exit: crouch → drop.
|
|
174
|
+
if (controller.intent.crouch) {
|
|
175
|
+
controller.signals.onLedgeRelease.send1({ reason: "drop" });
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// -- Exit: exertion saturated → slip.
|
|
180
|
+
if (controller.state.exertion >= 1.0) {
|
|
181
|
+
controller.signals.onLedgeRelease.send1({ reason: "slip" });
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// -- Hold: snap to hang position, zero velocity, tick exertion.
|
|
186
|
+
// Hang just OUTSIDE the wall face, gripping the top edge: the body
|
|
187
|
+
// centre sits a capsule radius (+ a small face gap) out from the face
|
|
188
|
+
// along its outward normal. Anchoring on the wall — not the body's
|
|
189
|
+
// facing — keeps the body clear of the wall even when the ledge was
|
|
190
|
+
// reached at an oblique angle (e.g. off a wall-run into the wall),
|
|
191
|
+
// where a facing-relative offset would sink it into a thin wall.
|
|
192
|
+
const standoff = controller.config.body.radius + cfg.hangOffsetForward;
|
|
193
|
+
bodyTransform.position.set(
|
|
194
|
+
this._anchorX + this._nx * standoff,
|
|
195
|
+
this._edgeY + cfg.hangOffsetY,
|
|
196
|
+
this._anchorZ + this._nz * standoff,
|
|
197
|
+
);
|
|
198
|
+
runtime.velocityX = 0;
|
|
199
|
+
runtime.velocityY = 0;
|
|
200
|
+
runtime.velocityZ = 0;
|
|
201
|
+
controller.state.grounded = false;
|
|
202
|
+
|
|
203
|
+
// Exertion rises while hanging — fatigue. Mass-scaled like the
|
|
204
|
+
// rest of the exertion system.
|
|
205
|
+
controller.state.exertion = clamp(
|
|
206
|
+
controller.state.exertion + cfg.exertionRiseRate * dt
|
|
207
|
+
* runtime.massRatios.exertionRiseScale,
|
|
208
|
+
0, 1,
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Mantle.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/Mantle.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IAOQ,6CAA6C;IAC7C,WAAW;IACX,uCAAuC;IACvC,kBAAoB;IACpB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,cAAc;IAGlB,
|
|
1
|
+
{"version":3,"file":"Mantle.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/control/first-person/abilities/Mantle.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IAOQ,6CAA6C;IAC7C,WAAW;IACX,uCAAuC;IACvC,kBAAoB;IACpB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,cAAc;IAGlB,kEA+BC;IAED,gDAyCC;IAED,wBAGC;IAED,wFAwCC;IAED,oDAEC;CACJ;wBAjMuB,cAAc"}
|