文章目錄
- 定義一些屬性用于作為傷害基礎還有獲取要打出去的傷害
- 創建一個ECC(里面執行傷害的計算)
- 在執行ECC的GE之前需要修改ECC需要調用的值,也可以不改直接計算
- 在屬性中監聽ECC輸出的那個值然后處理扣血
定義一些屬性用于作為傷害基礎還有獲取要打出去的傷害
傷害的傳遞位置和接收位置
創建一個ECC(里面執行傷害的計算)
傷害的計算
// 幻雨喜歡小貓咪#pragma once#include "CoreMinimal.h"
#include "GameplayEffectExecutionCalculation.h"
#include "ECC_AttackDamage.generated.h"/*** */
UCLASS()
class UECC_AttackDamage : public UGameplayEffectExecutionCalculation
{GENERATED_BODY()
public:UECC_AttackDamage();virtual void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const override;
};
在DEFINE_ATTRIBUTE_CAPTUREDEF
中第三個輸入確定這個屬性是來自與施法者還是目標挨打者
DEFINE_ATTRIBUTE_CAPTUREDEF(UCAttributeSet, BaseDamage, Source, false);
最后要在這里輸出傷害
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UCAttributeSet::GetAttackDamageAttribute(), //獲取到傷害屬性EGameplayModOp::Additive, //加法BaseDamage //傷害));
用到的屬性都走struct FDamageStatics
的流程另外在構造函數的時候也要走RelevantAttributesToCapture.Add(DamageStatics().BaseDamageDef);
的流程。
// 幻雨喜歡小貓咪#include "GAS/Executions/ECC_AttackDamage.h"#include "GAS/Core/CAttributeSet.h"
#include "GAS/Core/CHeroAttributeSet.h"struct FDamageStatics
{// FGameplayEffectAttributeCaptureDefinition// 基礎傷害DECLARE_ATTRIBUTE_CAPTUREDEF(BaseDamage);// 攻擊百分比DECLARE_ATTRIBUTE_CAPTUREDEF(AttackPowerCoefficient);// 物理攻擊DECLARE_ATTRIBUTE_CAPTUREDEF(AttackPower);// 護甲穿透DECLARE_ATTRIBUTE_CAPTUREDEF(ArmorPenetration);// 護甲穿透百分比DECLARE_ATTRIBUTE_CAPTUREDEF(ArmorPenetrationPercent);// 傷害加深DECLARE_ATTRIBUTE_CAPTUREDEF(DamageAmplification);// 敵方的防御DECLARE_ATTRIBUTE_CAPTUREDEF(Armor);// 傷害減免DECLARE_ATTRIBUTE_CAPTUREDEF(DamageReduction);FDamageStatics(){// 參數:1.屬性集 2.屬性名 3.目標還是自身 4.是否設置快照(true為創建時獲取,false為應用時獲取)DEFINE_ATTRIBUTE_CAPTUREDEF(UCAttributeSet, BaseDamage, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCAttributeSet, AttackPowerCoefficient, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCAttributeSet, AttackPower, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCHeroAttributeSet, ArmorPenetration, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCHeroAttributeSet, ArmorPenetrationPercent, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCHeroAttributeSet, DamageAmplification, Source, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCAttributeSet, Armor, Target, false);DEFINE_ATTRIBUTE_CAPTUREDEF(UCHeroAttributeSet, DamageReduction, Target, false);}
};
// 靜態數據訪問函數(單例模式)
static FDamageStatics& DamageStatics()
{static FDamageStatics Statics;return Statics;
}UECC_AttackDamage::UECC_AttackDamage()
{// 將屬性添加到捕獲列表中RelevantAttributesToCapture.Add(DamageStatics().BaseDamageDef);RelevantAttributesToCapture.Add(DamageStatics().AttackPowerDef);RelevantAttributesToCapture.Add(DamageStatics().AttackPowerCoefficientDef);RelevantAttributesToCapture.Add(DamageStatics().ArmorPenetrationDef);RelevantAttributesToCapture.Add(DamageStatics().ArmorPenetrationPercentDef);RelevantAttributesToCapture.Add(DamageStatics().DamageAmplificationDef);RelevantAttributesToCapture.Add(DamageStatics().ArmorDef);RelevantAttributesToCapture.Add(DamageStatics().DamageReductionDef);
}void UECC_AttackDamage::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams,FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{// 獲取游戲效果規范和上下文const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();FGameplayEffectContextHandle EffectContextHandle = Spec.GetContext();// 獲取來源和目標標簽const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();// 初始化評估參數FAggregatorEvaluateParameters EvaluateParameters;EvaluateParameters.SourceTags = SourceTags;EvaluateParameters.TargetTags = TargetTags;// 計算基礎傷害值float BaseDamage = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().BaseDamageDef, EvaluateParameters, BaseDamage);// 獲取攻擊力float AttackPower = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().AttackPowerDef, EvaluateParameters, AttackPower);// 獲取護甲穿透百分比float ArmorPenetrationPercent = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorPenetrationPercentDef, EvaluateParameters, ArmorPenetrationPercent);// 獲取護甲穿透float ArmorPenetration = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorPenetrationDef, EvaluateParameters, ArmorPenetration);// 獲取目標護甲float TargetArmor = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorDef, EvaluateParameters, TargetArmor);// 獲取傷害加深float DamageAmp = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().DamageAmplificationDef, EvaluateParameters, DamageAmp);// 獲取敵方的傷害減免float DamageReduction = 0.0f;ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().DamageReductionDef, EvaluateParameters, DamageReduction);// 1. 處理固定護甲穿透TargetArmor = FMath::Max(0.0f, TargetArmor - ArmorPenetration);// 2. 處理百分比護甲穿透TargetArmor = FMath::Max(0.0f, TargetArmor * (1.0f - FMath::Min(ArmorPenetrationPercent, 100.0f) / 100.0f));// 3. 計算護甲減免(計算出來的是免傷率)float ArmorReduction = TargetArmor / (TargetArmor + 100.0f);BaseDamage *= (1.0f - FMath::Min(ArmorReduction / 100.0f + DamageReduction/100.0f, 1.0f));// 4. 應用傷害加深(百分比提升)BaseDamage *= (1.0f + DamageAmp / 100.0f);// 5. 輸出到AttackDamage屬性if (BaseDamage > 0.0f){// 添加輸出修飾符OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(UCAttributeSet::GetAttackDamageAttribute(), //獲取到傷害屬性EGameplayModOp::Additive, //加法BaseDamage //傷害));}
}
創建一個傷害GE,該GE只需要在執行里添加一個計算類就能調用了
在執行ECC的GE之前需要修改ECC需要調用的值,也可以不改直接計算
重新構建傷害效果結構體
// 傷害效果定義
USTRUCT(BlueprintType)
struct FGenericDamageEffectDef
{GENERATED_BODY()public:FGenericDamageEffectDef();// 傷害類型UPROPERTY(EditAnywhere)TSubclassOf<UGameplayEffect> DamageEffect;// 基礎傷害大小UPROPERTY(EditAnywhere)float BaseDamage;// 屬性的百分比傷害加成UPROPERTY(EditAnywhere)TMap<FGameplayTag, float> DamageTypes;// 力的大小UPROPERTY(EditAnywhere)FVector PushVelocity;
};
傷害的應用,可以創建一個ApplyDamage。
void UCGameplayAbility::ApplyDamage(AActor* TargetActor,const FGenericDamageEffectDef& Damage, int Level)
{const UAbilitySystemComponent* ASC = GetAbilitySystemComponentFromActorInfo();AActor* AvatarActor = GetAvatarActorFromActorInfo();// 創建效果上下文, 設置能力 、源對象 和 施加者FGameplayEffectContextHandle ContextHandle = ASC->MakeEffectContext();ContextHandle.SetAbility(this);ContextHandle.AddSourceObject(AvatarActor);ContextHandle.AddInstigator(AvatarActor, AvatarActor);float NewDamage = Damage.BaseDamage;// 通過屬性的值來修改傷害值for(auto& Pair : Damage.DamageTypes){bool bFound ;float AttributeValue = GetAbilitySystemComponentFromActorInfo()->GetGameplayAttributeValue(Pair.Key, bFound);if (bFound){NewDamage += AttributeValue * Pair.Value / 100.f;}}// 修改一下基礎傷害的值,供ECC調用GetAbilitySystemComponentFromActorInfo()->SetNumericAttributeBase(UCAttributeSet::GetBaseDamageAttribute(), NewDamage);// 創建效果Spec句柄,指定效果類、能力等級和上下文FGameplayEffectSpecHandle EffectSpecHandle = ASC->MakeOutgoingSpec(Damage.DamageEffect, Level, ContextHandle);// 在目標上應用游戲效果規范ApplyGameplayEffectSpecToTarget(GetCurrentAbilitySpecHandle(),GetCurrentActorInfo(),GetCurrentActivationInfo(),EffectSpecHandle,UAbilitySystemBlueprintLibrary::AbilityTargetDataFromActor(TargetActor));
}
也可以創建一個Make函數,只修改一下傷害(至于Level為啥沒用,我還在思考這個數值用怎么樣的形式好)
void UCGameplayAbility::MakeDamage(const FGenericDamageEffectDef& Damage, int Level)
{float NewDamage = Damage.BaseDamage;//通過標簽設置GE使用的配置for(auto& Pair : Damage.DamageTypes){bool bFound ;float AttributeValue = GetAbilitySystemComponentFromActorInfo()->GetGameplayAttributeValue(Pair.Key, bFound);if (bFound){NewDamage += AttributeValue * Pair.Value / 100.f;}}GetAbilitySystemComponentFromActorInfo()->SetNumericAttributeBase(UCAttributeSet::GetBaseDamageAttribute(), NewDamage);
}
使用轟炸的時候作為列子,依然保持調用這個藍圖的傷害賦值,只需要調用一下Make函數對基礎傷害賦值一下就好了
void UGA_GroundBlast::TargetConfirmed(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{if (!K2_CommitAbility()){K2_EndAbility();return;}// 僅在服務器上執行傷害和擊退if (K2_HasAuthority()){MakeDamage(DamageEffectDef,GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));// 對目標應用傷害效果BP_ApplyGameplayEffectToTarget(TargetDataHandle, DamageEffectDef.DamageEffect, GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));// 對目標施加推力PushTargets(TargetDataHandle, DamageEffectDef.PushVelocity);}FGameplayCueParameters BlastingGameplayCueParameters;// 設置特效的位置BlastingGameplayCueParameters.Location = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, 1).ImpactPoint;// 設置特效的大小BlastingGameplayCueParameters.RawMagnitude = TargetAreaRadius;// 播放沖擊特效和攝像機震動GetAbilitySystemComponentFromActorInfo()->ExecuteGameplayCue(BlastGameplayCueTag, BlastingGameplayCueParameters);GetAbilitySystemComponentFromActorInfo()->ExecuteGameplayCue(UCAbilitySystemStatics::GetCameraShakeGameplayCueTag(), BlastingGameplayCueParameters);// 播放釋放動畫UAnimInstance* OwnerAnimInst = GetOwnerAnimInstance();if (OwnerAnimInst){OwnerAnimInst->Montage_Play(CastMontage);}UE_LOG(LogTemp, Warning, TEXT("技能發射"));K2_EndAbility();
}
如果不調用這個藍圖的賦值Ge的函數的話,可以根據Combo的傷害賦值的方式,換一個賦值傷害的函數
void UGA_GroundBlast::TargetConfirmed(const FGameplayAbilityTargetDataHandle& TargetDataHandle)
{if (!K2_CommitAbility()){K2_EndAbility();return;}// 僅在服務器上執行傷害和擊退if (K2_HasAuthority()){// 對目標應用傷害效果// BP_ApplyGameplayEffectToTarget(TargetDataHandle, DamageEffectDef.DamageEffect, GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));// 獲取命中目標的數量TArray<AActor*> HitActors = UAbilitySystemBlueprintLibrary::GetAllActorsFromTargetData(TargetDataHandle);for (int32 i = 0; i < HitActors.Num(); ++i){AActor* HitActor = HitActors[i];// 檢查 HitResult 是否有效if (HitActor){UE_LOG(LogTemp, Warning, TEXT("命中Actor: %s"), *HitActor->GetName());ApplyDamage(HitActor, DamageEffectDef, GetAbilityLevel(CurrentSpecHandle, CurrentActorInfo));}}// ApplyDamage// 對目標施加推力PushTargets(TargetDataHandle, DamageEffectDef.PushVelocity);}FGameplayCueParameters BlastingGameplayCueParameters;// 設置特效的位置BlastingGameplayCueParameters.Location = UAbilitySystemBlueprintLibrary::GetHitResultFromTargetData(TargetDataHandle, 1).ImpactPoint;// 設置特效的大小BlastingGameplayCueParameters.RawMagnitude = TargetAreaRadius;// 播放沖擊特效和攝像機震動GetAbilitySystemComponentFromActorInfo()->ExecuteGameplayCue(BlastGameplayCueTag, BlastingGameplayCueParameters);GetAbilitySystemComponentFromActorInfo()->ExecuteGameplayCue(UCAbilitySystemStatics::GetCameraShakeGameplayCueTag(), BlastingGameplayCueParameters);// 播放釋放動畫UAnimInstance* OwnerAnimInst = GetOwnerAnimInstance();if (OwnerAnimInst){OwnerAnimInst->Montage_Play(CastMontage);}UE_LOG(LogTemp, Warning, TEXT("技能發射"));K2_EndAbility();
}
在屬性中監聽ECC輸出的那個值然后處理扣血
傷害的接收在屬性的PostGameplayEffectExecute
函數里監聽ECC最后輸出的屬性,然后扣血。(至于為什么我的暴擊放在這里這么麻煩的計算呢,我想直接在這里計算出暴擊然后調個GC,應該可以吧我還沒寫呢)
void UCAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{// 傷害if (Data.EvaluatedData.Attribute == GetAttackDamageAttribute()){float NewDamage = GetAttackDamage();SetAttackDamage(0.f);if (NewDamage > 0.f){UAbilitySystemComponent* SourceASC = Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent();if (SourceASC){bool bFound = false;const float EffectiveCriticalHitChance = SourceASC->GetGameplayAttributeValue(UCHeroAttributeSet::GetCriticalStrikeChanceAttribute(), bFound);if (bFound){bFound = false;if (const bool bCriticalHit = FMath::RandRange(1, 100) < EffectiveCriticalHitChance){const float CriticalStrikeDamage = SourceASC->GetGameplayAttributeValue(UCHeroAttributeSet::GetCriticalStrikeDamageAttribute(), bFound);if (bFound){NewDamage *= (1.f + CriticalStrikeDamage / 100.f);UE_LOG(LogTemp, Warning, TEXT("暴擊"))}}}}const float NewHealth = GetHealth() - NewDamage;SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth()));UE_LOG(LogTemp, Warning, TEXT("NewDamage: %f"), NewDamage)// Source是輸出者,Target是挨打的// UE_LOG(LogTemp, Warning, TEXT("SourceASCName: %s"), *Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent()->GetName())// UE_LOG(LogTemp, Warning, TEXT("TargetASCName: %s"), *UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Data.Target.AbilityActorInfo->AvatarActor.Get())->GetName())// UE_LOG(LogTemp, Warning, TEXT("SourceName: %s"), *Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get()->GetName())// UE_LOG(LogTemp, Warning, TEXT("TargetName: %s"), *Data.Target.AbilityActorInfo->AvatarActor.Get()->GetName())}}
}
創建一個測試用的GE看看能不能行
打了幾炮確實可行
在對小兵測試一下,確實是根據施法者的
我的屬性值寫的有點亂的說
// 幻雨喜歡小貓咪#pragma once#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "CAttributeSet.generated.h"//宏的設置,編譯時會默認給變量生成相應的Getter以及Setter函數,當前設置會生成四個函數,獲取屬性,獲取值,設置值,以及初始化值。
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/*** */
UCLASS()
class UCAttributeSet : public UAttributeSet
{GENERATED_BODY()
public:// 用于聲明哪些屬性需要在網絡中進行復制virtual void GetLifetimeReplicatedProps( TArray< class FLifetimeProperty > & OutLifetimeProps ) const override;// 當Attribute的CurrentValue被改變之前調用virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;// 僅在instant Gameplay Effect使Attribute的BaseValue改變時觸發virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData & Data) override;//virtual bool PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data) override;UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health)FGameplayAttributeData Health;ATTRIBUTE_ACCESSORS(UCAttributeSet, Health)UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth)FGameplayAttributeData MaxHealth;ATTRIBUTE_ACCESSORS(UCAttributeSet, MaxHealth)UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Mana)FGameplayAttributeData Mana;ATTRIBUTE_ACCESSORS(UCAttributeSet, Mana)UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxMana)FGameplayAttributeData MaxMana;ATTRIBUTE_ACCESSORS(UCAttributeSet, MaxMana)// 傳值的基礎傷害UPROPERTY(ReplicatedUsing = OnRep_BaseDamage)FGameplayAttributeData BaseDamage;ATTRIBUTE_ACCESSORS(UCAttributeSet, BaseDamage)// 攻擊力系數UPROPERTY(ReplicatedUsing = OnRep_AttackPowerCoefficient)FGameplayAttributeData AttackPowerCoefficient;ATTRIBUTE_ACCESSORS(UCAttributeSet, AttackPowerCoefficient)// 物理傷害UPROPERTY(ReplicatedUsing = OnRep_AttackDamage)FGameplayAttributeData AttackDamage;ATTRIBUTE_ACCESSORS(UCAttributeSet, AttackDamage)// 法術傷害UPROPERTY(ReplicatedUsing = OnRep_MagicDamage)FGameplayAttributeData MagicDamage;ATTRIBUTE_ACCESSORS(UCAttributeSet, MagicDamage)// 真實傷害UPROPERTY(ReplicatedUsing = OnRep_TrueDamage)FGameplayAttributeData TrueDamage;ATTRIBUTE_ACCESSORS(UCAttributeSet, TrueDamage)/** 攻擊力(物理攻擊強度) */UPROPERTY(ReplicatedUsing = OnRep_AttackPower)FGameplayAttributeData AttackPower;ATTRIBUTE_ACCESSORS(UCAttributeSet, AttackPower)/** 法術強度(魔法攻擊強度) */UPROPERTY(ReplicatedUsing = OnRep_MagicPower)FGameplayAttributeData MagicPower;ATTRIBUTE_ACCESSORS(UCAttributeSet, MagicPower)// 護甲值UPROPERTY(ReplicatedUsing = OnRep_Armor)FGameplayAttributeData Armor;ATTRIBUTE_ACCESSORS(UCAttributeSet, Armor)/** 法術抗性(減少受到的魔法傷害) */UPROPERTY(ReplicatedUsing = OnRep_MagicResistance)FGameplayAttributeData MagicResistance;ATTRIBUTE_ACCESSORS(UCAttributeSet, MagicResistance)// 移動速度UPROPERTY(ReplicatedUsing = OnRep_MoveSpeed)FGameplayAttributeData MoveSpeed;ATTRIBUTE_ACCESSORS(UCAttributeSet, MoveSpeed)// 移動加速度UPROPERTY(ReplicatedUsing = OnRep_MoveAcceleration)FGameplayAttributeData MoveAcceleration;ATTRIBUTE_ACCESSORS(UCAttributeSet, MoveAcceleration)UFUNCTION()void OnRep_Health(const FGameplayAttributeData& OldHealth);UFUNCTION()void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);UFUNCTION()void OnRep_Mana(const FGameplayAttributeData& OldMana);UFUNCTION()void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana);UFUNCTION()void OnRep_AttackDamage(const FGameplayAttributeData& OldAttackDamage);UFUNCTION()void OnRep_Armor(const FGameplayAttributeData& OldArmor);UFUNCTION()void OnRep_MoveSpeed(const FGameplayAttributeData& OldMoveSpeed);UFUNCTION()void OnRep_MoveAcceleration(const FGameplayAttributeData& OldMoveAcceleration);UFUNCTION()void OnRep_AttackPower(const FGameplayAttributeData& OldAttackPower);UFUNCTION()void OnRep_MagicPower(const FGameplayAttributeData& OldMagicPower);UFUNCTION()void OnRep_MagicResistance(const FGameplayAttributeData& OldMagicResistance);UFUNCTION()void OnRep_AttackPowerCoefficient(const FGameplayAttributeData& OldAttackPowerCoefficient);UFUNCTION()void OnRep_BaseDamage(const FGameplayAttributeData& OldBaseDamage);UFUNCTION()void OnRep_MagicDamage(const FGameplayAttributeData& OldMagicDamage);UFUNCTION()void OnRep_TrueDamage(const FGameplayAttributeData& OldTrueDamage);};
// 幻雨喜歡小貓咪#include "GAS/Core/CAttributeSet.h"
#include "GAS/Core/CHeroAttributeSet.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"void UCAttributeSet::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{Super::GetLifetimeReplicatedProps(OutLifetimeProps);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, Health, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, Mana, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MaxMana, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, BaseDamage, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, AttackPowerCoefficient, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, AttackDamage, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MagicDamage, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, TrueDamage, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, AttackPower, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MagicPower, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, Armor, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MagicResistance, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MoveSpeed, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCAttributeSet, MoveAcceleration, COND_None, REPNOTIFY_Always);
}void UCAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{if (Attribute == GetHealthAttribute()){NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth());}if (Attribute == GetManaAttribute()){NewValue = FMath::Clamp(NewValue, 0.f, GetMaxMana());}
}void UCAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{if (Data.EvaluatedData.Attribute == GetHealthAttribute()){SetHealth(FMath::Clamp(GetHealth(), 0, GetMaxHealth()));//SetCachedHealthPercent(GetHealth()/GetMaxHealth());}if (Data.EvaluatedData.Attribute == GetManaAttribute()){SetMana(FMath::Clamp(GetMana(), 0, GetMaxMana()));//SetCachedManaPercent(GetMana()/GetMaxMana());}// 傷害if (Data.EvaluatedData.Attribute == GetAttackDamageAttribute()){float NewDamage = GetAttackDamage();SetAttackDamage(0.f);if (NewDamage > 0.f){UAbilitySystemComponent* SourceASC = Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent();if (SourceASC){bool bFound = false;const float EffectiveCriticalHitChance = SourceASC->GetGameplayAttributeValue(UCHeroAttributeSet::GetCriticalStrikeChanceAttribute(), bFound);if (bFound){bFound = false;if (const bool bCriticalHit = FMath::RandRange(1, 100) < EffectiveCriticalHitChance){const float CriticalStrikeDamage = SourceASC->GetGameplayAttributeValue(UCHeroAttributeSet::GetCriticalStrikeDamageAttribute(), bFound);if (bFound){NewDamage *= (1.f + CriticalStrikeDamage / 100.f);UE_LOG(LogTemp, Warning, TEXT("暴擊"))}}}}const float NewHealth = GetHealth() - NewDamage;SetHealth(FMath::Clamp(NewHealth, 0.f, GetMaxHealth()));UE_LOG(LogTemp, Warning, TEXT("NewDamage: %f"), NewDamage)// Source是輸出者,Target是挨打的// UE_LOG(LogTemp, Warning, TEXT("SourceASCName: %s"), *Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent()->GetName())// UE_LOG(LogTemp, Warning, TEXT("TargetASCName: %s"), *UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Data.Target.AbilityActorInfo->AvatarActor.Get())->GetName())// UE_LOG(LogTemp, Warning, TEXT("SourceName: %s"), *Data.EffectSpec.GetContext().GetOriginalInstigatorAbilitySystemComponent()->AbilityActorInfo->AvatarActor.Get()->GetName())// UE_LOG(LogTemp, Warning, TEXT("TargetName: %s"), *Data.Target.AbilityActorInfo->AvatarActor.Get()->GetName())}}
}void UCAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, Health, OldHealth);
}void UCAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MaxHealth, OldMaxHealth);
}void UCAttributeSet::OnRep_Mana(const FGameplayAttributeData& OldMana)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, Mana, OldMana);
}void UCAttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MaxMana, OldMaxMana);
}void UCAttributeSet::OnRep_AttackDamage(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, AttackDamage, OldValue);
}void UCAttributeSet::OnRep_Armor(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, Armor, OldValue);
}void UCAttributeSet::OnRep_MoveSpeed(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MoveSpeed, OldValue);
}void UCAttributeSet::OnRep_MoveAcceleration(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MoveAcceleration, OldValue);
}void UCAttributeSet::OnRep_AttackPower(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, AttackPower, OldValue);
}void UCAttributeSet::OnRep_MagicPower(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MagicPower, OldValue);
}void UCAttributeSet::OnRep_MagicResistance(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MagicResistance, OldValue);
}void UCAttributeSet::OnRep_AttackPowerCoefficient(const FGameplayAttributeData& OldAttackPowerCoefficient)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, AttackPowerCoefficient, OldAttackPowerCoefficient);
}void UCAttributeSet::OnRep_BaseDamage(const FGameplayAttributeData& OldBaseDamage)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, BaseDamage, OldBaseDamage);
}void UCAttributeSet::OnRep_MagicDamage(const FGameplayAttributeData& OldMagicDamage)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, MagicDamage, OldMagicDamage);
}void UCAttributeSet::OnRep_TrueDamage(const FGameplayAttributeData& OldTrueDamage)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCAttributeSet, TrueDamage, OldTrueDamage);
}
// 幻雨喜歡小貓咪#pragma once#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "CHeroAttributeSet.generated.h"// 屬性訪問器宏,自動生成屬性的Getter/Setter等
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)/*** 英雄屬性集(UCHeroAttributeSet)* 用于管理英雄的成長屬性、經驗、等級、升級點、金幣等* 支持屬性同步、屬性變化回調等功能*/
UCLASS()
class UCHeroAttributeSet : public UAttributeSet
{GENERATED_BODY()
public:// 屬性訪問器聲明(自動生成標準接口)ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Intelligence) // 智力ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Strength) // 力量ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Experience) // 當前經驗ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, PrevLevelExperience) // 上一級所需經驗ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, NextLevelExperience) // 下一級所需經驗ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Level) // 當前等級ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, UpgradePoint) // 可用升級點ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MaxLevel) // 最大等級ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MaxLevelExperience) // 滿級所需經驗ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Gold) // 金幣ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, StrengthGrowthRate) // 力量成長率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, IntelligenceGrowthRate) // 智力成長率// 英雄的屬性配置ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, AttackPowerGrowthRate) // 攻擊力成長率(每等級增加的攻擊力數值)ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MagicPowerGrowthRate) // 法術強度成長率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, HealthRegen) // 生命回復速率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, HealthRegenGrowthRate) // 生命回復速率成長率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, ManaRegen) // 法力回復速率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, ManaRegenGrowthRate) // 法力回復速率成長率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, ArmorPenetration) // 護甲穿透ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MagicPenetration) // 法術穿透ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, ArmorPenetrationPercent)// 護甲穿透百分比ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MagicPenetrationPercent)// 法術穿透百分比ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, LifeSteal) // 生命偷取ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, MagicLifeSteal) // 法術吸血ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, CooldownReduction) // 冷卻縮減ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, CriticalStrikeChance) // 暴擊率ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, CriticalStrikeDamage) // 暴擊傷害ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, Toughness) // 韌性ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, DamageAmplification) // 傷害加深(增加對目標造成的傷害百分比)ATTRIBUTE_ACCESSORS(UCHeroAttributeSet, DamageReduction) // 傷害減免(減少受到的傷害百分比)// 屬性同步(網絡復制)配置virtual void GetLifetimeReplicatedProps( TArray< class FLifetimeProperty > & OutLifetimeProps ) const override;
// private:// 智力UPROPERTY(ReplicatedUsing = OnRep_Intelligence)FGameplayAttributeData Intelligence;// 力量UPROPERTY(ReplicatedUsing = OnRep_Strength)FGameplayAttributeData Strength;// 當前經驗UPROPERTY(ReplicatedUsing = OnRep_Experience)FGameplayAttributeData Experience;// 力量成長率UPROPERTY()FGameplayAttributeData StrengthGrowthRate;// 智力成長率UPROPERTY()FGameplayAttributeData IntelligenceGrowthRate;/** 攻擊力成長率(每等級增加的攻擊力數值) */UPROPERTY()FGameplayAttributeData AttackPowerGrowthRate;/** 法術強度成長率(每等級增加的法術強度數值) */UPROPERTY()FGameplayAttributeData MagicPowerGrowthRate;/** 生命回復速率(每秒回復的生命值) */UPROPERTY(ReplicatedUsing = OnRep_HealthRegen)FGameplayAttributeData HealthRegen;/** 生命回復速率成長率(每等級增加的生命回復速率) */UPROPERTY()FGameplayAttributeData HealthRegenGrowthRate;/** 法力回復速率(每秒回復的法力值) */UPROPERTY(ReplicatedUsing = OnRep_ManaRegen)FGameplayAttributeData ManaRegen;/** 法力回復速率成長率(每等級增加的法力回復速率) */UPROPERTY()FGameplayAttributeData ManaRegenGrowthRate;/** 護甲穿透(減少目標護甲的效果) */UPROPERTY(ReplicatedUsing = OnRep_ArmorPenetration)FGameplayAttributeData ArmorPenetration;/** 法術穿透(減少目標法術抗性的效果) */UPROPERTY(ReplicatedUsing = OnRep_MagicPenetration)FGameplayAttributeData MagicPenetration;/** 護甲穿透百分比(減少目標護甲的百分比效果) */UPROPERTY(ReplicatedUsing = OnRep_ArmorPenetrationPercent)FGameplayAttributeData ArmorPenetrationPercent;/** 法術穿透百分比(減少目標法術抗性的百分比效果) */UPROPERTY(ReplicatedUsing = OnRep_MagicPenetrationPercent)FGameplayAttributeData MagicPenetrationPercent;/** 生命偷取(造成物理傷害時回復生命值的百分比) */UPROPERTY(ReplicatedUsing = OnRep_LifeSteal)FGameplayAttributeData LifeSteal;/** 法術吸血(造成法術傷害時回復生命值的百分比) */UPROPERTY(ReplicatedUsing = OnRep_MagicLifesteal)FGameplayAttributeData MagicLifeSteal;/** 冷卻縮減(減少技能冷卻時間的百分比) */UPROPERTY(ReplicatedUsing = OnRep_CooldownReduction)FGameplayAttributeData CooldownReduction;/** 暴擊率(普通攻擊暴擊的幾率) */UPROPERTY(ReplicatedUsing = OnRep_CriticalStrikeChance)FGameplayAttributeData CriticalStrikeChance;// 暴擊傷害UPROPERTY(ReplicatedUsing = OnRep_CriticalStrikeDamage)FGameplayAttributeData CriticalStrikeDamage;/** 韌性(減少被控制效果影響的時間) */UPROPERTY(ReplicatedUsing = OnRep_Toughness)FGameplayAttributeData Toughness;/** 傷害加深(增加對目標造成的傷害百分比) */UPROPERTY(ReplicatedUsing = OnRep_DamageAmplification)FGameplayAttributeData DamageAmplification;/** 傷害減免(減少受到的傷害百分比) */UPROPERTY(ReplicatedUsing = OnRep_DamageReduction)FGameplayAttributeData DamageReduction;// 上一級所需經驗UPROPERTY(ReplicatedUsing = OnRep_PrevLevelExperience)FGameplayAttributeData PrevLevelExperience;// 下一級所需經驗UPROPERTY(ReplicatedUsing = OnRep_NextLevelExperience)FGameplayAttributeData NextLevelExperience;// 當前等級UPROPERTY(ReplicatedUsing = OnRep_Level)FGameplayAttributeData Level;// 可用升級點UPROPERTY(ReplicatedUsing = OnRep_UpgradePoint)FGameplayAttributeData UpgradePoint;// 最大等級UPROPERTY(ReplicatedUsing = OnRep_MaxLevel)FGameplayAttributeData MaxLevel;// 滿級所需經驗UPROPERTY(ReplicatedUsing = OnRep_MaxLevelExperience)FGameplayAttributeData MaxLevelExperience;// 金幣UPROPERTY(ReplicatedUsing = OnRep_Gold)FGameplayAttributeData Gold;// 屬性同步回調(用于客戶端屬性變化通知)UFUNCTION()void OnRep_Intelligence(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_Strength(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_Experience(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_PrevLevelExperience(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_NextLevelExperience(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_Level(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_UpgradePoint(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_MaxLevel(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_MaxLevelExperience(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_Gold(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_HealthRegen(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_ManaRegen(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_MagicPenetration(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_ArmorPenetrationPercent(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_MagicPenetrationPercent(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_LifeSteal(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_MagicLifeSteal(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_CooldownReduction(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_CriticalStrikeChance(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_CriticalStrikeDamage(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_Toughness(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_DamageAmplification(const FGameplayAttributeData& OldValue);UFUNCTION()void OnRep_DamageReduction(const FGameplayAttributeData& OldValue);
};
// 幻雨喜歡小貓咪#include "GAS/Core/CHeroAttributeSet.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"void UCHeroAttributeSet::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{Super::GetLifetimeReplicatedProps(OutLifetimeProps);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Intelligence, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Strength, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Experience, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, PrevLevelExperience, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, NextLevelExperience, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Level, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, UpgradePoint, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MaxLevel, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MaxLevelExperience, COND_None, REPNOTIFY_Always);DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Gold, COND_None, REPNOTIFY_Always);// DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, AttackPowerGrowthRate, COND_None, REPNOTIFY_Always)// DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MagicPowerGrowthRate, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, HealthRegen, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, ManaRegen, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, ArmorPenetration, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MagicPenetration, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, ArmorPenetrationPercent, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MagicPenetrationPercent, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, LifeSteal, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, MagicLifeSteal, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, CooldownReduction, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, CriticalStrikeChance, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, CriticalStrikeDamage, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, Toughness, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, DamageAmplification, COND_None, REPNOTIFY_Always)DOREPLIFETIME_CONDITION_NOTIFY(UCHeroAttributeSet, DamageReduction, COND_None, REPNOTIFY_Always)
}void UCHeroAttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Intelligence, OldValue);
}void UCHeroAttributeSet::OnRep_Strength(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Strength, OldValue);
}void UCHeroAttributeSet::OnRep_Experience(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Experience, OldValue);
}void UCHeroAttributeSet::OnRep_PrevLevelExperience(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, PrevLevelExperience, OldValue);
}void UCHeroAttributeSet::OnRep_NextLevelExperience(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, NextLevelExperience, OldValue);
}void UCHeroAttributeSet::OnRep_Level(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Level, OldValue);
}void UCHeroAttributeSet::OnRep_UpgradePoint(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, UpgradePoint, OldValue);
}void UCHeroAttributeSet::OnRep_MaxLevel(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, MaxLevel, OldValue);
}void UCHeroAttributeSet::OnRep_MaxLevelExperience(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, MaxLevelExperience, OldValue);
}void UCHeroAttributeSet::OnRep_Gold(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Gold, OldValue);
}void UCHeroAttributeSet::OnRep_HealthRegen(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, HealthRegen, OldValue);
}void UCHeroAttributeSet::OnRep_ManaRegen(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, ManaRegen, OldValue);
}void UCHeroAttributeSet::OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, ArmorPenetration, OldValue);
}void UCHeroAttributeSet::OnRep_MagicPenetration(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, MagicPenetration, OldValue);
}void UCHeroAttributeSet::OnRep_ArmorPenetrationPercent(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, ArmorPenetrationPercent, OldValue);
}void UCHeroAttributeSet::OnRep_MagicPenetrationPercent(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, MagicPenetrationPercent, OldValue);
}void UCHeroAttributeSet::OnRep_LifeSteal(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, LifeSteal, OldValue);
}void UCHeroAttributeSet::OnRep_MagicLifeSteal(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, MagicLifeSteal, OldValue);
}void UCHeroAttributeSet::OnRep_CooldownReduction(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, CooldownReduction, OldValue);
}void UCHeroAttributeSet::OnRep_CriticalStrikeChance(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, CriticalStrikeChance, OldValue);
}void UCHeroAttributeSet::OnRep_CriticalStrikeDamage(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, CriticalStrikeDamage, OldValue);
}void UCHeroAttributeSet::OnRep_Toughness(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, Toughness, OldValue);
}void UCHeroAttributeSet::OnRep_DamageAmplification(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, DamageAmplification, OldValue);
}void UCHeroAttributeSet::OnRep_DamageReduction(const FGameplayAttributeData& OldValue)
{GAMEPLAYATTRIBUTE_REPNOTIFY(UCHeroAttributeSet, DamageReduction, OldValue);
}