Ersetze HealthComponent und StaminaComponent durch GAS-basierte AttributeSets (`UHealthAttributeSet`, `UStaminaAttributeSet`) und füge `UAbilitySystemComponent` hinzu. Implementiere neue GameplayEffects (`UGE_HealthDamage`, `UGE_HealthHealing`, `UGE_HealthDebuff`, `UGE_StaminaFatiguePenalty`) und eine Modifikator-Berechnung (`UMMC_MaxStaminaFatiguePenalty`). Erweitere `AKingshearthLegacyCharacter` um Methoden zur Attributmanipulation (`ApplyDamage`, `SpendStamina`, etc.) und Stamina-Regeneration. Aktualisiere UI-Widgets (`HealthBarWidget`, `StaminaBarWidget`) zur Nutzung der neuen AttributeSets. Entferne Legacy-Code für Health- und Stamina-Komponenten. Füge neue Assets (Niagara-Systeme, Materialien, Texturen) hinzu und passe Projektkonfiguration an (z. B. `GameplayAbilities`-Modul, `r.Substrate`).
87 lines
2.3 KiB
C++
87 lines
2.3 KiB
C++
#include "StaminaAttributeSet.h"
|
|
|
|
UStaminaAttributeSet::UStaminaAttributeSet()
|
|
{
|
|
InitStamina(100.0f);
|
|
InitMaxStamina(100.0f);
|
|
InitFatigue(0.0f);
|
|
}
|
|
|
|
void UStaminaAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
|
|
{
|
|
Super::PreAttributeChange(Attribute, NewValue);
|
|
|
|
if (Attribute == GetStaminaAttribute())
|
|
{
|
|
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxStamina());
|
|
}
|
|
else if (Attribute == GetMaxStaminaAttribute())
|
|
{
|
|
NewValue = FMath::Max(NewValue, 0.0f);
|
|
}
|
|
else if (Attribute == GetFatigueAttribute())
|
|
{
|
|
NewValue = FMath::Clamp(NewValue, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
void UStaminaAttributeSet::PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const
|
|
{
|
|
Super::PreAttributeBaseChange(Attribute, NewValue);
|
|
|
|
// ApplyModToAttribute (SpendStamina/RestoreStamina/regen) writes BaseValue through this hook, not
|
|
// PreAttributeChange - without clamping here, a large delta (e.g. RestoreStamina's debug "fill to max")
|
|
// pushes BaseValue past MaxStamina. PreAttributeChange still clamps the displayed CurrentValue, but the
|
|
// bloated BaseValue then absorbs every subsequent spend/regen delta before CurrentValue moves again.
|
|
if (Attribute == GetStaminaAttribute())
|
|
{
|
|
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxStamina());
|
|
}
|
|
else if (Attribute == GetMaxStaminaAttribute())
|
|
{
|
|
NewValue = FMath::Max(NewValue, 0.0f);
|
|
}
|
|
else if (Attribute == GetFatigueAttribute())
|
|
{
|
|
NewValue = FMath::Clamp(NewValue, 0.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
void UStaminaAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
|
|
{
|
|
Super::PostAttributeChange(Attribute, OldValue, NewValue);
|
|
|
|
if (Attribute == GetStaminaAttribute())
|
|
{
|
|
if (!FMath::IsNearlyEqual(OldValue, NewValue))
|
|
{
|
|
OnStaminaChanged.Broadcast(NewValue);
|
|
}
|
|
|
|
if (OldValue > 0.0f && NewValue <= 0.0f)
|
|
{
|
|
OnExhausted.Broadcast();
|
|
}
|
|
}
|
|
else if (Attribute == GetMaxStaminaAttribute())
|
|
{
|
|
if (!FMath::IsNearlyEqual(OldValue, NewValue))
|
|
{
|
|
// MaxStamina shrank/grew (typically GE_StaminaFatiguePenalty re-evaluating) - pull Stamina back in range.
|
|
ClampStamina();
|
|
}
|
|
}
|
|
else if (Attribute == GetFatigueAttribute())
|
|
{
|
|
if (!FMath::IsNearlyEqual(OldValue, NewValue))
|
|
{
|
|
OnFatigueChanged.Broadcast(NewValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UStaminaAttributeSet::ClampStamina()
|
|
{
|
|
SetStamina(FMath::Clamp(GetStamina(), 0.0f, GetMaxStamina()));
|
|
}
|