From b1b200e5d2aabaaa524f4e5852f9adf126f63a11 Mon Sep 17 00:00:00 2001 From: Tom Boullay Date: Mon, 11 May 2026 13:09:50 +0200 Subject: [PATCH] update: lock player movement during repair --- src/world/player/PlayerController.tsx | 60 +++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/src/world/player/PlayerController.tsx b/src/world/player/PlayerController.tsx index 6467d84..2f045dd 100644 --- a/src/world/player/PlayerController.tsx +++ b/src/world/player/PlayerController.tsx @@ -24,6 +24,8 @@ import { PLAYER_XZ_DAMPING_FACTOR, } from "@/data/player/playerConfig"; import { InteractionManager } from "@/managers/InteractionManager"; +import { useGameStore } from "@/managers/stores/useGameStore"; +import type { MissionStep } from "@/types/gameplay/repairMission"; import type { Vector3Tuple } from "@/types/three/three"; type Keys = { @@ -73,11 +75,39 @@ function setMovementKey(keys: Keys, key: string, pressed: boolean): boolean { } } +function isRepairMovementLocked(step: MissionStep): boolean { + return ( + step === "inspected" || + step === "fragmented" || + step === "scanning" || + step === "repairing" || + step === "reassembling" + ); +} + +function useRepairMovementLocked(): boolean { + return useGameStore((state) => { + switch (state.mainState) { + case "bike": + return isRepairMovementLocked(state.bike.currentStep); + case "pylone": + return isRepairMovementLocked(state.pylone.currentStep); + case "ferme": + return isRepairMovementLocked(state.ferme.currentStep); + case "intro": + case "outro": + return false; + } + }); +} + export function PlayerController({ octree, spawnPosition, }: PlayerControllerProps): null { const camera = useThree((state) => state.camera); + const movementLocked = useRepairMovementLocked(); + const movementLockedRef = useRef(movementLocked); const keys = useRef({ ...DEFAULT_KEYS }); const velocity = useRef(new THREE.Vector3()); const onFloor = useRef(false); @@ -104,16 +134,36 @@ export function PlayerController({ camera.position.copy(capsule.current.end); }, [camera, spawnPosition]); + useEffect(() => { + movementLockedRef.current = movementLocked; + + if (!movementLocked) return; + + keys.current = { ...DEFAULT_KEYS }; + wantsJump.current = false; + velocity.current.setX(0); + velocity.current.setZ(0); + }, [movementLocked]); + useEffect(() => { const interaction = InteractionManager.getInstance(); const handleKeyDown = (event: KeyboardEvent): void => { if (setMovementKey(keys.current, event.key, true)) { + if (movementLockedRef.current) { + keys.current = { ...DEFAULT_KEYS }; + } event.preventDefault(); return; } if (event.key === JUMP_KEY) { + if (movementLockedRef.current) { + wantsJump.current = false; + event.preventDefault(); + return; + } + wantsJump.current = true; event.preventDefault(); return; @@ -172,10 +222,12 @@ export function PlayerController({ } _wishDir.set(0, 0, 0); - if (keys.current.forward) _wishDir.add(_forward); - if (keys.current.backward) _wishDir.sub(_forward); - if (keys.current.left) _wishDir.sub(_right); - if (keys.current.right) _wishDir.add(_right); + if (!movementLocked) { + if (keys.current.forward) _wishDir.add(_forward); + if (keys.current.backward) _wishDir.sub(_forward); + if (keys.current.left) _wishDir.sub(_right); + if (keys.current.right) _wishDir.add(_right); + } if (_wishDir.lengthSq() > 0) _wishDir.normalize(); const accel = onFloor.current