UE5多人MOBA+GAS 番外篇:使用ECC(UGameplayEffectExecutionCalculation)制作傷害計算的流程

文章目錄

  • 定義一些屬性用于作為傷害基礎還有獲取要打出去的傷害
  • 創建一個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);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/89984.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/89984.shtml
英文地址,請注明出處:http://en.pswp.cn/web/89984.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringBoot實戰0-5

接口文檔&#xff1a;通俗的講&#xff0c;接口文檔能告訴開發者接口能返回的數據&#xff0c;以及為了獲取這些數據&#xff0c;開發者需要輸入什么樣的數據&#xff0c;請求哪個接口&#xff08;即規范&#xff09;為什么使用接口文檔&#xff1a;1、項目開發過程中前后端工程…

二、SpringBoot-REST開發

rest開發&#xff08;表現形式轉換&#xff09;&#xff1a; 1、優點&#xff1a;隱藏訪問資源的行為&#xff0c;無法通過地址得知對資源是何種操作&#xff0c;書寫簡化 2、GET查詢 POST 新增/保存 PUT&#xff08;修改/更新&#xff09; DELETE&#xff08;刪除&#xff09;…

大數據之路:阿里巴巴大數據實踐——離線數據開發

數據開發平臺 統一計算平臺MaxCompute&#xff1a;主要服務于海量數據的存儲和計算 &#xff0c;提供完善的數據導入方案&#xff0c; 以及多種經典的分布式計算模型&#xff0c;提供海量數據倉庫的解決方案&#xff0c;能夠更快速地解決用戶的海量數據計算問題&#xff0c;有效…

我的網頁聊天室設計

一、需求分析1.用戶管理模塊注冊功能實現一個注冊頁面。注冊頁面上包含了一個輸入框&#xff0c;輸入用戶名和密碼. 注冊成功后可以跳轉到登錄頁面.登錄功能實現一個登錄頁面。登錄頁面上包含一個輸入框。輸入用戶名和密碼. 登錄成功后可以跳轉到主頁面.2.主界面用戶信息左上角…

數據結構自學Days10 -- 二叉樹的常用實現

? 一、為什么要學習二叉樹&#xff1f; 1. &#x1f4e6; 組織數據的高效方式 二叉樹可以快速插入、刪除、查找數據&#xff0c;尤其在平衡時&#xff0c;時間復雜度為 $O(\log n)$。 適合表示分層結構&#xff08;如組織結構、文件系統、語法樹&#xff09;。 2. &#x…

Java注解家族--`@ResponseBody`

ResponseBody ResponseBody是 Spring 框架中的一個注解&#xff0c;在基于 Spring 的 Web 開發中扮演著重要角色&#xff0c;以下是對它的詳細總結&#xff1a; 1.定義與基本功能 定義&#xff1a;ResponseBody注解用于將 Controller 方法的返回值&#xff0c;通過適當的 HttpM…

react-window 大數據列表和表格數據渲染組件之虛擬滾動

簡介 React Window 是一個高效的 React 組件庫&#xff0c;專為渲染大數據列表和表格數據而設計。它通過”虛擬化”技術&#xff08;也稱為”窗口化”或”列表虛擬化”&#xff09;解決了在 React 應用中渲染大量數據時的性能問題。與傳統方法不同&#xff0c;React Window 只…

Eltable tree形式,序號列實現左對齊,并且每下一層都跟上一層的錯位距離拉大

要的是如圖所示效果序號加個class-name寫樣式然后給eltable加indent屬性就可以了&#xff0c;我設置的25

FOC算法中SIMULINK一些常用模塊(2)-Permanent Magnet Synchronous Machine模塊

一&#xff0c;介紹這三個模塊一起介紹了&#xff0c;由左到右&#xff0c;分別是電源模塊&#xff0c;驅動模塊和電機模塊。主要介紹一下電機模塊二&#xff0c;DC Voltage SourceDC Voltage Source 模塊是用于表示直流電壓源的基本組件&#xff0c;可以提供恒流直壓&#xff…

RPG62.制作敵人攻擊波數二:攻擊ui

