add blueprints

This commit is contained in:
Lefteris Notas
2026-05-19 13:22:27 +03:00
parent f71bc678b2
commit 411edea8ce
138 changed files with 23330 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
# 49 — BP_WeaponBase
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`Actor` (attached to character via `AttachToComponent`)
### Dependencies
- [`BPC_InventoryComponent`](../04-inventory/25_BPC_InventoryComponent.md)
- [`BPC_EquipmentSystem`](../04-inventory/28_BPC_EquipmentSystem.md)
- [`BPC_PlayerCameraManager`](../02-player/14_BPC_PlayerCameraManager.md)
- [`BPC_DamageHandler`](53_BPC_DamageHandlerComponent.md)
- [`DA_WeaponData`](../12-content/60_DA_WeaponDataAsset.md)
- [`I_Damageable`](../01-core/03_I_Damageable.md)
- [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md)
### Purpose
Base class for all weapon actors (ranged and melee). Provides common weapon lifecycle: equip, unequip, fire input, ammo tracking integration, aim-down-sights, and weapon state machine. Designed to be extended by [`BP_RangedWeapon`](50_BP_RangedWeapon.md) and [`BP_MeleeWeapon`](51_BP_MeleeWeapon.md).
### Responsibilities
- Attach/detach from character socket on equip/unequip
- Manage weapon state (holstered / equipping / ready / firing / reloading)
- Handle fire input (start / stop) — base delegates to subclass
- Track aim-down-sights state and apply camera FOV transition
- Fire event dispatchers for UI state changes
- Communicate with [`BPC_EquipmentSystem`](../04-inventory/28_BPC_EquipmentSystem.md) for weapon selection
- Communicate with inventory for ammo consumption
### Does NOT Handle
- Specific fire logic (raycast / projectile / melee hitbox) — that is subclass
- Ammo math (that is [`BPC_AmmoComponent`](52_BPC_AmmoComponent.md))
- Damage calculation (that is [`BPC_DamageHandler`](53_BPC_DamageHandlerComponent.md))
- Visual / audio feedback (that is [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md))
- UI display (that is HUD widget)
### Variables
| Name | Type | Description |
|------|------|-------------|
| `WeaponData` | DA_WeaponData | Weapon definition asset |
| `WeaponState` | EWeaponState | Current state machine |
| `SkeletalMesh` | USkeletalMeshComponent | Weapon visual |
| `WeaponRoot` | USceneComponent | Attachment root |
| `HolsterSocket` | FName | Socket name for holstered |
| `EquipSocket` | FName | Socket name for ready |
| `AimDownSightsFOV` | Float | FOV when ADS (e.g. 60.0) |
| `DefaultFOV` | Float | Normal FOV |
| `ADSInterpSpeed` | Float | Camera blend speed |
| `bIsAiming` | Bool | Currently ADS |
| `FireRateTimer` | FTimerHandle | Fire rate control |
| `bCanFire` | Bool | Not on cooldown |
| `EquipDuration` | Float | Seconds for equip animation |
| `HolsterDuration` | Float | Seconds for holster animation |
| `RecoilPitch` | Float | Camera pitch per shot |
| `RecoilYaw` | Float | Camera yaw per shot |
### Enums
| Enum | Values | Description |
|------|--------|-------------|
| `EWeaponState` | Holstered, Equipping, Ready, Firing, Reloading, Holstering, Broken | Weapon lifecycle |
| `EWeaponFireMode` | SemiAutomatic, FullAutomatic, BurstFire, ChargeAndRelease, MeleeSwing | Fire type |
### Functions / Events
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `Equip` | — | — | Play equip anim, attach to EquipSocket, set state to Ready |
| `Holster` | — | — | Play holster anim, attach to HolsterSocket, set state to Holstered |
| `StartFire` | — | — | Begin fire loop (if auto) or single fire (semi) |
| `StopFire` | — | — | End fire loop |
| `CanFire` | — | Bool | Check state, ammo, cooldown |
| `OnFire` | — | — | Virtual: subclass implements actual fire logic |
| `StartReload` | — | — | Begin reload sequence |
| `FinishReload` | — | — | Called after reload anim |
| `StartAim` | — | — | Blend camera to ADS FOV |
| `StopAim` | — | — | Blend camera back to DefaultFOV |
| `SetWeaponState` | NewState: EWeaponState | — | Change state and broadcast |
| `GetWeaponTag` | — | GameplayTag | Return weapon identifier |
| `OnWeaponBroken` | — | — | Weapon disabled (durability zero) |
### Event Dispatchers
| Name | Parameters | Fired When |
|------|-----------|-----------|
| `OnWeaponStateChanged` | NewState: EWeaponState, OldState: EWeaponState | State machine change |
| `OnWeaponEquipped` | WeaponRef: BP_WeaponBase | Ready to use |
| `OnWeaponHolstered` | WeaponRef: BP_WeaponBase | Stored away |
| `OnFireStarted` | — | Fire input received and valid |
| `OnFireStopped` | — | Fire input released |
| `OnAimStarted` | — | ADS enter |
| `OnAimStopped` | — | ADS exit |
| `OnReloadStarted` | — | Reload begin |
| `OnReloadCompleted` | — | Reload finish |
| `OnWeaponBroken` | — | Durability depleted |
### Blueprint Flow
```
[StartFire]
└─► If !CanFire → return
└─► Set WeaponState = Firing
└─► Broadcast OnFireStarted
└─► Call OnFire (subclass override)
└─► If FireMode == FullAutomatic → start FireRateTimer loop
└─► If FireMode == SemiAutomatic → block until timer clears
[StopFire]
└─► Clear FireRateTimer
└─► If FireMode == BurstFire → let burst complete, then stop
└─► Set WeaponState = Ready
└─► Broadcast OnFireStopped
[StartReload]
└─► If WeaponState != Ready → return
└─► Set WeaponState = Reloading
└─► Broadcast OnReloadStarted
└─► Start animation or timer for reload duration
└─► On completion → FinishReload
[FinishReload]
└─► BPC_AmmoComponent.RefillAmmo(WeaponData.MagazineSize)
└─► Set WeaponState = Ready
└─► Broadcast OnReloadCompleted
[StartAim / StopAim]
└─► Set bIsAiming
└─► Get BPC_PlayerCameraManager from owner
└─► Set FOV with interp speed
└─► Broadcast OnAimStarted / OnAimStopped
```
### Communications With
| Target System | Method | Why |
|---------------|--------|-----|
| [`BPC_EquipmentSystem`](../04-inventory/28_BPC_EquipmentSystem.md) | Direct | Get/return weapon socket assignment |
| [`BPC_AmmoComponent`](52_BPC_AmmoComponent.md) | Get Component | Check / consume / refill ammo |
| [`BPC_DamageHandler`](53_BPC_DamageHandlerComponent.md) | Get Component | Delegate damage processing |
| [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) | Get Component | Play muzzle flash, hit FX, sounds |
| [`BPC_PlayerCameraManager`](../02-player/14_BPC_PlayerCameraManager.md) | Get from Owner | ADS FOV blend |
| [`BPC_InventoryComponent`](../04-inventory/25_BPC_InventoryComponent.md) | Get from Owner | Check ammo inventory |
| HUD Widget | Dispatcher (via GM) | Update crosshair, ammo display |
| Owner (Player Character) | Direct | Animation blueprint queries weapon state |
### Reuse Notes
Subclass for ranged or melee specific fire implementations. The state machine prevents firing during reload, equip, or holster sequences. Weapons are data-driven via `DA_WeaponData` — design changes never require blueprint edits.

