Introduce the HubScreen as the main interface for managing resources, units, and mission selection, integrating with the GameStateManager for dynamic data binding. Implement the MissionBoard component to display and select available missions, enhancing user interaction with mission details and selection logic. Update the GameStateManager to handle transitions between game states, ensuring a seamless experience for players. Add tests for HubScreen and MissionBoard to validate functionality and integration with the overall game architecture.
101 lines
3.7 KiB
Markdown
101 lines
3.7 KiB
Markdown
---
|
|
description: Combat state and movement logic for turn-based combat loop
|
|
globs: src/systems/TurnSystem.js, src/systems/MovementSystem.js, src/types/CombatState.ts, src/types/Actions.ts
|
|
alwaysApply: false
|
|
---
|
|
|
|
# **Combat State & Movement Rule**
|
|
|
|
This rule defines the logic for managing the Turn-Based Combat Loop and the execution of Movement Actions.
|
|
|
|
## **1. TypeScript Interfaces (Data Models)**
|
|
|
|
```typescript
|
|
export type CombatPhase =
|
|
| "INIT"
|
|
| "TURN_START"
|
|
| "WAITING_FOR_INPUT"
|
|
| "EXECUTING_ACTION"
|
|
| "TURN_END"
|
|
| "COMBAT_END";
|
|
|
|
export interface CombatState {
|
|
/** Whether combat is currently active */
|
|
isActive: boolean;
|
|
/** Current Round number */
|
|
round: number;
|
|
/** Ordered list of Unit IDs for the current round */
|
|
turnQueue: string[];
|
|
/** The ID of the unit currently taking their turn */
|
|
activeUnitId: string | null;
|
|
/** Current phase of the turn loop */
|
|
phase: CombatPhase;
|
|
}
|
|
|
|
// src/types/Actions.ts
|
|
|
|
export interface ActionRequest {
|
|
type: "MOVE" | "SKILL" | "ITEM" | "WAIT";
|
|
sourceId: string;
|
|
targetId?: string; // For targeted skills
|
|
targetPosition?: { x: number; y: number; z: number }; // For movement/AoE
|
|
skillId?: string;
|
|
itemId?: string;
|
|
}
|
|
|
|
export interface MovementResult {
|
|
success: boolean;
|
|
path: { x: number; y: number; z: number }[];
|
|
costAP: number;
|
|
finalPosition: { x: number; y: number; z: number };
|
|
}
|
|
```
|
|
|
|
## **2. Conditions of Acceptance (CoA)**
|
|
|
|
These checks ensure the combat loop feels fair and responsive.
|
|
|
|
### **System: TurnSystem (src/systems/TurnSystem.js)**
|
|
|
|
- **CoA 1: Initiative Roll:** Upon starting combat, all active units must be sorted into the turnQueue based on their Speed stat (Highest First)
|
|
- **CoA 2: Turn Start Hygiene:** When a unit's turn begins:
|
|
- Their `currentAP` must reset to `baseAP`
|
|
- Status effects (DoTs) must tick
|
|
- Cooldowns must decrement
|
|
- **CoA 3: Cycling:** Calling `endTurn()` must move the `activeUnitId` to the next in the queue. If the queue is empty, increment round and re-roll/reset the queue
|
|
|
|
### **System: MovementSystem (src/systems/MovementSystem.js)**
|
|
|
|
- **CoA 1: Validation:** Moving to a tile must fail if:
|
|
- The tile is blocked/occupied
|
|
- No path exists
|
|
- The unit has insufficient AP for the _entire_ path
|
|
- **CoA 2: Execution:** A successful move must:
|
|
- Update the Unit's position in the UnitManager
|
|
- Update the VoxelGrid occupancy map
|
|
- Deduct the correct AP cost (including terrain modifiers)
|
|
- **CoA 3: Path Snapping:** If the user clicks a tile, but the unit only has AP to reach halfway, the system should allow moving to the _furthest reachable tile_ on that path (optional QoL)
|
|
|
|
## **3. Implementation Requirements**
|
|
|
|
### **The Turn System**
|
|
|
|
Create `src/systems/TurnSystem.js`. It should manage the CombatState.
|
|
|
|
1. Implement `startCombat(units)`: Sorts units by speed into turnQueue and sets phase to TURN_START
|
|
2. Implement `startTurn()`: Refills the active unit's AP, processes cooldowns/statuses, and sets phase to WAITING_FOR_INPUT
|
|
3. Implement `endTurn()`: Rotates the queue. If queue is empty, start new Round
|
|
4. It should accept the UnitManager in the constructor to access unit stats
|
|
5. Dispatch events: `combat-start`, `turn-start`, `turn-end`
|
|
|
|
### **The Movement System**
|
|
|
|
Create `src/systems/MovementSystem.js`. It coordinates Pathfinding, VoxelGrid, and UnitManager.
|
|
|
|
1. Implement `validateMove(unit, targetPos)`: Returns `{ valid: boolean, cost: number, path: [] }`. It checks `A*` pathfinding and compares cost vs `unit.currentAP`
|
|
2. Implement `executeMove(unit, targetPos)`:
|
|
- Validates the move first
|
|
- Updates `grid.moveUnit(unit, targetPos)`
|
|
- Deducts AP
|
|
- Returns a Promise that resolves when the visual movement (optional animation hook) would handle it, or immediately for logic
|
|
|