Let's talk

RSAsyncWaitTagCount.cpp

Source/RSGasHelpers/Private/RSAsyncWaitTagCount.cpp Raw Download ZIP

Click a line number to link it. Shift-click to select a range.

1// Copyright (c) 2026 Reignance Studios. MIT License, see LICENSE.
2
3#include "RSAsyncWaitTagCount.h"
4
5#include "AbilitySystemComponent.h"
6#include "RSAbilitySystemLibrary.h"
7
8URSAsyncWaitTagCount* URSAsyncWaitTagCount::WaitGameplayTagCount(AActor* Actor, FGameplayTag Tag, bool bFireInitialCount)
9{
10 URSAsyncWaitTagCount* Action = NewObject<URSAsyncWaitTagCount>();
11 Action->WeakASC = URSAbilitySystemLibrary::FindAbilitySystemComponent(Actor);
12 Action->WatchedTag = Tag;
13 Action->bFireInitial = bFireInitialCount;
14 Action->RegisterWithGameInstance(Actor);
15 return Action;
16}
17
18void URSAsyncWaitTagCount::Activate()
19{
20 UAbilitySystemComponent* ASC = WeakASC.Get();
21 if (!ASC || !WatchedTag.IsValid())
22 {
23 // Common on clients: the PlayerState (and its ASC) has not replicated yet.
24 // Retry from OnRep_PlayerState instead of polling.
25 Cancel();
26 return;
27 }
28
29 // AnyCountChange, not NewOrRemoved: stacks going from 2 to 3 matter to a UI too.
30 Binding = ASC->RegisterGameplayTagEvent(WatchedTag, EGameplayTagEventType::AnyCountChange)
31 .AddUObject(this, &URSAsyncWaitTagCount::HandleTagChanged);
32
33 if (bFireInitial)
34 {
35 OnCountChanged.Broadcast(WatchedTag, ASC->GetTagCount(WatchedTag));
36 }
37}
38
39void URSAsyncWaitTagCount::HandleTagChanged(const FGameplayTag Tag, int32 NewCount)
40{
41 OnCountChanged.Broadcast(Tag, NewCount);
42}
43
44void URSAsyncWaitTagCount::Cancel()
45{
46 if (UAbilitySystemComponent* ASC = WeakASC.Get())
47 {
48 if (Binding.IsValid())
49 {
50 ASC->UnregisterGameplayTagEvent(Binding, WatchedTag, EGameplayTagEventType::AnyCountChange);
51 }
52 }
53 Binding.Reset();
54 Super::Cancel();
55}

Still desyncing in packaged builds?

Free code fixes one symptom. A Diagnostic finds the cause across your project in two days.