0. 개요

새롭게 생성한 커스텀 게임플레이 이펙트 컨텍스트를 활용할 것이다.

데미지 계산 식에서 블록 또는 크리티컬이 발생할 때 컨텍스트의 불리언을 변경한다.

 

 

1. 커스텀 이펙트 컨텍스트 활용

(1) 데미지 계산식 수정 - ExecCalc_Damage

	// Block Chance 가져와서 블록이 발생했는지 확인
	float TargetBlockChance = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().BlockChanceDef, EvalParams, TargetBlockChance);
	TargetBlockChance = FMath::Max<float>(TargetBlockChance, 0.f);

	const bool bBlocked = FMath::RandRange(1, 100) < TargetBlockChance;
	
	// 불리언 설정
	FGameplayEffectContextHandle EffectContextHandle = Spec.GetContext();
	FGameplayEffectContext* Context = EffectContextHandle.Get();
	FAuraGameplayEffectContext* AuraContext = static_cast<FAuraGameplayEffectContext*>(Context);
	AuraContext->SetIsBlockedHit(bBlocked);

	// 발생 시 데미지는 절반
	if (bBlocked)
	{
		Damage = Damage / 2.f;
	}

이제 게임플레이 이펙트 컨텍스트를 가져와 커스텀 게임플레이 이펙트 컨텍스트로 캐스팅한 뒤 bIsBlocked와 bIsCriticalHit을 활용할 것이다.

 

 

(2) 커스텀 어빌리티 시스템 라이브러리 - AuraAbilitySystemLibrary

이제 커스텀 라이브러리를 통해 블루프린트에서 블록과 크리티컬 적중 여부를 가져올 수 있도록 설정한다.

 

(2-1) Getter

	UFUNCTION(BlueprintPure, Category="AuraAbilitySystemLibrary|GameplayEffects")
	static bool IsBlockedHit(const FGameplayEffectContextHandle& EffectContextHandle);

	UFUNCTION(BlueprintPure, Category = "AuraAbilitySystemLibrary|GameplayEffects")
	static bool IsCriticalHit(const FGameplayEffectContextHandle& EffectContextHandle);
bool UAuraAbilitySystemLibrary::IsBlockedHit(const FGameplayEffectContextHandle& EffectContextHandle)
{
	// 커스텀 컨텍스트로 캐스팅
	if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
	{
		return AuraEffectContext->IsBlockedHit();
	}
	return false;
}

bool UAuraAbilitySystemLibrary::IsCriticalHit(const FGameplayEffectContextHandle& EffectContextHandle)
{
	// 커스텀 컨텍스트로 캐스팅
	if (const FAuraGameplayEffectContext* AuraEffectContext = static_cast<const FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
	{
		return AuraEffectContext->IsCriticalHit();
	}
	return false;
}

 

 

(2-2) Setter

	UFUNCTION(BlueprintCallable, category = "AuraAbilitySystemLibrary|GameplayEffects")
	// const가 아니면 출력핀이 됨
	static void SetIsBlockedHit(UPARAM(ref) FGameplayEffectContextHandle& EffectContextHandle, bool bInIsBlockedHit);
    
	UFUNCTION(BlueprintCallable, category = "AuraAbilitySystemLibrary|GameplayEffects")
	// const가 아니면 출력핀이 됨
	static void SetIsCriticalHit(UPARAM(ref) FGameplayEffectContextHandle& EffectContextHandle, bool bInIsCriticalHit);
};

non-const 참조를 넘기면 언리얼에서는 자동으로 출력핀으로 설정한다.

해당 참조를 입력핀으로 바꾸기 위해서 UPARAM(ref)를 사용한다.

void UAuraAbilitySystemLibrary::SetIsBlockedHit(FGameplayEffectContextHandle& EffectContextHandle, bool bInIsBlockedHit)
{
	// 커스텀 컨텍스트로 캐스팅
	if (FAuraGameplayEffectContext* AuraEffectContext = static_cast<FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
	{
		AuraEffectContext->SetIsBlockedHit(bInIsBlockedHit);
	}
}

void UAuraAbilitySystemLibrary::SetIsCriticalHit(FGameplayEffectContextHandle& EffectContextHandle, bool bInIsCriticalHit)
{
	// 커스텀 컨텍스트로 캐스팅
	if (FAuraGameplayEffectContext* AuraEffectContext = static_cast<FAuraGameplayEffectContext*>(EffectContextHandle.Get()))
	{
		AuraEffectContext->SetIsCriticalHit(bInIsCriticalHit);
	}
}

 

 

(3) 데미지 계산식 수정 - ExecCalc_Damage

이제 커스텀 라이브러리를 사용해 코드를 단순화 할 수 있다.

	// 불리언 설정
	FGameplayEffectContextHandle EffectContextHandle = Spec.GetContext();
	UAuraAbilitySystemLibrary::SetIsBlockedHit(EffectContextHandle, bBlocked);
	// 최종 크리티컬
	float FinalCriticalHitChance = SourceCriticalHitChance - (TargetCriticalHitResistance * CriticalHitResistanceCoefficient);

	const bool bCriticalHit = FMath::RandRange(1, 100) < FinalCriticalHitChance;
	UAuraAbilitySystemLibrary::SetIsCriticalHit(EffectContextHandle, bCriticalHit);

 

 

2. 플로팅 데미지에 색 띄우기 - 사전 작업

private:
	// 콜백 데이터에서 꺼내와 구조체에 저장
	void SetEffectProperties(const FGameplayEffectModCallbackData & Data, FEffectProperties& Props) const;
	void ShowFloatingText(const FEffectProperties& Props, float Damage, bool bBlockedHit, bool bCriticalHit) const;
};
void UAuraAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData & Data)
{
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            else
            {
                // HitReact 태그 부여
                FGameplayTagContainer TagContainer;
                TagContainer.AddTag(FAuraGameplayTags::Get().Effects_HitReact);

                // 부여된 어빌리티를 찾아서 활성화
                Props.TargetASC->TryActivateAbilitiesByTag(TagContainer);
            }

            const bool bBlock = UAuraAbilitySystemLibrary::IsBlockedHit(Props.EffectContextHandle);
            const bool bCriticalHit = UAuraAbilitySystemLibrary::IsCriticalHit(Props.EffectContextHandle);
            ShowFloatingText(Props, LocalIncomingDamage, bBlock, bCriticalHit);
        }
    }
}

발생하는 데미지 위젯 블루프린트에 색을 입히기 위한 사전 작업이다.