114 lines
3 KiB
JavaScript
114 lines
3 KiB
JavaScript
|
|
import { narrativeManager } from "./NarrativeManager.js";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* MissionManager.js
|
||
|
|
* Handles the state of the current mission, objectives, and narrative triggers.
|
||
|
|
*/
|
||
|
|
export class MissionManager {
|
||
|
|
constructor(gameLoop) {
|
||
|
|
this.gameLoop = gameLoop;
|
||
|
|
this.activeMission = null;
|
||
|
|
this.objectives = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Loads a mission definition and starts the sequence.
|
||
|
|
* @param {Object} missionDef - The JSON definition.
|
||
|
|
*/
|
||
|
|
startMission(missionDef) {
|
||
|
|
console.log(`Mission Start: ${missionDef.title}`);
|
||
|
|
this.activeMission = missionDef;
|
||
|
|
this.objectives = missionDef.objectives.map((obj) => ({
|
||
|
|
...obj,
|
||
|
|
current: 0,
|
||
|
|
complete: false,
|
||
|
|
}));
|
||
|
|
|
||
|
|
// 1. Check for Narrative Intro
|
||
|
|
if (this.activeMission.narrative_intro) {
|
||
|
|
this.gameLoop.setPhase("CINEMATIC");
|
||
|
|
|
||
|
|
// Load narrative data (Mocking fetch for prototype)
|
||
|
|
// In real app: const data = await fetch(`assets/data/narrative/${id}.json`)
|
||
|
|
const narrativeData = this._mockLoadNarrative(
|
||
|
|
this.activeMission.narrative_intro
|
||
|
|
);
|
||
|
|
|
||
|
|
// Hook into narrative end to start gameplay
|
||
|
|
const onEnd = () => {
|
||
|
|
narrativeManager.removeEventListener("narrative-end", onEnd);
|
||
|
|
this.beginGameplay();
|
||
|
|
};
|
||
|
|
narrativeManager.addEventListener("narrative-end", onEnd);
|
||
|
|
|
||
|
|
// Start the show
|
||
|
|
narrativeManager.startSequence(narrativeData);
|
||
|
|
} else {
|
||
|
|
// No intro, jump straight to deployment
|
||
|
|
this.beginGameplay();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
beginGameplay() {
|
||
|
|
console.log("Mission: Narrative complete. Deploying.");
|
||
|
|
// Trigger the GameLoop to generate the world based on Mission Biome Config
|
||
|
|
this.gameLoop.generateWorld(this.activeMission.biome_config);
|
||
|
|
this.gameLoop.setPhase("DEPLOYMENT");
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Called whenever an event happens (Enemy death, Item pickup)
|
||
|
|
*/
|
||
|
|
onGameEvent(event) {
|
||
|
|
if (!this.activeMission) return;
|
||
|
|
|
||
|
|
let changed = false;
|
||
|
|
|
||
|
|
this.objectives.forEach((obj) => {
|
||
|
|
if (obj.complete) return;
|
||
|
|
|
||
|
|
if (obj.type === "ELIMINATE_ENEMIES" && event.type === "ENEMY_DEATH") {
|
||
|
|
obj.current++;
|
||
|
|
if (obj.current >= obj.target_count) {
|
||
|
|
obj.complete = true;
|
||
|
|
changed = true;
|
||
|
|
console.log("Objective Complete: Eliminate Enemies");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
if (changed) {
|
||
|
|
this.checkMissionSuccess();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
checkMissionSuccess() {
|
||
|
|
const allComplete = this.objectives.every((o) => o.complete);
|
||
|
|
if (allComplete) {
|
||
|
|
console.log("MISSION SUCCESS!");
|
||
|
|
// Trigger Outro or End Level
|
||
|
|
if (this.activeMission.narrative_outro) {
|
||
|
|
// Play Outro...
|
||
|
|
} else {
|
||
|
|
this.gameLoop.endLevel(true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
_mockLoadNarrative(id) {
|
||
|
|
// Placeholder: This would actually load the JSON file we defined earlier
|
||
|
|
return {
|
||
|
|
id: id,
|
||
|
|
nodes: [
|
||
|
|
{
|
||
|
|
id: "1",
|
||
|
|
text: "Commander, we've arrived at the coordinates.",
|
||
|
|
speaker: "Vanguard",
|
||
|
|
type: "DIALOGUE",
|
||
|
|
next: "END",
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|