1。經典創建userwidget&#xff0c;使用xmbtextblock&#xff0c;結構如下。然后設置動畫與音頻&#xff0c;上下的參數是一樣的&#xff0c;轉到圖表打開BP_SurvialGameMode2.再創建一個widget&#xff0c;結構如下新添的動畫打開XMBGameModeBase&#xff0c;創建構造函數AXMB…

DL00691-基于深度學習的軸承表面缺陷目標檢測含源碼python

DL00691-基于深度學習的軸承表面缺陷目標檢測含源碼python

Word 中為什么我的圖片一拖就亂跑,怎么精確定位?

核心原因&#xff1a;文字環繞方式 (Text Wrapping) 問題的根源在于圖片的**“文字環繞”**設置。 默認狀態&#xff1a;“嵌入型” (In Line with Text) 當您插入一張圖片時&#xff0c;Word默認會把它當作一個巨大的文字字符來處理。這就是為什么您拖動它時&#xff0c;它會像…

Linux物理地址空間入門:從硬件到內核內存的基石

目錄 一、物理地址空間是什么&#xff1f; 二、物理地址空間的構成&#xff1a;不僅僅是內存 三、Linux內核如何管理物理地址空間 &#xff08;1&#xff09;物理內存的碎片化問題 &#xff08;2&#xff09;物理地址的分區管理 &#xff08;3&#xff09;物理地址與內核…

【2025最新版】PDFelement全能PDF編輯器

工具https://pan.quark.cn/s/a56d17fd05dd強大全能的PDF編輯神器PDFelementPro 全能PDF工具套裝 PDF閱讀器 PDF創建器 PDF編輯器 PDF注釋器 PDF轉換器 OCR識別工具 表單填寫和創建 數據提取 批量處理 更多詳情萬興PDF專業版特性。格式轉換&#xff1a;PDFelement輕松…

基于單片機汽車駕駛防瞌睡防疲勞報警器自動熄火設計

&#xff08;一&#xff09;系統功能設計 51單片機汽車駕駛防疲勞防瞌睡報警器自動熄火15 本系統由STC89C52單片機、蜂鳴器、ADXL345重力加速度傳感器、繼電器控制、按鍵、指示燈及電源組成。 1、通過按鍵點亮led燈&#xff0c;代表車輛啟動和熄火。 2、車輛啟動后&#xff0c;…

OpenCV中的卷積高斯模糊與中值模糊

目錄 一、卷積高斯模糊 (Gaussian Blur) 1. 原理與數學基礎 2. OpenCV函數實現 3. 關鍵參數說明 4. 代碼示例 5. 特點與應用 二、中值模糊 (Median Blur) 1. 原理與數學基礎 2. OpenCV函數實現 3. 關鍵參數說明 4. 代碼示例 5. 特點與應用 三、兩種模糊方法對比分析…

macbookpro m1 max本兒上速搭一個elasticsearch+kibana環境

一、找個目錄&#xff0c;新建一個: docker-compose.yml version: "3.9" services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0 # 與 Kibana 版本一致container_name: elasticsearchenvironment:- discovery.typesingle-node- xpa…

部署zabbix企業級分布式監控

一. 監控系統的功能概述監控、從中文的字義來看&#xff0c;有兩個內容&#xff0c;一是檢測&#xff0c;二是控制。重點在第一個字眼&#xff0c;即檢測、預防的意思。監控&#xff0c;對應的英文單詞是 Monitoring。在計算機領域&#xff0c;可以將其分為5種監控類型。應用性…

【重學MySQL】redolog binlog

目錄 Buffer Pool是什么&#xff1f; redo log&#xff08;Innodb獨有&#xff09; 為什么需要redolog&#xff1f; 類比的方式巧記redolog binlog&#xff08;Server層獨有&#xff09; binlog是干啥的&#xff1f; 為什么有了 binlog&#xff0c; 還要有 redo log&…

企業信息化建設技術底座建設解決方案

1、企業數字化底座與數字化綜述2、企業數字化底座與數字化總體架構3、企業數字化底座與數字化規劃設計4、企業數字化底座與數字化建設運營5、企業數字化底座與數字化未來展望篇幅有限以下只展示部分截圖&#xff1a;