# **Combat Integration Specification: Wiring the Engine** This document defines how the TurnSystem and MovementSystem integrate into the existing GameLoop. ## **1. System Ownership** The GameLoop is the central owner of these systems. It ensures they share the same source of truth (VoxelGrid and UnitManager). **GameLoop Structure Update:** ```js class GameLoop { constructor() { // ... existing systems ... this.grid = null; this.unitManager = null; // NEW: Combat Logic Systems this.turnSystem = null; // Manages Initiative & Round state this.movementSystem = null; // Manages Pathfinding & Position updates } init(container) { // ... existing init ... // Instantiate logic systems (they are stateless until startLevel) this.turnSystem = new TurnSystem(); this.movementSystem = new MovementSystem(); } } ``` ## **2. Integration Point: Level Initialization** When startLevel() runs, the new Grid and UnitManager must be injected into the combat systems so they act on the current map. **Location:** src/core/GameLoop.js -> startLevel() ```js async startLevel(runData) { // ... generate grid and units ... // WIRING: Connect Systems to Data this.movementSystem.setContext(this.grid, this.unitManager); this.turnSystem.setContext(this.unitManager); // WIRING: Listen for Turn Changes (to update UI/Input state) this.turnSystem.addEventListener('turn-start', (e) => this._onTurnStart(e.detail)); } ``` ## **3. Integration Point: Transition to Combat** The transition from "Placing Units" to "Fighting" happens in finalizeDeployment. This is where the Turn System takes control. **Location:** src/core/GameLoop.js -> finalizeDeployment() ```js finalizeDeployment() { // ... spawn enemies ... this.setPhase('COMBAT'); // WIRING: Hand control to TurnSystem const allUnits = this.unitManager.getAllUnits(); this.turnSystem.startCombat(allUnits); // UI Update: Show Combat HUD // (Handled via event listeners in index.html) } ``` ## **4. Integration Point: Input Routing (The "Game Loop")** When the game is in COMBAT phase, inputs must be routed to the active system based on context (Moving vs Targeting). **Location:** src/core/GameLoop.js -> triggerSelection() (called by InputManager) ```js triggerSelection() { const cursor = this.inputManager.getCursorPosition(); // PHASE: DEPLOYMENT (Existing Logic) if (this.phase === 'DEPLOYMENT') { // ... deploy logic ... } // PHASE: COMBAT (New Logic) else if (this.phase === 'COMBAT') { const activeUnit = this.turnSystem.getActiveUnit(); // Security Check: Is it actually the player's turn? if (activeUnit.team !== 'PLAYER') return; // Context A: Unit is trying to MOVE if (this.combatState === 'SELECTING_MOVE') { // DELEGATE to MovementSystem if (this.movementSystem.isValidMove(activeUnit, cursor)) { this.movementSystem.executeMove(activeUnit, cursor); // Updating AP is handled internally or via event } } // Context B: Unit is targeting a SKILL else if (this.combatState === 'TARGETING_SKILL') { // Delegate to SkillSystem (Future) } } } ``` ## **5. Visualizing Range (The "Update Loop")** The blue movement grid needs to update whenever the active unit changes or moves. **Location:** src/core/GameLoop.js -> animate() or Event Handler ```js _onTurnStart(unit) { if (unit.team === 'PLAYER') { // Ask MovementSystem for reachable tiles const tiles = this.movementSystem.getReachableTiles(unit); // Ask VoxelManager to highlight them this.voxelManager.highlightTiles(tiles, 'BLUE'); } else { this.voxelManager.clearHighlights(); // Trigger AI processing } } ```