第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,332 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Attributes/AS_Combat.h"
#include "Net/UnrealNetwork.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameplayEffectExtension.h"
#include "GGA_GameplayAttributesHelper.h"
#include "GGA_AttributeSystemComponent.h"
namespace AS_Combat
{
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Damage, TEXT("GGF.Attribute.CombatSet.Damage"), "The damage that will apply to target")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(DamageNegation, TEXT("GGF.Attribute.CombatSet.DamageNegation"), "The damage reduction(percentage) for incoming health damage")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(GuardDamageNegation, TEXT("GGF.Attribute.CombatSet.GuardDamageNegation"), "The damage reduction(percentage) for incoming health damage while guarding")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(StaminaDamage, TEXT("GGF.Attribute.CombatSet.StaminaDamage"), "The stamina damage that will apply to target")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(StaminaDamageNegation, TEXT("GGF.Attribute.CombatSet.StaminaDamageNegation"), "The damage reduction(percentage) for incoming stamina damage")
}
UAS_Combat::UAS_Combat()
{
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Combat::Damage,GetDamageAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Combat::DamageNegation,GetDamageNegationAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Combat::GuardDamageNegation,GetGuardDamageNegationAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Combat::StaminaDamage,GetStaminaDamageAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Combat::StaminaDamageNegation,GetStaminaDamageNegationAttribute());
}
void UAS_Combat::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, Damage, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, DamageNegation, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, GuardDamageNegation, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, StaminaDamage, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, StaminaDamageNegation, COND_None, REPNOTIFY_Always);
}
void UAS_Combat::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePreAttributeChange(this,Attribute,NewValue);
}
}
}
bool UAS_Combat::PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data)
{
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
return ASS->ReceivePreGameplayEffectExecute(this, Data);
}
}
return Super::PreGameplayEffectExecute(Data);
}
void UAS_Combat::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostAttributeChange(this, Attribute, OldValue, NewValue);
}
}
}
void UAS_Combat::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostGameplayEffectExecute(this,Data);
}
}
}
void UAS_Combat::AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute, const FGameplayAttributeData& MaxAttribute, float NewMaxValue,
const FGameplayAttribute& AffectedAttributeProperty)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
const float CurrentMaxValue = MaxAttribute.GetCurrentValue();
if (!FMath::IsNearlyEqual(CurrentMaxValue, NewMaxValue) && AbilityComp)
{
// Change current value to maintain the current Val / Max percent
const float CurrentValue = AffectedAttribute.GetCurrentValue();
float NewDelta = (CurrentMaxValue > 0.f) ? (CurrentValue * NewMaxValue / CurrentMaxValue) - CurrentValue : NewMaxValue;
AbilityComp->ApplyModToAttributeUnsafe(AffectedAttributeProperty, EGameplayModOp::Additive, NewDelta);
}
}
FGameplayAttribute UAS_Combat::Bp_GetDamageAttribute()
{
return ThisClass::GetDamageAttribute();
}
float UAS_Combat::Bp_GetDamage() const
{
return GetDamage();
}
void UAS_Combat::Bp_SetDamage(float NewValue)
{
SetDamage(NewValue);
}
void UAS_Combat::Bp_InitDamage(float NewValue)
{
InitDamage(NewValue);
}
void UAS_Combat::OnRep_Damage(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, Damage, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetDamageAttribute(),GetDamage(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Combat::Bp_GetDamageNegationAttribute()
{
return ThisClass::GetDamageNegationAttribute();
}
float UAS_Combat::Bp_GetDamageNegation() const
{
return GetDamageNegation();
}
void UAS_Combat::Bp_SetDamageNegation(float NewValue)
{
SetDamageNegation(NewValue);
}
void UAS_Combat::Bp_InitDamageNegation(float NewValue)
{
InitDamageNegation(NewValue);
}
void UAS_Combat::OnRep_DamageNegation(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, DamageNegation, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetDamageNegationAttribute(),GetDamageNegation(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Combat::Bp_GetGuardDamageNegationAttribute()
{
return ThisClass::GetGuardDamageNegationAttribute();
}
float UAS_Combat::Bp_GetGuardDamageNegation() const
{
return GetGuardDamageNegation();
}
void UAS_Combat::Bp_SetGuardDamageNegation(float NewValue)
{
SetGuardDamageNegation(NewValue);
}
void UAS_Combat::Bp_InitGuardDamageNegation(float NewValue)
{
InitGuardDamageNegation(NewValue);
}
void UAS_Combat::OnRep_GuardDamageNegation(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, GuardDamageNegation, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetGuardDamageNegationAttribute(),GetGuardDamageNegation(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Combat::Bp_GetStaminaDamageAttribute()
{
return ThisClass::GetStaminaDamageAttribute();
}
float UAS_Combat::Bp_GetStaminaDamage() const
{
return GetStaminaDamage();
}
void UAS_Combat::Bp_SetStaminaDamage(float NewValue)
{
SetStaminaDamage(NewValue);
}
void UAS_Combat::Bp_InitStaminaDamage(float NewValue)
{
InitStaminaDamage(NewValue);
}
void UAS_Combat::OnRep_StaminaDamage(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, StaminaDamage, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetStaminaDamageAttribute(),GetStaminaDamage(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Combat::Bp_GetStaminaDamageNegationAttribute()
{
return ThisClass::GetStaminaDamageNegationAttribute();
}
float UAS_Combat::Bp_GetStaminaDamageNegation() const
{
return GetStaminaDamageNegation();
}
void UAS_Combat::Bp_SetStaminaDamageNegation(float NewValue)
{
SetStaminaDamageNegation(NewValue);
}
void UAS_Combat::Bp_InitStaminaDamageNegation(float NewValue)
{
InitStaminaDamageNegation(NewValue);
}
void UAS_Combat::OnRep_StaminaDamageNegation(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, StaminaDamageNegation, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetStaminaDamageNegationAttribute(),GetStaminaDamageNegation(),OldValue.GetCurrentValue());
}
}
}

View File

@@ -0,0 +1,251 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Attributes/AS_Health.h"
#include "Net/UnrealNetwork.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameplayEffectExtension.h"
#include "GGA_GameplayAttributesHelper.h"
#include "GGA_AttributeSystemComponent.h"
namespace AS_Health
{
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Health, TEXT("GGF.Attribute.HealthSet.Health"), "Current health of an actor.(actor的当前生命值)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(MaxHealth, TEXT("GGF.Attribute.HealthSet.MaxHealth"), "Max health value of an actor.(actor的最大生命值)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(IncomingHealing, TEXT("GGF.Attribute.HealthSet.IncomingHealing"), "Incoming healing. This is mapped directly to +Health.(即将到来的恢复值,映射为+Health)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(IncomingDamage, TEXT("GGF.Attribute.HealthSet.IncomingDamage"), "Incoming damage. This is mapped directly to -Health(即将到来的伤害值,映射为-Health)")
}
UAS_Health::UAS_Health()
{
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Health::Health,GetHealthAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Health::MaxHealth,GetMaxHealthAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Health::IncomingHealing,GetIncomingHealingAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Health::IncomingDamage,GetIncomingDamageAttribute());
}
void UAS_Health::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, MaxHealth, COND_None, REPNOTIFY_Always);
}
void UAS_Health::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetHealthAttribute())
{
NewValue = FMath::Clamp(NewValue,0,GetMaxHealth());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePreAttributeChange(this,Attribute,NewValue);
}
}
}
bool UAS_Health::PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data)
{
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
return ASS->ReceivePreGameplayEffectExecute(this, Data);
}
}
return Super::PreGameplayEffectExecute(Data);
}
void UAS_Health::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);
if (Attribute == GetMaxHealthAttribute())
{
AdjustAttributeForMaxChange(Health, OldValue, NewValue, GetHealthAttribute());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostAttributeChange(this, Attribute, OldValue, NewValue);
}
}
}
void UAS_Health::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(),0,GetMaxHealth()));
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostGameplayEffectExecute(this,Data);
}
}
}
void UAS_Health::AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute, const FGameplayAttributeData& MaxAttribute, float NewMaxValue,
const FGameplayAttribute& AffectedAttributeProperty)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
const float CurrentMaxValue = MaxAttribute.GetCurrentValue();
if (!FMath::IsNearlyEqual(CurrentMaxValue, NewMaxValue) && AbilityComp)
{
// Change current value to maintain the current Val / Max percent
const float CurrentValue = AffectedAttribute.GetCurrentValue();
float NewDelta = (CurrentMaxValue > 0.f) ? (CurrentValue * NewMaxValue / CurrentMaxValue) - CurrentValue : NewMaxValue;
AbilityComp->ApplyModToAttributeUnsafe(AffectedAttributeProperty, EGameplayModOp::Additive, NewDelta);
}
}
FGameplayAttribute UAS_Health::Bp_GetHealthAttribute()
{
return ThisClass::GetHealthAttribute();
}
float UAS_Health::Bp_GetHealth() const
{
return GetHealth();
}
void UAS_Health::Bp_SetHealth(float NewValue)
{
SetHealth(NewValue);
}
void UAS_Health::Bp_InitHealth(float NewValue)
{
InitHealth(NewValue);
}
void UAS_Health::OnRep_Health(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, Health, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetHealthAttribute(),GetHealth(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Health::Bp_GetMaxHealthAttribute()
{
return ThisClass::GetMaxHealthAttribute();
}
float UAS_Health::Bp_GetMaxHealth() const
{
return GetMaxHealth();
}
void UAS_Health::Bp_SetMaxHealth(float NewValue)
{
SetMaxHealth(NewValue);
}
void UAS_Health::Bp_InitMaxHealth(float NewValue)
{
InitMaxHealth(NewValue);
}
void UAS_Health::OnRep_MaxHealth(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, MaxHealth, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetMaxHealthAttribute(),GetMaxHealth(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Health::Bp_GetIncomingHealingAttribute()
{
return ThisClass::GetIncomingHealingAttribute();
}
float UAS_Health::Bp_GetIncomingHealing() const
{
return GetIncomingHealing();
}
void UAS_Health::Bp_SetIncomingHealing(float NewValue)
{
SetIncomingHealing(NewValue);
}
FGameplayAttribute UAS_Health::Bp_GetIncomingDamageAttribute()
{
return ThisClass::GetIncomingDamageAttribute();
}
float UAS_Health::Bp_GetIncomingDamage() const
{
return GetIncomingDamage();
}
void UAS_Health::Bp_SetIncomingDamage(float NewValue)
{
SetIncomingDamage(NewValue);
}

View File

@@ -0,0 +1,209 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Attributes/AS_Mana.h"
#include "Net/UnrealNetwork.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameplayEffectExtension.h"
#include "GGA_GameplayAttributesHelper.h"
#include "GGA_AttributeSystemComponent.h"
namespace AS_Mana
{
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Mana, TEXT("GGF.Attribute.ManaSet.Mana"), "Current mana of an actor.(actor的当前魔法值)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(MaxMana, TEXT("GGF.Attribute.ManaSet.MaxMana"), "Max mana value of an actor.(actor的最大魔法值)")
}
UAS_Mana::UAS_Mana()
{
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Mana::Mana,GetManaAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Mana::MaxMana,GetMaxManaAttribute());
}
void UAS_Mana::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, Mana, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, MaxMana, COND_None, REPNOTIFY_Always);
}
void UAS_Mana::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetManaAttribute())
{
NewValue = FMath::Clamp(NewValue,0,GetMaxMana());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePreAttributeChange(this,Attribute,NewValue);
}
}
}
bool UAS_Mana::PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data)
{
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
return ASS->ReceivePreGameplayEffectExecute(this, Data);
}
}
return Super::PreGameplayEffectExecute(Data);
}
void UAS_Mana::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);
if (Attribute == GetMaxManaAttribute())
{
AdjustAttributeForMaxChange(Mana, OldValue, NewValue, GetManaAttribute());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostAttributeChange(this, Attribute, OldValue, NewValue);
}
}
}
void UAS_Mana::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetManaAttribute())
{
SetMana(FMath::Clamp(GetMana(),0,GetMaxMana()));
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostGameplayEffectExecute(this,Data);
}
}
}
void UAS_Mana::AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute, const FGameplayAttributeData& MaxAttribute, float NewMaxValue,
const FGameplayAttribute& AffectedAttributeProperty)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
const float CurrentMaxValue = MaxAttribute.GetCurrentValue();
if (!FMath::IsNearlyEqual(CurrentMaxValue, NewMaxValue) && AbilityComp)
{
// Change current value to maintain the current Val / Max percent
const float CurrentValue = AffectedAttribute.GetCurrentValue();
float NewDelta = (CurrentMaxValue > 0.f) ? (CurrentValue * NewMaxValue / CurrentMaxValue) - CurrentValue : NewMaxValue;
AbilityComp->ApplyModToAttributeUnsafe(AffectedAttributeProperty, EGameplayModOp::Additive, NewDelta);
}
}
FGameplayAttribute UAS_Mana::Bp_GetManaAttribute()
{
return ThisClass::GetManaAttribute();
}
float UAS_Mana::Bp_GetMana() const
{
return GetMana();
}
void UAS_Mana::Bp_SetMana(float NewValue)
{
SetMana(NewValue);
}
void UAS_Mana::Bp_InitMana(float NewValue)
{
InitMana(NewValue);
}
void UAS_Mana::OnRep_Mana(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, Mana, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetManaAttribute(),GetMana(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Mana::Bp_GetMaxManaAttribute()
{
return ThisClass::GetMaxManaAttribute();
}
float UAS_Mana::Bp_GetMaxMana() const
{
return GetMaxMana();
}
void UAS_Mana::Bp_SetMaxMana(float NewValue)
{
SetMaxMana(NewValue);
}
void UAS_Mana::Bp_InitMaxMana(float NewValue)
{
InitMaxMana(NewValue);
}
void UAS_Mana::OnRep_MaxMana(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, MaxMana, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetMaxManaAttribute(),GetMaxMana(),OldValue.GetCurrentValue());
}
}
}

