Implement first-person climbing mechanics in navigation controller

This commit is contained in:
2026-04-30 00:17:35 +02:00
parent 653f3f4d32
commit e38f0501b7

View File

@@ -11,6 +11,14 @@ import {
resolvePlayerStartActionInputs, resolvePlayerStartActionInputs,
resolvePlayerStartLookInput, resolvePlayerStartLookInput,
} from "./player-input-bindings"; } from "./player-input-bindings";
import {
CLIMB_INPUT_ACTIVE_THRESHOLD,
CLIMB_SPEED_METERS_PER_SECOND,
computeClimbPlaneMovement,
shouldEnterClimbing,
shouldExitClimbing,
type RuntimePlayerClimbSurface
} from "./player-climbing";
import { import {
createIdleRuntimeLocomotionState, createIdleRuntimeLocomotionState,
stepPlayerLocomotion stepPlayerLocomotion
@@ -121,6 +129,8 @@ export class FirstPersonNavigationController implements NavigationController {
private jumpBufferRemainingMs = 0; private jumpBufferRemainingMs = 0;
private coyoteTimeRemainingMs = 0; private coyoteTimeRemainingMs = 0;
private jumpHoldRemainingMs = 0; private jumpHoldRemainingMs = 0;
private climbSurface: RuntimePlayerClimbSurface | null = null;
private climbLatchBlocked = false;
activate(ctx: RuntimeControllerContext): void { activate(ctx: RuntimeControllerContext): void {
this.context = ctx; this.context = ctx;
@@ -225,6 +235,8 @@ export class FirstPersonNavigationController implements NavigationController {
this.jumpBufferRemainingMs = 0; this.jumpBufferRemainingMs = 0;
this.coyoteTimeRemainingMs = 0; this.coyoteTimeRemainingMs = 0;
this.jumpHoldRemainingMs = 0; this.jumpHoldRemainingMs = 0;
this.climbSurface = null;
this.climbLatchBlocked = false;
this.previousTelemetry = null; this.previousTelemetry = null;
ctx.setRuntimeMessage(null); ctx.setRuntimeMessage(null);
ctx.setPlayerControllerTelemetry(null); ctx.setPlayerControllerTelemetry(null);
@@ -267,6 +279,8 @@ export class FirstPersonNavigationController implements NavigationController {
this.jumpBufferRemainingMs = 0; this.jumpBufferRemainingMs = 0;
this.coyoteTimeRemainingMs = 0; this.coyoteTimeRemainingMs = 0;
this.jumpHoldRemainingMs = 0; this.jumpHoldRemainingMs = 0;
this.climbSurface = null;
this.climbLatchBlocked = false;
} }
update(dt: number): void { update(dt: number): void {
@@ -297,6 +311,12 @@ export class FirstPersonNavigationController implements NavigationController {
); );
} }
if (
this.stepClimbing(dt, inputState, playerMovement, this.yawRadians)
) {
return;
}
const locomotionStep = stepPlayerLocomotion( const locomotionStep = stepPlayerLocomotion(
{ {
dt, dt,
@@ -397,6 +417,8 @@ export class FirstPersonNavigationController implements NavigationController {
this.jumpBufferRemainingMs = 0; this.jumpBufferRemainingMs = 0;
this.coyoteTimeRemainingMs = 0; this.coyoteTimeRemainingMs = 0;
this.jumpHoldRemainingMs = 0; this.jumpHoldRemainingMs = 0;
this.climbSurface = null;
this.climbLatchBlocked = false;
this.inWaterVolume = false; this.inWaterVolume = false;
this.inFogVolume = false; this.inFogVolume = false;
this.updateCameraTransform(); this.updateCameraTransform();