chore: address code quality audit findings
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled

This commit is contained in:
Tom Boullay
2026-05-28 08:31:42 +02:00
parent 947025cbf5
commit d654565f87
73 changed files with 890 additions and 1457 deletions
+11 -20
View File
@@ -509,12 +509,7 @@ Gère :
- menu ouvert/fermé ;
- volumes ;
- sous-titres ;
- langue ;
- `repairRuntime`.
Piège :
`repairRuntime` est stocké et affiché, mais pas encore utilisé par `RepairGame`.
- langue.
### Subtitle store
@@ -531,16 +526,15 @@ Phrase simple :
Si on te pose une question précise, réponds vrai.
| Sujet | Réponse honnête |
| ------------------------- | ------------------------------------------------------------------------ |
| Lock mouvement réparation | Le hook existe mais retourne `false`, donc pas actif actuellement. |
| `repairRuntime` JS/Python | Le choix est stocké dans settings, mais pas consommé par le repair game. |
| Old debug flags | `noMusic`, `noMap`, `noDialogues`, etc. ne sont plus branchés. |
| Player physics | Le joueur n'est pas Rapier, il utilise capsule + octree. |
| Collision map | L'octree vient de nodes dédiés, actuellement `terrain`. |
| Editor save | Ce sont des endpoints Vite dev, pas une API de prod. |
| Cinematics | `GameCinematics` est monté seulement pendant `outro` dans `World`. |
| Hand tracking depth | Le `z` MediaPipe est relatif, pas une vraie profondeur monde stable. |
| Sujet | Réponse honnête |
| ------------------------- | -------------------------------------------------------------------- |
| Lock mouvement réparation | Les étapes repair actives bloquent le déplacement via le hook dédié. |
| Old debug flags | `noMusic`, `noMap`, `noDialogues`, etc. ne sont plus branchés. |
| Player physics | Le joueur n'est pas Rapier, il utilise capsule + octree. |
| Collision map | L'octree vient de nodes dédiés, actuellement `terrain`. |
| Editor save | Ce sont des endpoints Vite dev, pas une API de prod. |
| Cinematics | `GameCinematics` est monté seulement pendant `outro` dans `World`. |
| Hand tracking depth | Le `z` MediaPipe est relatif, pas une vraie profondeur monde stable. |
## Si l'évaluateur ouvre un fichier au hasard
@@ -833,8 +827,6 @@ Pour réutiliser le même flow sur plusieurs missions et garder les variations d
### Qu'est-ce qui est incomplet ?
- pas de vrai `GameManager` global ;
- lock mouvement réparation désactivé ;
- `repairRuntime` pas consommé ;
- editor save uniquement en dev ;
- hand tracking encore approximatif sur profondeur et smoothing.
@@ -869,8 +861,7 @@ Fichiers à avoir en tête :
Réponses pièges à réviser :
- lock mouvement repair désactivé actuellement ;
- `repairRuntime` pas consommé ;
- lock mouvement repair actif sur les étapes dédiées ;
- player pas Rapier ;
- save editor pas production ;
- old boot flags non branchés.
-2
View File
@@ -51,8 +51,6 @@ public/models/electricienne_animated/model.gltf
with the `Dance` animation.
`src/hooks/animation/useCharacterAnimation.ts` is a hook-level alternative for components that need to own their group ref and animation controls directly.
## GLTF Reuse
Use `useClonedObject` when a GLTF scene is reused by a component instance. It memoizes `scene.clone(true)` and keeps clone creation out of render churn.
+10 -33
View File
@@ -52,7 +52,7 @@ intro → start-intro → naming → bienvenue → star-move → mission2 → se
- **Actions** :
- Stocke `activityCity: false` dans le store Zustand
- Joue l'audio `alertCentral`
- **État** : Les objets avec hook `useActivityCity()` détectent le changement et jouent leurs animations
- **État** : Les systèmes lisent `activityCity` depuis `useGameStore` pour adapter leur comportement
- **Attente** : Le joueur atteint la zone de trigger pour `searching_problem`
### 7. `searching_problem`
@@ -81,15 +81,13 @@ intro → start-intro → naming → bienvenue → star-move → mission2 → se
| Fichier | Rôle |
| --------------------------------------- | --------------------------------------------------------- |
| `src/stores/gameStore.ts` | Store Zustand pour l'état global du jeu |
| `src/stateManager/GameStepManager.ts` | Synchronise avec le store Zustand |
| `src/managers/stores/useGameStore.ts` | Store Zustand pour l'état global du jeu |
| `src/components/game/GameFlow.tsx` | Gère les transitions automatiques et la lecture audio |
| `src/components/ui/IntroUI.tsx` | Affiche l'input pour le prénom et le message de bienvenue |
| `src/components/zone/ZoneDetection.tsx` | Détecte quand le joueur entre dans une zone |
| `src/components/3d/CentralObject.tsx` | Objet interactif "central" pour la mission 2 |
| `src/world/GameStageContent.tsx` | Monte les contenus de mission dans la scène |
| `src/data/audioConfig.ts` | Chemins des fichiers audio |
| `src/data/zones.ts` | Configuration des zones de transition |
| `src/hooks/useActivityCity.ts` | Hook pour détecter le changement d'activité de la ville |
---
@@ -134,35 +132,14 @@ export const ZONES: Zone[] = [
## Store Zustand
```typescript
// src/stores/gameStore.ts
// src/managers/stores/useGameStore.ts
interface GameState {
step: GameStep;
activityCity: boolean;
playerName: string;
canMove: boolean;
setStep: (step: GameStep) => void;
setActivityCity: (value: boolean) => void;
setPlayerName: (name: string) => void;
setCanMove: (canMove: boolean) => void;
}
```
---
## Hooks personnalisés
### useActivityCity
Permet aux objets 3D de réagir au changement d'activité de la ville :
```typescript
import { useActivityCity } from "@/hooks/useActivityCity";
function MyAnimatedObject() {
const activityCity = useActivityCity(); // true par défaut, false en mission2
// L'animation se déclenche quand activityCity change à false
// Utiliser useEffect pour réagir au changement
mainState: MainGameState;
missionFlow: {
activityCity: boolean;
canMove: boolean;
playerName: string;
};
}
```
+1 -8
View File
@@ -160,7 +160,6 @@ State:
- `dialogueVolume`
- `subtitlesEnabled`
- `subtitleLanguage`
- `repairRuntime`
Audio setters clamp values between `0` and `1`, then call:
@@ -170,8 +169,6 @@ AudioManager.getInstance().setCategoryVolume(category, nextVolume);
This keeps UI state and browser audio state synchronized.
Current caveat: `repairRuntime` is stored and displayed in the settings menu, but the repair game does not consume it yet. Treat it as a staged architecture hook rather than an active runtime switch.
## Subtitle Store
`useSubtitleStore` is intentionally tiny.
@@ -222,13 +219,11 @@ Current overlays:
- `GameStateDebugPanel`: compact debug UI for viewing and switching main/sub states
- `Crosshair`: player aiming helper
- `InteractPrompt`: interaction prompt
- `RepairMovementLockIndicator`: indicator intended for repair movement lock
- `RepairMovementLockIndicator`: indicator shown while repair steps lock movement
- `HandTrackingVisualizer`: hand tracking SVG fallback/debug visualization
- `Subtitles`: active dialogue subtitle overlay
- `GameSettingsMenu`: options menu and settings controls
Current caveat: `useRepairMovementLocked()` returns `false` immediately on the current branch, so the movement-lock rule and indicator exist but are disabled at runtime.
## Regression Rules
- Do not store per-frame values in Zustand.
@@ -241,6 +236,4 @@ Current caveat: `useRepairMovementLocked()` returns `false` immediately on the c
## Next Steps
- Decide whether `repairRuntime` should be removed, implemented, or clearly labeled as experimental.
- Re-enable or remove the repair movement-lock rule depending on desired gameplay.
- Move broader mission orchestration into a clearer layer if intro, mission, dialogue, and cinematic branching grows.
+2 -2
View File
@@ -80,9 +80,9 @@ This document lists the user-visible and developer-facing features implemented i
- Fragmentation through repair-case trigger or two-fists hand gesture
- Exploded model visualization through `ExplodableModel`
- Scan visual that steps through exploded parts
- Broken-part detection by configured `nodeName`, with fallback to first scanned parts
- Broken-part detection by configured `nodeName`, with diagnostics when configured parts are missing
- Persistent broken-part highlight and broken-part prompt after discovery
- Grabbable replacement part choices, including decoys
- Grabbable replacement part choices, including distractor parts
- Grabbable broken parts that must be deposited back into the case
- Snap-to-placeholder placement
- Correct-part, wrong-part, and stored-part visual feedback
+2 -2
View File
@@ -33,11 +33,11 @@ For implementation details, see `docs/technical/repair-game.md`.
In `waiting`, the active mission renders its repair object and the `interagir.webm` prompt in the game scene. The interaction uses the shared focus/raycast interaction system, so the player still gets the normal `E` prompt.
When the player inspects the object, `RepairGame` writes `inspected` through the generic mission store action. The repair case then appears from the mission config with a small pop animation. When the player is close enough, the case model floats upward and rotates gently to signal interactivity. The codebase also contains a shared repair movement-lock hook and HTML indicator, but `useRepairMovementLocked()` currently returns `false`, so movement remains available during the repair flow on the current branch.
When the player inspects the object, `RepairGame` writes `inspected` through the generic mission store action. The repair case then appears from the mission config with a small pop animation. When the player is close enough, the case model floats upward and rotates gently to signal interactivity. The shared repair movement-lock hook and HTML indicator keep movement disabled during active repair steps.
In `inspected`, `RepairGame` can also move to `fragmented`. Keyboard input goes through the shared focus/raycast interaction system on the repair case, so the player must be close enough and aim at the case before pressing `E`. The hand-tracking path still uses a two-fists hold gesture and is state-based, so it does not depend on being inside a local object interaction radius.
In `fragmented`, the repair object is rendered with `ExplodableModel`, then automatically advances to `scanning`. In `scanning`, the exploded model remains visible, a blue scan visual moves from part to part, and a red halo/wire marker plus the configured broken UI video stay attached to configured broken parts after the scanner reaches them. The scan can match a specific `nodeName` when mission data provides one, otherwise it falls back to the first scanned parts as placeholder broken parts. In `repairing`, the case opens in a larger focused transform, `RepairCaseModel` traverses the case GLTF for empty nodes named `placeholder_*`, several grabbable replacement parts appear on those placeholder positions, and releasing a part near a placeholder snaps it into place with a short GSAP animation. Scanned broken parts are also rendered as grabbable objects and must be deposited into a compatible placeholder before the final install target validates. If `brokenParts[].placeholderName` is configured, that broken part snaps only to the matching placeholder; otherwise it can use any available placeholder. If the current case asset has no placeholder nodes, the flow keeps using fallback focus positions. Replacement parts show green or red placement feedback after snapping, broken parts show stored feedback after deposit, and the install target gives a short blocked feedback if the player tries to validate too early. The install target only validates when the configured correct replacement part is placed and all scanned broken parts have been deposited. In `reassembling`, the exploded model animates back into its assembled position with green completion particles before the flow moves to `done`. In `done`, the repaired object remains visible with a completion target; validating closes the repair case first, then plays the case exit animation before advancing the global mission progression.
In `fragmented`, the repair object is rendered with `ExplodableModel`, then automatically advances to `scanning`. In `scanning`, the exploded model remains visible, a blue scan visual moves from part to part, and a red halo/wire marker plus the configured broken UI video stay attached to configured broken parts after the scanner reaches them. The scan matches configured broken parts by `nodeName` and reports diagnostics when a configured node is missing. In `repairing`, the case opens in a larger focused transform, `RepairCaseModel` traverses the case GLTF for empty nodes named `placeholder_*`, several grabbable replacement parts appear on those slot positions, and releasing a part near a slot snaps it into place with a short GSAP animation. Scanned broken parts are also rendered as grabbable objects and must be deposited into a compatible slot before the final install target validates. If `brokenParts[].caseSlotName` is configured, that broken part snaps only to the matching slot; otherwise it can use any available slot. If the current case asset has no slot nodes, the flow keeps using fallback focus positions and logs the fallback. Replacement parts show green or red placement feedback after snapping, broken parts show stored feedback after deposit, and the install target gives a short blocked feedback if the player tries to validate too early. The install target only validates when the configured correct replacement part is placed and all scanned broken parts have been deposited. In `reassembling`, the exploded model animates back into its assembled position with green completion particles before the flow moves to `done`. In `done`, the repaired object remains visible with a completion target; validating closes the repair case first, then plays the case exit animation before advancing the global mission progression.
The mission config now carries the mission-specific variations. `bike` repairs one cooling core, `pylone` scans and stores both the lamp relay and a damaged panel with slower scan/reassembly timing, and `ferme` scans and stores an irrigation pump plus humidity sensor with faster scan/reassembly timing.