Add core gameplay systems and data assets for player mechanics
- Implemented DA_EquipmentConfig for managing equipment resistances, durability, and weight. - Created DA_ItemData to serve as a base item data asset with various item types and properties. - Introduced BPC_HealthSystem for managing player health and death events. - Added BPC_MovementStateSystem to handle player movement modes with event delegation. - Developed BPC_StaminaSystem to track player stamina and exhaustion states. - Established BPC_StateManager as a central authority for managing player action states and gating. - Created BPC_StressSystem to monitor and respond to player stress levels. - Implemented PC_CoreController and PS_CorePlayerState for player controller and state management. - Developed SS_SaveManager for save/load functionality with slot management and serialization. - Introduced DA_StateGatingTable for defining action gating rules based on gameplay tags. - Added BPC_DamageReceptionSystem to process incoming damage and apply resistance calculations. - Implemented BPC_HitReactionSystem for managing hit reactions based on damage received. - Created BPC_ShieldDefenseSystem to manage shield health and blocking mechanics. - Added PG_FrameworkEditor.Target.cs for editor build configuration.
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — BPC_DamageReceptionSystem Implementation
|
||||
|
||||
#include "Weapons/BPC_DamageReceptionSystem.h"
|
||||
#include "Player/BPC_HealthSystem.h"
|
||||
#include "Weapons/BPC_ShieldDefenseSystem.h"
|
||||
#include "Weapons/BPC_HitReactionSystem.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogFrameworkDamage, Log, All);
|
||||
|
||||
UBPC_DamageReceptionSystem::UBPC_DamageReceptionSystem()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = false;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Damage Calculation — Hot Path
|
||||
// ============================================================================
|
||||
|
||||
float UBPC_DamageReceptionSystem::ApplyDamage(float RawDamage, AActor* DamageCauser,
|
||||
FGameplayTag DamageType, FVector HitLocation, FVector HitDirection)
|
||||
{
|
||||
if (RawDamage <= 0.0f || !DamageType.IsValid())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Step 1: Calculate damage multiplier from modifiers.
|
||||
float Multiplier = GetDamageMultiplier(DamageType);
|
||||
|
||||
// Step 2: Apply resistance.
|
||||
float Resistance = CalculateResistance(DamageType);
|
||||
float ResistedAmount = RawDamage * Resistance;
|
||||
|
||||
// Step 3: Calculate final damage.
|
||||
float FinalDamage = (RawDamage * Multiplier) - ResistedAmount;
|
||||
FinalDamage = FMath::Max(FinalDamage, 0.0f); // No negative damage.
|
||||
|
||||
// Check for flat reduction modifiers.
|
||||
for (const FDamageModifier& Mod : DamageModifiers)
|
||||
{
|
||||
if (Mod.DamageType == DamageType && Mod.bFlatReduction)
|
||||
{
|
||||
FinalDamage = FMath::Max(FinalDamage - Mod.FlatReduction, 1.0f); // Minimum 1 damage.
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Apply shield absorption if available.
|
||||
if (CachedShieldSystem)
|
||||
{
|
||||
// Shield absorbs damage before health.
|
||||
// FinalDamage = CachedShieldSystem->AbsorbDamage(FinalDamage);
|
||||
}
|
||||
|
||||
// Step 5: Route to health system.
|
||||
if (CachedHealthSystem)
|
||||
{
|
||||
// CachedHealthSystem->ApplyHealthDamage(FinalDamage);
|
||||
}
|
||||
|
||||
// Step 6: Evaluate hit reaction.
|
||||
EvaluateHitReaction(FinalDamage, DamageCauser, HitDirection);
|
||||
|
||||
// Step 7: Broadcast.
|
||||
OnDamageReceived.Broadcast(RawDamage, FinalDamage, DamageCauser, DamageType, HitLocation);
|
||||
|
||||
if (ResistedAmount > 0.0f)
|
||||
{
|
||||
OnDamageResisted.Broadcast(ResistedAmount, DamageType,
|
||||
FString::Printf(TEXT("Resistance: %.1f%%"), Resistance * 100.0f));
|
||||
}
|
||||
|
||||
UE_LOG(LogFrameworkDamage, Verbose, TEXT("ApplyDamage — Raw: %.1f → Final: %.1f (Type: %s, Resist: %.1f%%)"),
|
||||
RawDamage, FinalDamage, *DamageType.GetTagName().ToString(), Resistance * 100.0f);
|
||||
|
||||
return FinalDamage;
|
||||
}
|
||||
|
||||
float UBPC_DamageReceptionSystem::CalculateResistance(FGameplayTag DamageType) const
|
||||
{
|
||||
if (!DamageType.IsValid())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Base resistance + equipment-specific bonuses.
|
||||
float TotalResistance = BaseResistance;
|
||||
|
||||
if (EquipmentConfig)
|
||||
{
|
||||
// EquipmentConfig would provide per-damage-type resistance values.
|
||||
// TotalResistance += EquipmentConfig->GetResistance(DamageType);
|
||||
}
|
||||
|
||||
return FMath::Clamp(TotalResistance, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float UBPC_DamageReceptionSystem::GetDamageMultiplier(FGameplayTag DamageType) const
|
||||
{
|
||||
if (!DamageType.IsValid())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
for (const FDamageModifier& Mod : DamageModifiers)
|
||||
{
|
||||
if (Mod.DamageType == DamageType && !Mod.bFlatReduction)
|
||||
{
|
||||
return Mod.Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f; // No modifier — normal damage.
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Hit Reaction
|
||||
// ============================================================================
|
||||
|
||||
void UBPC_DamageReceptionSystem::EvaluateHitReaction(float FinalDamage, AActor* DamageCauser,
|
||||
FVector HitDirection)
|
||||
{
|
||||
if (FinalDamage >= KnockdownThreshold)
|
||||
{
|
||||
UE_LOG(LogFrameworkDamage, Log, TEXT("EvaluateHitReaction — Knockdown! (%.1f damage)"), FinalDamage);
|
||||
OnKnockedDown.Broadcast(DamageCauser, FinalDamage);
|
||||
}
|
||||
else if (FinalDamage >= StaggerThreshold)
|
||||
{
|
||||
UE_LOG(LogFrameworkDamage, Verbose, TEXT("EvaluateHitReaction — Stagger (%.1f damage)"), FinalDamage);
|
||||
OnStaggered.Broadcast(DamageCauser, FinalDamage);
|
||||
}
|
||||
|
||||
// Route to dedicated hit reaction system for animation selection.
|
||||
if (CachedHitReactionSystem)
|
||||
{
|
||||
// CachedHitReactionSystem->PlayHitReaction(FinalDamage, HitDirection, DamageCauser);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user