godot-combat-system
Expert patterns for combat systems including hitbox/hurtbox architecture, damage calculation (DamageData class), health components, combat state machines, combo systems, ability cooldowns, and damage popups. Use for action games, RPGs, or fighting games. Trigger keywords: Hitbox, Hurtbox, DamageData
By thedivergentai · 355 installs
npx skills add thedivergentai/gd-agentic-skills --skill godot-combat-system
Source repository · Upstream listing
NEVER Do
NEVER use direct damage references ( target.health = 10 ) — Bypass armor, resistances, and i frames. Always DamageData + HealthComponent.take damage .
NEVER forget invincibility frames (i frames) — Multi hit shapes otherwise tick every physics frame. Apply a short invuln window after a successful hit.
NEVER keep hitboxes active permanently — Enable/disable with AnimationPlayer tracks or timed code; permanent monitoring causes ghost hits.
NEVER use groups for physics based hit filtering — Prefer collision layers/masks (C++ filter). Groups are secondary logic, not the physics gate.
NEVER emit damage signals without a DamageData object — Raw numbers lose type, source, knockback, and crit context.
NEVER use raw strings for elemental damage types — Use enum / @export flags bitfields. String "physical" violates this skill’s own contract.
NEVER use try/catch to validate targets — GDScript has no exceptions. Use has method(&"take damage") / is checks.
NEVER hardcode hitstun with OS.delay msec() — Blocks the OS thread. Use tweens / Engine.time scale + ignore time scale timers.
NEVER apply RigidBody impulses in process() — Use physics process / integrate forces .
NEVER couple UI lifebars inside the Player script — Emit health changed ; HUD listens.
NEVER leave CollisionShapes active on dead entities — set deferred("disabled", true) on death.
NEVER scale CollisionShapes non uniformly — Scale the shape resource ( radius , size ), not the node transform unevenly.
NEVER use instanced Nodes for base combat stats — Prefer Resource / RefCounted containers; duplicate() per instance.
NEVER use standard strings for high frequency state names — Prefer StringName ( &"attacking" ).
NEVER forget duplicate() on shared Resource stats — Shared templates = shared health pools.
Golden Path (MANDATORY)
1. [damage data.gd](scripts/damage data.gd) — typed DamageData Resource with enum / flags for damage types (no String elements).
2. [health component.gd](scripts/health component.gd) — take damage + i frame gate + health changed / died signals.
3. [hitbox hurtbox.gd](scripts/hitbox hurtbox.gd) / [hitbox component.gd](scripts/hitbox component.gd) — Area hit delivery into hurtboxes.
4. [combat system patterns.gd](scripts/combat system patterns.gd) — duck typing, hit stop, nodeless AoE, frame sync.
Do NOT re inline Hitbox/Health/Combo/Ability tutorials in scenes. Route abilities to [godot ability system](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot ability system/SKILL.md); compose components per [godot composition](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot composition/SKILL.md); FSMs via [godot state machine advanced](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot state machine advanced/SKILL.md).
Decision Tree
Task Load Do NOT Load
Define damage payload damage data.gd String damage type fields
HP + i frames health component.gd Direct health = n
Melee/projectile volumes hitbox hurtbox.gd / hitbox component.gd Permanent monitoring Areas
AoE / hit stop / duck type combat system patterns.gd Spawn temp Areas every tick
Ability cooldowns / skill bar godot ability system Inline AbilityManager novels here
Combo buffers godot input handling + state machine Embedding hit logic in input
Damage Type Contract (aligned with NEVER)
Hitboxes must pass DamageData (or equivalent AttackData built from the same flags), never "Physical" strings.
Available Scripts
[damage data.gd](scripts/damage data.gd) — MANDATORY DamageData Resource + type flags.
[health component.gd](scripts/health component.gd) — MANDATORY Health + i frames golden path.
[hitbox hurtbox.gd](scripts/hitbox hurtbox.gd) — MANDATORY before Area combat wiring.
[hitbox component.gd](scripts/hitbox component.gd) — 3D Area hitbox companion (flags aligned).
[combat system patterns.gd](scripts/combat system patterns.gd) — MANDATORY for AoE / hit stop / duck typing.
[combo system.gd](scripts/combo system.gd) — windowed combo buffer (Do NOT Load if no combos).
[combat state.gd](scripts/combat state.gd) — lightweight combat FSM gate.
[damage popup.gd](scripts/damage popup.gd) — floating damage label tween (pool in production).
[combat logger.gd](scripts/combat logger.gd) — batched combat telemetry JSON.
[networked damage manager.gd](scripts/networked damage manager.gd) — server validate damage RPC shell.
[hitbox visualizer.gd](scripts/hitbox visualizer.gd) — toggle collision debug colors.
Elite Deltas (keep short)
Combat telemetry: batch JSON flushes via [combat logger.gd](scripts/combat logger.gd).
Authoritative damage: [networked damage manager.gd](scripts/networked damage manager.gd) — clients request; server validates.
Hitbox debug: [hitbox visualizer.gd](scripts/hitbox visualizer.gd) + SceneTree.debug collisions hint .
Combos / popups / FSM: [combo system.gd](scripts/combo system.gd), [damage popup.gd](scripts/damage popup.gd), [combat state.gd](scripts/combat state.gd).
MANDATORY for telemetry, networked hits, combos, and moved inline tutorials: [elite combat patterns.md](references/elite combat patterns.md). Do NOT Load for first DamageData + HealthComponent pass.
Reference
Progressive disclosure: Skim Official Documentation only for the APIs you are implementing (Areas, layers/masks, Resources, signals, timers, animation hit windows). Open Related Skills when wiring adjacent systems—do not preload the whole lattice.
Official Documentation
[Using Area2D](https://docs.godotengine.org/en/stable/tutorials/physics/using area 2d.html) — Hitbox/hurtbox combat is Area overlap detection ( area entered / monitoring), not CharacterBody movement queries.
[Physics introduction](https://docs.godotengine.org/en/stable/tutorials/physics/physics introduction.html) — Prefer collision layers/masks for hit filtering; groups are slower and do not replace physics masks for high frequency combat.
[Area2D](https://docs.godotengine.org/en/stable/classes/class area2d.html) — 2D hit volumes: monitoring / monitorable , area entered , and layer/mask bits for team/faction filtering.
[Area3D](https://docs.godotengine.org/en/stable/classes/class area3d.html) — 3D HitboxComponent / hurtbox volumes use the same Area overlap model with 3D layers and shapes.
[CollisionShape2D](https://docs.godotengine.org/en/stable/classes/class collisionshape2d.html) — Enable/disable attack shapes with set deferred("disabled", …) so the physics server is not mutated mid step; never non uniform scale the node.
[PhysicsShapeQueryParameters3D](https://docs.godotengine.org/en/stable/classes/class physicsshapequeryparameters3d.html) — Nodeless AoE/explosions via intersect shape on PhysicsDirectSpaceState3D without spawning temporary Area nodes.
[AnimationPlayer](https://docs.godotengine.org/en/stable/classes/class animationplayer.html) — Drive hitbox active windows from animation tracks (or method calls) so attacks are not permanently monitoring.
[Resources](https://docs.godotengine.org/en/stable/tutorials/scripting/resources.html) — Keep DamageData / combat stats as data ( Resource / RefCounted ), and duplicate() shared templates per instance so enemies do not share one health pool.
[Using signals](https://docs.godotengine.org/en/stable/getting started/step by step/signals.html) — Emit health changed / died / damage events so HUD and VFX subscribe without coupling lifebars into the player script.
[SceneTreeTimer](https://docs.godotengine.org/en/stable/classes/class scenetreetimer.html) — Hit stop after Engine.time scale = 0 must use create timer(..., ignore time scale=true) or the thaw timer freezes with the world.
[Tween](https://docs.godotengine.org/en/stable/classes/class tween.html) — Interruptible hitstun/flash VFX: kill and recreate tweens on consecutive hits instead of stacking parallel flash animations.
[High level multiplayer](https://docs.godotengine.org/en/stable/tutorials/networking/high level multiplayer.html) — Authoritative damage: clients request hits; the server validates and confirms via @rpc before applying take damage .
Related Skills
Prerequisites
[godot 2d physics](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot 2d physics/SKILL.md) — Area layers/masks, CollisionShape2D deferred disable, and space queries are the physics substrate under hitbox/hurtbox filtering.
[godot signal architecture](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot signal architecture/SKILL.md) — Damage, health, and death signals need clear ownership so combat components stay decoupled from UI and AI listeners.
[godot composition](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot composition/SKILL.md) — Prefer HealthComponent / HitboxComponent children over baking combat into a monolithic Character script.
[godot resource data patterns](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot resource data patterns/SKILL.md) — DamageData , elemental flags, and combat stats belong in Resource/ RefCounted data with safe duplicate() on spawn.
Complements
[godot ability system](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot ability system/SKILL.md) — Abilities resolve into this skill’s damage/targeting pipeline; keep ability metadata separate from DamageData .
[godot rpg stats](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot rpg stats/SKILL.md) — Armor, resistances, crit chance, and modifier stacks feed take damage before health is written.
[godot animation player](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot animation player/SKILL.md) — Attack animations own hitbox enable windows, cancel frames, and recovery locks for combos.
[godot state machine advanced](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot state machine advanced/SKILL.md) — IDLE/ATTACKING/BLOCKING/STUNNED combat states belong in a character FSM that gates can act , not ad hoc bool soup.
[godot input handling](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot input handling/SKILL.md) — Combo buffers and attack actions should call into combat/combo systems from the action map rather than embedding hit logic in input callbacks.
Downstream / consumers
[godot monte carlo balancer](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot monte carlo balancer/SKILL.md) — After DamageData, i frames, cooldowns, and crit curves are tunable, Monte Carlo sims prove DPS/TTK bands before shipping difficulty.
[godot multiplayer networking](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot multiplayer networking/SKILL.md) — Predicted hits, lag compensation, and authority checks build on the DamageData + server validate RPC split.
[godot genre action rpg](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot genre action rpg/SKILL.md) — Action RPG combat loops assemble hitboxes, abilities, stats, and progression genre glue on top of this skill.
Master
[godot master](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot master/SKILL.md) — Library router and mirrored module entry; use when discovering peer skills or syncing shared script mirrors after Domain Skill edits.