View File

@@ -0,0 +1,127 @@
# 52 — BPC_AmmoComponent
## Blueprint Spec — UE 5.55.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.01.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

View File

@@ -0,0 +1,149 @@
# 54 — BPC_CombatFeedbackComponent
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- [`BP_WeaponBase`](49_BP_WeaponBase.md) — Owner weapon
- [`BPC_DamageHandlerComponent`](53_BPC_DamageHandlerComponent.md) — Damage result data
- [`DA_WeaponData`](../12-content/60_DA_WeaponDataAsset.md) — FX/sound references
- [`DA_ImpactFXConfig`](../12-content/62_DA_ImpactFXConfigDataAsset.md) — Surface impact map
- [`AudioManager`](../09-atmosphere/69_BPC_AudioManager.md) — Spatial audio requests
- [`VFXManager`](../09-atmosphere/70_BPC_VFXManager.md) — Particle system pooling
### Purpose
Centralized visual and audio feedback for combat actions. Decouples weapon and damage logic from presentation. Manages muzzle flash, tracer trajectories, impact decals and particles, bullet holes, hit confirmation UI numbers, weapon sounds (fire, reload, empty click, melee whoosh), and screen effects (camera shake, hit directional indicator). Implemented as a reusable component attached to weapon actors.
### Variables
| Name | Type | Description |
|------|------|-------------|
| `WeaponMesh` | USkeletalMeshComponent | Reference to owner weapon mesh |
| `MuzzleFlashPS` | UParticleSystem | Muzzle flash effect |
| `TracerPS` | UParticleSystem | Tracer trail effect |
| `TracerSpawnChance` | Float | 0.01.0 probability per shot |
| `MuzzleSocketName` | FName | Spawn point name |
| `ImpactDecalMap` | TMap<PhysicalMaterial, UMaterialInterface> | Surface material → decal |
| `ImpactParticleMap` | TMap<PhysicalMaterial, UParticleSystem> | Surface → hit particle |
| `ImpactDecalLifeSpan` | Float | Seconds before decal fades |
| `ImpactDecalSize` | FVector | Decal projection scale |
| `FireSound` | USoundBase | Fire sound cue |
| `FireSoundTail` | USoundBase | Tail loop (full auto) |
| `ReloadSound` | USoundBase | Reload start |
| `ReloadFinishSound` | USoundBase | Reload complete |
| `EmptyClickSound` | USoundBase | Empty magazine fire attempt |
| `MeleeWhooshSound` | USoundBase | Melee swing whoosh |
| `MeleeHitSound` | USoundBase | Melee impact |
| `BlockSound` | USoundBase | Block/parry impact |
| `CameraShakeClass` | TSubclassOf<UCameraShakeBase> | Per-weapon shake profile |
| `ScreenHitIndicatorClass` | TSubclassOf<UUserWidget> | Hit direction HUD overlay |
| `HitNumberWidgetClass` | TSubclassOf<UUserWidget> | Floating damage number |
| `BulletHolePool` | Array<ABulletHoleActor> | Reusable pooled actors |
| `MaxBulletHoles` | Int | Pool limit (e.g. 50) |
### Structs
| Struct | Fields | Description |
|--------|--------|-------------|
| `FImpactContext` | HitLocation: FVector, HitNormal: FVector, HitMaterial: UPhysicalMaterial, bIsCrit: Bool, Damage: Float, bIsKill: Bool | Full hit data for FX |
### Functions
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `PlayMuzzleFlash` | — | — | Spawn muzzle particle at socket |
| `SpawnTracer` | EndPoint: FVector | — | Line trail particle from muzzle to impact |
| `SpawnImpactFX` | Impact: FImpactContext | — | Decal + particle at hit location |
| `SpawnBulletHole` | Location: FVector, Rotation: FRotator | AActor | Pooled bullet hole actor |
| `PlayFireSound` | — | — | Fire sound with optional tail |
| `StopFireSound` | — | — | End tail loop |
| `PlayReloadSound` | — | — | Reload start |
| `PlayReloadFinishSound` | — | — | Reload complete |
| `PlayEmptyClickSound` | — | — | Dry fire |
| `PlayMeleeWhoosh` | — | — | Melee attack sound |
| `PlayMeleeHitSound` | Impact: FImpactContext | — | Melee impact sound |
| `PlayBlockSound` | — | — | Block/parry impact |
| `PlayCameraShake` | — | — | Fire camera shake |
| `ShowHitNumber` | Damage: Float, Location: FVector, IsCrit: Bool | — | Floating damage widget |
| `ShowHitIndicator` | DamageDirection: FVector | — | Screen edge indicator |
| `GetImpactContextFromHit` | HitResult: FHitResult | FImpactContext | Extract material, location etc. |
| `PlayHitConfirmationSound` | bIsKill: Bool | — | Hit marker or kill sound |
| `InitializePool` | — | — | Spawn bullet hole pool |
### Blueprint Flow
```
[OnFire → called by WeaponBase]
└─► PlayMuzzleFlash
└─► SpawnTracer(EndPoint)
└─► PlayFireSound (if full auto: start tail loop)
└─► PlayCameraShake
[OnHit → called by DamageHandler dispatcher]
└─► FX Pipeline:
ImpactCtx = GetImpactContextFromHit(Hit)
If ImpactCtx.bIsCrit: PlayCritImpactFX
Else: SpawnImpactFX(ImpactCtx)
SpawnBulletHole(ImpactCtx.HitLocation, RotationFromNormal)
PlayMeleeHitSound or generic hit sound
ShowHitNumber(ImpactCtx.Damage, ImpactCtx.HitLocation, ImpactCtx.bIsCrit)
ShowHitIndicator(GetDirectionFromInstigator)
If ImpactCtx.bIsKill: PlayKillConfirmation
[OnAmmoEmpty → called by AmmoComponent dispatcher]
└─► PlayEmptyClickSound
[OnReloadStarted/Completed → called by AmmoComponent dispatcher]
└─► PlayReloadSound / PlayReloadFinishSound
```
### Pooled Bullet Hole System
```
[InitializePool]
└─► For i = 1 .. MaxBulletHoles:
Spawn ABulletHoleActor deactivated
Add to BulletHolePool
[SpawnBulletHole]
└─► Find first inactive actor in pool
└─► If none → recycle oldest active
└─► Set transform, set decal material based on surface
└─► Activate, start life timer
```
### Impact Decal Material Mapping
| Physical Material | Decal Material | Particle System |
|-------------------|---------------|-----------------|
| Concrete | T_ConcreteDecal | P_ConcreteHit |
| Metal | T_MetalDecal | P_MetalSparks |
| Wood | T_WoodDecal | P_WoodSplinters |
| Flesh | T_FleshDecal | P_BloodSplash |
| Glass | T_GlassDecal | P_GlassShards |
| Water | T_WaterRipple | P_WaterSplash |
| Default | T_BulletHole | P_GenericHit |
### Communications With
| Target | Method | Why |
|--------|--------|-----|
| [`BP_WeaponBase`](49_BP_WeaponBase.md) | Owner | Fire/reload/empty event hooks |
| [`BPC_AmmoComponent`](52_BPC_AmmoComponent.md) | Dispatcher listener | Empty click, reload sounds |
| [`BPC_DamageHandlerComponent`](53_BPC_DamageHandlerComponent.md) | Dispatcher listener | Hit FX on damage dealt |
| [`BPC_PlayerCameraManager`](../02-player/14_BPC_PlayerCameraManager.md) | Get from Owner | Camera shake |
| [`AudioManager`](../09-atmosphere/69_BPC_AudioManager.md) | Get Game Instance | Spatial audio for distant sounds |
| [`VFXManager`](../09-atmosphere/70_BPC_VFXManager.md) | Get Game Instance | Particle pooling |
| HUD Widget | Direct or Dispatcher | Hit marker and damage numbers |
| Bullet Hole Pool | Direct | Spawn / recycle |
### Reuse Notes
- Pure presentation component: swap entire feedback profile by replacing DA_WeaponData FX references
- Impact material map driven by physical materials, no hardcoded surface checks
- Pooled bullet holes prevent spawn/despawn overhead
- Camera shake per weapon allows distinct feel (pistol vs shotgun)
- All sounds use distance-based attenuation curves from the audio manager

