- 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.
9.2 KiB
9.2 KiB
BPC_MeleeSystem — Melee Weapon Component
Blueprint Spec — UE 5.5–5.7
Parent Class
ActorComponent
Dependencies
BPC_DamageReceptionSystemBPC_CombatFeedbackComponentI_DamageableDA_WeaponData- 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 | 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 |
Get Component | Apply melee damage and stagger |
BPC_CombatFeedbackComponent |
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 |
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_MeleeWeapontoBPC_MeleeSystemper Master naming convention. - Cross-references updated:
BPC_DamageHandlerComponent→BPC_DamageReceptionSystem.
Manual Implementation Guide
Class Setup
- Create Blueprint Class: Parent =
ActorComponent, Name =BPC_MeleeSystem - Attach to
BP_WeaponBasesubclass:BP_MeleeWeapon - 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