3.4 KiB
3.4 KiB
Combat System
Overview
A stateless CombatSystem node that creates pre-combat proposals and applies combat resolution between two units. The system encapsulates all combat stat calculation so other systems don't need to know proposal logic.
CombatProposal Resource
resources/resource_definitions/combat_proposal.gd
A Resource containing two sides — attacker and defender. Each side holds:
- A reference to the
Unitnode - Pre-combat snapshot stats via an inner class
CombatantStats:hp: int— fromcurrent_stats.current_hpsp: int— fromcurrent_stats.current_sphit: int— calculated asown hit - opponent's evaatk: int— fromcurrent_stats.phys_atkdef: int— fromcurrent_stats.phys_defspd: int— fromcurrent_stats.spd
Stat Calculation
For the attacker side:
atk= attacker'sphys_atkdef= attacker'sphys_defhit= attacker'shit- defender'sevahp,sp,spdcopied directly from attacker'scurrent_stats
For the defender side:
atk= defender'sphys_atkdef= defender'sphys_defhit= defender'shit- attacker'sevahp,sp,spdcopied directly from defender'scurrent_stats
In the future, different attacks may swap between physical and magic stats, but for now only physical stats are used.
CombatSystem Node
nodes/combat_system.gd
A Node added to the strategy phase scene tree. Stateless — operates purely on units passed in.
create_proposal(attacker: Unit, defender: Unit) -> CombatProposal
- Reads both units'
current_stats - Builds a
CombatProposalwith snapshot stats for each side - Applies cross-calculations (hit - eva)
- Returns the proposal without modifying any unit state
apply_proposal(proposal: CombatProposal) -> void
- Attacker strikes: Roll random int 1–100. If roll <= attacker's calculated
hit, applymax(attacker.atk - defender.def, 0)damage to the defender Unit'scurrent_stats.current_hp(modifies the actual unit, not the snapshot). - Counterattack: If the defender Unit's
current_stats.current_hp > 0after the attack, roll 1–100 for defender. If roll <= defender's calculatedhit, applymax(defender.atk - attacker.def, 0)damage to the attacker Unit'scurrent_stats.current_hp.
- Damage has a floor of 0 (no negative damage / healing).
- Range is ignored for now. In the future, counterattack will depend on whether the defender has skills at appropriate range (defaulting to a "defend" action if not).
Scene Integration
The CombatSystem node is added to scenes/strategy_phase.tscn as a sibling of PlayerController, CombatMap, etc. No exports needed.
CombatTest (Node2D)
├─ CombatUI
├─ CombatMap
├─ PlayerController
├─ CombatSystem <-- new
├─ Camera2D
└─ AudioStreamPlayer
Files Changed
| File | Change |
|---|---|
resources/resource_definitions/combat_proposal.gd |
New — CombatProposal resource with CombatantStats inner class |
nodes/combat_system.gd |
New — CombatSystem node with create_proposal and apply_proposal |
scenes/strategy_phase.tscn |
Add CombatSystem node to scene tree |
Out of Scope
- Magic attack/defense selection (future: different attack types swap stats)
- Range-based counterattack eligibility (future: defend action when no skills in range)
- Critical hits
- UI for displaying the combat proposal
- Animations or visual feedback for combat resolution