aether-shards/.agent/rules/logic/TurnSystem/RULE.md

3 KiB

description globs alwaysApply
Turn resolution specification - the tick system for transitioning between unit turns src/systems/TurnSystem.js, src/systems/TurnSystem.ts, src/types/TurnSystem.ts 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

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