Add air movement controls for player in App.tsx and related files
This commit is contained in:
@@ -10878,6 +10878,52 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="form-field form-field--toggle">
|
||||
<span className="label">Air Move: Jump</span>
|
||||
<input
|
||||
data-testid="player-start-movement-air-move-jump-enabled"
|
||||
type="checkbox"
|
||||
checked={
|
||||
playerStartMovementTemplateDraft.jump.moveWhileJumping
|
||||
}
|
||||
onChange={(event) =>
|
||||
commitPlayerStartMovementTemplateDraft(
|
||||
{
|
||||
jump: {
|
||||
moveWhileJumping:
|
||||
event.currentTarget.checked
|
||||
}
|
||||
},
|
||||
{
|
||||
schedule: true
|
||||
}
|
||||
)
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="form-field form-field--toggle">
|
||||
<span className="label">Air Move: Fall</span>
|
||||
<input
|
||||
data-testid="player-start-movement-air-move-fall-enabled"
|
||||
type="checkbox"
|
||||
checked={
|
||||
playerStartMovementTemplateDraft.jump.moveWhileFalling
|
||||
}
|
||||
onChange={(event) =>
|
||||
commitPlayerStartMovementTemplateDraft(
|
||||
{
|
||||
jump: {
|
||||
moveWhileFalling:
|
||||
event.currentTarget.checked
|
||||
}
|
||||
},
|
||||
{
|
||||
schedule: true
|
||||
}
|
||||
)
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="form-field form-field--toggle">
|
||||
<span className="label">Bunny Hopping</span>
|
||||
<input
|
||||
|
||||
@@ -1359,6 +1359,16 @@ function readPlayerStartMovementTemplate(value: unknown, label: string) {
|
||||
`${label}.jump.variableHeight`,
|
||||
preset.jump.variableHeight
|
||||
),
|
||||
moveWhileJumping: readOptionalBoolean(
|
||||
jump?.moveWhileJumping,
|
||||
`${label}.jump.moveWhileJumping`,
|
||||
preset.jump.moveWhileJumping
|
||||
),
|
||||
moveWhileFalling: readOptionalBoolean(
|
||||
jump?.moveWhileFalling,
|
||||
`${label}.jump.moveWhileFalling`,
|
||||
preset.jump.moveWhileFalling
|
||||
),
|
||||
maxHoldMs:
|
||||
jump?.maxHoldMs === undefined
|
||||
? preset.jump.maxHoldMs
|
||||
|
||||
@@ -1348,6 +1348,28 @@ function validatePlayerStartEntity(
|
||||
);
|
||||
}
|
||||
|
||||
if (!isBoolean(entity.movementTemplate?.jump?.moveWhileJumping)) {
|
||||
diagnostics.push(
|
||||
createDiagnostic(
|
||||
"error",
|
||||
"invalid-player-start-move-while-jumping",
|
||||
"Player Start move while jumping setting must be a boolean.",
|
||||
`${path}.movementTemplate.jump.moveWhileJumping`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isBoolean(entity.movementTemplate?.jump?.moveWhileFalling)) {
|
||||
diagnostics.push(
|
||||
createDiagnostic(
|
||||
"error",
|
||||
"invalid-player-start-move-while-falling",
|
||||
"Player Start move while falling setting must be a boolean.",
|
||||
`${path}.movementTemplate.jump.moveWhileFalling`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isBoolean(entity.movementTemplate?.jump?.bunnyHop)) {
|
||||
diagnostics.push(
|
||||
createDiagnostic(
|
||||
|
||||
@@ -15,7 +15,8 @@ import {
|
||||
type WorldSettings
|
||||
} from "./world-settings";
|
||||
|
||||
export const SCENE_DOCUMENT_VERSION = 33 as const;
|
||||
export const SCENE_DOCUMENT_VERSION = 34 as const;
|
||||
export const PLAYER_START_AIR_CONTROL_SCENE_DOCUMENT_VERSION = 34 as const;
|
||||
export const WHITEBOX_BEVEL_SCENE_DOCUMENT_VERSION = 32 as const;
|
||||
export const PLAYER_START_LOCOMOTION_CORE_SCENE_DOCUMENT_VERSION = 32 as const;
|
||||
export const PLAYER_START_MOVEMENT_TEMPLATE_SCENE_DOCUMENT_VERSION =
|
||||
|
||||
@@ -147,6 +147,8 @@ export interface PlayerStartJumpSettings {
|
||||
coyoteTimeMs: number;
|
||||
variableHeight: boolean;
|
||||
maxHoldMs: number;
|
||||
moveWhileJumping: boolean;
|
||||
moveWhileFalling: boolean;
|
||||
bunnyHop: boolean;
|
||||
bunnyHopBoost: number;
|
||||
}
|
||||
@@ -301,6 +303,8 @@ export const DEFAULT_PLAYER_START_JUMP_BUFFER_MS = 0;
|
||||
export const DEFAULT_PLAYER_START_COYOTE_TIME_MS = 0;
|
||||
export const DEFAULT_PLAYER_START_VARIABLE_JUMP_HEIGHT = false;
|
||||
export const DEFAULT_PLAYER_START_VARIABLE_JUMP_MAX_HOLD_MS = 160;
|
||||
export const DEFAULT_PLAYER_START_MOVE_WHILE_JUMPING = true;
|
||||
export const DEFAULT_PLAYER_START_MOVE_WHILE_FALLING = true;
|
||||
export const DEFAULT_PLAYER_START_BUNNY_HOP = false;
|
||||
export const DEFAULT_PLAYER_START_BUNNY_HOP_BOOST = 0.05;
|
||||
export const DEFAULT_PLAYER_START_SPRINT_SPEED_MULTIPLIER = 1.65;
|
||||
@@ -317,6 +321,8 @@ export const DEFAULT_PLAYER_START_JUMP_SETTINGS: PlayerStartJumpSettings = {
|
||||
coyoteTimeMs: DEFAULT_PLAYER_START_COYOTE_TIME_MS,
|
||||
variableHeight: DEFAULT_PLAYER_START_VARIABLE_JUMP_HEIGHT,
|
||||
maxHoldMs: DEFAULT_PLAYER_START_VARIABLE_JUMP_MAX_HOLD_MS,
|
||||
moveWhileJumping: DEFAULT_PLAYER_START_MOVE_WHILE_JUMPING,
|
||||
moveWhileFalling: DEFAULT_PLAYER_START_MOVE_WHILE_FALLING,
|
||||
bunnyHop: DEFAULT_PLAYER_START_BUNNY_HOP,
|
||||
bunnyHopBoost: DEFAULT_PLAYER_START_BUNNY_HOP_BOOST
|
||||
};
|
||||
@@ -335,6 +341,8 @@ export const RESPONSIVE_PLAYER_START_JUMP_SETTINGS: PlayerStartJumpSettings = {
|
||||
coyoteTimeMs: RESPONSIVE_PLAYER_START_COYOTE_TIME_MS,
|
||||
variableHeight: true,
|
||||
maxHoldMs: RESPONSIVE_PLAYER_START_VARIABLE_JUMP_MAX_HOLD_MS,
|
||||
moveWhileJumping: DEFAULT_PLAYER_START_MOVE_WHILE_JUMPING,
|
||||
moveWhileFalling: DEFAULT_PLAYER_START_MOVE_WHILE_FALLING,
|
||||
bunnyHop: DEFAULT_PLAYER_START_BUNNY_HOP,
|
||||
bunnyHopBoost: DEFAULT_PLAYER_START_BUNNY_HOP_BOOST
|
||||
};
|
||||
@@ -513,6 +521,8 @@ function clonePlayerStartJumpSettings(
|
||||
coyoteTimeMs: settings.coyoteTimeMs,
|
||||
variableHeight: settings.variableHeight,
|
||||
maxHoldMs: settings.maxHoldMs,
|
||||
moveWhileJumping: settings.moveWhileJumping,
|
||||
moveWhileFalling: settings.moveWhileFalling,
|
||||
bunnyHop: settings.bunnyHop,
|
||||
bunnyHopBoost: settings.bunnyHopBoost
|
||||
};
|
||||
@@ -751,6 +761,10 @@ export function createPlayerStartMovementTemplate(
|
||||
variableHeight:
|
||||
overrides.jump?.variableHeight ?? preset.jump.variableHeight,
|
||||
maxHoldMs: overrides.jump?.maxHoldMs ?? preset.jump.maxHoldMs,
|
||||
moveWhileJumping:
|
||||
overrides.jump?.moveWhileJumping ?? preset.jump.moveWhileJumping,
|
||||
moveWhileFalling:
|
||||
overrides.jump?.moveWhileFalling ?? preset.jump.moveWhileFalling,
|
||||
bunnyHop: overrides.jump?.bunnyHop ?? preset.jump.bunnyHop,
|
||||
bunnyHopBoost:
|
||||
overrides.jump?.bunnyHopBoost ?? preset.jump.bunnyHopBoost
|
||||
@@ -799,6 +813,14 @@ export function createPlayerStartMovementTemplate(
|
||||
jump.maxHoldMs,
|
||||
"Player Start variable jump max hold milliseconds"
|
||||
);
|
||||
assertBoolean(
|
||||
jump.moveWhileJumping,
|
||||
"Player Start move while jumping setting"
|
||||
);
|
||||
assertBoolean(
|
||||
jump.moveWhileFalling,
|
||||
"Player Start move while falling setting"
|
||||
);
|
||||
assertBoolean(jump.bunnyHop, "Player Start bunny hop setting");
|
||||
assertNonNegativeFiniteNumber(
|
||||
jump.bunnyHopBoost,
|
||||
@@ -867,6 +889,10 @@ export function inferPlayerStartMovementTemplateKind(
|
||||
createPlayerStartMovementTemplate({ kind: presetKind }).jump.variableHeight &&
|
||||
candidate.jump.maxHoldMs ===
|
||||
createPlayerStartMovementTemplate({ kind: presetKind }).jump.maxHoldMs &&
|
||||
candidate.jump.moveWhileJumping ===
|
||||
createPlayerStartMovementTemplate({ kind: presetKind }).jump.moveWhileJumping &&
|
||||
candidate.jump.moveWhileFalling ===
|
||||
createPlayerStartMovementTemplate({ kind: presetKind }).jump.moveWhileFalling &&
|
||||
candidate.jump.bunnyHop ===
|
||||
createPlayerStartMovementTemplate({ kind: presetKind }).jump.bunnyHop &&
|
||||
candidate.jump.bunnyHopBoost ===
|
||||
@@ -923,6 +949,8 @@ export function arePlayerStartMovementTemplatesEqual(
|
||||
left.jump.coyoteTimeMs === right.jump.coyoteTimeMs &&
|
||||
left.jump.variableHeight === right.jump.variableHeight &&
|
||||
left.jump.maxHoldMs === right.jump.maxHoldMs &&
|
||||
left.jump.moveWhileJumping === right.jump.moveWhileJumping &&
|
||||
left.jump.moveWhileFalling === right.jump.moveWhileFalling &&
|
||||
left.jump.bunnyHop === right.jump.bunnyHop &&
|
||||
left.jump.bunnyHopBoost === right.jump.bunnyHopBoost &&
|
||||
left.sprint.speedMultiplier === right.sprint.speedMultiplier &&
|
||||
|
||||
@@ -63,6 +63,8 @@ function cloneRuntimePlayerMovement(
|
||||
coyoteTimeMs: movement.jump.coyoteTimeMs,
|
||||
variableHeight: movement.jump.variableHeight,
|
||||
maxHoldMs: movement.jump.maxHoldMs,
|
||||
moveWhileJumping: movement.jump.moveWhileJumping,
|
||||
moveWhileFalling: movement.jump.moveWhileFalling,
|
||||
bunnyHop: movement.jump.bunnyHop,
|
||||
bunnyHopBoost: movement.jump.bunnyHopBoost
|
||||
},
|
||||
|
||||
@@ -239,6 +239,18 @@ function computePlanarSpeedFromDisplacement(
|
||||
return Math.hypot(displacement.x, displacement.z) / dt;
|
||||
}
|
||||
|
||||
function clearPlanarMovementInput(
|
||||
input: PlayerStartActionInputState
|
||||
): PlayerStartActionInputState {
|
||||
return {
|
||||
...input,
|
||||
moveForward: 0,
|
||||
moveBackward: 0,
|
||||
moveLeft: 0,
|
||||
moveRight: 0
|
||||
};
|
||||
}
|
||||
|
||||
function isWaterLocomotionMode(
|
||||
locomotionMode: RuntimeLocomotionMode | null | undefined
|
||||
): boolean {
|
||||
@@ -480,6 +492,17 @@ export function stepPlayerLocomotion(
|
||||
coyoteTimeRemainingMs = 0;
|
||||
}
|
||||
|
||||
const airMovementAllowed =
|
||||
currentlyGrounded ||
|
||||
jumpTriggered ||
|
||||
currentSwimmableWater ||
|
||||
(options.verticalVelocity > VERTICAL_ASCENT_EPSILON
|
||||
? options.movement.jump.moveWhileJumping
|
||||
: options.movement.jump.moveWhileFalling);
|
||||
const planarInput = airMovementAllowed
|
||||
? options.input
|
||||
: clearPlanarMovementInput(options.input);
|
||||
|
||||
const requestedPlanarSpeed =
|
||||
activeShape.mode !== "none" && !currentSwimmableWater
|
||||
? jumpTriggered
|
||||
@@ -490,7 +513,7 @@ export function stepPlayerLocomotion(
|
||||
: groundedRequestedPlanarSpeed;
|
||||
const planarMotionFromInput = computePlanarMotion(
|
||||
options.movementYawRadians,
|
||||
options.input,
|
||||
planarInput,
|
||||
requestedPlanarSpeed,
|
||||
options.dt
|
||||
);
|
||||
|
||||
@@ -285,6 +285,8 @@ function clonePlayerStartJumpSettings(
|
||||
coyoteTimeMs: jump.coyoteTimeMs,
|
||||
variableHeight: jump.variableHeight,
|
||||
maxHoldMs: jump.maxHoldMs,
|
||||
moveWhileJumping: jump.moveWhileJumping,
|
||||
moveWhileFalling: jump.moveWhileFalling,
|
||||
bunnyHop: jump.bunnyHop,
|
||||
bunnyHopBoost: jump.bunnyHopBoost
|
||||
};
|
||||
|
||||
@@ -77,6 +77,8 @@ function cloneRuntimePlayerMovement(
|
||||
coyoteTimeMs: movement.jump.coyoteTimeMs,
|
||||
variableHeight: movement.jump.variableHeight,
|
||||
maxHoldMs: movement.jump.maxHoldMs,
|
||||
moveWhileJumping: movement.jump.moveWhileJumping,
|
||||
moveWhileFalling: movement.jump.moveWhileFalling,
|
||||
bunnyHop: movement.jump.bunnyHop,
|
||||
bunnyHopBoost: movement.jump.bunnyHopBoost
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user