用数据表初始化角色属性
在CGameplayAbilityTypes
添加新的结构体用作数据表
// 英雄基础属性结构体(用于数据表)
USTRUCT(BlueprintType)
struct FHeroBaseStats : public FTableRowBase
{
GENERATED_BODY()
public:
FHeroBaseStats();
// 英雄类
UPROPERTY(EditAnywhere)
TSubclassOf<AActor> Class;
// 力量
UPROPERTY(EditAnywhere)
float Strength;
// 智力
UPROPERTY(EditAnywhere)
float Intelligence;
// 力量成长率
UPROPERTY(EditAnywhere)
float StrengthGrowthRate;
// 智力成长率
UPROPERTY(EditAnywhere)
float IntelligenceGrowthRate;
// 基础最大生命
UPROPERTY(EditAnywhere)
float BaseMaxHealth;
// 基础最大法力
UPROPERTY(EditAnywhere)
float BaseMaxMana;
// 基础攻击力
UPROPERTY(EditAnywhere)
float BaseAttackDamage;
// 基础护甲
UPROPERTY(EditAnywhere)
float BaseArmor;
// 基础移动速度
UPROPERTY(EditAnywhere)
float BaseMoveSpeed;
};
创建数据表格填数值
UCLASS()
class UCAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
UCAbilitySystemComponent();
// 初始化基础属性
void InitializeBaseAttributes();
// 服务器初始化
void ServerSideInit();
private:
// 基础属性数据表
UPROPERTY(EditDefaultsOnly, Category = "Base Stats")
TObjectPtr<UDataTable> BaseStatDataTable;
void UCAbilitySystemComponent::InitializeBaseAttributes()
{
if (!BaseStatDataTable || !GetOwner())
{
return;
}
const FHeroBaseStats* BaseStats = nullptr;
for (const TPair<FName, uint8*>& DataPair : BaseStatDataTable->GetRowMap())
{
BaseStats = BaseStatDataTable->FindRow<FHeroBaseStats>(DataPair.Key, "");
if (BaseStats && BaseStats->Class == GetOwner()->GetClass())
{
break; //找到后退出
}
}
if (BaseStats)
{
// 设置基础战斗属性
SetNumericAttributeBase(UCAttributeSet::GetMaxHealthAttribute(), BaseStats->BaseMaxHealth); // 最大生命值
SetNumericAttributeBase(UCAttributeSet::GetMaxManaAttribute(), BaseStats->BaseMaxMana); // 最大魔法值
SetNumericAttributeBase(UCAttributeSet::GetAttackDamageAttribute(), BaseStats->BaseAttackDamage); // 攻击伤害
SetNumericAttributeBase(UCAttributeSet::GetArmorAttribute(), BaseStats->BaseArmor); // 护甲值
SetNumericAttributeBase(UCAttributeSet::GetMoveSpeedAttribute(), BaseStats->BaseMoveSpeed); // 移动速度
// 设置角色成长属性
SetNumericAttributeBase(UCHeroAttributeSet::GetStrengthAttribute(), BaseStats->Strength); // 力量
SetNumericAttributeBase(UCHeroAttributeSet::GetStrengthGrowthRateAttribute(), BaseStats->StrengthGrowthRate); // 力量成长率
SetNumericAttributeBase(UCHeroAttributeSet::GetIntelligenceAttribute(), BaseStats->Intelligence); // 智力
SetNumericAttributeBase(UCHeroAttributeSet::GetIntelligenceGrowthRateAttribute(), BaseStats->IntelligenceGrowthRate); // 智力成长率
}
}
void UCAbilitySystemComponent::ServerSideInit()
{
InitializeBaseAttributes();
ApplyInitialEffects();
GiveInitialAbilities();
}
基础角色中更改一下
void ACCharacter::ServerSideInit()
{
// 设置当前角色作为Owner和Avatar,用于后续的能力和效果应用
CAbilitySystemComponent->InitAbilityActorInfo(this, this);
CAbilitySystemComponent->ServerSideInit();
}
把数据表格放入角色中
这里的初始化就可以删掉了
把属性上的速度与角色的速度绑定起来
CCharacter
#pragma region GAS组件相关
public:
// 移动速度改变回调
void MoveSpeedUpdatad(const FOnAttributeChangeData& Data);
void ACCharacter::BindGASChangeDelegates()
{
if (CAbilitySystemComponent)
{
CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Dead).AddUObject(this, &ACCharacter::DeathTagUpdated);
CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Stun).AddUObject(this, &ACCharacter::StunTagUpdated);
CAbilitySystemComponent->RegisterGameplayTagEvent(TGameplayTags::Stats_Aim).AddUObject(this, &ACCharacter::AimTagUpdated);
CAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CAttributeSet->GetMoveSpeedAttribute()).AddUObject(this, &ACCharacter::MoveSpeedUpdatad);
}
}
void ACCharacter::MoveSpeedUpdatad(const FOnAttributeChangeData& Data)
{
GetCharacterMovement()->MaxWalkSpeed = Data.NewValue;
}
使用MMC计算伤害
MMC_BaseAttackDamage
创建后在GE添加这个计算类
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_BaseAttackDamage.generated.h"
/**
*
*/
UCLASS()
class UMMC_BaseAttackDamage : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
UMMC_BaseAttackDamage();
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
private:
FGameplayEffectAttributeCaptureDefinition DamageCaptureDef;
FGameplayEffectAttributeCaptureDefinition ArmorCaptureDef;
};
通过CalculateBaseMagnitude_Implementation
返回的值就是最终输出扣多少血的值
// 幻雨喜欢小猫咪
#include "GAS/MMC/MMC_BaseAttackDamage.h"
#include "GAS/Core/CAttributeSet.h"
UMMC_BaseAttackDamage::UMMC_BaseAttackDamage()
{
// 捕获伤害属性
DamageCaptureDef.AttributeToCapture = UCAttributeSet::GetAttackDamageAttribute();
// 属性来源指定为释放者
DamageCaptureDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Source;
// 捕获目标的护甲属性
ArmorCaptureDef.AttributeToCapture = UCAttributeSet::GetArmorAttribute();
ArmorCaptureDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target;
// 添加捕获属性
RelevantAttributesToCapture.Add(DamageCaptureDef);
RelevantAttributesToCapture.Add(ArmorCaptureDef);
}
float UMMC_BaseAttackDamage::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
FAggregatorEvaluateParameters EvalParams;
// 绑定源/目标标签
EvalParams.SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
EvalParams.TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
float AttackDamage = 0.f;
// 获取攻击力属性值(通过DamageCaptureDef定义的捕获规则)
GetCapturedAttributeMagnitude(DamageCaptureDef, Spec, EvalParams, AttackDamage); // 获取源的属性值
float Armor = 0.f;
// 获取目标护甲属性值(通过ArmorCaptureDef定义的捕获规则)
GetCapturedAttributeMagnitude(ArmorCaptureDef, Spec, EvalParams, Armor); // 获取目标的属性值
// 计算最终伤害
// 公式:Damage = AttackDamage * (1 - Armor / (Armor + 100))
// 护甲减伤率 = Armor / (Armor + 100)
float Damage = AttackDamage * (1 - Armor / (Armor + 100));
return -Damage;
}