aether-shards/.cursor/rules/logic/TurnSystem/RULE.md
Matthew Mone 2c86d674f4 Add mission debrief and procedural mission generation features
- Introduce the MissionDebrief component to display after-action reports, including XP, rewards, and squad status.
- Implement the MissionGenerator class to create procedural side missions, enhancing replayability and resource management.
- Update mission schema to include mission objects for INTERACT objectives, improving mission complexity.
- Enhance GameLoop and MissionManager to support new mission features and interactions.
- Add tests for MissionDebrief and MissionGenerator to ensure functionality and integration within the game architecture.
2026-01-01 16:08:54 -08:00

78 lines
3 KiB
Markdown

---
description: Turn resolution specification - the tick system for transitioning between unit turns
globs: src/systems/TurnSystem.js, src/systems/TurnSystem.ts, src/types/TurnSystem.ts
alwaysApply: false
---
# **Turn Resolution Rule**
This rule defines the logic that occurs the moment a unit presses "End Turn". It transitions the game from one actor to the next using a time-based simulation.
## **1. The Logic Flow**
When `endTurn()` is called:
1. **Resolution (Old Unit):**
- **Cooldowns:** Decrement cooldowns on all skills by 1
- **Status Effects:** Tick durations of active effects (Buffs/Debuffs). Remove expired ones
- **Charge Reset:** The unit's `chargeMeter` is reset to 0 (or reduced by action cost)
2. **Time Advancement (The "Tick"):**
- The system enters a `while(no_active_unit)` loop
- **Tick:** Every unit gains `Charge += Speed`
- **Check:** Does anyone have `Charge >= 100`?
- _Yes:_ Stop looping. The unit with the highest Charge is the **New Active Unit**
- _No:_ Continue looping
3. **Activation (New Unit):**
- **AP Refill:** Set `currentAP` to `maxAP`
- **Start Triggers:** Fire `ON_TURN_START` events (e.g., "Take Poison Damage")
- **Input Unlock:** If Player, unlock UI. If Enemy, trigger AI
## **2. TypeScript Interfaces**
```typescript
// src/types/TurnSystem.ts
export interface TurnState {
/** The ID of the unit currently acting */
activeUnitId: string | null;
/** How many "Ticks" have passed in total (Time) */
globalTime: number;
/** Ordered list of who acts next (predicted) for the UI */
projectedQueue: string[];
}
export interface TurnEvent {
type: 'TURN_CHANGE';
previousUnitId: string;
nextUnitId: string;
/** Did we wrap around a "virtual round"? */
isNewRound: boolean;
}
```
## **3. Conditions of Acceptance (CoA)**
**CoA 1: Speed determines frequency**
- If Unit A has Speed 20 and Unit B has Speed 10:
- Unit A should act roughly twice as often as Unit B over 10 turns
**CoA 2: Queue Prediction**
- The system must expose a `getPredictedQueue(depth)` method that "simulates" future ticks without applying them, so the UI can show the "Next 5 Units" list correctly
**CoA 3: Status Duration**
- A Status Effect with `duration: 1` applied on Turn X must expire exactly at the _start_ of the unit's _next_ turn (Turn X+1), ensuring it affects them for one full action phase
## **4. Implementation Requirements**
Create `src/systems/TurnSystem.js`:
1. **State:** Maintain a `globalTick` counter and reference to UnitManager
2. **End Turn Logic:** Implement `endTurn(unit)`. Reset the unit's charge to 0. Tick their cooldowns/statuses
3. **Time Loop:** Implement `advanceToNextTurn()`. Loop through all alive units, adding Speed to Charge. Stop as soon as one or more units reach 100
4. **Tie Breaking:** If multiple units pass 100 in the same tick, the one with the highest total charge goes first. If equal, Player beats Enemy
5. **Prediction:** Implement `simulateQueue(depth)` which clones the current charge state and runs the loop virtually to return an array of the next depth Unit IDs