0. 개요

이전 포스트에서 배웠던 게임플레이 이펙트의 실행 계산을 이용하여 데미지를 계산한다.

 

 

1. 커스텀 실행 계산 클래스 생성

GameplayEffectExecutionCalculation를 상속받는 C++ 클래스를 생성한다.

접두사는 ExecCalc_를 사용한다.

#include "CoreMinimal.h"
#include "GameplayEffectExecutionCalculation.h"
#include "ExecCalc_Damage.generated.h"

/**
 * 
 */
UCLASS()
class AURA_API UExecCalc_Damage : public UGameplayEffectExecutionCalculation
{
	GENERATED_BODY()
	
public:
	UExecCalc_Damage();

	virtual void Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutexecutionOutput) const override;
};

Execute는 서버에서 실행되어 클라이언트로 전달되는 클라이언트 RPC이므로 Execute 함수에 실제 구현부인 Execute_Implementation 함수가 있으며, 이 함수를 오버라이드하여 사용한다.

void UExecCalc_Damage::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutexecutionOutput) const
{
	const UAbilitySystemComponent* SourceASC = ExecutionParams.GetSourceAbilitySystemComponent();
	const UAbilitySystemComponent* TargetASC = ExecutionParams.GetTargetAbilitySystemComponent();

	const AActor* SourceAvatar = SourceASC ? SourceASC->GetAvatarActor() : nullptr;
	const AActor* TargetAvatar = TargetASC ? TargetASC->GetAvatarActor() : nullptr;

	const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();

	// 속성 캡쳐

}

ExecutionParams 구조체를 통해 타겟과 소스의 ASC, 게임플레이 이펙트 스펙, 타겟과 소스 AvatarActor를 가져올 수 있다.

 

 

2. 속성 캡쳐(Capturing Attribute)

 

6-6. 커스텀 수정자 크기 계산(MMC) - (2) MMC 생성, 게임플레이 이펙트에 적용

0. 개요이전 포스트에서 MMC의 정의를 학습하고 ASC(Ability System Component)에 레벨을 도입했다. 6-5. 커스텀 수정자 크기 계산(MMC ; Modifier Magnitude Calculation) - (1) 정의, 레벨 개념 추가0. 개요특정 클래스

crat.tistory.com

해당 포스트에서 속성을 캡처한 것과 유사한 방법을 사용한다.

 

(1) 정적 구조체와 매크로

// 단일 인스턴스 - 정적 구조체
struct AuraDamageStatics
{
	// 속성에 대한 Def 생성
	DECLARE_ATTRIBUTE_CAPTUREDEF(Armor);
	
	AuraDamageStatics()
	{
		// 정적 클래스, 속성, 소스 or 타겟, 스냅샷 여부
		DEFINE_ATTRIBUTE_CAPTUREDEF(UAuraAttributeSet, Armor, Target, false);
	}
};

static const AuraDamageStatics& DamageStatics()
{
	static AuraDamageStatics DStatics;
	return DStatics;
}

속성 값을 캡쳐하기 위해 자동으로 FGameplayEffectAttributeCaptureDefinition을 만들어주는 매크로를 사용할 것이다.

DECLARE_ATTRIBUTE_CAPTUREDEF는 입력한 텍스트에 대한 Def와 Property를 만들어준다.

(ArmorDef, ArmoProperty)

 

DEFINE_ATTRIBUTE_CAPTUREDEF는 속성이 있는 정적 클래스, 캡쳐할 속성, 소스 or 타겟, 스냅샷 여부에 따라 속성에 대한 Definition을 만들어준다.

(AuraAttributeSet에서 Armor와 관련된 속성을 찾아 ArmorDef와 ArmorProperty에 값을 넣어줌)

 

이를 구조체로 생성하고, DamageStatics 정적 함수를 만들어 인스턴스로 사용할 것이다.

인스턴스로 만들어 사용하는 것은 속성을 캡쳐할 때의 편의성을 위한 것이다.

 

 

(2) 생성자

UExecCalc_Damage::UExecCalc_Damage()
{
	RelevantAttributesToCapture.Add(DamageStatics().ArmorDef);
}

캡쳐할 속성을 Array에 담아 보관한다.

 

 

(3) Execute 구현부

void UExecCalc_Damage::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutexecutionOutput) const
{
	const UAbilitySystemComponent* SourceASC = ExecutionParams.GetSourceAbilitySystemComponent();
	const UAbilitySystemComponent* TargetASC = ExecutionParams.GetTargetAbilitySystemComponent();

	const AActor* SourceAvatar = SourceASC ? SourceASC->GetAvatarActor() : nullptr;
	const AActor* TargetAvatar = TargetASC ? TargetASC->GetAvatarActor() : nullptr;

	const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();

	// 이펙트 스펙에서 소스와 대상에 대한 태그 가져오기
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();

	FAggregatorEvaluateParameters EvalParams;
	EvalParams.SourceTags = SourceTags;
	EvalParams.TargetTags = TargetTags;

	float Armor = 0.f;

	// Armor 속성 캡쳐
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorDef, EvalParams, Armor);

	// Armor 클램핑
	Armor = FMath::Max<float>(0.f, Armor);

	// 테스트용 아머 추가
	++Armor;

	const FGameplayModifierEvaluatedData EvalData(DamageStatics().ArmorProperty, EGameplayModOp::Additive, Armor);

	OutexecutionOutput.AddOutputModifier(EvalData);
}

MMC에서와 같이 캡쳐된 속성에 대한 Magnitude를 계산하기 위해서는 AggregatorEvaluateParameters 구조체가 필요하다.

해당 구조체에 소스 태그와 타겟 태그를 저장하여 함수로 넘겨준다.

이후 값을 클램핑하고 커스텀 계산 식에 따라 값을 최종적으로 넘겨준다.

(Armor에 대해 Armor 만큼의 값을 증가시킴)

 

 

(4) 게임플레이 이펙트에 실행 계산 추가

이제 생성한 계산 클래스를 이펙트에 추가한다.