feat(repair): introduce focus bubble shroud for repair mini-game

Adds a dark expanding sphere around the repair model when the player
enters the immersive repair phases (fragmented / scanning / repairing /
reassembling). The bubble grows from 0 to 10m using GSAP expo.out over
2.5s and reverses on focus end, visually isolating the player from the
surrounding map.

- New useRepairFocusStore tracks active state + world center.
- New RepairFocusBubble renders a BackSide sphere shell + a soft cocoon
  decor pass (grid floor + directional light + ambient) inside.
- RepairGame drives setFocus from its lifecycle effect.
- Mounted in both GameStageContent and TestMap so behaviour matches in
  the production scene and the physics test scene.

Also drops the now-unused EBIKE_CONFIG_KEY constant in
GameStageContent.tsx (leftover from a previous remount-key strategy).
This commit is contained in:
Tom Boullay
2026-06-02 22:57:18 +02:00
parent be5d03a30c
commit 220a661d6d
5 changed files with 193 additions and 7 deletions
@@ -0,0 +1,25 @@
import { create } from "zustand";
import type { Vector3Tuple } from "@/types/three/three";
/**
* Tracks whether a repair mini-game is currently in its "focused" phase
* (fragmented / scanning / repairing / reassembling). When active, a dark
* sphere expands around the repair model to visually isolate the player
* from the rest of the map. The store also exposes the world-space center
* of the bubble so map content can dim/hide content outside it if needed.
*/
interface RepairFocusStore {
active: boolean;
center: Vector3Tuple;
setFocus: (active: boolean, center?: Vector3Tuple) => void;
}
export const useRepairFocusStore = create<RepairFocusStore>((set) => ({
active: false,
center: [0, 0, 0],
setFocus: (active, center) =>
set((state) => ({
active,
center: center ?? state.center,
})),
}));