View File

@@ -0,0 +1,123 @@
# BPC_DamageReceptionSystem — Damage Reception System
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md) — Interface on damage targets
- [`BP_WeaponBase`](49_BP_WeaponBase.md) — Owner weapon (optional)
- [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) — Damage recipient
- [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) — Damage FX forwarding
- [`DA_WeaponData`](../14-data-assets/) — Damage/penetration values
- `Engine.DamageType` — UE5 damage type system
### Purpose
Centralized damage calculation and application service. Decouples weapon fire logic from damage math. Handles damage types, armor penetration, critical hit rolls, damage falloff over distance, and damage event logging. Can be attached to weapons, projectiles, or trap actors.
### Variables
| Name | Type | Description |
|------|------|-------------|
| `DamageMultiplier` | Float | Per-instance modifier (e.g. weak spot) |
| `bUseDamageFalloff` | Bool | Enable distance-based damage reduction |
| `FalloffStartDistance` | Float | Distance before falloff begins (cm) |
| `FalloffEndDistance` | Float | Distance where damage reaches minimum |
| `MinDamageFactor` | Float | 0.01.0, minimum damage at max range |
| `DamageType` | TSubclassOf<UDamageType> | UE5 damage type class |
| `LastDamageDealt` | float | Most recent damage output (debug/logging) |
| `LastHitActor` | AActor | Most recent recipient |
| `bShowDamageNumbers` | Bool | Debug toggle |
| `CritChanceOverride` | Float | If > 0, overrides weapon default |
| `CritMultiplierOverride` | Float | If > 0, overrides weapon default |
### Structs
| Struct | Fields | Description |
|--------|--------|-------------|
| `FDamageResult` | DamageDealt: Float, bWasCrit: Bool, bWasBlocked: Bool, DamageTypeTag: FGameplayTag, HitLocation: FVector, HitNormal: FVector | Damage calculation output |
| `FDamageRequest` | BaseDamage: Float, Instigator: AActor, DamageCauser: AActor, HitInfo: FHitResult, DamageType: TSubclassOf<UDamageType>, bIsMelee: Bool | Incoming damage data |
### Functions
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `ProcessDamageRequest` | Request: FDamageRequest | FDamageResult | Main calculation entry |
| `ApplyDamageToActor` | Target: AActor, Request: FDamageRequest | Bool | Apply via interface or engine ApplyDamage |
| `CalculateDamageFalloff` | BaseDamage: Float, Distance: Float | Float | Linear interpolation between start/end |
| `RollForCriticalHit` | CritChance: Float | Bool | Random roll against chance |
| `CalculateArmorPenetration` | BaseDamage: Float, ArmorValue: Float | Float | Armor reduction math |
| `ApplyWeakSpotMultiplier` | Damage: Float, WeakSpotTag: FGameplayTag | Float | From character weak spot config |
| `OnDamageApplied` | Result: FDamageResult | — | Broadcast event |
| `GetDistanceToTarget` | Target: AActor | Float | Distance from weapon muzzle to hit |
| `LogDamageEvent` | Result: FDamageResult | — | For analytics / combat log |
| `SetDamageMultiplier` | Multiplier: Float | — | Runtime override (e.g. buff) |
### Event Dispatchers
| Name | Parameters | Fired When |
|------|-----------|-----------|
| `OnDamageDealt` | Target: AActor, Damage: Float, IsCrit: Bool, DamageTypeTag: FGameplayTag | Damage applied successfully |
| `OnDamageBlocked` | Target: AActor, BlockedDamage: Float | Damage reduced by armor / block |
| `OnCriticalHit` | Target: AActor, Damage: Float | Critical hit confirmed |
| `OnWeakSpotHit` | Target: AActor, WeakSpotTag: FGameplayTag | Weak spot damage |
| `OnKillConfirmed` | Target: AActor | Target health <= 0 |
### Blueprint Flow
```
[ProcessDamageRequest]
└─► CurrentDamage = Request.BaseDamage
└─► If bUseDamageFalloff:
Distance = GetDistanceToTarget(Request.Instigator)
CurrentDamage = CalculateDamageFalloff(CurrentDamage, Distance)
└─► If Request.bIsMelee:
CurrentDamage *= DamageMultiplier
└─► // Crit roll
bCrit = RollForCriticalHit(CritChanceOverride > 0 ? CritChanceOverride : WeaponData.CritChance)
If bCrit: CurrentDamage *= CritMultiplierOverride > 0 ? CritMultiplierOverride : WeaponData.CritMultiplier
└─► // Armor penetration (if target has armor system)
If target has component:
ArmorValue = target.GetArmorValue()
CurrentDamage = CalculateArmorPenetration(CurrentDamage, ArmorValue)
Else: Armor reduction not applied
└─► // Weak spot
If hit bone is weak spot:
CurrentDamage = ApplyWeakSpotMultiplier(CurrentDamage, WeakSpotTag)
└─► Populate FDamageResult
└─► ApplyDamageToActor(Request.Instigator, Result)
└─► OnDamageApplied(Result)
└─► If target health <= 0: OnKillConfirmed(target)
└─► Return Result
```
```
[ApplyDamageToActor]
└─► If target implements I_Damageable:
target.I_Damageable.ApplyDamage(Result)
└─► Else:
target.TakeDamage(Result.DamageDealt, DamageEvent, ...)
└─► Return true if successfully applied
```
### Communications With
| Target | Method | Why |
|--------|--------|-----|
| [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md) | Interface call | Primary damage path |
| [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) | Get on Target | Direct health modify |
| [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) | Get from Weapon Owner | Damage numbers, hit confirmation |
| [`DA_WeaponData`](../14-data-assets/) | Direct read | Base damage, crit, falloff params |
| Analytics / Stats Tracker | Dispatcher | Damage tracking for stats |
| HUD | Dispatcher (via GM) | Damage numbers and death feed |
### Reuse Notes
- Pure calculation component — no visual or audio feedback
- Damage falloff is linear between start and end distance
- Armor penetration formula: `FinalDamage = Damage * (100 / (100 + ArmorValue))` (standard UE style)
- Weak spots are identified by bone name or gameplay tag on the target actor
- Dispatchers allow UI and feedback to react without coupling
- Renamed from `BPC_DamageHandlerComponent` to `BPC_DamageReceptionSystem` per Master naming convention.

