Release Healer Man 0.1.5

This commit is contained in:
phenom committed 2026-08-18 16:22:19 -04:00
1 parent f4c9cf356c
commit 55cfd43d66
62 files changed
+3030 -153

No files matched your search

+74 -25
View File
@@ -50,6 +50,13 @@ import {
updatePlayerJumpTiming,
type CharacterVerticalMotion,
} from "../game/playerJump";
import {
PLAYER_CHARACTER_CONTROLLER_OFFSET,
PLAYER_GROUND_STICK_VELOCITY,
airbornePlayerVerticalVelocity,
configurePlayerCharacterController,
playerFrameDeltaSeconds,
} from "../game/playerMovement";
import { activeManastormStageAssetPackage } from "../game/manastormStageLoader";
import { useGameStore } from "../game/store";
@@ -85,11 +92,13 @@ interface PlayerControllerProps extends PlayerRigRefs {
function placeAtActiveSpawn(body: RapierRigidBody, orbit: OrbitState): void {
const spawn = useGameStore.getState().activeSpawn;
body.setTranslation({
const translation = {
x: spawn.footPosition[0],
y: spawn.footPosition[1] + PLAYER_CENTER_HEIGHT,
z: spawn.footPosition[2],
}, true);
};
body.setTranslation(translation, true);
body.setNextKinematicTranslation(translation);
body.setLinvel({ x: 0, y: 0, z: 0 }, true);
body.setAngvel({ x: 0, y: 0, z: 0 }, true);
orbit.yaw = spawn.yaw;
@@ -122,8 +131,19 @@ function PlayerController({
() => new rapier.Ray({ x: 0, y: 0, z: 0 }, { x: 0, y: -1, z: 0 }),
[rapier],
);
const characterController = useMemo(
() => configurePlayerCharacterController(
world.createCharacterController(PLAYER_CHARACTER_CONTROLLER_OFFSET),
),
[world],
);
const jumpTimingRef = useRef(createPlayerJumpTiming());
const verticalPresentationTimingRef = useRef(createCharacterVerticalPresentationTiming());
const verticalVelocityRef = useRef(0);
useEffect(() => () => {
world.removeCharacterController(characterController);
}, [characterController, world]);
useEffect(() => {
if (bodyRef.current) placeAtActiveSpawn(bodyRef.current, orbitRef.current);
@@ -131,6 +151,7 @@ function PlayerController({
clearJumpRequest();
jumpTimingRef.current = createPlayerJumpTiming(performance.now());
verticalPresentationTimingRef.current = createCharacterVerticalPresentationTiming();
verticalVelocityRef.current = 0;
verticalMotionRef.current = "grounded";
}, [bodyRef, orbitRef, resetRevision, spawn, verticalMotionRef]);
@@ -160,7 +181,6 @@ function PlayerController({
orbit.pitch = clampCameraPitch(orbit.pitch + snapshot.lookY * delta * 1.55);
}
const velocity = body.linvel();
const translation = body.translation();
if (![translation.x, translation.y, translation.z].every(Number.isFinite)) {
placeAtActiveSpawn(body, orbit);
@@ -181,20 +201,25 @@ function PlayerController({
undefined,
body,
);
let grounded = velocity.y <= 0.5 && isWalkableGroundHit(groundHit, groundProbeLength);
const groundedBeforeMove = verticalVelocityRef.current <= 0.5
&& isWalkableGroundHit(groundHit, groundProbeLength);
const requestedAtMs = consumeJumpRequest();
const gameplayBlocked = paused || mapOpen || companionOpen || controlledUntil > Date.now();
const gameplayBlocked = paused
|| mapOpen
|| companionOpen
|| useCombatStore.getState().health <= 0
|| controlledUntil > Date.now();
if (gameplayBlocked) {
cancelBufferedPlayerJump(jumpTimingRef.current);
movingRef.current = false;
verticalMotionRef.current = updateCharacterVerticalPresentation(
verticalPresentationTimingRef.current,
grounded,
velocity.y,
groundedBeforeMove,
verticalVelocityRef.current,
nowMs,
false,
);
body.setLinvel({ x: 0, y: velocity.y, z: 0 }, true);
body.setNextKinematicTranslation(translation);
return;
}
if (requestedAtMs !== null) bufferPlayerJump(jumpTimingRef.current, requestedAtMs);
@@ -202,11 +227,42 @@ function PlayerController({
const shouldJump = updatePlayerJumpTiming(
jumpTimingRef.current,
nowMs,
grounded,
velocity.y,
groundedBeforeMove,
verticalVelocityRef.current,
);
const verticalVelocity = shouldJump ? PLAYER_JUMP_VELOCITY : velocity.y;
if (shouldJump) grounded = false;
const movementDeltaSeconds = playerFrameDeltaSeconds(delta);
let verticalVelocity = shouldJump
? PLAYER_JUMP_VELOCITY
: groundedBeforeMove
? PLAYER_GROUND_STICK_VELOCITY
: airbornePlayerVerticalVelocity(verticalVelocityRef.current, movementDeltaSeconds);
const [worldX, worldZ] = cameraRelativeMovement(
snapshot.moveX,
snapshot.moveForward,
orbit.yaw,
);
if (body.numColliders() === 0) return;
characterController.computeColliderMovement(
body.collider(0),
{
x: worldX * MOVE_SPEED * movementDeltaSeconds,
y: verticalVelocity * movementDeltaSeconds,
z: worldZ * MOVE_SPEED * movementDeltaSeconds,
},
rapier.QueryFilterFlags.EXCLUDE_SENSORS | rapier.QueryFilterFlags.EXCLUDE_DYNAMIC,
);
const computedMovement = characterController.computedMovement();
const nextTranslation = {
x: translation.x + computedMovement.x,
y: translation.y + computedMovement.y,
z: translation.z + computedMovement.z,
};
body.setNextKinematicTranslation(nextTranslation);
const grounded = !shouldJump && characterController.computedGrounded();
if (grounded && verticalVelocity <= 0) verticalVelocity = 0;
verticalVelocityRef.current = verticalVelocity;
verticalMotionRef.current = updateCharacterVerticalPresentation(
verticalPresentationTimingRef.current,
grounded,
@@ -215,13 +271,6 @@ function PlayerController({
shouldJump,
);
const [worldX, worldZ] = cameraRelativeMovement(
snapshot.moveX,
snapshot.moveForward,
orbit.yaw,
);
body.setLinvel({ x: worldX * MOVE_SPEED, y: verticalVelocity, z: worldZ * MOVE_SPEED }, true);
const moving = Math.hypot(worldX, worldZ) > 0.05;
movingRef.current = moving;
if (avatarRef.current && moving) {
@@ -235,11 +284,11 @@ function PlayerController({
: null;
const belowRecoveryPlane = activeManastormPackage
? isBelowManastormRecoveryPlane(
translation.y,
nextTranslation.y,
activeManastormPackage.anchors.map((anchor) => anchor.position[1]),
dungeon.bounds,
)
: isBelowDungeonRecoveryPlane(translation.y, dungeon.bounds);
: isBelowDungeonRecoveryPlane(nextTranslation.y, dungeon.bounds);
if (belowRecoveryPlane) {
useGameStore.getState().resetAtActiveSpawn();
return;
@@ -249,9 +298,9 @@ function PlayerController({
if (reportAccumulator.current >= 0.1) {
reportAccumulator.current = 0;
const footPosition: [number, number, number] = [
translation.x,
translation.y - PLAYER_CENTER_HEIGHT,
translation.z,
nextTranslation.x,
nextTranslation.y - PLAYER_CENTER_HEIGHT,
nextTranslation.z,
];
const distanceDelta = planarDistance(lastReported.current, footPosition);
useGameStore.getState().updatePlayerSnapshot({
@@ -268,7 +317,7 @@ function PlayerController({
<RigidBody
ref={bodyRef}
name="player-capsule"
type="dynamic"
type="kinematicPosition"
colliders={false}
canSleep={false}
enabledRotations={[false, false, false]}