add: configure mission-specific repair variants
This commit is contained in:
@@ -139,6 +139,8 @@ For repair missions, it mounts the reusable `RepairGame` component with a missio
|
||||
|
||||
`RepairGame` reads the active mission step from the store and writes transitions through generic actions such as `setMissionStep` and `completeMission`. This keeps the scene component small and avoids mission-specific branching inside the repair flow. The production repair flow currently supports `waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission` state transitions.
|
||||
|
||||
Mission-specific behavior stays in `src/data/gameplay/repairMissions.ts`: each mission can define its broken nodes, placeholder targets, scan duration, and reassembly duration without adding mission branches to `RepairGame`.
|
||||
|
||||
That means the scene can progressively move toward this pattern:
|
||||
|
||||
```tsx
|
||||
|
||||
@@ -30,7 +30,7 @@ This document lists features that are implemented in the current codebase.
|
||||
## Repair Gameplay
|
||||
|
||||
- Reusable production `RepairGame` mounted for `bike`, `pylone`, and `ferme` mission states
|
||||
- Repair mission config shared through `src/data/gameplay/repairMissions.ts`
|
||||
- Repair mission config shared through `src/data/gameplay/repairMissions.ts`, including per-mission broken nodes, placeholder targets, scan timing, and reassembly timing
|
||||
- Repair-game flow supports `waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission` with `.webm` prompts, repair case spawn/opening/exit, focused repair-case view, case placeholder traversal, snap-to-placeholder placement, broken-part deposit, `E`, two-fists hold input, exploded and inverse reassembly transitions, completion particles, per-part scan visuals, persistent red broken-part markers, centered broken-part UI videos, multiple grabbable replacement choices, correct-part install validation, and mission completion
|
||||
|
||||
## Audio
|
||||
|
||||
@@ -37,6 +37,8 @@ In `inspected`, `RepairGame` can also move to `fragmented`. The player can use t
|
||||
|
||||
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. 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 that 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.
|
||||
|
||||
## Key Files
|
||||
|
||||
- `src/world/GameStageContent.tsx` mounts production `RepairGame` instances for `bike`, `pylone`, and `ferme`.
|
||||
|
||||
@@ -14,6 +14,8 @@ export function RepairReassemblyStep({
|
||||
onComplete,
|
||||
}: RepairReassemblyStepProps): React.JSX.Element {
|
||||
const [split, setSplit] = useState(true);
|
||||
const reassemblySeconds =
|
||||
config.reassemblySeconds ?? REPAIR_REASSEMBLY_SECONDS;
|
||||
|
||||
useEffect(() => {
|
||||
const closeTimeoutId = window.setTimeout(() => {
|
||||
@@ -21,13 +23,13 @@ export function RepairReassemblyStep({
|
||||
}, 50);
|
||||
const completeTimeoutId = window.setTimeout(() => {
|
||||
onComplete();
|
||||
}, REPAIR_REASSEMBLY_SECONDS * 1000);
|
||||
}, reassemblySeconds * 1000);
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(closeTimeoutId);
|
||||
window.clearTimeout(completeTimeoutId);
|
||||
};
|
||||
}, [onComplete]);
|
||||
}, [onComplete, reassemblySeconds]);
|
||||
|
||||
return (
|
||||
<group>
|
||||
|
||||
@@ -260,7 +260,7 @@ function getPlaceholderTargets(
|
||||
|
||||
return REPLACEMENT_START_OFFSETS.map(
|
||||
(offset, index): RepairCasePlaceholder => ({
|
||||
name: `fallback_${index + 1}`,
|
||||
name: `placeholder_${index + 1}`,
|
||||
position: [
|
||||
REPAIR_CASE_FOCUS_POSITION[0] + offset[0],
|
||||
REPAIR_CASE_FOCUS_POSITION[1] + offset[1],
|
||||
|
||||
@@ -30,6 +30,7 @@ export function RepairScanSequence({
|
||||
const [parts, setParts] = useState<readonly ExplodedPart[]>([]);
|
||||
const [activePartIndex, setActivePartIndex] = useState(0);
|
||||
const activePart = parts[activePartIndex];
|
||||
const scanPartSeconds = config.scanPartSeconds ?? REPAIR_SCAN_PART_SECONDS;
|
||||
const brokenPartIndexes = getBrokenPartIndexes(parts, config.brokenParts);
|
||||
const visibleBrokenPartIndexes = brokenPartIndexes.filter(
|
||||
(partIndex) => partIndex <= activePartIndex,
|
||||
@@ -48,12 +49,12 @@ export function RepairScanSequence({
|
||||
|
||||
return nextIndex;
|
||||
});
|
||||
}, REPAIR_SCAN_PART_SECONDS * 1000);
|
||||
}, scanPartSeconds * 1000);
|
||||
|
||||
return () => {
|
||||
window.clearTimeout(timeoutId);
|
||||
};
|
||||
}, [activePartIndex, config, onComplete, parts]);
|
||||
}, [activePartIndex, config, onComplete, parts, scanPartSeconds]);
|
||||
|
||||
return (
|
||||
<group>
|
||||
|
||||
@@ -441,7 +441,7 @@ Ce document liste les fonctionnalités présentes dans le code actuel.
|
||||
## Gameplay de réparation
|
||||
|
||||
- \`RepairGame\` de production réutilisable monté pour les états de mission \`bike\`, \`pylone\` et \`ferme\`
|
||||
- Configuration de mission partagée via \`src/data/gameplay/repairMissions.ts\`
|
||||
- Configuration de mission partagée via \`src/data/gameplay/repairMissions.ts\`, avec nodes cassés, placeholders cibles, timing de scan et timing de réassemblage propres à chaque mission
|
||||
- Flow repair-game avec \`waiting -> inspected -> fragmented -> scanning -> repairing -> reassembling -> done -> next mission\`, prompts \`.webm\`, apparition/ouverture/sortie de la mallette, vue focalisée de la mallette, traverse des placeholders de mallette, placement avec snap vers placeholder, dépôt des pièces cassées, touche \`E\`, hold deux poings, transition de modèle explosé, réassemblage inverse avec particules, scan visuel par pièce, marqueur rouge persistant et vidéo UI centrée sur les pièces cassées, plusieurs choix de pièces grabbables, validation de la bonne pièce et complétion de mission
|
||||
|
||||
## Audio
|
||||
|
||||
@@ -24,7 +24,9 @@ export interface RepairMissionConfig {
|
||||
interactUiPath: string;
|
||||
brokenUiPath: string;
|
||||
case: RepairMissionCaseConfig;
|
||||
reassemblySeconds?: number;
|
||||
requiredReplacementPartId: string;
|
||||
scanPartSeconds?: number;
|
||||
brokenParts: readonly RepairMissionPartConfig[];
|
||||
replacementParts: readonly RepairMissionPartConfig[];
|
||||
}
|
||||
@@ -54,6 +56,8 @@ export const REPAIR_MISSIONS = {
|
||||
{
|
||||
id: "bike-cooling-core",
|
||||
label: "Cooling core",
|
||||
nodeName: "Cylinder",
|
||||
placeholderName: "placeholder_1",
|
||||
},
|
||||
],
|
||||
replacementParts: [
|
||||
@@ -77,17 +81,28 @@ export const REPAIR_MISSIONS = {
|
||||
pylone: {
|
||||
id: "pylone",
|
||||
label: "Power pylon",
|
||||
description: "Generic description",
|
||||
description:
|
||||
"Restore the pylon lamp relay and damaged panel before reconnecting the grid",
|
||||
modelPath: "/models/pylone/model.gltf",
|
||||
stageUiPath: "/assets/UI/centrale.webm",
|
||||
interactUiPath: REPAIR_INTERACT_UI_PATH,
|
||||
brokenUiPath: REPAIR_BROKEN_UI_PATH,
|
||||
case: DEFAULT_REPAIR_CASE,
|
||||
reassemblySeconds: 1.8,
|
||||
requiredReplacementPartId: "pylone-grid-relay-replacement",
|
||||
scanPartSeconds: 1.4,
|
||||
brokenParts: [
|
||||
{
|
||||
id: "pylone-grid-relay",
|
||||
label: "Grid relay",
|
||||
nodeName: "lampe",
|
||||
placeholderName: "placeholder_1",
|
||||
},
|
||||
{
|
||||
id: "pylone-damaged-panel",
|
||||
label: "Damaged solar panel",
|
||||
nodeName: "panneau2",
|
||||
placeholderName: "placeholder_2",
|
||||
},
|
||||
],
|
||||
replacementParts: [
|
||||
@@ -111,17 +126,26 @@ export const REPAIR_MISSIONS = {
|
||||
ferme: {
|
||||
id: "ferme",
|
||||
label: "Vertical farm",
|
||||
description: "Generic description",
|
||||
description:
|
||||
"Stabilize the irrigation loop and humidity sensor before restarting the farm",
|
||||
modelPath: "/models/fermeverticale/model.gltf",
|
||||
stageUiPath: "/assets/UI/laferme.webm",
|
||||
interactUiPath: REPAIR_INTERACT_UI_PATH,
|
||||
brokenUiPath: REPAIR_BROKEN_UI_PATH,
|
||||
case: DEFAULT_REPAIR_CASE,
|
||||
reassemblySeconds: 1.2,
|
||||
requiredReplacementPartId: "ferme-irrigation-pump-replacement",
|
||||
scanPartSeconds: 0.9,
|
||||
brokenParts: [
|
||||
{
|
||||
id: "ferme-irrigation-pump",
|
||||
label: "Irrigation pump",
|
||||
placeholderName: "placeholder_1",
|
||||
},
|
||||
{
|
||||
id: "ferme-humidity-sensor",
|
||||
label: "Humidity sensor",
|
||||
placeholderName: "placeholder_2",
|
||||
},
|
||||
],
|
||||
replacementParts: [
|
||||
|
||||
Reference in New Issue
Block a user