보키_기록용

[GameplayAbilitySystem] Ability C++로 만들기 본문

언리얼/Framework

[GameplayAbilitySystem] Ability C++로 만들기

bokki0117 2022. 8. 30. 10:13

전에 공부했던 Gameplay Ability System 관련해서 예제들이 Ability를 다 BP로 만들어서 C++로 만들어보고자 한다.

 

  • 위 링크 글에서 GA_Punch를 C++로 만들기
#include "CoreMinimal.h"
#include "Core/Ability/GASTestGameplayAbility.h"
#include "PunchAbility.generated.h"

class UAbilityTask_SuccessFailEvent;
/**
 * 
 */
UCLASS()
class GAMEPLAYABILITYTEST_API UPunchAbility : public UGASTestGameplayAbility
{
	GENERATED_BODY()

protected:
	UPunchAbility();

	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;

	virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;

	// WaitSuccessFailEvent(Ability Task)를 호출할 함수를 만들어준다. 해당 함수에서 Delegate 함수를 바인딩할 것이다.
	UAbilityTask_SuccessFailEvent* CreateWaitSuccessFailEvent(FGameplayTag SuccessTag, FGameplayTag FailedTag,
		AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false, bool OnlyMatchExact = true);

	// WaitSuccessFailEvent Delegate 바인딩용 Success Event 함수
	UFUNCTION()
	void OnSuccessGameplayEvent(FGameplayEventData Payload);

	// WaitSuccessFailEvent Delegate 바인딩용 Failed Event 함수
	UFUNCTION()
	void OnFailedGameplayEvent(FGameplayEventData Payload);

protected:
	// WaitSuccessFailEvent Task를 끝내기 위함.
	UPROPERTY(BlueprintReadOnly, VisibleDefaultsOnly, Category = "AbilityTask")
	UAbilityTask_SuccessFailEvent* AsyncTask { nullptr };
};

 

#include "Core/Ability/PunchAbility.h"

#include "Core/Ability/AbilityTask_SuccessFailEvent.h"
#include "Actors/GASTestCharacter.h"

UPunchAbility::UPunchAbility()
{
	AbilityInputID = EGASTestAbilityInputID::Punch;
}

void UPunchAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
                                    const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
	
	if(AGASTestCharacter* Character = Cast<AGASTestCharacter>(ActorInfo->OwnerActor))
	{
		Character->PlayAbilityAnimation(EGASTestAbilityInputID::Punch);

		AsyncTask = CreateWaitSuccessFailEvent(FGameplayTag::RequestGameplayTag(TEXT("Weapon.Hit")), FGameplayTag::RequestGameplayTag(TEXT("Weapon.NoHit")), nullptr, true);

		Character->HandlePunch();
	}
}

void UPunchAbility::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
	const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled)
{
	Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);

	if(AsyncTask)
	{
		AsyncTask->EndTask();
	}
}

UAbilityTask_SuccessFailEvent* UPunchAbility::CreateWaitSuccessFailEvent(FGameplayTag SuccessTag,
	FGameplayTag FailedTag, AActor* OptionalExternalTarget, bool OnlyTriggerOnce, bool OnlyMatchExact)
{
	if (UAbilityTask_SuccessFailEvent* InWait = UAbilityTask_SuccessFailEvent::WaitSuccessFailEvent(this, SuccessTag, FailedTag, OptionalExternalTarget, OnlyTriggerOnce, OnlyMatchExact))
	{
		InWait->SuccessEventReceived.AddDynamic(this, &UPunchAbility::OnSuccessGameplayEvent);

		InWait->FailedEventReceived.AddDynamic(this, &UPunchAbility::OnFailedGameplayEvent);

		InWait->Activate();

		return InWait;
	}

	return nullptr;
}

void UPunchAbility::OnSuccessGameplayEvent(FGameplayEventData Payload)
{
	// DamageEffect는 캐릭터에 TSubclassOf<UGameplayEffect>로 정의되어 있음.
	if (AGASTestCharacter* Character = Cast<AGASTestCharacter>(CurrentActorInfo->OwnerActor))
	{
		for(const TSubclassOf<UGameplayEffect>& DamageEffect : Character->GetDamageEffects())
		{
			ApplyGameplayEffectToTarget(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, Payload.TargetData, DamageEffect, 1, 1);
		}
	}

	K2_EndAbility();
}

void UPunchAbility::OnFailedGameplayEvent(FGameplayEventData Payload)
{
	K2_EndAbility();
}

 

 

Comments