133 lines
3.7 KiB
Markdown
133 lines
3.7 KiB
Markdown
|
|
# **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
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|