# BPC_FirearmSystem — Firearm Component

## Blueprint Spec — UE 5.5–5.7

---

### Parent Class
`ActorComponent`

### Dependencies
- [`BPC_AmmoComponent`](52_BPC_AmmoComponent.md) — Ammo management
- [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md) — Damage application
- [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) — Visual/audio feedback
- [`BPC_CameraStateLayer`](../02-player/14_BPC_CameraStateLayer.md) — Recoil & ADS
- [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md) — Interface for hit targets
- [`DA_WeaponData`](../14-data-assets/) — Weapon definition

### Purpose
Ranged weapon specialization. Handles line trace / projectile fire, weapon spread, bullet drop simulation, and multi-hit logic. Used by firearms (pistols, rifles, shotguns) and charge weapons.

### Variables

| Name | Type | Description |
|------|------|-------------|
| `FireType` | EFireType | Hitscan, Projectile, Hybrid |
| `ShootEffectType` | EShotEffect | Single, Spread, Charge |
| `Range` | Float | Max effective range (cm) |
| `SpreadAngle` | Float | Base spread in degrees |
| `SpreadRecoveryRate` | Float | Per-second recovery from spread |
| `CurrentSpread` | Float | Running spread (fired recently) |
| `MaxSpread` | Float | Spread cap |
| `BulletsPerShot` | Int | e.g. shotgun = 8 |
| `ProjectileClass` | Actor (Blueprint) | Only for Projectile / Hybrid fire types |
| `FireSocket` | FName | Muzzle attachment point |
| `MuzzleLocation` | USceneComponent | Muzzle transform reference |
| `HitScanImpacts` | Array<FHitResult> | Notify component for decals |

### Enums

| Enum | Values | Description |
|------|--------|-------------|
| `EFireType` | Hitscan, Projectile, Hybrid | Ray → Instant or Bullet actor |
| `EShotEffect` | SingleShot, SpreadShot, ChargeShot | Fire pattern |

### Functions

| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `PerformHitscanFire` | EWeaponFireMode | Array<FHitResult> | Line trace from camera to crosshair; no bullet |
| `SpawnProjectile` | Direction: FVector | Actor | Spawn projectile actor with initial velocity |
| `CalculateSpread` | — | FVector | Apply random offset within CurrentSpread cone |
| `OnFire_Implementation` | — | — | Override of WeaponBase::OnFire; runs hit scan or spawns projectile |
| `ApplyRecoil` | — | — | Add camera rotation via CameraStateLayer |
| `ConsumeAmmo` | — | — | Delegate to BPC_AmmoComponent |
| `GetEffectiveRange` | — | Float | Return weapon range from data asset |

### Blueprint Flow

```
[OnFire]
  └─► If FireType == Hitscan
         For i = 1 .. BulletsPerShot:
            AimDir = OwnerCamera.ForwardVector + CalculateSpread
            PerformHitscanFire returns HitResults
            For each hit:
                if actor implements I_Damageable:
                    BPC_DamageReceptionSystem.ApplyDamage(WeaponData.Damage, Hit)
                BPC_CombatFeedbackComponent.SpawnImpactFX(Hit)
  └─► If FireType == Projectile
         For i = 1 .. BulletsPerShot:
            AimDir = OwnerCamera.ForwardVector + CalculateSpread
            SpawnProjectile(AimDir * WeaponData.ProjectileSpeed)
  └─► If FireType == Hybrid
         Perform hitscan + spawn projectile for missed overlap area
  └─► ApplyRecoil
  └─► ConsumeAmmo
  └─► BPC_CombatFeedbackComponent.PlayMuzzleFlash
  └─► BPC_CombatFeedbackComponent.PlayFireSound

[CalculateSpread]
  └─► CurrentSpread = FMath::Min(CurrentSpread + WeaponData.SpreadPerShot, MaxSpread)
  └─► Return random vector in cone of CurrentSpread degrees

[OnFireStopped — super]
  └─► Begin spread recovery: CurrentSpread → 0 over SpreadRecoveryRate seconds
  └─► BPC_CombatFeedbackComponent.StopFireSound
```

