From 4c75afced41eaec5ed9f6d7b066b6b346ad085b0 Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Mon, 29 Jun 2026 10:39:41 +0200 Subject: [PATCH 1/4] Update FlowNode_ComponentObserver.cpp UFlowNode_ComponentObserver: fix SuccessCount persistence on save during Success flow --- .../Private/Nodes/Actor/FlowNode_ComponentObserver.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Flow/Private/Nodes/Actor/FlowNode_ComponentObserver.cpp b/Source/Flow/Private/Nodes/Actor/FlowNode_ComponentObserver.cpp index 770c0d26e..03e1a9984 100644 --- a/Source/Flow/Private/Nodes/Actor/FlowNode_ComponentObserver.cpp +++ b/Source/Flow/Private/Nodes/Actor/FlowNode_ComponentObserver.cpp @@ -40,7 +40,11 @@ void UFlowNode_ComponentObserver::ExecuteInput(const FName& PinName) void UFlowNode_ComponentObserver::OnLoad_Implementation() { - if (IdentityTags.IsValid()) + if (SuccessLimit > 0 && SuccessCount == SuccessLimit) + { + TriggerOutput(TEXT("Completed"), true); + } + else if (IdentityTags.IsValid()) { StartObserving(); } @@ -121,9 +125,9 @@ void UFlowNode_ComponentObserver::OnComponentUnregistered(UFlowComponent* Compon void UFlowNode_ComponentObserver::OnEventReceived() { + SuccessCount++; TriggerFirstOutput(false); - SuccessCount++; if (SuccessLimit > 0 && SuccessCount == SuccessLimit) { TriggerOutput(TEXT("Completed"), true); From 6842f9990379e948046d1660a6f96883a8fccb4b Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Tue, 8 Sep 2026 14:27:57 +0200 Subject: [PATCH 2/4] Add NotifyMatchType to OnNotifyFromActor FlowNode Introduced a EFlowTagMatchType, replacing the hardcoded exact-match check with a configurable one. This allows the node to listen for a parent Notify Tag and match against any of its child tags, instead of requiring an exact tag match. --- .../Actor/FlowNode_OnNotifyFromActor.cpp | 38 ++++++++----------- Source/Flow/Public/FlowTypes.h | 33 ++++++++++++++++ .../Nodes/Actor/FlowNode_OnNotifyFromActor.h | 3 ++ 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp b/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp index 575b73260..b32cc7e0b 100644 --- a/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp +++ b/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp @@ -6,7 +6,8 @@ #include UE_INLINE_GENERATED_CPP_BY_NAME(FlowNode_OnNotifyFromActor) UFlowNode_OnNotifyFromActor::UFlowNode_OnNotifyFromActor() - : bRetroactive(false) + : NotifyMatchType(EFlowTagMatchType::HasExact) + , bRetroactive(false) { #if WITH_EDITOR NodeDisplayStyle = FlowNodeStyle::Condition; @@ -20,9 +21,13 @@ void UFlowNode_OnNotifyFromActor::ObserveActor(TWeakObjectPtr Actor, TWe RegisteredActors.Emplace(Actor, Component); Component->OnNotifyFromComponent.AddUObject(this, &UFlowNode_OnNotifyFromActor::OnNotifyFromComponent); - if (bRetroactive && Component->GetRecentlySentNotifyTags().HasAnyExact(NotifyTags)) + if (bRetroactive) { - OnEventReceived(); + const bool NotifyMatches = FlowTypes::HasMatchingTags(Component->GetRecentlySentNotifyTags(), NotifyTags, NotifyMatchType); + if (NotifyMatches) + { + OnEventReceived(); + } } } } @@ -34,27 +39,14 @@ void UFlowNode_OnNotifyFromActor::ForgetActor(TWeakObjectPtr Actor, TWea void UFlowNode_OnNotifyFromActor::OnNotifyFromComponent(UFlowComponent* Component, const FGameplayTag& Tag) { - bool IdentityMatches = false; - - switch (IdentityMatchType) - { - case EFlowTagContainerMatchType::HasAny: - IdentityMatches = Component->IdentityTags.HasAny(IdentityTags); - break; - case EFlowTagContainerMatchType::HasAnyExact: - IdentityMatches = Component->IdentityTags.HasAnyExact(IdentityTags); - break; - case EFlowTagContainerMatchType::HasAll: - IdentityMatches = Component->IdentityTags.HasAll(IdentityTags); - break; - case EFlowTagContainerMatchType::HasAllExact: - IdentityMatches = Component->IdentityTags.HasAllExact(IdentityTags); - break; - } - - if (IdentityMatches && (!NotifyTags.IsValid() || NotifyTags.HasTagExact(Tag))) + const bool IdentityMatches = FlowTypes::HasMatchingTags(Component->IdentityTags, IdentityTags, IdentityMatchType); + if (IdentityMatches) { - OnEventReceived(); + const bool NotifyMatches = NotifyTags.IsValid() ? FlowTypes::HasMatchingTag(Tag, NotifyTags, NotifyMatchType) : true; + if (NotifyMatches) + { + OnEventReceived(); + } } } diff --git a/Source/Flow/Public/FlowTypes.h b/Source/Flow/Public/FlowTypes.h index 9b51d6c56..a5dec432f 100644 --- a/Source/Flow/Public/FlowTypes.h +++ b/Source/Flow/Public/FlowTypes.h @@ -77,6 +77,13 @@ enum class EFlowNetMode : uint8 SinglePlayerOnly UMETA(ToolTip = "Executed only in the single player, not available in multiplayer.") }; +UENUM(BlueprintType) +enum class EFlowTagMatchType : uint8 +{ + Has UMETA(ToolTip = "Check if container contains the tag."), + HasExact UMETA(ToolTip = "Check if container contains the tag, only allowing exact matches."), +}; + UENUM(BlueprintType) enum class EFlowTagContainerMatchType : uint8 { @@ -88,6 +95,32 @@ enum class EFlowTagContainerMatchType : uint8 namespace FlowTypes { + FORCEINLINE_DEBUGGABLE bool HasMatchingTag(const FGameplayTag& Tag, const FGameplayTagContainer& Container, const EFlowTagMatchType MatchType) + { + switch (MatchType) + { + case EFlowTagMatchType::Has: + return Tag.MatchesAny(Container); + case EFlowTagMatchType::HasExact: + return Tag.MatchesAnyExact(Container); + default: + return false; + } + } + + FORCEINLINE_DEBUGGABLE bool HasMatchingTags(const FGameplayTagContainer& Container, const FGameplayTagContainer& OtherContainer, const EFlowTagMatchType MatchType) + { + switch (MatchType) + { + case EFlowTagMatchType::Has: + return Container.HasAny(OtherContainer); + case EFlowTagMatchType::HasExact: + return Container.HasAnyExact(OtherContainer); + default: + return false; + } + } + FORCEINLINE_DEBUGGABLE bool HasMatchingTags(const FGameplayTagContainer& Container, const FGameplayTagContainer& OtherContainer, const EFlowTagContainerMatchType MatchType) { switch (MatchType) diff --git a/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h b/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h index 0a8709be1..1be580570 100644 --- a/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h +++ b/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h @@ -19,6 +19,9 @@ class FLOW_API UFlowNode_OnNotifyFromActor : public UFlowNode_ComponentObserver UPROPERTY(EditAnywhere, Category = "Notify") FGameplayTagContainer NotifyTags; + UPROPERTY(EditAnywhere, Category = "Notify") + EFlowTagMatchType NotifyMatchType; + /* If true, node will check given Notify Tag is present in the Recently Sent Notify Tags. * This might be helpful in multiplayer, if client-side Flow Node started work after server sent the Notify. */ UPROPERTY(EditAnywhere, Category = "Notify") From 5fa6b71b1a44e4dbce4925ebbf9b621f2062a88c Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Tue, 8 Sep 2026 14:37:01 +0200 Subject: [PATCH 3/4] Update FlowNode_OnNotifyFromActor.cpp Fixed Automerge --- Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp b/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp index c7158f994..a0af6972b 100644 --- a/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp +++ b/Source/Flow/Private/Nodes/Actor/FlowNode_OnNotifyFromActor.cpp @@ -6,8 +6,6 @@ #include UE_INLINE_GENERATED_CPP_BY_NAME(FlowNode_OnNotifyFromActor) UFlowNode_OnNotifyFromActor::UFlowNode_OnNotifyFromActor() - : NotifyMatchType(EFlowTagMatchType::HasExact) - , bRetroactive(false) { #if WITH_EDITOR NodeDisplayStyle = FlowNodeStyle::Condition; From 48d40af8b6ec2520683040c6ad016d8b1869d767 Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Tue, 8 Sep 2026 14:39:08 +0200 Subject: [PATCH 4/4] Fix Automatic Merge EFlowTagMatchType::HasExact as Default value of NotifyMatchType --- Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h b/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h index 660655ead..3306f1c0a 100644 --- a/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h +++ b/Source/Flow/Public/Nodes/Actor/FlowNode_OnNotifyFromActor.h @@ -20,7 +20,7 @@ class FLOW_API UFlowNode_OnNotifyFromActor : public UFlowNode_ComponentObserver FGameplayTagContainer NotifyTags; UPROPERTY(EditAnywhere, Category = "Notify") - EFlowTagMatchType NotifyMatchType; + EFlowTagMatchType NotifyMatchType = EFlowTagMatchType::HasExact; /* If true, node will check given Notify Tag is present in the Recently Sent Notify Tags. * This might be helpful in multiplayer, if client-side Flow Node started work after server sent the Notify. */