godot-turn-system
0
总安装量
3
周安装量
安装命令
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-turn-system
Agent 安装分布
opencode
3
gemini-cli
3
codex
3
claude-code
2
github-copilot
2
Skill 文档
Turn System
Turn order calculation, action points, phase management, and timeline systems define turn-based combat.
Available Scripts
active_time_battle.gd
Framework for Active Time Battle (ATB) systems with async action support.
timeline_turn_manager.gd
Expert timeline-based turn manager with interrupts and simultaneous actions.
NEVER Do in Turn Systems
- NEVER recalculate turn order every action â Sort 50 combatants after every move? O(n log n) Ã actions = lag. Calculate once per round, update on stat changes only.
- NEVER use speed ties without determinism â Two units same speed, random order? Non-reproducible replays. Break ties with secondary stat (ID, position, etc.).
- NEVER forget to validate action costs â Allow action without checking points? Negative AP = exploits. ALWAYS
if can_perform_action(cost)before deducting. - NEVER hardcode phase transitions â
if phase == 0: phase = 1for 10 phases? Unmaintainable. Use enum + match OR array of phase handlers. - NEVER skip turn timeout for networked games â Wait forever for player input? Griefing exploit. ALWAYS implement turn timer with default action.
- NEVER emit turn_ended before cleanup â Signal listeners start next turn, previous hasn’t cleaned up? State corruption. Cleanup FIRST, then emit.
# turn_manager.gd (AutoLoad)
extends Node
signal turn_started(combatant: Node)
signal turn_ended(combatant: Node)
signal round_ended
var combatants: Array[Node] = []
var turn_order: Array[Node] = []
var current_turn_index: int = 0
func start_combat(participants: Array[Node]) -> void:
combatants = participants
calculate_turn_order()
start_next_turn()
func calculate_turn_order() -> void:
turn_order = combatants.duplicate()
turn_order.sort_custom(func(a, b): return a.speed > b.speed)
func start_next_turn() -> void:
if current_turn_index >= turn_order.size():
current_turn_index = 0
round_ended.emit()
calculate_turn_order() # Recalculate each round
var current := turn_order[current_turn_index]
turn_started.emit(current)
func end_turn() -> void:
var current := turn_order[current_turn_index]
turn_ended.emit(current)
current_turn_index += 1
start_next_turn()
Action Point System
# combatant.gd
extends Node
@export var max_action_points: int = 3
var current_action_points: int = 3
func start_turn() -> void:
current_action_points = max_action_points
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
Turn Phases
enum Phase { DRAW, MAIN, END }
var current_phase: Phase = Phase.DRAW
func advance_phase() -> void:
match current_phase:
Phase.DRAW:
current_phase = Phase.MAIN
Phase.MAIN:
current_phase = Phase.END
Phase.END:
TurnManager.end_turn()
current_phase = Phase.DRAW
Best Practices
- Speed-Based – Initiative determines order
- Action Points – Limit actions per turn
- Timeout – Add turn timer for online play
Reference
- Related:
godot-combat-system,godot-rpg-stats
Related
- Master Skill: godot-master