add: configure mission-specific repair variants

This commit is contained in:
Tom Boullay
2026-05-08 02:41:57 +01:00
parent 41a3846205
commit 0b519a20dc
8 changed files with 40 additions and 9 deletions
@@ -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>
+1 -1
View File
@@ -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
+26 -2
View File
@@ -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: [