From 5a40339c63f05ace5525f3faf4667c06fafe0787 Mon Sep 17 00:00:00 2001 From: Ingarnm <121302342+Ingarnm@users.noreply.github.com> Date: Thu, 18 Sep 2025 20:53:31 +0300 Subject: [PATCH] [Dev] Update TryActivateAbilityAndWait task --- .../Tasks/AA_TryActivateAbilityAndWait.cpp | 145 ++++++++---------- .../Tasks/AA_TryActivateAbilityAndWait.h | 37 +++-- 2 files changed, 87 insertions(+), 95 deletions(-) diff --git a/Source/UHLGAS/Private/Tasks/AA_TryActivateAbilityAndWait.cpp b/Source/UHLGAS/Private/Tasks/AA_TryActivateAbilityAndWait.cpp index 1faa897..c8722b9 100644 --- a/Source/UHLGAS/Private/Tasks/AA_TryActivateAbilityAndWait.cpp +++ b/Source/UHLGAS/Private/Tasks/AA_TryActivateAbilityAndWait.cpp @@ -1,129 +1,113 @@ // Pavel Penkov 2025 All Rights Reserved. + + #include "Tasks/AA_TryActivateAbilityAndWait.h" #include "AbilitySystemBlueprintLibrary.h" #include "AbilitySystemComponent.h" -#include "UHLGASBlueprintLibrary.h" -#include "Abilities/GameplayAbility.h" -#include "Data/PayloadWithInstancedStructs.h" -#include "Utils/UnrealHelperLibraryBPL.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(AA_TryActivateAbilityAndWait) void UAA_TryActivateAbilityAndWait::OnAbilityActivate(UGameplayAbility* ActivatedAbility) { - if (!IncludeTriggeredAbilities && ActivatedAbility->IsTriggered()) - { - return; - } - - const FGameplayTagContainer& AbilityTags = ActivatedAbility->GetAssetTags(); - if (WithTag.IsValid() && !AbilityTags.HasTag(WithTag)) - { - // Failed tag check - return; - } - - if (ShouldBroadcastDelegates()) + if (const UAbilitySystemComponent* ASC = GetAbilitySystemComponent()) { - OnActivate.Broadcast(ActivatedAbility); + if (TrackedAbilitySpecHandle.IsValid()) + { + if (FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromHandle(TrackedAbilitySpecHandle)) + { + if (Spec->GetPrimaryInstance() == ActivatedAbility) + { + if (ShouldBroadcastDelegates()) + { + OnActivate.Broadcast(ActivatedAbility); + } + } + } + } } - - // if (TriggerOnce) - // { - // EndAction(); - // } } void UAA_TryActivateAbilityAndWait::OnAbilityDeactivate(UGameplayAbility* ActivatedAbility) { - const FGameplayTagContainer& AbilityTags = ActivatedAbility->GetAssetTags(); - if (WithTag.IsValid() && !AbilityTags.HasTag(WithTag)) - { - // Failed tag check - return; - } - - if (ShouldBroadcastDelegates()) + if (const UAbilitySystemComponent* ASC = GetAbilitySystemComponent()) { - OnEndAbility.Broadcast(ActivatedAbility); - } - - if (TriggerOnce) - { - EndAction(); + if (TrackedAbilitySpecHandle.IsValid()) + { + if (FGameplayAbilitySpec* Spec = ASC->FindAbilitySpecFromHandle(TrackedAbilitySpecHandle)) + { + if (Spec->GetPrimaryInstance() == ActivatedAbility) + { + if (ShouldBroadcastDelegates()) + { + OnEndAbility.Broadcast(ActivatedAbility); + EndAction(); + } + } + } + } } } -UAA_TryActivateAbilityAndWait* UAA_TryActivateAbilityAndWait::TryActivateAbilityAndWait(AActor* TargetActor, - FGameplayTag InWithTag, bool bUsingEvent_In, const TArray& PayloadInfo, bool InIncludeTriggeredAbilities, bool bAllowRemoteActivation, bool InTriggerOnce) + +UAA_TryActivateAbilityAndWait* UAA_TryActivateAbilityAndWait::TryActivateAbilityAndWait(AActor* TargetActor, FGameplayTagQuery TagQuery, bool bAllowRemoteActivation) { UAA_TryActivateAbilityAndWait* MyObj = NewObject(); MyObj->SetAbilityActor(TargetActor); - MyObj->WithTag = InWithTag; - MyObj->bUsingEvent = bUsingEvent_In; - MyObj->IncludeTriggeredAbilities = InIncludeTriggeredAbilities; - MyObj->TriggerOnce = InTriggerOnce; + MyObj->TagQuery = TagQuery; MyObj->bAllowRemoteActivation = bAllowRemoteActivation; - MyObj->PayloadInfo = PayloadInfo; return MyObj; } -// UAA_TryActivateAbilityAndWait* UAA_TryActivateAbilityAndWait::WaitForAbilityDeactivateWithTagRequirements( -// AActor* TargetActor, FGameplayTagRequirements TagRequirements, bool InIncludeTriggeredAbilities, -// bool InTriggerOnce) -// { -// UAA_TryActivateAbilityAndWait* MyObj = NewObject(); -// MyObj->SetAbilityActor(TargetActor); -// MyObj->TagRequirements = TagRequirements; -// MyObj->IncludeTriggeredAbilities = InIncludeTriggeredAbilities; -// MyObj->TriggerOnce = InTriggerOnce; -// return MyObj; -// } -// -// UAA_TryActivateAbilityAndWait* UAA_TryActivateAbilityAndWait::WaitForAbilityDeactivate_Query( -// AActor* TargetActor, FGameplayTagQuery Query, bool InIncludeTriggeredAbilities, bool InTriggerOnce) -// { -// UAA_TryActivateAbilityAndWait* MyObj = NewObject(); -// MyObj->SetAbilityActor(TargetActor); -// MyObj->Query = Query; -// MyObj->IncludeTriggeredAbilities = InIncludeTriggeredAbilities; -// MyObj->TriggerOnce = InTriggerOnce; -// return MyObj; -// } - void UAA_TryActivateAbilityAndWait::Activate() { Super::Activate(); if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent()) { + //@TODO: Оба делегата были в одном хендле, мб вернуть? OnAbilityActivateDelegateHandle = ASC->AbilityActivatedCallbacks.AddUObject(this, &UAA_TryActivateAbilityAndWait::OnAbilityActivate); - OnAbilityActivateDelegateHandle = ASC->AbilityEndedCallbacks.AddUObject(this, &UAA_TryActivateAbilityAndWait::OnAbilityDeactivate); + OnAbilityDeactivateDelegateHandle = ASC->AbilityEndedCallbacks.AddUObject(this, &UAA_TryActivateAbilityAndWait::OnAbilityDeactivate); bool bActivated = false; - if (bUsingEvent) - { - UPayloadWithInstancedStructs* Payload = NewObject(); - Payload->InstancedStructs = PayloadInfo; - FGameplayEventData EventData; - EventData.OptionalObject = Payload; - int32 ActivatedAbilitiesCount = ASC->HandleGameplayEvent(WithTag, &EventData); - bActivated = (ActivatedAbilitiesCount > 0); - } - else { - bActivated = UUHLGASBlueprintLibrary::TryActivateAbilityWithTag(ASC, WithTag, bAllowRemoteActivation); + TArray OutAbilityHandles; + ASC->FindAllAbilitiesMatchingQuery(OutAbilityHandles, TagQuery); + + if (OutAbilityHandles.Num() > 0) + { + int32 Index = 0; + while (Index < OutAbilityHandles.Num() && !bActivated) + { + FGameplayAbilitySpecHandle AbilitySpecHandle = OutAbilityHandles[Index]; + if (AbilitySpecHandle.IsValid()) + { + TrackedAbilitySpecHandle = AbilitySpecHandle; + bActivated = ASC->TryActivateAbility(TrackedAbilitySpecHandle, bAllowRemoteActivation); + } + Index++; + } + } } if (!bActivated) { + //If ability dint activated + if (ShouldBroadcastDelegates()) + { + OnActivationFailed.Broadcast(); + } EndAction(); } } else { + //If ability dint activated + if (ShouldBroadcastDelegates()) + { + OnActivationFailed.Broadcast(); + } EndAction(); } } @@ -133,7 +117,10 @@ void UAA_TryActivateAbilityAndWait::EndAction() if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent()) { ASC->AbilityActivatedCallbacks.Remove(OnAbilityActivateDelegateHandle); + ASC->AbilityActivatedCallbacks.Remove(OnAbilityDeactivateDelegateHandle); } Super::EndAction(); } + + diff --git a/Source/UHLGAS/Public/Tasks/AA_TryActivateAbilityAndWait.h b/Source/UHLGAS/Public/Tasks/AA_TryActivateAbilityAndWait.h index dc54d5c..1344eb3 100644 --- a/Source/UHLGAS/Public/Tasks/AA_TryActivateAbilityAndWait.h +++ b/Source/UHLGAS/Public/Tasks/AA_TryActivateAbilityAndWait.h @@ -1,10 +1,10 @@ // Pavel Penkov 2025 All Rights Reserved. + #pragma once #include "CoreMinimal.h" #include "Abilities/Async/AbilityAsync.h" -#include "StructUtils/InstancedStruct.h" #include "AA_TryActivateAbilityAndWait.generated.h" /** @@ -17,23 +17,26 @@ class UHLGAS_API UAA_TryActivateAbilityAndWait : public UAbilityAsync public: UFUNCTION() - void OnAbilityActivate(UGameplayAbility *ActivatedAbility); + void OnAbilityActivate(UGameplayAbility* ActivatedAbility); UFUNCTION() void OnAbilityDeactivate(UGameplayAbility *ActivatedAbility); + + /* + UFUNCTION() + void OnAbilityActivationFailed(const UGameplayAbility *ActivatedAbility, const FGameplayTagContainer& GameplayTagContainer); + */ + /** * Wait until the specified gameplay attribute is changed on a target ability system component * It will keep listening as long as OnlyTriggerOnce = false * If used in an ability graph, this async action will wait even after activation ends. It's recommended to use WaitForAttributeChange instead. * - * If InstancedStructs specified will "SendGameplayEventToActor" with "UPayloadWithInstancedStructs" in "OptionalObject1" - * you should fill "AbilityTriggers" in GameplayAbility to activate it with this Event, * also to wait for activate/endability "WithTag" should be GameplayAbility "AbilityTags"(not strict tag check) * TODO: "PayloadInfo" not great solution probably better to check AN_FireGameplayEvent with its OptionalObject1/2 */ - UFUNCTION(BlueprintCallable, Category = "UnrealHelperLibrary|Ability|Tasks", meta = (DefaultToSelf = "TargetActor", BlueprintInternalUseOnly = "TRUE")) - static UAA_TryActivateAbilityAndWait* TryActivateAbilityAndWait(AActor* TargetActor, FGameplayTag WithTag, - bool bUsingEvent, const TArray& PayloadInfo, bool IncludeTriggeredAbilities=false, bool bAllowRemoteActivation=true, bool TriggerOnce=true); + UFUNCTION(BlueprintCallable, Category = "Ability|Tasks", meta = (DefaultToSelf = "TargetActor", BlueprintInternalUseOnly = "TRUE")) + static UAA_TryActivateAbilityAndWait* TryActivateAbilityAndWait(AActor* TargetActor, FGameplayTagQuery TagQuery, bool bAllowRemoteActivation=true); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWaitAbilityActivateDelegate, UGameplayAbility*, ActivatedAbility); UPROPERTY(BlueprintAssignable) @@ -43,21 +46,23 @@ class UHLGAS_API UAA_TryActivateAbilityAndWait : public UAbilityAsync UPROPERTY(BlueprintAssignable) FWaitAbilityActivateDelegate OnEndAbility; + DECLARE_DYNAMIC_MULTICAST_DELEGATE(FWaitAbilityActivationFailedDelegate); + UPROPERTY(BlueprintAssignable) + FWaitAbilityActivationFailedDelegate OnActivationFailed; + protected: virtual void Activate() override; virtual void EndAction() override; - FGameplayTag WithTag; - FGameplayTag WithoutTag; - TArray PayloadInfo; - bool bUsingEvent = false; - bool IncludeTriggeredAbilities = false; - bool TriggerOnce; +protected: + FGameplayTagQuery TagQuery; bool bAllowRemoteActivation = true; FGameplayTagRequirements TagRequirements; - FGameplayTagQuery Query; - -protected: + //@TODO: Оба делегата были в одном хендле, мб вернуть? FDelegateHandle OnAbilityActivateDelegateHandle; + FDelegateHandle OnAbilityDeactivateDelegateHandle; + +private: + FGameplayAbilitySpecHandle TrackedAbilitySpecHandle; };