/** * NarrativeManager.js * Manages the flow of story events, dialogue, and tutorials. * Extends EventTarget to broadcast UI updates. */ export class NarrativeManager extends EventTarget { constructor() { super(); this.currentSequence = null; this.currentNode = null; this.history = new Set(); // Track played sequences IDs } /** * Loads and starts a narrative sequence. * @param {Object} sequenceData - The JSON object of the conversation. */ startSequence(sequenceData) { if (!sequenceData || !sequenceData.nodes) { console.error("Invalid sequence data"); return; } console.log(`Starting Narrative: ${sequenceData.id}`); this.currentSequence = sequenceData; this.history.add(sequenceData.id); // Find first node (usually index 0 or id '1') this.currentNode = sequenceData.nodes[0]; this.broadcastUpdate(); } /** * Advances to the next node in the sequence. */ next() { if (!this.currentNode) return; // 1. Handle Triggers (Side Effects) if (this.currentNode.trigger) { this.dispatchEvent( new CustomEvent("narrative-trigger", { detail: { action: this.currentNode.trigger }, }) ); } // 2. Find Next Node const nextId = this.currentNode.next; if (nextId === "END" || !nextId) { this.endSequence(); } else { this.currentNode = this.currentSequence.nodes.find( (n) => n.id === nextId ); this.broadcastUpdate(); } } /** * Handles player choice selection. */ makeChoice(choiceIndex) { if (!this.currentNode.choices) return; const choice = this.currentNode.choices[choiceIndex]; const nextId = choice.next; if (choice.trigger) { this.dispatchEvent( new CustomEvent("narrative-trigger", { detail: { action: choice.trigger }, }) ); } this.currentNode = this.currentSequence.nodes.find((n) => n.id === nextId); this.broadcastUpdate(); } endSequence() { console.log("Narrative Ended"); this.currentSequence = null; this.currentNode = null; this.dispatchEvent(new CustomEvent("narrative-end")); } broadcastUpdate() { this.dispatchEvent( new CustomEvent("narrative-update", { detail: { node: this.currentNode, active: !!this.currentNode, }, }) ); } } // Export singleton for global access export const narrativeManager = new NarrativeManager();