# **Turn Lifecycle Specification: Activation & Reset**

This document defines the exact state changes that occur when a unit becomes active (Start Turn) and when they finish (End Turn).

## **1. Start of Turn (Activation Phase)**

This logic runs immediately when TurnSystem identifies a unit as the new active actor.

### **A. Action Point (AP) Regeneration**

The unit must be given their budget for the turn.

- **Formula:** Base AP (3) + Math.floor(Speed / 5).
- **Constraint:** AP does _not_ roll over. It resets to this max value every turn. This encourages players to use their actions rather than hoard them.

### **B. Cooldown Reduction**

- Iterate through all skills in unit.skills.
- If cooldown > 0, decrement by 1.
- _Note:_ This ensures a skill used on Turn 1 with a 1-turn cooldown is ready again on Turn 2.

### **C. Status Effect Tick (The "Upkeep" Step)**

- Iterate through unit.statusEffects.
- **Apply Effect:** If the effect is a "DoT" (Damage over Time) or "HoT" (Heal over Time), apply the value now.
- **Decrement Duration:** Reduce the effect's duration by 1.
- **Expire:** If duration reaches 0, remove the effect immediately (unless it is "Permanent").
- **Stun Check:** If a STUN status is active, skip the Action Phase and immediately trigger **End Turn**.

## **2. End of Turn (Resolution Phase)**

This logic runs when the player clicks "End Turn" or the AI finishes its logic.

### **A. Charge Meter Consumption**

- **Logic:** We do _not_ set Charge to 0. We subtract 100.
- **Why?** If a unit has 115 Charge (because they are very fast), setting it to 0 deletes that extra 15 speed advantage. Subtracting 100 lets them keep the 15 head-start on the next race.
- **Formula:** unit.chargeMeter = Math.max(0, unit.chargeMeter - 100).

### **B. Action Slot Reset**

- Reset flags like hasMoved, hasAttacked, or standardActionUsed to false so the UI is clean for the next time they act.

## **3. The Tick Loop (The "Race")**

This runs whenever no unit is currently active.

```js
while (no_unit_has_100_charge) {
 globalTick++;
 for (all_units as unit) {
 // Gain Charge
 unit.chargeMeter += unit.stats.speed;

        // Cap?
        // No cap, but we check for >= 100 break condition
    }

}
// Sort by Charge (Descending) -> Highest Charge wins
```
