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