UE5多人MOBA+GAS 25、创建数据表初始化属性,使用MMC计算伤害

发布于:2025-07-18 ⋅ 阅读:(20) ⋅ 点赞:(0)

用数据表初始化角色属性

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;
}

网站公告

今日签到

点亮在社区的每一天
去签到