--- name: godot-turn-system description: "Expert blueprint for turn-based combat with turn order, action points, phase management, and timeline systems for strategy/RPG games. Covers speed-based initiative, interrupts, and simultaneous turns. Use when implementing turn-based combat OR tactical systems. Keywords turn-based, initiative, action points, phase, round, turn order, combat." --- ## NEVER Do (Expert Anti-Patterns) ### Order & Determinism - NEVER recalculate turn order every action; strictly sort once per round or ONLY when a speed-relevant stat changes to prevent O(n log n) lag. - NEVER use random tie-breaking for initiative; strictly use a secondary static attribute (Agility, ID, or persistent "luck") for **deterministic replays**. - NEVER modify an active turn-order queue while iterating it; strictly iterate over a `duplicate()` or apply queue modifications after the loop. - NEVER broadcast global turn state changes using immediate `call_group()`; strictly use **`call_group_flags(SceneTree.GROUP_CALL_DEFERRED, ...)`** to prevent frame spikes when notifying hundreds of units. - NEVER rely on the Node hierarchy as the source of truth; strictly use a **Dictionary board state** for logical grid coordinates. ### Logic & Action Economy - NEVER deduct Action Points (AP) before validation; strictly call `can_perform_action(cost)` before applying `current_ap -= cost` to prevent exploits. - NEVER hardcode phase transitions (`if phase == 0`); strictly use an **enum + match** or a dedicated State Machine for Draw/Main/End phases. - NEVER emit "Turn Ended" before internal cleanup; strictly reset AP and tick status effects **BEFORE** signaling the next turn. - NEVER use exact floating-point equality (`==`) for AP checks; strictly use `>=` or `is_equal_approx()` for robust comparisons. ### Tactical Grid & UI - NEVER use generic `AStar2D` for tile grids; strictly use **`AStarGrid2D`** for 10x faster pathfinding and native diagonal handling. - NEVER forget to call **`update()`** on `AStarGrid2D` after changing obstacle states; if you toggle `set_point_solid()`, the grid MUST refresh before the next query. - NEVER lock the main thread with `while` loops for input; strictly use the **await keyword** or signals to yield execution back to the Tree. - NEVER handle turn decisions with `is_action_pressed()`; strictly use `is_action_just_pressed()` for discrete, frame-locked menu input. - NEVER skip turn timeouts in networked games; strictly implement a **server-side timer** with a default "pass" action to prevent griefing. See **Networked Turn Timeout** golden path below. --- ## Decision Tree — Pick a Turn Model | Need | Choose | **MANDATORY** script | |------|--------|----------------------| | Discrete rounds (chess / tactics / card phases) | Round + initiative queue + AP phases | [turn_system_patterns.gd](scripts/turn_system_patterns.gd) | | Continuous gauges (FF-style ATB) | Per-actor gauge fill in `_process` | [active_time_battle.gd](scripts/active_time_battle.gd) | | Timeline / CTB with interrupts & prediction | Event timeline + predictive UI | [timeline_turn_manager.gd](scripts/timeline_turn_manager.gd) | > **Do NOT** invent a fourth model inline. Read the matching script before coding. ## Expert Components (scripts/) - [turn_system_patterns.gd](scripts/turn_system_patterns.gd) — Match-based phase machines, UndoRedo, `AStarGrid2D` board helpers. - [active_time_battle.gd](scripts/active_time_battle.gd) — ATB gauges, pause-on-ready, async action handoff. - [timeline_turn_manager.gd](scripts/timeline_turn_manager.gd) — Timeline / CTB with interrupts and pre-visualization. - [turn_predictor.gd](scripts/turn_predictor.gd) — Simulate ATB gauges for timeline UI preview. - [combat_stats_resource.gd](scripts/combat_stats_resource.gd) — Deterministic damage preview Resource for hover UI. ## TurnManager Autoload — Interface Contract Only Keep the Autoload thin. **Do not** paste full queue math here — implement in the script chosen above. ```gdscript # turn_manager.gd (AutoLoad) — contract only extends Node signal turn_started(combatant: Node) signal turn_ended(combatant: Node) signal round_ended signal turn_timed_out(combatant: Node) # multiplayer: server default-pass func start_combat(participants: Array[Node]) -> void: pass func end_turn() -> void: pass func request_pass(combatant: Node) -> void: pass # default action on timeout ``` ## Networked Turn Timeout (Golden Path) Referenced from NEVER: server owns the clock; clients never decide "pass." 1. On `turn_started`, server starts a one-shot `Timer` / `SceneTreeTimer` (authoritative). 2. On timeout: server calls `request_pass(current)` (or auto-end-turn), then emits `turn_timed_out`. 3. Clients only render the countdown; never mutate the turn queue locally. 4. Pair with [godot-multiplayer-networking](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-multiplayer-networking/SKILL.md) for host-auth RPC. ## Action Points (Contract) ```gdscript func can_perform_action(cost: int) -> bool: return current_action_points >= cost func perform_action(cost: int) -> bool: if not can_perform_action(cost): return false current_action_points -= cost return true ``` Phases: prefer `enum Phase { DRAW, MAIN, END }` + `match`, or route to [godot-state-machine-advanced](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-state-machine-advanced/SKILL.md). Full ATB / timeline math lives in the MANDATORY scripts — do not duplicate Elite snippets here. ## Deep recipes (on demand) > LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in `scripts/` — never delete, only move. | Topic | Reference | |-------|-----------| | ATB / prediction / previews | [elite-turn-patterns.md](references/elite-turn-patterns.md) | ## Reference > Progressive disclosure: open Official Documentation links only when researching a specific API; > load Related Skills when routing work to a peer domain — do not preload the whole lattice. ### Official Documentation - [Idle and Physics Processing](https://docs.godotengine.org/en/stable/tutorials/scripting/idle_and_physics_processing.html) — When turn ticks belong in `_process` vs `_physics_process` vs pure event steps. - [Using signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html) — Turn-start / turn-end / unit-acted events without polling gauges. - [Resources](https://docs.godotengine.org/en/stable/tutorials/scripting/resources.html) — Initiative/speed stats as Resources for sim and UI prediction. - [Singletons (Autoload)](https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html) — TurnManager ownership boundaries. - [GDScript basics](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html) — `await` sequencing for multi-phase turns. - [Object](https://docs.godotengine.org/en/stable/classes/class_object.html) — Signal connect flags for turn bus listeners. - [SceneTree](https://docs.godotengine.org/en/stable/classes/class_scenetree.html) — Pausing gameplay while menus resolve turn choices. - [Timer](https://docs.godotengine.org/en/stable/classes/class_timer.html) — Optional realtime turn clocks without busy loops. - [Tween](https://docs.godotengine.org/en/stable/classes/class_tween.html) — Animating ATB gauges and turn handoff juice. - [AnimationPlayer](https://docs.godotengine.org/en/stable/classes/class_animationplayer.html) — Action animations that must finish before the next turn. - [MultiplayerAPI](https://docs.godotengine.org/en/stable/classes/class_multiplayerapi.html) — Authoritative turn order in networked matches. - [JSON](https://docs.godotengine.org/en/stable/classes/class_json.html) — Deterministic turn replay / seed logs for balance labs. ### Related Skills #### Prerequisites - [godot-project-foundations](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-project-foundations/SKILL.md) — Scene and Autoload placement for TurnManager. - [godot-signal-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-signal-architecture/SKILL.md) — Turn bus contracts (signals up, commands down). - [godot-resource-data-patterns](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-resource-data-patterns/SKILL.md) — Speed/initiative Resources shared with combat/UI. - [godot-autoload-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-autoload-architecture/SKILL.md) — Lifecycle of a global turn orchestrator. #### Complements - [godot-state-machine-advanced](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-state-machine-advanced/SKILL.md) — Per-unit states nested under turn phases. - [godot-combat-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-combat-system/SKILL.md) — Actions resolved inside a granted turn. - [godot-rpg-stats](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-rpg-stats/SKILL.md) — Speed/AGI feeding ATB gauges. - [godot-ability-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ability-system/SKILL.md) — Cooldowns measured in turns, not wall-clock only. - [godot-tweening](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-tweening/SKILL.md) — Gauge fill and handoff presentation. - [godot-multiplayer-networking](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-multiplayer-networking/SKILL.md) — Host-auth turn order and lockstep. #### Downstream / consumers - [godot-genre-action-rpg](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-genre-action-rpg/SKILL.md) — ATB/turn hybrids in ARPG/JRPG-adjacent combat. - [godot-genre-card-game](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-genre-card-game/SKILL.md) — Card turns and priority windows. - [godot-genre-rts](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-genre-rts/SKILL.md) — Discrete orders in strategy loops. - [godot-monte-carlo-balancer](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-monte-carlo-balancer/SKILL.md) — Simulate turn matrices for speed/action fairness. #### Master - [godot-master](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-master/SKILL.md) — Library router and mirrored module entry for turn systems.