aether-shards/specs/CombatIntegration.spec.md
Matthew Mone 56aa6d79df Add Combat Skill Usage and Targeting System Specifications
Introduce detailed specifications for combat skill usage, including interaction flow, state machine updates, and the skill targeting system. Implement the SkillTargetingSystem to handle targeting validation and area of effect calculations. Enhance the CombatHUD specification to define the UI overlay for combat phases. Integrate these systems into the GameLoop for improved combat mechanics and user experience.
2025-12-23 21:01:54 -08:00

3.7 KiB

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:

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()

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()

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)

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

_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
 }
}