243 lines
7.0 KiB
C++
243 lines
7.0 KiB
C++
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
|
|
|
|
|
#include "CombatFlow/GCS_AttackResultProcessor.h"
|
|
#include "AbilitySystemBlueprintLibrary.h"
|
|
#include "AbilitySystemComponent.h"
|
|
#include "AbilitySystemGlobals.h"
|
|
#include "GameplayCueFunctionLibrary.h"
|
|
#include "GameFramework/Pawn.h"
|
|
#include "AbilitySystem/GCS_GameplayEffectContext.h"
|
|
#include "CombatFlow/GCS_CombatFlow.h"
|
|
#include "UObject/ObjectSaveContext.h"
|
|
#include "Utilities/GGA_GameplayCueFunctionLibrary.h"
|
|
#include "Utility/GCS_CombatFunctionLibrary.h"
|
|
|
|
bool UGCS_AttackResultProcessor::ProcessIncomingAttackResult(const FGCS_AttackResult& AttackResult)
|
|
{
|
|
if (!AttackResult.bConsumed)
|
|
{
|
|
HandleIncomingAttackResult(AttackResult);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
EGCS_AttackResultProcessorPolicy UGCS_AttackResultProcessor::GetExecutePolicy_Implementation() const
|
|
{
|
|
return ExecutePolicy;
|
|
}
|
|
|
|
class UWorld* UGCS_AttackResultProcessor::GetWorld() const
|
|
{
|
|
if (AActor* OwningActor = GetOwningActor())
|
|
{
|
|
return OwningActor->GetWorld();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
AActor* UGCS_AttackResultProcessor::GetOwningActor() const
|
|
{
|
|
if (UGCS_CombatFlow* Flow = Cast<UGCS_CombatFlow>(GetOuter()))
|
|
{
|
|
return Flow->GetFlowOwner();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
UAbilitySystemComponent* UGCS_AttackResultProcessor::GetOwningAbilitySystemComponent() const
|
|
{
|
|
if (AActor* OwningActor = GetOwningActor())
|
|
{
|
|
return UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(OwningActor);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
FString UGCS_AttackResultProcessor::GetEditorFriendlyName_Implementation() const
|
|
{
|
|
return TEXT("");
|
|
}
|
|
|
|
void UGCS_AttackResultProcessor::HandleIncomingAttackResult_Implementation(const FGCS_AttackResult& AttackResult) const
|
|
{
|
|
}
|
|
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
void UGCS_AttackResultProcessor::PreSave(FObjectPreSaveContext SaveContext)
|
|
{
|
|
EditorFriendlyName = GetEditorFriendlyName();
|
|
Super::PreSave(SaveContext);
|
|
}
|
|
#endif
|
|
|
|
bool UGCS_AttackResultProcessor_WithTagRequirement::ProcessIncomingAttackResult(const FGCS_AttackResult& AttackResult)
|
|
{
|
|
if (!AttackResult.bConsumed)
|
|
{
|
|
bool bMatchSourceQuery = SourceTagQuery.IsEmpty() || SourceTagQuery.Matches(AttackResult.AggregatedSourceTags);
|
|
bool bMatchTargetQuery = TargetTagQuery.IsEmpty() || TargetTagQuery.Matches(AttackResult.AggregatedTargetTags);
|
|
|
|
if (bMatchSourceQuery && bMatchTargetQuery)
|
|
{
|
|
HandleIncomingAttackResult(AttackResult);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FString UGCS_AttackResultProcessor_WithTagRequirement::GetSourceTagQueryDesc() const
|
|
{
|
|
return SourceTagQuery.GetDescription();
|
|
}
|
|
|
|
FString UGCS_AttackResultProcessor_WithTagRequirement::GetTargetTagQueryDesc() const
|
|
{
|
|
return TargetTagQuery.GetDescription();
|
|
}
|
|
|
|
void UGCS_AttackResultProcessor_Death::HandleIncomingAttackResult_Implementation(const FGCS_AttackResult& AttackResult) const
|
|
{
|
|
UAbilitySystemComponent* ASC = GetOwningAbilitySystemComponent();
|
|
if (ASC)
|
|
{
|
|
if (true)
|
|
{
|
|
}
|
|
}
|
|
Super::HandleIncomingAttackResult_Implementation(AttackResult);
|
|
}
|
|
|
|
void UGCS_AttackResultProcessor_GameplayEvent::HandleIncomingAttackResult_Implementation(const FGCS_AttackResult& AttackResult) const
|
|
{
|
|
APawn* OwningPawn = Cast<APawn>(GetOwningActor());
|
|
if (OwningPawn == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (OwningPawn->HasAuthority() || OwningPawn->IsLocallyControlled())
|
|
{
|
|
UAbilitySystemComponent* ASC = bSendToAttacker ? AttackResult.EffectContextHandle.GetInstigatorAbilitySystemComponent() : GetOwningAbilitySystemComponent();
|
|
if (IsValid(ASC))
|
|
{
|
|
FGameplayEventData Payload = FGameplayEventData();
|
|
|
|
FGameplayTagContainer InstigatorTags = AttackResult.AggregatedSourceTags;
|
|
if (const FGCS_ContextPayload_Combat* CombatPayload = UGCS_CombatFunctionLibrary::EffectContextGetMutableCombatPayload(AttackResult.EffectContextHandle))
|
|
{
|
|
InstigatorTags.AppendTags(CombatPayload->DynamicTags);
|
|
}
|
|
|
|
Payload.Instigator = AttackResult.EffectContextHandle.GetInstigator();
|
|
// Payload.OptionalObject = AttackResult.OptionalObject;
|
|
Payload.Target = OwningPawn;
|
|
Payload.ContextHandle = AttackResult.EffectContextHandle;
|
|
Payload.InstigatorTags = InstigatorTags;
|
|
Payload.TargetTags = AttackResult.AggregatedTargetTags;
|
|
|
|
for (const FGameplayTag& Tag : EventTriggers)
|
|
{
|
|
// UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(OwningPawn, Tag, Payload);
|
|
Payload.EventTag = Tag;
|
|
// FScopedPredictionWindow NewScopedWindow(ASC, true);
|
|
ASC->HandleGameplayEvent(Tag, &Payload);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FString UGCS_AttackResultProcessor_GameplayEvent::GetEditorFriendlyName_Implementation() const
|
|
{
|
|
FString Result;
|
|
|
|
for (FGameplayTag EventTrigger : EventTriggers)
|
|
{
|
|
if (EventTrigger.IsValid())
|
|
{
|
|
TArray<FString> Parts;
|
|
EventTrigger.GetTagName().ToString().ParseIntoArray(Parts,TEXT("."));
|
|
if (Parts.Num() > 0)
|
|
{
|
|
Result.Append(FString::Format(TEXT(" ({0}) "), {Parts.Last()}));
|
|
}
|
|
}
|
|
}
|
|
|
|
return FString::Format(TEXT("Send Event:{0}"), {Result});
|
|
}
|
|
|
|
void UGCS_AttackResultProcessor_GameplayCue::HandleIncomingAttackResult_Implementation(const FGCS_AttackResult& AttackResult) const
|
|
{
|
|
AActor* OwningActor = GetOwningActor();
|
|
if (!OwningActor)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TArray<FGameplayTag> CuesToTrigger = GameplayCues;
|
|
|
|
FGCS_AttackDefinition Atk = UGCS_CombatFunctionLibrary::EffectContextGetAttackDefinition(AttackResult.EffectContextHandle);
|
|
|
|
if (!Atk.TargetGameplayCues.IsEmpty())
|
|
{
|
|
CuesToTrigger = Atk.TargetGameplayCues;
|
|
}
|
|
|
|
FGameplayCueParameters Params = FGameplayCueParameters();
|
|
if (const FHitResult* HitResult = AttackResult.EffectContextHandle.GetHitResult())
|
|
{
|
|
if (HitResult->GetActor() == OwningActor)
|
|
{
|
|
Params = UGameplayCueFunctionLibrary::MakeGameplayCueParametersFromHitResult(*HitResult);
|
|
}
|
|
}
|
|
|
|
FGameplayTagContainer InstigatorTags = AttackResult.AggregatedSourceTags;
|
|
if (const FGCS_ContextPayload_Combat* CombatPayload = UGCS_CombatFunctionLibrary::EffectContextGetMutableCombatPayload(AttackResult.EffectContextHandle))
|
|
{
|
|
InstigatorTags.AppendTags(CombatPayload->DynamicTags);
|
|
Params.RawMagnitude = CombatPayload->GetTaggedValue(RawMagnitudeTag);
|
|
Params.NormalizedMagnitude = CombatPayload->GetTaggedValue(NormalizedMagnitudeTag);
|
|
}
|
|
|
|
Params.AggregatedSourceTags = InstigatorTags;
|
|
Params.AggregatedTargetTags = AttackResult.AggregatedTargetTags;
|
|
Params.EffectCauser = AttackResult.EffectContextHandle.GetEffectCauser();
|
|
Params.Instigator = AttackResult.EffectContextHandle.GetInstigator();
|
|
|
|
Params.EffectContext = AttackResult.EffectContextHandle;
|
|
|
|
ModifyGameplayCueParametersBeforeExecute(Params);
|
|
|
|
for (const FGameplayTag& Cue : CuesToTrigger)
|
|
{
|
|
if (!Cue.IsValid())
|
|
{
|
|
continue;
|
|
}
|
|
UGGA_GameplayCueFunctionLibrary::ExecuteGameplayCueLocal(OwningActor, Cue, Params);
|
|
}
|
|
}
|
|
|
|
FString UGCS_AttackResultProcessor_GameplayCue::GetEditorFriendlyName_Implementation() const
|
|
{
|
|
FString Result;
|
|
for (FGameplayTag EventTrigger : GameplayCues)
|
|
{
|
|
if (EventTrigger.IsValid())
|
|
{
|
|
TArray<FString> Parts;
|
|
EventTrigger.GetTagName().ToString().ParseIntoArray(Parts,TEXT("."));
|
|
if (Parts.Num() > 0)
|
|
{
|
|
Result.Append(FString::Format(TEXT(" ({0}) "), {Parts.Last()}));
|
|
}
|
|
}
|
|
}
|
|
return FString::Format(TEXT("Execute cues:{0}"), {Result});
|
|
}
|