# 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 | 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 | 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