forked from phenom/healer-man
Release Healer Man 0.1.5
This commit is contained in:
1 parent
f4c9cf356c
commit
55cfd43d66
62 files changed
+3030
-153
No files matched your search
+74
-25
@@ -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]}
|
||||
|
||||
Reference in new issue
Block a user