- Added BPC_UsableWorldObjectSystem for handling various interactable world objects with detailed manual implementation guide. - Introduced BPC_ActiveItemSystem to manage quick slots and active item usage, including cycling and selection logic. - Implemented BPC_DocumentArchiveSystem for managing collectible documents with read tracking and categorization. - Developed BPC_JournalSystem for narrative entries with auto-adding features based on gameplay events. - Created BPC_KeyItemSystem for key management with consumable and persistent key support. - Enhanced BPC_FirearmSystem for ranged weapon mechanics, including hitscan and projectile firing. - Updated BPC_MeleeSystem for melee combat with combo and blocking mechanics. - Established BPC_ReloadSystem for managing weapon reloading processes, including partial reloads and state management.
245 lines
9.2 KiB
Markdown
245 lines
9.2 KiB
Markdown
# BPC_MeleeSystem — Melee Weapon Component
|
||
|
||
## Blueprint Spec — UE 5.5–5.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`.
|
||
|
||
---
|
||
|
||
## Manual Implementation Guide
|
||
|
||
### Class Setup
|
||
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_MeleeSystem`
|
||
2. Attach to `BP_WeaponBase` subclass: `BP_MeleeWeapon`
|
||
3. Add `HitDetectionCollision` (Capsule or Box component) to weapon — disabled by default
|
||
|
||
### Variable Init (BeginPlay)
|
||
```
|
||
Event BeginPlay
|
||
├─ Set SwingPhase = Idle
|
||
├─ Set ComboStep = 0
|
||
├─ Set bCanCombo = false
|
||
├─ Set bIsBlocking = false
|
||
├─ Disable HitDetectionCollision (NoCollision)
|
||
├─ Get Owner Weapon → Read DA_WeaponData for: ComboWindowDuration, ChargeDuration, ParryWindow, StaggerDuration
|
||
└─ Get Owner → Find BPC_DamageReceptionSystem → Cache
|
||
```
|
||
|
||
### Function Implementations
|
||
|
||
#### `StartSwing(AttackType: EAttackType)` → `void`
|
||
|
||
```
|
||
[Function: StartSwing]
|
||
Step 1: Branch on SwingPhase != Idle AND SwingPhase != Recovery → Return (can't chain now)
|
||
Step 2: Set SwingPhase = WindUp
|
||
Step 3: Build montage section name:
|
||
If this is combo: "Combo_" + ComboStep
|
||
If AttackType == HeavyAttack: prefix "Heavy_"
|
||
If AttackType == ChargeAttack: "Charge_"
|
||
Step 4: Play Montage (SwingMontage, Section = built section name)
|
||
Step 5: Set bHitRegistered = false, Clear HitActors array
|
||
Step 6: Fire OnSwingStarted(AttackType, ComboStep)
|
||
```
|
||
|
||
**Nodes:** `Switch on EAttackType`, `Build String`, `Play Montage` (with Starting Section), `Clear Array`
|
||
|
||
#### `OnSwingActive()` → `void` *(Called by Animation Notify: "Notify_Active")*
|
||
|
||
```
|
||
Step 1: Set SwingPhase = Active
|
||
Step 2: HitDetectionCollision.SetCollisionEnabled(QueryOnly)
|
||
Step 3: Set bHitRegistered = false
|
||
```
|
||
|
||
#### `OnSwingHit(HitResult)` → `void` *(Called by HitDetectionCollision OnComponentBeginOverlap)*
|
||
|
||
```
|
||
Step 1: Get Hit Actor from Overlap → Cast to Actor
|
||
Step 2: ForEach HitActors → if match found → Return (already hit this actor this swing)
|
||
Step 3: Add HitActor to HitActors
|
||
Step 4: If HitActor implements I_Damageable:
|
||
Get BPC_DamageReceptionSystem → Call ApplyMeleeDamage:
|
||
BaseDamage = WeaponData.Damage
|
||
Multiplier: Light=1.0, Heavy=1.8, Charge=2.5, Sprint=1.5
|
||
HitLocation = HitResult.ImpactPoint
|
||
Apply impulse in swing direction
|
||
Step 5: Get BPC_CombatFeedbackComponent → Call PlayHitFX(HitResult)
|
||
Step 6: Apply Stagger to HitActor
|
||
```
|
||
|
||
#### `OnSwingRecovery()` → `void` *(Animation Notify: "Notify_Recovery")*
|
||
|
||
```
|
||
Step 1: Set SwingPhase = Recovery
|
||
Step 2: HitDetectionCollision.SetCollisionEnabled(NoCollision)
|
||
Step 3: Clear HitActors
|
||
Step 4: Set bCanCombo = true
|
||
Step 5: Start Timer (ComboWindowDuration) → On timer: if no combo received → OnSwingComplete()
|
||
```
|
||
|
||
#### `OnSwingComplete()` → `void`
|
||
|
||
```
|
||
Step 1: Set SwingPhase = Idle
|
||
Step 2: Set bCanCombo = false
|
||
Step 3: Set ComboStep = 0
|
||
Step 4: Fire OnSwingFinished
|
||
```
|
||
|
||
#### `StartBlock()` → `void`
|
||
|
||
```
|
||
Step 1: Set bIsBlocking = true
|
||
Step 2: Play block montage loop section
|
||
Step 3: Get Owner Character → Get CharacterMovement → Set MaxWalkSpeed *= 0.5
|
||
Step 4: Set ParryWindow timer: bParryActive = true for ParryWindow seconds
|
||
On timer end → bParryActive = false
|
||
```
|
||
|
||
#### `EndBlock()` → `void`
|
||
|
||
```
|
||
Step 1: Set bIsBlocking = false
|
||
Step 2: Stop block montage
|
||
Step 3: Restore MaxWalkSpeed
|
||
```
|
||
|
||
### Build Checklist
|
||
- [ ] Create BPC_MeleeSystem, add to BP_MeleeWeapon
|
||
- [ ] Add HitDetectionCollision component (Capsule/Box, NoCollision by default)
|
||
- [ ] Create SwingMontage with sections: Combo_1, Combo_2, Combo_3, Heavy_1, Charge_1
|
||
- [ ] Place Animation Notifies: Notify_Active, Notify_Recovery, Notify_CanCombo, Notify_ParryWindow
|
||
- [ ] Implement phase state machine: Idle→WindUp→Active→Recovery→(combo)→Idle
|
||
- [ ] Bind HitDetectionCollision.OnComponentBeginOverlap → OnSwingHit
|
||
- [ ] Implement combo system with bCanCombo window timer
|
||
- [ ] Implement block/parry with damage reduction and stagger reflection |