# 52 — BPC_AmmoComponent

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- [`BP_WeaponBase`](49_BP_WeaponBase.md) — Owner weapon
- [`BPC_InventoryComponent`](../04-inventory/25_BPC_InventoryComponent.md) — Consumable ammo items
- [`DA_WeaponData`](../12-content/60_DA_WeaponDataAsset.md) — Magazine size, ammo type
- [`DA_AmmoType`](../12-content/61_DA_AmmoTypeDataAsset.md) — Ammo definition

### Purpose
Manages ammunition state for a weapon: current magazine count, total reserve, reload logic, ammo type validation, and UI updates. Attached to each weapon actor as a child component.

### Variables

| Name | Type | Description |
|------|------|-------------|
| `WeaponDataRef` | DA_WeaponData | Weapon data asset (set at construction) |
| `CurrentMagazineAmmo` | Int | Bullets currently in magazine |
| `ReserveAmmo` | Int | Total carried ammo of matching type |
| `MaxMagazineSize` | Int | From weapon data |
| `AmmoTypeTag` | FGameplayTag | e.g. Tag.Ammo.9mm |
| `bInfiniteAmmo` | Bool | Debug / cheat toggle |
| `ReloadType` | EReloadType | Full, Partial, SingleBullet |
| `ReloadTimeMultiplier` | Float | Per-weapon reload speed scaling |
| `AmmoHistory` | Array<FAmmoEntry> | Save/load stack |

### Structs

| Struct | Fields | Description |
|--------|--------|-------------|
| `FAmmoEntry` | AmmoTypeTag: FGameplayTag, MagazineCount: Int, ReserveCount: Int | State for save/load |

### Enums

| Enum | Values | Description |
|------|--------|-------------|
| `EReloadType` | FullMagazine, PartialFill, SingleBulletLoad | How reload animation works |

### Functions

| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `InitializeAmmo` | WeaponData: DA_WeaponData | — | Set magazine size, count from reserve |
| `CanFire` | — | Bool | MagazineAmmo > 0 |
| `ConsumeAmmo` | Count: Int (default 1) | Int (remaining) | Remove from magazine |
| `StartReload` | — | Bool | Check reserve; if > 0 begin reload |
| `FinishReload` | — | — | Refill magazine from reserve; update UI |
| `GetCurrentMagazineAmmo` | — | Int | UI binding |
| `GetReserveAmmo` | — | Int | UI binding |
| `AddAmmo` | Count: Int, AmmoTag: FGameplayTag | — | From pickup / reward |
| `RemoveAmmoFromReserve` | Count: Int | — | Manufacturing / crafting |
| `GetAmmoPercent` | — | Float | 0.0–1.0 for progress bar |
| `IsAmmoEmpty` | — | Bool | Magazine + Reserve == 0 |
| `OnAmmoChanged` | — | — | Trigger dispatcher |

### Event Dispatchers

| Name | Parameters | Fired When |
|------|-----------|-----------|
| `OnAmmoUpdated` | CurrentMagazine: Int, Reserve: Int | Any ammo change |
| `OnReloadStarted` | ReloadTime: Float | Reload begin |
| `OnReloadCompleted` | — | Reload end |
| `OnOutOfAmmo` | — | Magazine + Reserve == 0 |
| `OnAmmoPickup` | AmmoTypeTag: FGameplayTag, Count: Int | Ammo added |

### Blueprint Flow

```
[InitializeAmmo]
  └─► MaxMagazineSize = WeaponData.MagazineSize
  └─► AmmoTypeTag = WeaponData.AmmoType
  └─► If start with full: CurrentMagazineAmmo = MaxMagazineSize
  └─► Else CurrentMagazineAmmo = 0

[ConsumeAmmo(Count)]
  └─► If bInfiniteAmmo → return
  └─► CurrentMagazineAmmo = FMath::Max(0, CurrentMagazineAmmo - Count)
  └─► OnAmmoChanged

[StartReload]
  └─► If ReserveAmmo <= 0 → broadcast OnOutOfAmmo → return false
  └─► If ReloadType == FullMagazine:
         AmountNeeded = MaxMagazineSize - CurrentMagazineAmmo
         Taken = FMath::Min(AmountNeeded, ReserveAmmo)
  └─► If ReloadType == PartialFill:
         Taken = FMath::Min(ReloadAmount, ReserveAmmo) // per stage
  └─► If ReloadType == SingleBulletLoad:
         Taken = 1
  └─► ReserveAmmo -= Taken
  └─► Wait for ReloadTime (configured in WeaponData)
  └─► CurrentMagazineAmmo += Taken
  └─► OnAmmoChanged
  └─► Return true

[FinishReload — called by animation notify or timer]
  └─► Fill magazine based on remaining reserve
  └─► Broadcast OnReloadCompleted

[AddAmmo(Count, AmmoTag)]
  └─► If AmmoTag matches AmmoTypeTag:
         ReserveAmmo += Count
         Broadcast OnAmmoPickup(AmmoTag, Count)
         OnAmmoChanged
```

### Communications With

| Target | Method | Why |
|--------|--------|-----|
| [`BP_WeaponBase`](49_BP_WeaponBase.md) | Owner | Ammo check before fire, reload notification |
| [`BPC_InventoryComponent`](../04-inventory/25_BPC_InventoryComponent.md) | Get from Player | Add/remove ammo items from inventory |
| HUD Widget | Dispatcher (via Owner) | Ammo counter and low ammo warning |
| Save/Load System | GetSaveData / LoadFromData | Persist ammo state |
| Owner Animation BP | Direct | Reload animation play |
| [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) | Get Component | Click on empty fire attempt |

### Reuse Notes
- Designed for magazine-fed and chamber-fed weapons
- SingleBulletLoad used for shotguns / break-action weapons
- Reload can be interrupted by StartFire if loaded magazine > 0
- Ammo pickup broadcasts to allow UI, audio, VFX reactions