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