View File

@@ -0,0 +1,200 @@
# BPC_DeathCauseTracker — Death Cause Tracker
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- **Requires:** [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) — Receives OnDeath dispatcher for recording cause
- **Required By:** [`BPC_DeathHandlingSystem`](../05-saveload/BPC_DeathHandlingSystem.md) — Reads LastDeathCause and DeathHistory
- **Required By:** [`BPC_RunHistoryTracker`](../05-saveload/BPC_RunHistoryTracker.md) — Reads death history for summary
- **Required By:** [`BPC_AdaptiveEnvironmentDirector`](../10-adaptive/BPC_AdaptiveEnvironmentDirector.md) — Reads death patterns for adaptation
- **Engine/Plugin Requirements:** GameplayTags (for ChapterTag in DeathRecord)
### Purpose
Records the cause and context of the player's death for use by the death handling system, adaptive systems, and run summary. Tracks full session death history with cause type, location, instigator, timestamp, and chapter context.
---
## 1. Enums
```text
Enum Name: E_DeathCause
(DisplayName = "Death Cause")
Values:
Melee = 0 // Killed by melee attack
Projectile = 1 // Killed by projectile/firearm
Environmental = 2 // Killed by environment (fall, trap, fire zone)
Scripted = 3 // Scripted/cinematic kill
Psychic = 4 // Killed by psychic/supernatural force
InstantKill = 5 // Instant-kill mechanic
Unknown = 6 // Cause cannot be determined
```
---
## 2. Structs
### `S_DeathRecord`
| Field | Type | Description |
|-------|------|-------------|
| `Cause` | E_DeathCause | How the player died |
| `Location` | Vector | World position of death |
| `Instigator` | Actor | What/who killed the player (nullable) |
| `Timestamp` | Float | Game time of death in seconds |
| `ChapterTag` | GameplayTag | Which chapter the death occurred in |
---
## 3. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `MaxDeathHistorySize` | Integer | 50 | DeathTracking | Maximum number of death records to retain |
### Internal (Private / Protected, No Expose)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `LastDeathCause` | E_DeathCause | Unknown | Internal | Cause of the most recent death |
| `LastDeathLocation` | Vector | (0,0,0) | Internal | World position of last death |
| `LastDeathInstigator` | Actor | None | Internal | Actor that caused last death |
| `DeathHistory` | Array of S_DeathRecord | Empty | Internal | Full session death log |
---
## 4. Functions
### Public Functions
#### `RecordDeath` → `void`
- **Description:** Called when player dies. Stores cause, location, instigator, timestamp, and chapter tag into a new S_DeathRecord.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Cause` | E_DeathCause | How the player died |
| `Location` | Vector | World position of death |
| `Instigator` | Actor | Killing actor (optional) |
- **Blueprint Authority:** Any
- **Flow:** Create S_DeathRecord → populate fields → add to DeathHistory → update LastDeath* variables → trim history if over MaxDeathHistorySize → broadcast OnDeathRecorded
#### `GetLastDeathCause` → `E_DeathCause`
- **Description:** Returns the cause of the most recent death.
- **Parameters:** None
- **Blueprint Authority:** Any
#### `GetLastDeathLocation` → `Vector`
- **Description:** Returns the world location of the most recent death.
- **Parameters:** None
- **Blueprint Authority:** Any
#### `GetLastDeathInstigator` → `Actor`
- **Description:** Returns the actor that caused the most recent death (may be None).
- **Parameters:** None
- **Blueprint Authority:** Any
#### `GetDeathHistory` → `Array of S_DeathRecord`
- **Description:** Returns the full death history for this session.
- **Parameters:** None
- **Blueprint Authority:** Any
#### `GetDeathCount` → `Integer`
- **Description:** Returns the total number of deaths this session.
- **Parameters:** None
- **Blueprint Authority:** Any
#### `ClearDeathHistory` → `void`
- **Description:** Empties the death history and resets last death variables. Called on new game.
- **Parameters:** None
- **Blueprint Authority:** Server only (if multiplayer)
---
## 5. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnDeathRecorded` | DeathRecord: S_DeathRecord | Public | New death entry added to history |
| `OnFirstDeath` | Cause: E_DeathCause | Public | First death of the session (for tutorials/achievements) |
| `OnDeathCountThreshold` | Count: Integer | Public | Death count reaches a configured threshold (e.g., 10, 25, 50) |
---
## 6. Overridden Events / Custom Events
### Event: `OnHealthSystemDeath`
- **Description:** Subscribes to [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md)`OnDeath` dispatcher on BeginPlay. Routes damage event data to `RecordDeath`.
- **Flow:**
1. Extract DeathCause from S_DamageEvent
2. Map DamageType to E_DeathCause (Physical→Melee or Projectile, Fire→Environmental, etc.)
3. Get player world location
4. Call RecordDeath(Cause, Location, Instigator)
---
## 7. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[BeginPlay] --> B[Subscribe to BPC_HealthSystem.OnDeath]
B --> C[Idle — waiting for death]
C --> D{OnDeath dispatcher fires}
D --> E[Map DamageType → E_DeathCause]
E --> F[Get player world location]
F --> G[Get GS_CoreGameState.ActiveChapterTag]
G --> H[Create S_DeathRecord]
H --> I[Add to DeathHistory array]
I --> J[Update LastDeathCause / Location / Instigator]
J --> K{DeathHistory count == 1?}
K -->|Yes| L[Broadcast OnFirstDeath]
K -->|No| M[Check threshold milestones]
L --> N[Broadcast OnDeathRecorded]
M --> N
```
---
## 8. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) | Dispatcher (`OnDeath`) | `S_DamageEvent` (read Type, Instigator, HitLocation) |
| [`BPC_DeathHandlingSystem`](../05-saveload/BPC_DeathHandlingSystem.md) | Direct read | `LastDeathCause`, `LastDeathLocation`, `LastDeathInstigator` |
| [`BPC_RunHistoryTracker`](../05-saveload/BPC_RunHistoryTracker.md) | Direct read | `DeathHistory` array |
| [`BPC_AdaptiveEnvironmentDirector`](../10-adaptive/BPC_AdaptiveEnvironmentDirector.md) | Direct read | `DeathHistory` for death pattern analysis |
| [`SS_AchievementSystem`](../11-meta/SS_AchievementSystem.md) | Dispatcher (`OnDeathRecorded`) | Death count and cause for achievement checks |
| [`GS_CoreGameState`](../01-core/06_GS_CoreGameState.md) | Direct read | `ActiveChapterTag` for death record context |
---
## 9. Validation / Testing Checklist
- [ ] E_DeathCause enum has all 7 values defined
- [ ] S_DeathRecord struct contains all 5 fields
- [ ] RecordDeath correctly appends to DeathHistory and updates LastDeath* variables
- [ ] DeathHistory trimmed when exceeding MaxDeathHistorySize
- [ ] OnFirstDeath fires only on the first death of the session
- [ ] ClearDeathHistory resets all state for new game
- [ ] Edge case: Instigator can be None (environmental/fall deaths)
- [ ] Edge case: rapid successive deaths all recorded independently
- [ ] Edge case: death during cutscene with no damage event maps to Scripted or Unknown
---
## 10. Reuse Notes
- E_DeathCause can be extended per project (add new enum values)
- S_DeathRecord fields are generic enough for any genre
- MaxDeathHistorySize prevents unbounded memory growth in long sessions
- Death history is not persisted to save file by default — wire to I_Persistable if cross-session tracking needed
- ChapterTag in death record enables chapter-based analytics and adaptive tuning
---
*Specification based on Master Section 5.8, line 1836.*

View File

@@ -0,0 +1,105 @@
# BPC_FirearmSystem — Firearm Component
## Blueprint Spec — UE 5.55.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/`.

