Architecture Decision: Where Does the Manager Live?
| Scope | Policy | Script |
|---|---|---|
| Per character / enemy / turret | Scene-scoped manager as child (default) | ability_manager.gd or composition ability_container.gd on the entity |
| Shared unlock / loadout catalog across scenes | Autoload catalog / progression only (ranks, unlock flags) — not live cast state | Thin Autoload data; casts still go through the entity manager |
| Global "cast any ability anywhere" Autoload | Avoid | Breaks encapsulation and multiplayer authority |
Resolved policy: Live cooldowns, GCD, and execute() run on a scene-scoped AbilityManager / AbilityContainer under the caster. Autoloads may store unlock ranks; they must not be the combat cast oracle. Skill-tree UI reads/writes progression data, then calls into the caster’s manager — never /root/AbilityManager.use_* for combat.
NEVER Do
- NEVER tick cooldowns / status durations in
_process()— Use_physics_process(delta)or one-shot Timers so cooldowns stay deterministic under frame spikes. - NEVER forget global cooldown (GCD) when design needs anti-spam — Small shared lock (0.5–1.5s) between casts when required.
- NEVER hardcode ability effects in the manager — Strategy: each ability is a Resource / node with
execute()(ability_resource.gd). - NEVER allow casts during animation lock — Gate on
is_casting/ anim signals. - NEVER save remaining cooldown floats without time normalization — Persist absolute end timestamps (
Time.get_unix_time_from_system() + remaining). - NEVER put live combat cast state in a global Autoload — Scene-scoped manager (see decision table). Progression Autoloads are fine.
- NEVER blindly ban or blindly require object pools — GDScript refcounting makes pool-optional for light VFX; do pool when spawn/despawn of projectiles/AoE is high-frequency or allocation shows up in the profiler. Prefer instantiate/
queue_freeuntil measured otherwise. - NEVER grow deep ability inheritance trees — Compose Resources + containers (godot-composition).
Golden Path (MANDATORY)
- ability_resource.gd — data + virtual
execute() - ability_manager.gd or ability_container.gd — scene-scoped cast/cooldown
- buff_stat.gd — when buffs/modifiers exist
- Damage resolution → godot-combat-system
Do NOT paste inline AbilityManager / ComboSystem / SkillTreeManager novels into scenes. Skill trees are progression UI + prerequisite graphs that grant Resources to the caster’s container.
Available Scripts
- ability_resource.gd — MANDATORY before new abilities
- ability_manager.gd — MANDATORY Resource-driven cooldown registry (scene-scoped)
- ability_container.gd — MANDATORY alternative: node/Timer composition per ability
- buff_stat.gd — modular buff stats (Do NOT Load if no buffs)
- combo_tracker.gd — windowed combo chains → finisher abilities
- charge_ability.gd — multi-charge recharge (Flash-style)
- skill_node.gd / skill_tree_manager.gd — prerequisite graphs + point spend (progression only)
- status_effect.gd / status_effect_manager.gd — ticking DoTs/buffs (
duplicate(true)required) - ability_caster_network.gd — predict locally, authority validates RPC shell
Cooldown & Status Timing Contract
- Cooldown registry updates and status
process_tickmust use physics-frame delta (_physics_process) orTimernodes owned by the container. - Hit detection from abilities stays on the physics tick when applying impulses / queries.
- UI may read cooldown progress in
_process; it must not own the truth.
Expert Techniques (short)
- Dependency injection: parents inject caster context; abilities do not
get_node("/root/Player"). - Duck-typed hits:
has_method(&"take_damage")/ combat DamageData — see combat skill. - AoE:
call_groupor space queries; do not scan the whole tree each cast. - Networking: predict locally, authority validates
can_use+ costs (godot-multiplayer-networking). - Skill-tree visualizer:
@toolGraphEdit for design-time graphs; runtime still grants Resources to scene managers.
Status Effects & Combos (critical WHY)
CAUTION: Status/buff templates applied at runtime must use
duplicate(true). One poisoned.tresmutates every character sharing that asset — see status_effect_manager.gd.
- Combos: combo_tracker.gd — sequence window + recipe table; finishers remain normal
AbilityResourceentries. - Charges: charge_ability.gd — recharge ticks belong on
_physics_process, not UI_process. - Skill trees: skill_tree_manager.gd grants abilities to the caster's scene manager — progression Autoloads hold ranks only.
- Save cooldowns: persist absolute end timestamps (
Time.get_unix_time_from_system() + remaining), not raw remaining floats — prevents clock/load exploits.
MANDATORY for combos/charges/skill-tree/status/network depth beyond bullets above: elite-ability-patterns.md. Do NOT Load for a first AbilityResource + AbilityManager pass.
Reference
Progressive disclosure: Skim Official Documentation only for the APIs you are implementing (Resources, timers, signals, save, multiplayer). Open Related Skills when wiring adjacent systems—do not preload the whole lattice.
Official Documentation
- Resources — Ability definitions, buffs, and status effects should be
Resourcedata (not hardcoded manager switches) so designers can author and share assets. - Resource — Use
duplicate(true)when applying a status/buff template at runtime so one character’s ticking state cannot mutate the shared.tresfor everyone. - GDScript exports —
@export/@export_grouppower Inspector-tuned costs, cooldowns, prerequisites, and effect arrays on ability Resources. - Using signals — Emit
ability_cast,ability_ready, and cooldown lifecycle signals so UI and VFX subscribe without coupling to AbilityManager internals. - Scene organization — Keep “signals up, calls down”: parents/UI listen; managers call into ability Resources/nodes rather than reaching globally for combat state.
- Idle and Physics Processing — Tick cooldowns and GCD in
_physics_process(fixed delta); avoid_processfor cooldown math that desyncs under frame spikes. - Timer — One-shot
Timerchildren are a clean composition pattern for per-ability cooldowns in container-style managers. - SceneTreeTimer —
create_timer()/ await patterns fit cast times and short buff durations without adding persistent Timer nodes for every cast. - Groups — AoE abilities should
call_group(or query groups) instead of hand-rolled scene scans for every hit target. - Time — Persist cooldown end timestamps (
get_unix_time_from_system()+ remaining), not raw remaining floats, across save/load. - Saving games — Serialize ability unlock ranks and absolute cooldown end times with the rest of player progression data.
- High-level multiplayer — Authoritative cast validation +
@rpcconfirmation/cancel is the engine baseline for predicted ability casts.
Related Skills
Prerequisites
- godot-resource-data-patterns — Abilities, buffs, and skill-tree nodes are Resource-first; load this before inventing custom serialization or inheritance trees for ability data.
- godot-signal-architecture — Cast/ready/cooldown signals and UI hooks depend on disciplined signal ownership so AbilityManager stays decoupled from characters and HUD.
- godot-composition — Prefer AbilityContainer / component nodes over deep
BaseAbility → MagicAbility → FireAbilityinheritance for runtime behavior. - godot-gdscript-mastery — Virtual
execute()/can_cast(), typed Resources, and await-on-timer cast flows assume solid GDScript patterns.
Complements
- godot-combat-system — Damage, hit reactions, and targeting pipelines consume ability
execute()results; keep DamageData separate from ability metadata. - godot-rpg-stats — Mana/stamina costs, stat bonuses from skill ranks, and buff multipliers need a consistent stats/modifier layer.
- godot-input-handling — Hotbar / action-map input should call
can_use/use_abilityrather than embedding cooldown logic in input callbacks. - godot-animation-player — Animation lock and cast telegraphs gate ability spam; wire AnimationPlayer start/finish into
is_casting. - godot-state-machine-advanced — Cast, channel, and interrupt states belong in a character state machine that asks the ability manager, not the other way around.
- godot-save-load-systems — Skill ranks, unlock flags, and absolute cooldown end times must round-trip through the project save schema.
Downstream / consumers
- godot-monte-carlo-balancer — After cooldowns, costs, and damage/effect Resources are tunable, Monte Carlo loadout sims prove ability DPS/uptime bands before shipping curves.
- godot-multiplayer-networking — Predicted casts, authority checks, and rollback of failed RPCs build on the ability manager’s can_use / execute split.
- godot-genre-action-rpg — Action-RPG skill bars, skill trees, and ability chaining assemble this skill with combat, stats, and progression genre glue.
- godot-inventory-system — Consumable scrolls, skill books, and equipment that grants abilities bridge inventory grants into AbilityManager registration.
Master
- godot-master — Library router and mirrored module entry; use when discovering peer skills or syncing shared script mirrors after Domain Skill edits.