Files
UE5-Modular-Game-Framework/docs/blueprints/08-weapons/75_BPC_HitReactionSystem.md

257 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BPC_HitReactionSystem — Hit Reaction System
> **⚡ C++ Status: Stub** — `Source/PG_Framework/Public/Weapons/BPC_HitReactionSystem.h` provides the UCLASS shell, `PlayHitReaction()` stub, `FlinchThreshold`, and `RagdollThreshold`. **The C++ stub has NO gameplay logic.** **Create a BP child** and build ALL logic: hit reaction animation selection, stagger/knockdown/ragdoll trigger, directional response, camera trauma. Attach to player/enemy pawns. See `docs/developer/cpp-integration-guide.md`.
>
> ---
## 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.*
---
## Manual Implementation Guide
### Class Setup
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_HitReactionSystem`
2. Add to Player Character (or EnemyBase)
3. Create HitReactionMontages per damage type: Physical, Fire, Explosive, etc.
### Variable Init (BeginPlay)
```
Event BeginPlay
├─ Set CurrentTrauma = 0.0, bIsReacting = false
├─ Populate HitReactionMontages map (E_DamageType → AnimMontage)
├─ Cache: BPC_HealthSystem (bind OnDamageTaken), BPC_CameraStateLayer
└─ Start TraumaDecay timer (0.1s loop)
```
### Function Node-by-Node
#### `ProcessHitReaction(DamageEvent: S_DamageEvent)` → `void`
```
Step 1: If bIsReacting → Return (already playing reaction)
Step 2: Set LastDamageDirection = DamageEvent.HitNormal * -1 ← direction damage came from
Step 3: If DamageEvent.Amount >= RagdollThreshold:
Play ragdoll blend: ABP → Set bRagdoll=true, physics blend
Set bIsReacting = true → timer to recover
Return
Step 4: If DamageEvent.Amount >= FlinchThreshold:
Select montage: HitReactionMontages[DamageEvent.DamageType]
If multiple: pick NextReactionIndex, cycle it
Play Montage with blend from LastDamageDirection
Set bIsReacting = true
Step 5: Call ApplyTrauma(DamageEvent.Amount * 0.5)
Step 6: Fire OnHitReactionPlayed(DamageEvent)
Step 7: On montage complete → Set bIsReacting = false
```
#### `ApplyTrauma(Amount: Float)` → `void`
```
Step 1: CurrentTrauma = Min(100, CurrentTrauma + Amount)
Step 2: Push to camera: BPC_CameraStateLayer.ApplyPostProcessOverride(TraumaVignette, CurrentTrauma/100)
Step 3: Fire OnTraumaChanged(CurrentTrauma)
```
#### `TraumaDecay Tick` → `void` *(Timer 0.1s)*
```
CurrentTrauma = Max(0, CurrentTrauma - TraumaDecayRate * 0.1)
Update camera effect intensity
If zero: clear post-process override
```
### Build Checklist
- [ ] Create BPC_HitReactionSystem, add to Player Character
- [ ] Create hit reaction montages per damage type
- [ ] Implement ProcessHitReaction with threshold branching
- [ ] Implement ApplyTrauma with camera effect push
- [ ] Set up trauma decay timer
- [ ] Bind to BPC_HealthSystem.OnDamageTaken
- [ ] Test: take small hit → flinch; take big hit → ragdoll; trauma decays over time