View File

@@ -0,0 +1,192 @@
# BPC_HitReactionSystem — Hit Reaction System
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- **Requires:** [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) — Receives damage events
- **Requires:** [`BPC_CameraStateLayer`](../02-player/14_BPC_CameraStateLayer.md) — Camera trauma effects
- **Requires:** [`S_DamageEvent`](../02-player/08_BPC_HealthSystem.md) — Damage event struct (E_DamageType, Amount, HitLocation, HitNormal)
- **Requires:** [`E_DamageType`](../01-core/03_I_InterfaceLibrary.md) — Damage type enum for montage selection
- **Required By:** [`BPC_AdaptiveEnvironmentDirector`](../10-adaptive/BPC_AdaptiveEnvironmentDirector.md) — Reads trauma intensity for atmosphere
- **Engine/Plugin Requirements:** Animation Blueprint (ABP_PlayerBody), GASP animation hooks
### Purpose
Drives physical hit reaction behaviour: flinch animations, ragdoll blends, and camera trauma. Processes incoming damage events and triggers appropriate reaction animations based on damage magnitude, direction, and type.
---
## 1. Enums
*Uses `E_DamageType` from [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) — Physical, Fire, Psychic, Environmental, InstantKill, Scripted.*
---
## 2. Structs
*No new structs defined. Uses `S_DamageEvent` from [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md).*
---
## 3. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `FlinchThreshold` | Float | 5.0 | HitReaction | Minimum damage to trigger flinch animation |
| `RagdollThreshold` | Float | 50.0 | HitReaction | Damage amount that triggers ragdoll blend |
| `TraumaDecayRate` | Float | 2.0 | HitReaction | Camera trauma points recovered per second |
| `HitReactionMontages` | Map (E_DamageType → AnimMontage) | Empty | HitReaction | Per-damage-type hit reaction animations |
### Internal (Private / Protected, No Expose)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `CurrentTrauma` | Float | 0.0 | Internal | Accumulated camera trauma level |
| `bIsReacting` | Bool | False | Internal | Reaction animation currently playing |
| `LastDamageDirection` | Vector | (0,0,0) | Internal | Direction of most recent damage for animation blend |
| `NextReactionIndex` | Integer | 0 | Internal | Cycles through available montages per type for variety |
---
## 4. Functions
### Public Functions
#### `ProcessHitReaction` → `void`
- **Description:** Main entry point. Called when player receives damage. Determines reaction type based on damage amount vs thresholds.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `DamageEvent` | S_DamageEvent | Full damage context from HealthSystem |
- **Blueprint Authority:** Any
- **Flow:** Checks thresholds → selects montage → plays animation → applies trauma → broadcasts dispatchers
#### `ApplyTrauma` → `void`
- **Description:** Adds camera trauma based on damage amount.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Amount` | Float | Trauma points to add |
- **Blueprint Authority:** Any
#### `GetCurrentTrauma` → `Float`
- **Description:** Returns current accumulated trauma level (0100).
- **Parameters:** None
- **Blueprint Authority:** Any
#### `ResetTrauma` → `void`
- **Description:** Clears all accumulated camera trauma to zero.
- **Parameters:** None
- **Blueprint Authority:** Any
### Protected / Private Functions
#### `SelectHitReactionMontage` → `AnimMontage`
- **Description:** Picks a hit reaction montage based on damage type and cycles through available options for variety.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `DamageType` | E_DamageType | Type of damage received |
| `DamageAmount` | Float | Magnitude of damage |
- **Flow:** Look up HitReactionMontages map by damage type → cycle through entries → return selected montage
#### `TickTraumaDecay` → `void`
- **Description:** Called on tick to decay camera trauma toward zero at TraumaDecayRate.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `DeltaTime` | Float | Frame delta time |
- **Flow:** `CurrentTrauma = FMath::FInterpTo(CurrentTrauma, 0.0, DeltaTime, TraumaDecayRate)`
---
## 5. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnFlinchTriggered` | DamageType: E_DamageType, Amount: Float | Public | Flinch animation fired (damage below ragdoll threshold) |
| `OnRagdollBlend` | Amount: Float, Direction: Vector | Public | Ragdoll blend triggered (damage exceeded ragdoll threshold) |
| `OnTraumaChanged` | CurrentTrauma: Float | Public | Trauma level changed (for camera/screen effects) |
| `OnHitReactionComplete` | DamageType: E_DamageType | Public | Reaction animation finished playing |
---
## 6. Overridden Events / Custom Events
### Event: `ReceiveDamage`
- **Description:** Called by [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md) when player takes damage. Routes to `ProcessHitReaction`.
- **Flow:**
1. Extract damage amount and type from DamageEvent
2. If DamageAmount >= FlinchThreshold → ProcessHitReaction
3. If DamageAmount >= RagdollThreshold → trigger ragdoll blend instead
4. Calculate LastDamageDirection from HitLocation relative to player
5. ApplyTrauma proportional to damage amount
---
## 7. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[ReceiveDamage called] --> B{Damage >= RagdollThreshold?}
B -->|Yes| C[Disable input temporarily]
B -->|No| D{Damage >= FlinchThreshold?}
C --> E[Play ragdoll physics blend]
D -->|Yes| F[SelectHitReactionMontage by DamageType]
D -->|No| G[Skip reaction, only apply trauma]
F --> H[Play montage with directional blend]
H --> I[Broadcast OnFlinchTriggered]
I --> J[Wait for montage end]
J --> K[Broadcast OnHitReactionComplete]
E --> L[Set bIsReacting = true]
L --> M[Wait for ragdoll timer]
M --> N[Recover from ragdoll]
N --> K
G --> O[ApplyTrauma proportional to damage]
K --> O
O --> P[Broadcast OnTraumaChanged]
P --> Q[Camera system reads trauma]
```
---
## 8. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md) | Direct call | `S_DamageEvent` |
| [`BPC_CameraStateLayer`](../02-player/14_BPC_CameraStateLayer.md) | Dispatcher (`OnTraumaChanged`) | `CurrentTrauma: Float` |
| [`WBP_ScreenEffectController`](../06-ui/WBP_ScreenEffectController.md) | Dispatcher (`OnTraumaChanged`) | `CurrentTrauma: Float` |
| [`ABP_PlayerBody`](../02-player/13_BPC_EmbodimentSystem.md) | Direct (anim var write) | `LastDamageDirection`, reaction montage reference |
| [`BPC_AdaptiveEnvironmentDirector`](../10-adaptive/BPC_AdaptiveEnvironmentDirector.md) | Direct read | `CurrentTrauma` via getter |
---
## 9. Validation / Testing Checklist
- [ ] FlinchThreshold: damage at 5.0+ triggers flinch animation
- [ ] RagdollThreshold: damage at 50.0+ triggers ragdoll blend
- [ ] TraumaDecayRate: trauma reduces to zero over time when no damage received
- [ ] HitReactionMontages map: correct montage plays per E_DamageType
- [ ] Edge case: zero damage events do not trigger any reaction
- [ ] Edge case: rapid succession hits cycle through montage variations
- [ ] Edge case: death event (HealthSystem OnDeath) skips flinch, goes directly to ragdoll
---
## 10. Reuse Notes
- FlinchThreshold and RagdollThreshold can be tuned per project for desired combat feel
- HitReactionMontages map uses E_DamageType as key — add new damage types without modifying core logic
- Trauma system is separate from camera shake — trauma drives persistent wobble, shake is transient
- For non-combat projects, set FlinchThreshold very high (e.g., 9999) to disable reactions entirely
---
*Specification based on Master Section 5.7, line 1821.*

View File

@@ -0,0 +1,134 @@
# BPC_MeleeSystem — Melee Weapon Component
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md)
- [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md)
- [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md)
- [`DA_WeaponData`](../14-data-assets/)
- Owner Character Animation Blueprint
### Purpose
Melee weapon specialization. Handles swing detection, hitbox overlap checking during windup / active frames, and combo chain sequencing. Supports light attacks, heavy attacks, charge attacks, and block/parry.
### Variables
| Name | Type | Description |
|------|------|-------------|
| `ComboSection` | FName | Active montage section for combo |
| `ComboStep` | Int | Current combo step index |
| `bCanCombo` | Bool | True during window after hit or end of swing |
| `ComboWindowDuration` | Float | Seconds to chain next attack |
| `SwingMontage` | UAnimMontage | Full melee animation set |
| `HitDetectionCollision` | UCapsuleComponent | Overlap collision for hit detection |
| `bHitRegistered` | Bool | Prevents multi-hit on same swing |
| `HitActors` | Array<AActor> | Already hit this swing |
| `SwingPhase` | ESwingPhase | Windup / Active / Recovery / Idle |
| `ChargeDuration` | Float | Hold time for charged heavy attack |
| `bIsBlocking` | Bool | Currently blocking stance |
| `ParryWindow` | Float | Active parry frames in seconds |
| `bParryActive` | Bool | Within parry active window |
| `StaggerDuration` | Float | Hit reaction stun (self or target) |
### Enums
| Enum | Values | Description |
|------|--------|-------------|
| `ESwingPhase` | Idle, WindUp, Active, Recovery, ParryWindow | Attack animation phase |
| `EAttackType` | LightAttack, HeavyAttack, ChargeAttack, SprintAttack, ParryRiposte | Swing variant |
### Functions
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `StartSwing` | AttackType: EAttackType | — | Play montage section, set SwingPhase |
| `OnSwingWindup` | — | — | Begin hit detection |
| `OnSwingActive` | — | — | Enable HitDetectionCollision overlap |
| `OnSwingHit` | HitResult: FHitResult | — | Single hit registration |
| `OnSwingRecovery` | — | — | Disable hit collision, check combo window |
| `OnSwingComplete` | — | — | Return to Idle |
| `StartBlock` | — | — | Play blocking animation |
| `EndBlock` | — | — | Release block stance |
| `ParryCheck` | IncomingAttack | Bool | If parry window active → counter |
| `GetComboStep` | — | Int | Return current combo index |
| `ResetCombo` | — | — | Clear combo step counter |
### Blueprint Flow
```
[Combo Chain Logic]
LightAttackInput →
If SwingPhase == Idle:
ComboStep = 0
StartSwing(LightAttack)
ElseIf SwingPhase == Active || SwingPhase == Recovery:
If bCanCombo && ComboStep < MaxComboLength:
ComboStep++
StartSwing(LightAttack) — next section of montage
[OnSwingActive — called by Animation Notify]
└─► HitDetectionCollision.SetCollisionEnabled(QueryOnly)
└─► On overlap → OnSwingHit
[OnSwingHit]
└─► If HitActor already in HitActors → return
└─► Add HitActor to HitActors
└─► If HitActor implements I_Damageable:
BPC_DamageReceptionSystem.ApplyMeleeDamage(
Damage = WeaponData.Damage * AttackTypeMultiplier,
HitActor,
HitLocation,
ImpulseDirection
)
└─► BPC_CombatFeedbackComponent.PlayHitFX(HitResult)
└─► ApplyStagger(HitActor)
[OnSwingRecovery — called by Animation Notify]
└─► HitDetectionCollision.SetCollisionEnabled(NoCollision)
└─► HitActors.Empty
└─► Set bCanCombo = true
└─► Start timer for ComboWindowDuration
└─► If no combo input received → OnSwingComplete
[OnSwingComplete]
└─► SwingPhase = Idle
└─► bCanCombo = false
└─► ComboStep = 0
[StartBlock]
└─► bIsBlocking = true
└─► Play block montage loop section
└─► Owner movement speed reduced
[ParryCheck]
└─► If bParryActive && incoming swing phase == Active:
Play parry riposte animation
Stagger incoming attacker
Return true
└─► Return false
```
### Communications With
| Target | Method | Why |
|--------|--------|-----|
| [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md) | Get Component | Apply melee damage and stagger |
| [`BPC_CombatFeedbackComponent`](54_BPC_CombatFeedbackComponent.md) | Get Component | Swing whoosh, hit impact, block sparks |
| Owner Animation Blueprint | Direct | Query SwingPhase for animation state |
| Owner Character Movement | Direct | Reduce speed during block |
| Owner Character Input | Direct | Light / Heavy / Block input mapping |
| [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md) | Interface | Damage application on hit actors |
### Reuse Notes
- Uses animation notifies for phase transitions (Notify_Windup, Notify_Active, Notify_Recovery, Notify_CanCombo, Notify_ParryWindow).
- Combo system uses montage section names "Combo_1", "Combo_2", etc.
- Hit collision is a simple box or capsule that exists only during Active phase.
- Block reduces incoming damage via DamageReception; parry reflects stagger.
- Renamed from `BP_MeleeWeapon` to `BPC_MeleeSystem` per Master naming convention.
- Cross-references updated: `BPC_DamageHandlerComponent``BPC_DamageReceptionSystem`.

View File

@@ -0,0 +1,52 @@
# BPC_RecoilSystem — Actor Component
**File:** [`Content/Framework/Weapons/BPC_RecoilSystem`](Content/Framework/Weapons/BPC_RecoilSystem.uasset)
**Parent Class:** `UActorComponent`
**Dependencies:** [`DA_WeaponData`](49_BP_WeaponBase.md), [`BPC_FirearmSystem`](BPC_FirearmSystem.md), [`BPC_CameraStateLayer`](../02-player/14_BPC_CameraStateLayer.md)
**Purpose:** Handles procedural recoil: camera kick, recovery curve, and ADS recoil reduction. Works with `BPC_FirearmSystem` to apply per-weapon recoil patterns.
---
## Variables
| Name | Type | Description |
|------|------|-------------|
| `RecoilPattern` | CurveVector | Per-weapon kick pattern (X=pitch, Y=yaw) |
| `RecoverySpeed` | Float | How fast camera returns to rest |
| `ADSRecoilMultiplier` | Float | Recoil reduction while aiming (0.3-0.7) |
| `CurrentRecoilOffset` | Vector2D | Accumulated recoil offset |
| `bIsRecovering` | Bool | Recovery in progress |
## Functions / Events
| Name | Inputs | Outputs | What it does |
|------|--------|---------|--------------|
| `ApplyRecoil` | ShotCount: Integer, bADS: Bool | — | Applies recoil kick based on weapon pattern |
| `ResetRecoil` | — | — | Clears accumulated offset |
| `TickRecovery` | DeltaTime: Float | — | Lerps CurrentRecoilOffset back toward zero |
| `SetRecoilPattern` | Pattern: CurveVector | — | Loads per-weapon recoil data from DA_WeaponData |
## Blueprint Flow
```
[FirearmSystem fires] -> ApplyRecoil(shotCount, bADS)
-> Look up RecoilPattern value at shotCount index
-> Apply ADSRecoilMultiplier if bADS
-> Add to CurrentRecoilOffset
-> Push offset to BPC_CameraStateLayer
-> Start recovery timer on tick
```
## Communications With
| Target System | Method | Why |
|---------------|--------|-----|
| `BPC_FirearmSystem` | Direct call from ApplyRecoilRequest | Receives fire events |
| `BPC_CameraStateLayer` | Direct ApplyFOVModifier | Camera kick application |
## Reuse Notes
- RecoilPattern is a CurveVector from DA_WeaponData — swap per weapon
- For hitscan weapons, call ApplyRecoil on every shot. For projectile, call on fire release
- Recovery runs on tick when bIsRecovering; disable tick at rest for performance

View File

@@ -0,0 +1,62 @@
# BPC_ReloadSystem — Actor Component
**File:** [`Content/Framework/Weapons/BPC_ReloadSystem`](Content/Framework/Weapons/BPC_ReloadSystem.uasset)
**Parent Class:** `UActorComponent`
**Dependencies:** [`DA_WeaponData`](49_BP_WeaponBase.md), [`BPC_FirearmSystem`](BPC_FirearmSystem.md), [`BPC_AmmoResourceSystem`](../04-inventory/BPC_KeyItemSystem.md)
**Purpose:** Manages reload animations, timing, and ammo transfer from pool to weapon magazine. Supports tactical reload, partial reload, and reload interruption.
---
## Variables
| Name | Type | Description |
|------|------|-------------|
| `bIsReloading` | Bool | Reload in progress |
| `ReloadMontage` | AnimMontage | Per-weapon reload animation |
| `AmmoTypeTag` | GameplayTag | Which ammo pool to draw from |
| `bPartialReload` | Bool | Whether partial reload is supported |
| `RoundsToAdd` | Integer | How many rounds to transfer on reload complete |
## Functions / Events
| Name | Inputs | Outputs | What it does |
|------|--------|---------|--------------|
| `RequestReload` | — | — | Player presses reload; checks if reload needed |
| `BeginReload` | — | — | Plays reload montage, locks fire input |
| `CompleteReload` | — | — | Transfers ammo from pool to magazine |
| `InterruptReload` | — | — | Cancels reload, retains partial rounds if configured |
| `CanReload` | — | Bool | Checks magazine not full AND ammo pool has rounds |
## Event Dispatchers
| Name | Parameters | Fired when |
|------|-----------|-----------|
| `OnReloadStarted` | — | Reload begins |
| `OnReloadCompleted` | RoundsAdded: Integer | Reload finishes successfully |
| `OnReloadInterrupted` | RoundsAdded: Integer | Reload cancelled mid-way |
| `OnReloadFailed` | — | Cannot reload (full mag or no ammo) |
## Blueprint Flow
```
[Player presses Reload] -> CanReload?
-> Yes: BeginReload -> Play ReloadMontage -> bIsReloading = true -> Lock fire input
-> Animation Notify "TransferRounds" -> CompleteReload -> Consume ammo from pool
-> Unlock fire input -> Broadcast OnReloadCompleted
-> No: Broadcast OnReloadFailed
```
## Communications With
| Target System | Method | Why |
|---------------|--------|-----|
| `BPC_FirearmSystem` | Direct LockFire / UnlockFire | Prevent firing during reload |
| `BPC_AmmoResourceSystem` | Direct ConsumeAmmo | Draw rounds from ammo pool |
| `ABP_PlayerBody` | Animation Notify events | Reload animation timing |
## Reuse Notes
- ReloadMontage from DA_WeaponData per weapon; swap for each weapon type
- Partial reload enabled per weapon (e.g. shotguns use individual shell reloads)
- AmmoTypeTag links to correct ammo pool in BPC_AmmoResourceSystem

View File

@@ -0,0 +1,59 @@
# BPC_ShieldDefenseSystem — Actor Component
**File:** [`Content/Framework/Weapons/BPC_ShieldDefenseSystem`](Content/Framework/Weapons/BPC_ShieldDefenseSystem.uasset)
**Parent Class:** `UActorComponent`
**Dependencies:** [`BPC_DamageReceptionSystem`](BPC_DamageReceptionSystem.md), [`BPC_StaminaSystem`](../02-player/09_BPC_StaminaSystem.md)
**Purpose:** Manages defensive tools: shields, blocking, parrying. Works in both melee and ranged defense contexts.
---
## Variables
| Name | Type | Description |
|------|------|-------------|
| `bIsBlocking` | Bool | Block active |
| `BlockDamageReduction` | Float | % reduction while blocking (0.01.0) |
| `ParryWindow` | Float | Perfect parry timing window in seconds |
| `ShieldDurability` | Float | Current shield durability (0 = broken) |
| `MaxShieldDurability` | Float | Maximum durability |
| `BlockAngle` | Float | Max angle from forward vector for block to cover |
| `StaminaCostPerBlock` | Float | Stamina drain per blocked hit |
| `bCanParry` | Bool | Whether parry mechanic is enabled |
## Functions / Events
| Name | Inputs | Outputs | What it does |
|------|--------|---------|--------------|
| `BeginBlock` | — | — | Raises shield, starts blocking |
| `EndBlock` | — | — | Lowers shield, ends blocking |
| `ProcessHit` | Damage: S_DamageEvent | Bool (blocked) | Evaluates if hit was blocked or parried |
| `TryParry` | — | Bool | Checks if parry window is active |
| `BreakShield` | — | — | Reduces durability to 0, triggers break anim |
## Event Dispatchers
| Name | Parameters | Fired when |
|------|-----------|-----------|
| `OnBlockStarted` | — | Shield raised |
| `OnBlockEnded` | — | Shield lowered |
| `OnHitBlocked` | Damage: S_DamageEvent | Incoming hit blocked |
| `OnHitParried` | Instigator: Actor | Perfect parry executed |
| `OnShieldBroken` | — | Durability reaches 0 |
---
## Communications With
| Target System | Method | Why |
|---------------|--------|-----|
| `BPC_DamageReceptionSystem` | Interface hook | Intercepts incoming damage |
| `BPC_StaminaSystem` | Direct `ConsumeStamina` | Stamina cost per block |
| `BPC_HitReactionSystem` | Direct | Triggers parry follow-up window |
| `ABP_PlayerBody` | Animation Notify | Block/parry animation states |
## Reuse Notes
- ParryWindow drives a perfect-parry mechanic; set to 0 to disable parries
- BlockDamageReduction is per-shield from DA_WeaponData or DA_EquipmentConfig
- Shield durability adds wear mechanic; set MaxShieldDurability to 0 for indestructible shields