# 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 `Unit` node
- Pre-combat snapshot stats via an inner class `CombatantStats`:
  - `hp: int` — from `current_stats.current_hp`
  - `sp: int` — from `current_stats.current_sp`
  - `hit: int` — calculated as `own hit - opponent's eva`
  - `atk: int` — from `current_stats.phys_atk`
  - `def: int` — from `current_stats.phys_def`
  - `spd: int` — from `current_stats.spd`

### Stat Calculation

For the **attacker** side:
- `atk` = attacker's `phys_atk`
- `def` = attacker's `phys_def`
- `hit` = attacker's `hit` - defender's `eva`
- `hp`, `sp`, `spd` copied directly from attacker's `current_stats`

For the **defender** side:
- `atk` = defender's `phys_atk`
- `def` = defender's `phys_def`
- `hit` = defender's `hit` - attacker's `eva`
- `hp`, `sp`, `spd` copied directly from defender's `current_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 `CombatProposal` with snapshot stats for each side
- Applies cross-calculations (hit - eva)
- Returns the proposal without modifying any unit state

### `apply_proposal(proposal: CombatProposal) -> void`

1. **Attacker strikes:** Roll random int 1–100. If roll <= attacker's calculated `hit`, apply `max(attacker.atk - defender.def, 0)` damage to the defender Unit's `current_stats.current_hp` (modifies the actual unit, not the snapshot).
2. **Counterattack:** If the defender Unit's `current_stats.current_hp > 0` after the attack, roll 1–100 for defender. If roll <= defender's calculated `hit`, apply `max(defender.atk - attacker.def, 0)` damage to the attacker Unit's `current_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
