127 lines
5.0 KiB
Markdown
127 lines
5.0 KiB
Markdown
# 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 |