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.
3 KiB
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:
- 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
chargeMeteris reset to 0 (or reduced by action cost)
- 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
- The system enters a
- Activation (New Unit):
- AP Refill: Set
currentAPtomaxAP - Start Triggers: Fire
ON_TURN_STARTevents (e.g., "Take Poison Damage") - Input Unlock: If Player, unlock UI. If Enemy, trigger AI
- AP Refill: Set
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: 1applied 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:
- State: Maintain a
globalTickcounter and reference to UnitManager - End Turn Logic: Implement
endTurn(unit). Reset the unit's charge to 0. Tick their cooldowns/statuses - Time Loop: Implement
advanceToNextTurn(). Loop through all alive units, adding Speed to Charge. Stop as soon as one or more units reach 100 - 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
- 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