View File

@@ -0,0 +1,251 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "Attributes/AS_Stamina.h"
#include "Net/UnrealNetwork.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "GameplayEffectExtension.h"
#include "GGA_GameplayAttributesHelper.h"
#include "GGA_AttributeSystemComponent.h"
namespace AS_Stamina
{
UE_DEFINE_GAMEPLAY_TAG_COMMENT(Stamina, TEXT("GGF.Attribute.StaminaSet.Stamina"), "Current stamina of an actor.(actor的当前生命值)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(MaxStamina, TEXT("GGF.Attribute.StaminaSet.MaxStamina"), "Max stamina value of an actor.(actor的最大生命值)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(IncomingHealing, TEXT("GGF.Attribute.StaminaSet.IncomingHealing"), "Incoming healing. This is mapped directly to +Stamina.(即将到来的恢复值,映射为+Stamina)")
UE_DEFINE_GAMEPLAY_TAG_COMMENT(IncomingDamage, TEXT("GGF.Attribute.StaminaSet.IncomingDamage"), "Incoming damage. This is mapped directly to -Stamina(即将到来的伤害值,映射为-Stamina)")
}
UAS_Stamina::UAS_Stamina()
{
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Stamina::Stamina,GetStaminaAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Stamina::MaxStamina,GetMaxStaminaAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Stamina::IncomingHealing,GetIncomingHealingAttribute());
UGGA_GameplayAttributesHelper::RegisterTagToAttribute(AS_Stamina::IncomingDamage,GetIncomingDamageAttribute());
}
void UAS_Stamina::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, Stamina, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ThisClass, MaxStamina, COND_None, REPNOTIFY_Always);
}
void UAS_Stamina::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetStaminaAttribute())
{
NewValue = FMath::Clamp(NewValue,0,GetMaxStamina());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePreAttributeChange(this,Attribute,NewValue);
}
}
}
bool UAS_Stamina::PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data)
{
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
return ASS->ReceivePreGameplayEffectExecute(this, Data);
}
}
return Super::PreGameplayEffectExecute(Data);
}
void UAS_Stamina::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);
if (Attribute == GetMaxStaminaAttribute())
{
AdjustAttributeForMaxChange(Stamina, OldValue, NewValue, GetStaminaAttribute());
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostAttributeChange(this, Attribute, OldValue, NewValue);
}
}
}
void UAS_Stamina::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetStaminaAttribute())
{
SetStamina(FMath::Clamp(GetStamina(),0,GetMaxStamina()));
}
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceivePostGameplayEffectExecute(this,Data);
}
}
}
void UAS_Stamina::AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute, const FGameplayAttributeData& MaxAttribute, float NewMaxValue,
const FGameplayAttribute& AffectedAttributeProperty)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
const float CurrentMaxValue = MaxAttribute.GetCurrentValue();
if (!FMath::IsNearlyEqual(CurrentMaxValue, NewMaxValue) && AbilityComp)
{
// Change current value to maintain the current Val / Max percent
const float CurrentValue = AffectedAttribute.GetCurrentValue();
float NewDelta = (CurrentMaxValue > 0.f) ? (CurrentValue * NewMaxValue / CurrentMaxValue) - CurrentValue : NewMaxValue;
AbilityComp->ApplyModToAttributeUnsafe(AffectedAttributeProperty, EGameplayModOp::Additive, NewDelta);
}
}
FGameplayAttribute UAS_Stamina::Bp_GetStaminaAttribute()
{
return ThisClass::GetStaminaAttribute();
}
float UAS_Stamina::Bp_GetStamina() const
{
return GetStamina();
}
void UAS_Stamina::Bp_SetStamina(float NewValue)
{
SetStamina(NewValue);
}
void UAS_Stamina::Bp_InitStamina(float NewValue)
{
InitStamina(NewValue);
}
void UAS_Stamina::OnRep_Stamina(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, Stamina, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetStaminaAttribute(),GetStamina(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Stamina::Bp_GetMaxStaminaAttribute()
{
return ThisClass::GetMaxStaminaAttribute();
}
float UAS_Stamina::Bp_GetMaxStamina() const
{
return GetMaxStamina();
}
void UAS_Stamina::Bp_SetMaxStamina(float NewValue)
{
SetMaxStamina(NewValue);
}
void UAS_Stamina::Bp_InitMaxStamina(float NewValue)
{
InitMaxStamina(NewValue);
}
void UAS_Stamina::OnRep_MaxStamina(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ThisClass, MaxStamina, OldValue);
if (AActor* Actor = GetOwningActor())
{
if (UGGA_AttributeSystemComponent* ASS = Actor->FindComponentByClass<UGGA_AttributeSystemComponent>())
{
ASS->ReceiveAttributeChange(this,GetMaxStaminaAttribute(),GetMaxStamina(),OldValue.GetCurrentValue());
}
}
}
FGameplayAttribute UAS_Stamina::Bp_GetIncomingHealingAttribute()
{
return ThisClass::GetIncomingHealingAttribute();
}
float UAS_Stamina::Bp_GetIncomingHealing() const
{
return GetIncomingHealing();
}
void UAS_Stamina::Bp_SetIncomingHealing(float NewValue)
{
SetIncomingHealing(NewValue);
}
FGameplayAttribute UAS_Stamina::Bp_GetIncomingDamageAttribute()
{
return ThisClass::GetIncomingDamageAttribute();
}
float UAS_Stamina::Bp_GetIncomingDamage() const
{
return GetIncomingDamage();
}
void UAS_Stamina::Bp_SetIncomingDamage(float NewValue)
{
SetIncomingDamage(NewValue);
}