From 69c9770412a6cf39808cc15c1426554c52f2cd6a Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:24:39 -0700 Subject: [PATCH 1/9] - Added Parameterized Input Key Press Task --- .../WaitForInputKeyPressParameterized.cpp | 105 ++++++++++++++++++ .../Tasks/WaitForInputKeyPressParameterized.h | 49 ++++++++ 2 files changed, 154 insertions(+) create mode 100644 Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyPressParameterized.cpp create mode 100644 Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyPressParameterized.h diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyPressParameterized.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyPressParameterized.cpp new file mode 100644 index 00000000..35787514 --- /dev/null +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyPressParameterized.cpp @@ -0,0 +1,105 @@ +#include "Ability/Tasks/WaitForInputKeyPressParameterized.h" + +#include "EnhancedInputComponent.h" +#include "Components/GMCAbilityComponent.h" + +UGMCAbilityTask_WaitForInputKeyPressParameterized* UGMCAbilityTask_WaitForInputKeyPressParameterized::WaitForKeyPress(UGMCAbility* OwningAbility, UInputAction* InputAction) +{ + UGMCAbilityTask_WaitForInputKeyPressParameterized* Task = NewAbilityTask(OwningAbility); + Task->Ability = OwningAbility; + Task->InputActionToWaitFor = InputAction; + return Task; +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::Activate() +{ + Super::Activate(); + + if (Ability->bAllowMultipleInstances) { + UE_LOG(LogGMCAbilitySystem, Warning, TEXT("Ability %s is set to allow multiple instances and this should not be used with WaitForInputKeyPress AbilityTask !"), *Ability->GetName()); + ClientProgressTask(); + return; + } + + if (Ability->AbilityInputAction != nullptr) + { + UEnhancedInputComponent* const InputComponent = GetEnhancedInputComponent(); + + if (InputComponent) + { + const FEnhancedInputActionEventBinding& Binding = InputComponent->BindAction( + InputActionToWaitFor, ETriggerEvent::Started, this, + &UGMCAbilityTask_WaitForInputKeyPressParameterized::OnKeyPressed); + + InputBindingHandle = Binding.GetHandle(); + } + } + else + { + ClientProgressTask(); + } +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::OnKeyPressed(const FInputActionValue& InputActionValue) +{ + // Unbind from the input component so we don't fire multiple times. + if (UEnhancedInputComponent* InputComponent = GetValid(GetEnhancedInputComponent())) + { + InputComponent->RemoveActionBindingForHandle(InputBindingHandle); + InputBindingHandle = -1; + } + + ClientProgressTask(); +} + +UEnhancedInputComponent* UGMCAbilityTask_WaitForInputKeyPressParameterized::GetEnhancedInputComponent() const +{ + UInputComponent* InputComponent = Ability->OwnerAbilityComponent->GetOwner()->GetComponentByClass(); + if (InputComponent) + { + if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked(InputComponent)) + { + return EnhancedInputComponent; + } + } + return nullptr; +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::OnTaskCompleted() +{ + EndTask(); + Completed.Broadcast(); + bTaskCompleted = true; +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::OnDestroy(bool bInOwnerFinished) +{ + Super::OnDestroy(bInOwnerFinished); + + // If we're still bound to the input component for some reason, we'll want to unbind. + if (InputBindingHandle != -1) + { + if (UEnhancedInputComponent* InputComponent = GetValid(GetEnhancedInputComponent())) + { + InputComponent->RemoveActionBindingForHandle(InputBindingHandle); + InputBindingHandle = -1; + } + } +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::ProgressTask(FInstancedStruct& TaskData) +{ + Super::ProgressTask(TaskData); + OnTaskCompleted(); +} + +void UGMCAbilityTask_WaitForInputKeyPressParameterized::ClientProgressTask() +{ + FGMCAbilityTaskData TaskData; + TaskData.TaskType = EGMCAbilityTaskDataType::Progress; + TaskData.AbilityID = Ability->GetAbilityID(); + TaskData.TaskID = TaskID; + const FInstancedStruct TaskDataInstance = FInstancedStruct::Make(TaskData); + + Ability->OwnerAbilityComponent->QueueTaskData(TaskDataInstance); +} diff --git a/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyPressParameterized.h b/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyPressParameterized.h new file mode 100644 index 00000000..66328957 --- /dev/null +++ b/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyPressParameterized.h @@ -0,0 +1,49 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Ability/Tasks/GMCAbilityTaskBase.h" +#include "EnhancedInputComponent.h" +#include "Ability/GMCAbility.h" +#include "InstancedStruct.h" +#include "LatentActions.h" +#include "WaitForInputKeyPressParameterized.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FAbilityTaskWaitForInputKeyPressParameterized); + +/** + * + */ +UCLASS() +class GMCABILITYSYSTEM_API UGMCAbilityTask_WaitForInputKeyPressParameterized : public UGMCAbilityTaskBase { + GENERATED_BODY() + +public: + + void OnTaskCompleted(); + virtual void OnDestroy(bool bInOwnerFinished) override; + + virtual void ProgressTask(FInstancedStruct& TaskData) override; + virtual void ClientProgressTask() override; + + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", HidePin = "OwningAbility", DefaultToSelf = "OwningAbility"), DisplayName = "Wait For Input Key Press Parameterized", Category = "GMCAbilitySystem/Tasks") + static UGMCAbilityTask_WaitForInputKeyPressParameterized* WaitForKeyPress(UGMCAbility* OwningAbility, UInputAction* InputAction); + + //Overriding BP async action base + virtual void Activate() override; + + UPROPERTY(BlueprintAssignable) + FAbilityTaskWaitForInputKeyPressParameterized Completed; + + UPROPERTY() + UInputAction* InputActionToWaitFor = nullptr; + +protected: + + void OnKeyPressed(const FInputActionValue& InputActionValue); + +private: + + UEnhancedInputComponent* GetEnhancedInputComponent() const; + + int64 InputBindingHandle = -1; +}; From 18d005cc5efe66a5bdf858fba9493b19bd1e7e4b Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Tue, 6 May 2025 19:53:39 -0700 Subject: [PATCH 2/9] 5/6 --- .../Private/Ability/GMCAbility.cpp | 22 ++++++++ .../Ability/Tasks/GMCAbilityTaskBase.cpp | 26 +++++++--- .../Ability/Tasks/SetTargetDataByte.cpp | 2 +- .../Ability/Tasks/SetTargetDataFloat.cpp | 2 +- .../Tasks/SetTargetDataGameplayTag.cpp | 2 +- .../Ability/Tasks/SetTargetDataHit.cpp | 2 +- .../Tasks/SetTargetDataInstancedStruct.cpp | 2 +- .../Ability/Tasks/SetTargetDataInt.cpp | 2 +- .../Ability/Tasks/SetTargetDataObject.cpp | 2 +- .../Ability/Tasks/SetTargetDataTransform.cpp | 2 +- .../Ability/Tasks/SetTargetDataVector3.cpp | 9 +++- .../Ability/Tasks/WaitForInputKeyRelease.cpp | 32 +++++++++--- .../Components/GMCAbilityComponent.cpp | 52 ++++++++++--------- ...eplayDebuggerCategory_GMCAbilitySystem.cpp | 4 +- .../Private/Effects/GMCAbilityEffect.cpp | 19 +++++++ .../Public/Ability/GMCAbility.h | 4 ++ .../Public/Ability/Tasks/GMCAbilityTaskBase.h | 15 +++--- .../Ability/Tasks/WaitForInputKeyRelease.h | 12 +++-- .../Public/Components/GMCAbilityComponent.h | 6 +++ .../Public/Effects/GMCAbilityEffect.h | 9 +++- 20 files changed, 168 insertions(+), 58 deletions(-) diff --git a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp index acd90230..1acd0574 100644 --- a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp @@ -182,8 +182,30 @@ void UGMCAbility::CancelAbilities() UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability (tag) %s has been cancelled by (tag) %s"), *AbilityTag.ToString(), *AbilityToCancelTag.ToString()); } } + // Cancel by AbilityDefinition (generic category tags) + TArray DefinitionTags; + AbilityDefinition.GetGameplayTagArray(DefinitionTags); + + for (const FGameplayTag& DefinitionTag : DefinitionTags) + { + // Prevent self-cancellation + if (AbilityTag.MatchesTag(DefinitionTag)) + { + UE_LOG(LogGMCAbilitySystem, Warning, TEXT("Ability (tag) %s attempted to cancel itself via AbilityDefinition tag %s"), + *AbilityTag.ToString(), *DefinitionTag.ToString()); + continue; + } + + int Cancelled = OwnerAbilityComponent->EndAbilitiesByTag(DefinitionTag); + if (Cancelled > 0) + { + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability (tag) %s cancelled %d ability(ies) by AbilityDefinition tag: %s"), + *AbilityTag.ToString(), Cancelled, *DefinitionTag.ToString()); + } + } } + void UGMCAbility::ServerConfirm() { bServerConfirmed = true; diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/GMCAbilityTaskBase.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/GMCAbilityTaskBase.cpp index 798eb8c1..92ca9f1d 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/GMCAbilityTaskBase.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/GMCAbilityTaskBase.cpp @@ -30,11 +30,16 @@ void UGMCAbilityTaskBase::RegisterTask(UGMCAbilityTaskBase* Task) void UGMCAbilityTaskBase::Tick(float DeltaTime) { + +} + +void UGMCAbilityTaskBase::AncillaryTick(float DeltaTime){ // Locally controlled server pawns don't need to send heartbeats if (AbilitySystemComponent->GMCMovementComponent->IsLocallyControlledServerPawn()) return; // If not the server version of the component, send heartbeats - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer && + AbilitySystemComponent->GetNetMode() != NM_ListenServer) { if (ClientLastHeartbeatSentTime + HeartbeatInterval < AbilitySystemComponent->ActionTimer) { @@ -48,11 +53,6 @@ void UGMCAbilityTaskBase::Tick(float DeltaTime) Ability->EndAbility(); EndTask(); } - -} - -void UGMCAbilityTaskBase::AncillaryTick(float DeltaTime){ - } void UGMCAbilityTaskBase::ClientProgressTask() @@ -64,3 +64,17 @@ void UGMCAbilityTaskBase::ClientProgressTask() const FInstancedStruct TaskDataInstance = FInstancedStruct::Make(TaskData); Ability->OwnerAbilityComponent->QueueTaskData(TaskDataInstance); } + +void UGMCAbilityTaskBase::Heartbeat() +{ + AbilitySystemComponent->GMCMovementComponent->SV_SwapServerState(); + LastHeartbeatReceivedTime = AbilitySystemComponent->ActionTimer; + AbilitySystemComponent->GMCMovementComponent->SV_SwapServerState(); +} + +bool UGMCAbilityTaskBase::IsClientOrRemoteListenServerPawn() const +{ + return (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer && + AbilitySystemComponent->GetNetMode() != NM_ListenServer) || + AbilitySystemComponent->GMCMovementComponent->IsLocallyControlledServerPawn(); +} diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataByte.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataByte.cpp index 79883141..a7cf416f 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataByte.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataByte.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataByte::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataFloat.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataFloat.cpp index dd7df7f0..f75bc9f2 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataFloat.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataFloat.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataFloat::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataGameplayTag.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataGameplayTag.cpp index 6847bc08..9a122df0 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataGameplayTag.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataGameplayTag.cpp @@ -11,7 +11,7 @@ UGMCAbilityTask_SetTargetDataGameplayTag* UGMCAbilityTask_SetTargetDataGameplayT void UGMCAbilityTask_SetTargetDataGameplayTag::Activate(){ Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataHit.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataHit.cpp index f22f5d93..29bca21e 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataHit.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataHit.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataHit::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInstancedStruct.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInstancedStruct.cpp index 1c938a2e..0cc784b3 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInstancedStruct.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInstancedStruct.cpp @@ -11,7 +11,7 @@ UGMCAbilityTask_SetTargetDataInstancedStruct* UGMCAbilityTask_SetTargetDataInsta void UGMCAbilityTask_SetTargetDataInstancedStruct::Activate(){ Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInt.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInt.cpp index 11d3353c..d29774e8 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInt.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataInt.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataInt::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataObject.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataObject.cpp index ca7852c9..c848c8df 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataObject.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataObject.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataObject::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataTransform.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataTransform.cpp index ca1f9cd1..076bf3a6 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataTransform.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataTransform.cpp @@ -11,7 +11,7 @@ UGMCAbilityTask_SetTargetDataTransform* UGMCAbilityTask_SetTargetDataTransform:: void UGMCAbilityTask_SetTargetDataTransform::Activate(){ Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataVector3.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataVector3.cpp index c540e05f..c5f55b47 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataVector3.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/SetTargetDataVector3.cpp @@ -16,7 +16,7 @@ void UGMCAbilityTask_SetTargetDataVector3::Activate() { Super::Activate(); - if (AbilitySystemComponent->GetNetMode() != NM_DedicatedServer) + if (IsClientOrRemoteListenServerPawn()) { ClientProgressTask(); } @@ -25,6 +25,13 @@ void UGMCAbilityTask_SetTargetDataVector3::Activate() void UGMCAbilityTask_SetTargetDataVector3::ProgressTask(FInstancedStruct& TaskData) { Super::ProgressTask(TaskData); + if (TaskData.GetScriptStruct() != FGMCAbilityTaskTargetDataVector3::StaticStruct()) + { + UE_LOG(LogGMCAbilitySystem, Error, TEXT("UGMCAbilityTask_SetTargetDataVector3::ProgressTask: Invalid TaskData")); + EndTask(); + return; + } + const FGMCAbilityTaskTargetDataVector3 Data = TaskData.Get(); Completed.Broadcast(Data.Target); diff --git a/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyRelease.cpp b/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyRelease.cpp index 77d4396e..1c731eb3 100644 --- a/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyRelease.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/Tasks/WaitForInputKeyRelease.cpp @@ -5,17 +5,20 @@ #include "Components/GMCAbilityComponent.h" #include "Kismet/KismetSystemLibrary.h" -UGMCAbilityTask_WaitForInputKeyRelease* UGMCAbilityTask_WaitForInputKeyRelease::WaitForKeyRelease(UGMCAbility* OwningAbility, bool bCheckForReleaseDuringActivation) +UGMCAbilityTask_WaitForInputKeyRelease* UGMCAbilityTask_WaitForInputKeyRelease::WaitForKeyRelease(UGMCAbility* OwningAbility, bool bCheckForReleaseDuringActivation, float MaxDuration) { UGMCAbilityTask_WaitForInputKeyRelease* Task = NewAbilityTask(OwningAbility); Task->Ability = OwningAbility; Task->bShouldCheckForReleaseDuringActivation = bCheckForReleaseDuringActivation; + Task->MaxDuration = MaxDuration; return Task; } void UGMCAbilityTask_WaitForInputKeyRelease::Activate() { Super::Activate(); + + StartTime = AbilitySystemComponent->ActionTimer; UEnhancedInputComponent* const InputComponent = GetEnhancedInputComponent(); @@ -52,15 +55,24 @@ void UGMCAbilityTask_WaitForInputKeyRelease::Activate() } } -void UGMCAbilityTask_WaitForInputKeyRelease::OnKeyReleased(const FInputActionValue& InputActionValue) +void UGMCAbilityTask_WaitForInputKeyRelease::AncillaryTick(float DeltaTime) { - // Unbind since we're done now. - ClientProgressTask(); - if (UInputComponent* const InputComponent = GetValid(GetEnhancedInputComponent())) + Super::Tick(DeltaTime); + if (bTaskCompleted) return; + + Duration = AbilitySystemComponent->ActionTimer - StartTime; + OnTick.Broadcast(Duration); + + if (MaxDuration > 0 && Duration >= MaxDuration) { - InputComponent->RemoveActionBindingForHandle(InputBindingHandle); + ClientProgressTask(); } +} +void UGMCAbilityTask_WaitForInputKeyRelease::OnKeyReleased(const FInputActionValue& InputActionValue) +{ + // Unbind since we're done now. + ClientProgressTask(); InputBindingHandle = -1; } @@ -80,7 +92,8 @@ UEnhancedInputComponent* UGMCAbilityTask_WaitForInputKeyRelease::GetEnhancedInpu void UGMCAbilityTask_WaitForInputKeyRelease::OnTaskCompleted() { EndTask(); - Completed.Broadcast(); + Duration = AbilitySystemComponent->ActionTimer - StartTime; + Completed.Broadcast(Duration); bTaskCompleted = true; } @@ -108,6 +121,11 @@ void UGMCAbilityTask_WaitForInputKeyRelease::ProgressTask(FInstancedStruct& Task void UGMCAbilityTask_WaitForInputKeyRelease::ClientProgressTask() { + if (UInputComponent* const InputComponent = GetValid(GetEnhancedInputComponent())) + { + InputComponent->RemoveActionBindingForHandle(InputBindingHandle); + } + FGMCAbilityTaskData TaskData; TaskData.TaskType = EGMCAbilityTaskDataType::Progress; TaskData.AbilityID = Ability->GetAbilityID(); diff --git a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp index 3e8c36e6..c26198f9 100644 --- a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp +++ b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp @@ -82,12 +82,6 @@ void UGMC_AbilitySystemComponent::BindReplicationData() // We sort our attributes alphabetically by tag so that it's deterministic. for (auto& AttributeForBind : BoundAttributes.Attributes) { - GMCMovementComponent->BindSinglePrecisionFloat(AttributeForBind.BaseValue, - EGMC_PredictionMode::ServerAuth_Output_ClientValidated, - EGMC_CombineMode::CombineIfUnchanged, - EGMC_SimulationMode::Periodic_Output, - EGMC_InterpolationFunction::TargetValue); - GMCMovementComponent->BindSinglePrecisionFloat(AttributeForBind.Value, EGMC_PredictionMode::ServerAuth_Output_ClientValidated, EGMC_CombineMode::CombineIfUnchanged, @@ -113,13 +107,6 @@ void UGMC_AbilitySystemComponent::BindReplicationData() EGMC_InterpolationFunction::TargetValue); } - // Sync'd Action Timer - GMCMovementComponent->BindDoublePrecisionFloat(ActionTimer, - EGMC_PredictionMode::ServerAuth_Output_ClientValidated, - EGMC_CombineMode::CombineIfUnchanged, - EGMC_SimulationMode::None, - EGMC_InterpolationFunction::TargetValue); - // Granted Abilities GMCMovementComponent->BindGameplayTagContainer(GrantedAbilityTags, EGMC_PredictionMode::ServerAuth_Output_ClientValidated, @@ -172,6 +159,8 @@ void UGMC_AbilitySystemComponent::GenAncillaryTick(float DeltaTime, bool bIsComb TickActiveCooldowns(DeltaTime); + + SendTaskDataToActiveAbility(false); TickAncillaryActiveAbilities(DeltaTime); // Check if we have a valid operation @@ -180,8 +169,6 @@ void UGMC_AbilitySystemComponent::GenAncillaryTick(float DeltaTime, bool bIsComb { ProcessAbilityOperation(Operation, false); } - - SendTaskDataToActiveAbility(false); ClearAbilityAndTaskData(); QueuedEffectOperations_ClientAuth.ClearCurrentOperation(); @@ -538,11 +525,14 @@ bool UGMC_AbilitySystemComponent::IsServerOnly() const void UGMC_AbilitySystemComponent::GenPredictionTick(float DeltaTime) { bJustTeleported = false; - ActionTimer += DeltaTime; + // ActionTimer += DeltaTime; + ActionTimer = GMCMovementComponent->GetMoveTimestamp(); ApplyStartingEffects(); - + + SendTaskDataToActiveAbility(true); TickActiveAbilities(DeltaTime); + TickActiveEffects(DeltaTime); // Abilities @@ -562,7 +552,7 @@ void UGMC_AbilitySystemComponent::GenPredictionTick(float DeltaTime) ServerHandlePredictedPendingEffect(DeltaTime); - SendTaskDataToActiveAbility(true); + } void UGMC_AbilitySystemComponent::GenSimulationTick(float DeltaTime) @@ -1084,6 +1074,20 @@ bool UGMC_AbilitySystemComponent::CheckActivationTags(const UGMCAbility* Ability } +void UGMC_AbilitySystemComponent::ClearAbilityMap() +{ + // For each AbilityMap in the map AbilityMap: + for (auto& AbilityMapData : AbilityMap) + { + if (GrantedAbilityTags.HasTag(AbilityMapData.Value.InputTag)) + { + GrantedAbilityTags.RemoveTag(AbilityMapData.Value.InputTag); + } + } + + AbilityMap.Empty(); +} + void UGMC_AbilitySystemComponent::InitializeAbilityMap(){ for (UGMCAbilityMapData* StartingAbilityMap : AbilityMaps) { @@ -1121,12 +1125,12 @@ void UGMC_AbilitySystemComponent::RemoveAbilityMapData(const FAbilityMapData& Ab { AbilityMap.Remove(AbilityMapData.InputTag); } + + if (GrantedAbilityTags.HasTag(AbilityMapData.InputTag)) { - if (GrantedAbilityTags.HasTag(AbilityMapData.InputTag)) - { - GrantedAbilityTags.RemoveTag(AbilityMapData.InputTag); - } + GrantedAbilityTags.RemoveTag(AbilityMapData.InputTag); } + } void UGMC_AbilitySystemComponent::InitializeStartingAbilities() @@ -1689,7 +1693,7 @@ bool UGMC_AbilitySystemComponent::ApplyAbilityEffect(TSubclassOf Ids, EGMCAbil if (!GMCMovementComponent->IsExecutingMove() && GetNetMode() != NM_Standalone && !bInAncillaryTick) { - ensureMsgf(false, TEXT("[%20s] %s attempted a predicted removal of effects outside of a movement cycle! (%s)"), + ensureMsgf(false, TEXT("[%20s] %s attempted a predicted removal of effects outside of a movement cycle! (%s)"), *GetNetRoleAsString(GetOwnerRole()), *GetOwner()->GetName(), *GetEffectsNameAsString(GetEffectsByIds(Ids))); UE_LOG(LogGMCAbilitySystem, Error, TEXT("[%20s] %s attempted a predicted removal of effects outside of a movement cycle! (%s)"), *GetNetRoleAsString(GetOwnerRole()), *GetOwner()->GetName(), *GetEffectsNameAsString(GetEffectsByIds(Ids))); diff --git a/Source/GMCAbilitySystem/Private/Debug/GameplayDebuggerCategory_GMCAbilitySystem.cpp b/Source/GMCAbilitySystem/Private/Debug/GameplayDebuggerCategory_GMCAbilitySystem.cpp index 5d7b9cb0..515edddb 100644 --- a/Source/GMCAbilitySystem/Private/Debug/GameplayDebuggerCategory_GMCAbilitySystem.cpp +++ b/Source/GMCAbilitySystem/Private/Debug/GameplayDebuggerCategory_GMCAbilitySystem.cpp @@ -18,15 +18,17 @@ void FGameplayDebuggerCategory_GMCAbilitySystem::CollectData(APlayerController* if (DebugActor) { DataPack.ActorName = DebugActor->GetName(); - + if (const UGMC_AbilitySystemComponent* AbilityComponent = DebugActor->FindComponentByClass()) { + AbilityComponent->GMCMovementComponent->SV_SwapServerState(); DataPack.GrantedAbilities = AbilityComponent->GetGrantedAbilities().ToStringSimple(); DataPack.ActiveTags = AbilityComponent->GetActiveTags().ToStringSimple(); DataPack.Attributes = AbilityComponent->GetAllAttributesString(); DataPack.ActiveEffects = AbilityComponent->GetActiveEffectsString(); DataPack.ActiveEffectData = AbilityComponent->GetActiveEffectsDataString(); DataPack.ActiveAbilities = AbilityComponent->GetActiveAbilitiesString(); + AbilityComponent->GMCMovementComponent->SV_SwapServerState(); } } } diff --git a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp index bf1aa49e..bbb3cfd9 100644 --- a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp +++ b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp @@ -68,6 +68,7 @@ void UGMCAbilityEffect::StartEffect() AddTagsToOwner(); AddAbilitiesToOwner(); EndActiveAbilitiesFromOwner(EffectData.CancelAbilityOnActivation); + CancelAbilitiesByDefinition(); bHasAppliedEffect = true; @@ -347,3 +348,21 @@ void UGMCAbilityEffect::CheckState() default: break; } } + +void UGMCAbilityEffect::CancelAbilitiesByDefinition() +{ + if (!OwnerAbilityComponent) return; + + TArray DefinitionTags; + EffectData.EffectDefinition.GetGameplayTagArray(DefinitionTags); + + for (const FGameplayTag& Tag : DefinitionTags) + { + const int NumCancelled = OwnerAbilityComponent->EndAbilitiesByTag(Tag); + if (NumCancelled > 0) + { + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Effect (tag: %s) cancelled %d ability(ies) via EffectDefinition tag: %s"), + *EffectData.EffectTag.ToString(), NumCancelled, *Tag.ToString()); + } + } +} diff --git a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h index f8aa9341..d5b72e86 100644 --- a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h +++ b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h @@ -116,6 +116,10 @@ class GMCABILITYSYSTEM_API UGMCAbility : public UObject, public IGameplayTaskOwn UPROPERTY(EditAnywhere, meta=(Categories="Ability"), Category = "GMCAbilitySystem") FGameplayTag AbilityTag; + UPROPERTY(EditDefaultsOnly, Category = "GMCAbilitySystem", meta=(Categories="Ability")) + // Container for a more generalized definition of abilities + FGameplayTagContainer AbilityDefinition; + // An Effect that modifies attributes when the ability is activated UPROPERTY(EditAnywhere, Category = "GMCAbilitySystem") TSubclassOf AbilityCost; diff --git a/Source/GMCAbilitySystem/Public/Ability/Tasks/GMCAbilityTaskBase.h b/Source/GMCAbilitySystem/Public/Ability/Tasks/GMCAbilityTaskBase.h index 7deb59bc..f2795a31 100644 --- a/Source/GMCAbilitySystem/Public/Ability/Tasks/GMCAbilityTaskBase.h +++ b/Source/GMCAbilitySystem/Public/Ability/Tasks/GMCAbilityTaskBase.h @@ -64,10 +64,8 @@ class GMCABILITYSYSTEM_API UGMCAbilityTaskBase : public UGameplayTask // Task must make sure this is handled properly virtual void ClientProgressTask(); - void Heartbeat() - { - LastHeartbeatReceivedTime = AbilitySystemComponent->ActionTimer; - }; + virtual void Heartbeat(); + protected: bool bTaskCompleted; @@ -75,13 +73,18 @@ class GMCABILITYSYSTEM_API UGMCAbilityTaskBase : public UGameplayTask /** Task Owner that created us */ TWeakObjectPtr TaskOwner; + // Whether this task is running on a client or a client on a listen server + bool IsClientOrRemoteListenServerPawn() const; + private: // How often client sends heartbeats to server - float HeartbeatInterval = .5f; + float HeartbeatInterval = .1f; // Max time between heartbeats before server cancels task - float HeartbeatMaxInterval = 1.f; + float HeartbeatMaxInterval =.3f; float ClientLastHeartbeatSentTime; float LastHeartbeatReceivedTime; + + }; diff --git a/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyRelease.h b/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyRelease.h index 450ce726..59415f69 100644 --- a/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyRelease.h +++ b/Source/GMCAbilitySystem/Public/Ability/Tasks/WaitForInputKeyRelease.h @@ -6,7 +6,7 @@ #include "WaitForInputKeyRelease.generated.h" // DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUWaitForInputKeyReleaseAsyncActionPin, float, DurationHeld); -DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGMCAbilityTaskWaitForInputKeyRelease); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGMCAbilityTaskWaitForInputKeyRelease, float, Duration); UCLASS() @@ -29,14 +29,19 @@ class GMCABILITYSYSTEM_API UGMCAbilityTask_WaitForInputKeyRelease : public UGMCA * @return */ UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", HidePin = "OwningAbility", DefaultToSelf = "OwningAbility", BlueprintInternalUseOnly = "TRUE"), DisplayName="Wait For Input Key Release",Category = "GMCAbilitySystem/Tasks") - static UGMCAbilityTask_WaitForInputKeyRelease* WaitForKeyRelease(UGMCAbility* OwningAbility, bool bCheckForReleaseDuringActivation = true); + static UGMCAbilityTask_WaitForInputKeyRelease* WaitForKeyRelease(UGMCAbility* OwningAbility, bool bCheckForReleaseDuringActivation = true, float MaxDuration = 0.0f); //Overriding BP async action base virtual void Activate() override; + virtual void AncillaryTick(float DeltaTime) override; + UPROPERTY(BlueprintAssignable) FGMCAbilityTaskWaitForInputKeyRelease Completed; + UPROPERTY(BlueprintAssignable) + FGMCAbilityTaskWaitForInputKeyRelease OnTick; + protected: void OnKeyReleased(const FInputActionValue& InputActionValue); @@ -50,8 +55,9 @@ class GMCABILITYSYSTEM_API UGMCAbilityTask_WaitForInputKeyRelease : public UGMCA UEnhancedInputComponent* GetEnhancedInputComponent() const; int64 InputBindingHandle = -1; + + float MaxDuration; - // Todo: Add duration back in float StartTime; float Duration; double OldTime; diff --git a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h index 50724560..eb7f148c 100644 --- a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h +++ b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h @@ -555,6 +555,12 @@ class GMCABILITYSYSTEM_API UGMC_AbilitySystemComponent : public UGameplayTasksCo // Map of Ability Tags to Ability Classes TMap AbilityMap; +public: + // Empty the AbilityMap and remove all granted abilities from existing maps + UFUNCTION(BlueprintCallable) + void ClearAbilityMap(); + +private: // List of filtered tag delegates to call when tags change. TArray> FilteredTagDelegates; diff --git a/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h b/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h index b2d2a6c9..57c96019 100644 --- a/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h +++ b/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h @@ -106,6 +106,10 @@ struct FGMCAbilityEffectData UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GMCAbilitySystem") FGameplayTag EffectTag; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GMCAbilitySystem") + // Container for a more generalized definition of effects + FGameplayTagContainer EffectDefinition; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GMCAbilitySystem") FGameplayTagContainer GrantedTags; @@ -183,7 +187,8 @@ class GMCABILITYSYSTEM_API UGMCAbilityEffect : public UObject UFUNCTION(BlueprintCallable, Category = "GMCAbilitySystem") void InitializeEffect(FGMCAbilityEffectData InitializationData); - + + UFUNCTION(BlueprintCallable, Category = "GMCAbilitySystem") void EndEffect(); virtual void BeginDestroy() override; @@ -257,7 +262,7 @@ class GMCABILITYSYSTEM_API UGMCAbilityEffect : public UObject bool DuplicateEffectAlreadyApplied(); - + void CancelAbilitiesByDefinition(); public: From 289c218188a92e8494b2e8df0655b84c077e2ce3 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Tue, 6 May 2025 20:17:14 -0700 Subject: [PATCH 3/9] Update GMCAbilityComponent.cpp --- .../GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp index c18b77fc..0a8d527a 100644 --- a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp +++ b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp @@ -7,7 +7,6 @@ #include "GMCOrganicMovementComponent.h" #include "GMCPlayerController.h" #include "NiagaraFunctionLibrary.h" -#include "NiagaraFunctionLibrary.h" #include "Ability/GMCAbility.h" #include "Ability/GMCAbilityMapData.h" #include "Attributes/GMCAttributesData.h" From f08622ca36b0cbdffe3fb534a9a7ddab702211f4 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Wed, 7 May 2025 07:51:04 -0700 Subject: [PATCH 4/9] Update GMCAbility.cpp --- .../Private/Ability/GMCAbility.cpp | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp index 221f6f6c..c6fd6bd1 100644 --- a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp @@ -188,25 +188,32 @@ void UGMCAbility::CancelAbilities() UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability (tag) %s has been cancelled by (tag) %s"), *AbilityTag.ToString(), *AbilityToCancelTag.ToString()); } } - // Cancel by AbilityDefinition (generic category tags) - TArray DefinitionTags; - AbilityDefinition.GetGameplayTagArray(DefinitionTags); - for (const FGameplayTag& DefinitionTag : DefinitionTags) + FGameplayTagContainer TagsToMatch = CancelAbilitiesWithTag; + TagsToMatch.AppendTags(AbilityDefinition); + + if (TagsToMatch.Num() == 0) { - // Prevent self-cancellation - if (AbilityTag.MatchesTag(DefinitionTag)) + UE_LOG(LogGMCAbilitySystem, Warning, TEXT("No tags in CancelAbilitiesWithTag or AbilityDefinition for %s"), *AbilityTag.ToString()); + return; + } + + // should prob also append AbilityTag if want to use this system but left alone for now just in case + FGameplayTagQuery CancelQuery = FGameplayTagQuery::MakeQuery_MatchAnyTags(TagsToMatch); + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Generated Cancel Query: %s"), *CancelQuery.GetDescription()); + + for (const auto& ActiveAbility : OwnerAbilityComponent->GetActiveAbilities()) + { + if (ActiveAbility.Value == this) { - UE_LOG(LogGMCAbilitySystem, Warning, TEXT("Ability (tag) %s attempted to cancel itself via AbilityDefinition tag %s"), - *AbilityTag.ToString(), *DefinitionTag.ToString()); - continue; + continue; // prevent self-cancellation } - int Cancelled = OwnerAbilityComponent->EndAbilitiesByTag(DefinitionTag); - if (Cancelled > 0) + if (CancelQuery.Matches(ActiveAbility.Value->AbilityDefinition)) { - UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability (tag) %s cancelled %d ability(ies) by AbilityDefinition tag: %s"), - *AbilityTag.ToString(), Cancelled, *DefinitionTag.ToString()); + ActiveAbility.Value->SetPendingEnd(); + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability %s cancelled ability %s (matching query)"), + *AbilityTag.ToString(), *ActiveAbility.Value->AbilityTag.ToString()); } } } From 7451d8177aedd7617e4cb858ecc58a58cc5fdc06 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Wed, 7 May 2025 08:03:07 -0700 Subject: [PATCH 5/9] DefinitionTags --- Source/GMCAbilitySystem/Public/Ability/GMCAbility.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h index 0fa264b7..bea9f4bd 100644 --- a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h +++ b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h @@ -117,7 +117,7 @@ class GMCABILITYSYSTEM_API UGMCAbility : public UObject, public IGameplayTaskOwn UPROPERTY(EditAnywhere, meta=(Categories="Ability"), Category = "GMCAbilitySystem") FGameplayTag AbilityTag; - UPROPERTY(EditDefaultsOnly, Category = "GMCAbilitySystem", meta=(Categories="Ability")) + UPROPERTY(EditDefaultsOnly, Category = "GMCAbilitySystem") // Container for a more generalized definition of abilities FGameplayTagContainer AbilityDefinition; From 40e49d479d7147b50487b57d46da5fa48bb5c7d3 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Wed, 7 May 2025 08:54:11 -0700 Subject: [PATCH 6/9] query fixed for effects --- .../Components/GMCAbilityComponent.cpp | 20 ++++++++++++++++++ .../Private/Effects/GMCAbilityEffect.cpp | 21 ++++++++----------- .../Public/Components/GMCAbilityComponent.h | 4 ++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp index d8dd6c84..217ec552 100644 --- a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp +++ b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp @@ -446,6 +446,26 @@ int UGMC_AbilitySystemComponent::EndAbilitiesByClass(TSubclassOf Ab } +int UGMC_AbilitySystemComponent::EndAbilitiesByQuery(const FGameplayTagQuery& Query) +{ + int AbilitiesEnded = 0; + + for (const auto& Pair : ActiveAbilities) + { + if (UGMCAbility* Ability = Pair.Value) + { + if (Query.Matches(Ability->AbilityDefinition)) + { + Ability->SetPendingEnd(); + AbilitiesEnded++; + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("cancelled ability %s by query"), *Ability->AbilityTag.ToString()); + } + } + } + return AbilitiesEnded; +} + + int32 UGMC_AbilitySystemComponent::GetActiveAbilityCountByTag(FGameplayTag AbilityTag) { int32 Result = 0; diff --git a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp index bbb3cfd9..811dccd2 100644 --- a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp +++ b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp @@ -351,18 +351,15 @@ void UGMCAbilityEffect::CheckState() void UGMCAbilityEffect::CancelAbilitiesByDefinition() { - if (!OwnerAbilityComponent) return; + if (!OwnerAbilityComponent) return; - TArray DefinitionTags; - EffectData.EffectDefinition.GetGameplayTagArray(DefinitionTags); + // build query here + FGameplayTagContainer TagsToMatch = EffectData.EffectDefinition; + if (TagsToMatch.Num() == 0) return; - for (const FGameplayTag& Tag : DefinitionTags) - { - const int NumCancelled = OwnerAbilityComponent->EndAbilitiesByTag(Tag); - if (NumCancelled > 0) - { - UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Effect (tag: %s) cancelled %d ability(ies) via EffectDefinition tag: %s"), - *EffectData.EffectTag.ToString(), NumCancelled, *Tag.ToString()); - } - } + FGameplayTagQuery CancelQuery = FGameplayTagQuery::MakeQuery_MatchAnyTags(TagsToMatch); + int NumCancelled = OwnerAbilityComponent->EndAbilitiesByQuery(CancelQuery); + + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Effect %s cancelled %d ability(ies) via EffectDefinition query."), + *EffectData.EffectTag.ToString(), NumCancelled); } diff --git a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h index ad0f2bb9..da894513 100644 --- a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h +++ b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h @@ -218,6 +218,10 @@ class GMCABILITYSYSTEM_API UGMC_AbilitySystemComponent : public UGameplayTasksCo // End all abilities with the corresponding tag, returns the number of abilities ended int EndAbilitiesByClass(TSubclassOf AbilityClass); + UFUNCTION(BlueprintCallable, DisplayName = "End Abilities (By Definition Query)", Category="GMAS|Abilities") + // End all abilities with defintions matching query + int EndAbilitiesByQuery(const FGameplayTagQuery& Query); + UFUNCTION(BlueprintCallable, DisplayName="Count Activated Ability Instances (by tag)", Category="GMAS|Abilities") int32 GetActiveAbilityCountByTag(FGameplayTag AbilityTag); From d8f5387921ec0cfbe8f754e23753a06880bf6c19 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Wed, 7 May 2025 09:03:14 -0700 Subject: [PATCH 7/9] Update GMCAbility.cpp unnecessary warning --- Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp index c6fd6bd1..6c41bcc7 100644 --- a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp @@ -188,15 +188,11 @@ void UGMCAbility::CancelAbilities() UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Ability (tag) %s has been cancelled by (tag) %s"), *AbilityTag.ToString(), *AbilityToCancelTag.ToString()); } } - + FGameplayTagContainer TagsToMatch = CancelAbilitiesWithTag; TagsToMatch.AppendTags(AbilityDefinition); - if (TagsToMatch.Num() == 0) - { - UE_LOG(LogGMCAbilitySystem, Warning, TEXT("No tags in CancelAbilitiesWithTag or AbilityDefinition for %s"), *AbilityTag.ToString()); - return; - } + if (TagsToMatch.Num() == 0) return; // do nothing // should prob also append AbilityTag if want to use this system but left alone for now just in case FGameplayTagQuery CancelQuery = FGameplayTagQuery::MakeQuery_MatchAnyTags(TagsToMatch); From 226e3f1e94258c0fd1c2785e353c66d534fe225c Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Wed, 7 May 2025 10:24:00 -0700 Subject: [PATCH 8/9] Remove Effects By Definition Query --- .../Components/GMCAbilityComponent.cpp | 24 ++++++++++++++++--- .../Public/Components/GMCAbilityComponent.h | 5 +++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp index 217ec552..c33c13de 100644 --- a/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp +++ b/Source/GMCAbilitySystem/Private/Components/GMCAbilityComponent.cpp @@ -450,9 +450,9 @@ int UGMC_AbilitySystemComponent::EndAbilitiesByQuery(const FGameplayTagQuery& Qu { int AbilitiesEnded = 0; - for (const auto& Pair : ActiveAbilities) + for (const auto& ActiveAbilityData : ActiveAbilities) { - if (UGMCAbility* Ability = Pair.Value) + if (UGMCAbility* Ability = ActiveAbilityData.Value) { if (Query.Matches(Ability->AbilityDefinition)) { @@ -1866,7 +1866,6 @@ void UGMC_AbilitySystemComponent::RemoveActiveAbilityEffectByTag(FGameplayTag Ta } - TArray UGMC_AbilitySystemComponent::EffectsMatchingTag(const FGameplayTag& Tag, int32 NumToRemove) const { if (NumToRemove < -1 || !Tag.IsValid()) { @@ -1925,6 +1924,25 @@ int32 UGMC_AbilitySystemComponent::RemoveEffectByTagSafe(FGameplayTag InEffectTa return EffectsToRemove.Num(); } +int UGMC_AbilitySystemComponent::RemoveEffectsByQuery(const FGameplayTagQuery& Query, EGMCAbilityEffectQueueType QueueType) +{ + int EffectsRemoved = 0; + + for (const auto& EffectEntry : ActiveEffects) + { + if (UGMCAbilityEffect* Effect = EffectEntry.Value) + { + if (Query.Matches(Effect->EffectData.EffectDefinition)) + { + RemoveActiveAbilityEffectSafe(Effect, QueueType); + EffectsRemoved++; + UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("Removed effect %s by query"), *Effect->EffectData.EffectTag.ToString()); + } + } + } + return EffectsRemoved; +} + bool UGMC_AbilitySystemComponent::RemoveEffectByIdSafe(TArray Ids, EGMCAbilityEffectQueueType QueueType) { if (!Ids.Num()) { diff --git a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h index da894513..d2d72aa9 100644 --- a/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h +++ b/Source/GMCAbilitySystem/Public/Components/GMCAbilityComponent.h @@ -219,7 +219,7 @@ class GMCABILITYSYSTEM_API UGMC_AbilitySystemComponent : public UGameplayTasksCo int EndAbilitiesByClass(TSubclassOf AbilityClass); UFUNCTION(BlueprintCallable, DisplayName = "End Abilities (By Definition Query)", Category="GMAS|Abilities") - // End all abilities with defintions matching query + // End all abilities matching query int EndAbilitiesByQuery(const FGameplayTagQuery& Query); UFUNCTION(BlueprintCallable, DisplayName="Count Activated Ability Instances (by tag)", Category="GMAS|Abilities") @@ -378,6 +378,9 @@ class GMCABILITYSYSTEM_API UGMC_AbilitySystemComponent : public UGameplayTasksCo UFUNCTION(BlueprintCallable, Category="GMAS|Effects", DisplayName="Remove Effect by Handle") bool RemoveEffectByHandle(int EffectHandle, EGMCAbilityEffectQueueType QueueType); + UFUNCTION(BlueprintCallable, Category="GMAS|Effects", DisplayName="Remove Effects by Definition Query") + int32 RemoveEffectsByQuery(const FGameplayTagQuery& Query, EGMCAbilityEffectQueueType QueueType); + /** * Gets the number of active effects with the inputted tag. * Returns -1 if tag is invalid. From 67f4e94792e66e582882603b395bf158cad4b755 Mon Sep 17 00:00:00 2001 From: NarsBars <150587668+NarsBars@users.noreply.github.com> Date: Mon, 12 May 2025 10:51:30 -0700 Subject: [PATCH 9/9] Modify Ability/Effect Definition Containers --- .../GMCAbilitySystem/Private/Ability/GMCAbility.cpp | 11 +++++++++++ .../Private/Effects/GMCAbilityEffect.cpp | 11 +++++++++++ Source/GMCAbilitySystem/Public/Ability/GMCAbility.h | 3 +++ .../Public/Effects/GMCAbilityEffect.h | 4 ++++ 4 files changed, 29 insertions(+) diff --git a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp index 0abfa7c0..f585313a 100644 --- a/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp +++ b/Source/GMCAbilitySystem/Private/Ability/GMCAbility.cpp @@ -399,3 +399,14 @@ void UGMCAbility::ModifyBlockOtherAbilitiesViaDefinitionQuery(const FGameplayTag BlockOtherAbilitiesQuery = NewQuery; UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("BlockOtherAbilityByDefinitionQuery modified: %s"), *NewQuery.GetDescription()); } + +void UGMCAbility::ModifyAbilityDefinition(FGameplayTagContainer TagToAdd, FGameplayTagContainer TagToRemove) +{ + for (auto Tag : TagToAdd) { + AbilityDefinition.AddTag(Tag); + } + + for (auto Tag : TagToRemove) { + AbilityDefinition.RemoveTag(Tag); + } +} diff --git a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp index d9165783..59acf681 100644 --- a/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp +++ b/Source/GMCAbilitySystem/Private/Effects/GMCAbilityEffect.cpp @@ -407,3 +407,14 @@ void UGMCAbilityEffect::ModifyEndAbilitiesOnEndQuery(const FGameplayTagQuery& Ne EffectData.EndAbilityOnEndQuery = NewQuery; UE_LOG(LogGMCAbilitySystem, Verbose, TEXT("EndAbilityOnEndViaDefinitionQuery modified: %s"), *NewQuery.GetDescription()); } + +void UGMCAbilityEffect::ModifyEffectDefinition(FGameplayTagContainer TagToAdd, FGameplayTagContainer TagToRemove) +{ + for (auto Tag : TagToAdd) { + EffectData.EffectDefinition.AddTag(Tag); + } + + for (auto Tag : TagToRemove) { + EffectData.EffectDefinition.RemoveTag(Tag); + } +} diff --git a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h index a0b1cb03..784d5ead 100644 --- a/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h +++ b/Source/GMCAbilitySystem/Public/Ability/GMCAbility.h @@ -281,5 +281,8 @@ class GMCABILITYSYSTEM_API UGMCAbility : public UObject, public IGameplayTaskOwn UFUNCTION(BlueprintCallable, Category = "GMAS|Abilities|Queries") void ModifyBlockOtherAbilitiesViaDefinitionQuery(const FGameplayTagQuery& NewQuery); + UFUNCTION(BlueprintCallable, Category = "GMAS|Abilities") + void ModifyAbilityDefinition(FGameplayTagContainer TagToAdd, FGameplayTagContainer TagToRemove); + }; diff --git a/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h b/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h index 374e338b..48c68fff 100644 --- a/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h +++ b/Source/GMCAbilitySystem/Public/Effects/GMCAbilityEffect.h @@ -312,5 +312,9 @@ class GMCABILITYSYSTEM_API UGMCAbilityEffect : public UObject UFUNCTION(BlueprintCallable, Category = "GMCAbilitySystem|Effects|Queries") void ModifyEndAbilitiesOnEndQuery(const FGameplayTagQuery& NewQuery); + + UFUNCTION(BlueprintCallable, Category = "GMAS|Effects") + void ModifyEffectDefinition(FGameplayTagContainer TagToAdd, FGameplayTagContainer TagToRemove); + };