### Communications With

| Target | Method | Why |
|--------|--------|-----|
| [`BPC_AmmoComponent`](52_BPC_AmmoComponent.md) | Get Component | Ammo check / consume |
| [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md) | Get Component | Apply damage to hit targets |
| [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) | Get Component | Muzzle flash, tracers, impact FX |
| [`BPC_CameraStateLayer`](../02-player/14_BPC_CameraStateLayer.md) | Get from Owner | Recoil animation |
| Owner WeaponAnimBP | Animation Instance | Fire / Reload animations |
| HUD Widget | Dispatcher | Ammo count update |

### Reuse Notes
- Hit scan fire uses camera forward, not muzzle forward, for accuracy. Muzzle is for FX only.
- Spread is cumulative while firing, resets on recovery timer.
- Projectile type requires a child BP implementing `AP_BaseProjectile` with velocity and lifetime.
- Renamed from `BP_RangedWeapon` to `BPC_FirearmSystem` per Master naming convention.
- Cross-references updated: `BPC_DamageHandlerComponent` → `BPC_DamageReceptionSystem`, `BPC_PlayerCameraManager` → `BPC_CameraStateLayer`, `DA_WeaponData` → `14-data-assets/`.

---

## Manual Implementation Guide

### Class Setup
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_FirearmSystem`
2. Attach to `BP_WeaponBase` subclass: `BP_RangedWeapon`
3. Add FireSocket SceneComponent on weapon mesh (muzzle position)

### Variable Init (BeginPlay)
```
Event BeginPlay
  ├─ Read WeaponData from Owner BP_WeaponBase
  ├─ Set FireType = WeaponData.FireType (Hitscan/Projectile/Hybrid)
  ├─ Set Range = WeaponData.EffectiveRange
  ├─ Set SpreadAngle = WeaponData.BaseSpread
  ├─ Set BulletsPerShot = WeaponData.PelletsPerShot
  ├─ Set CurrentSpread = 0.0
  └─ Cache: BPC_AmmoComponent, BPC_CombatFeedbackComponent, BPC_CameraStateLayer
```

### Function Node-by-Node

#### `OnFire_Implementation()` *(Overrides BP_WeaponBase.OnFire)*
```
Step 1: Get Camera Forward Vector
Step 2: Switch on FireType:
  Hitscan: ForLoop (BulletsPerShot):
    AimDir = Forward + CalculateSpread()
    LineTraceByChannel: Start=Camera, End=Camera+AimDir*Range
    If Hit & Implements I_Damageable: ApplyDamage(WeaponData.Damage, HitResult)
    SpawnImpactFX(HitResult)
  Projectile: ForLoop (BulletsPerShot):
    Spawn ProjectileClass at FireSocket, velocity=AimDir*Speed
  Hybrid: Hitscan + projectile for near-miss area
Step 3: ApplyRecoil → CameraShake or AddControllerPitch/Yaw
Step 4: ConsumeAmmo on BPC_AmmoComponent
Step 5: PlayMuzzleFlash + PlayFireSound on CombatFeedback
Step 6: CurrentSpread += SpreadIncreasePerShot (clamped to MaxSpread)
```

#### `CalculateSpread()` → Vector *(Pure)*
```
RandomFloat(-1,1)*CurrentSpread → YawOffset
RandomFloat(-1,1)*CurrentSpread → PitchOffset
MakeRotator(PitchOffset, YawOffset, 0) → GetForwardVector
```

### Build Checklist
- [ ] Create BPC_FirearmSystem, attach to BP_RangedWeapon
- [ ] Add FireSocket at muzzle
- [ ] Implement OnFire with hitscan/projectile/hybrid switch
- [ ] Implement CalculateSpread
- [ ] Wire to AmmoComponent, CombatFeedback, CameraStateLayer
- [ ] Create ProjectileClass with ProjectileMovement for projectile weapons
- [ ] Test: fire at target → damage registers → FX plays → ammo count drops