Issue 1: HandleGameplayEvent can activate the same ability more than once with a certain configuration.
If an Ability activates by GameplayEvents as:
A.B.C
A.B
Whenever the event A.B.C triggers the ActivateAbility will trigger twice, whereas there was only one event. This should be prevented by only activating the ability once per gameplay event.
Issue 2 :Another issue is that the handling of the events is not accounting for deletes while “broadcasting” because the current implementation is executing from a copy of the MulticastDelegate. This causes client code to receive callbacks when it already was removed from the multicast delegate.
Also the return type of the function could return the array of activated abilities so that client code can react accordingly to it (by registering to end ability, for instance)
Have you had any related issues with this? Could these changes be integrated in the engine in the future?
I have added this code in the header. Attached is the cpp alternative implementation
`public:
///
/** Removes delegates with bound object for a specific tag container. Returns removed count /
int32 RemoveAllGameplayEventTagContainerDelegates(const FGameplayTagContainer& TagFilter, const UObject BoundObject);
/** Removes delegates with bound object for any tag container. Returns removed count /
int32 RemoveAllGameplayEventTagContainerDelegates(const UObject BoundObject);
/** Adds a new delegate to call when a certain gameplay event happens. It will only be called if it exactly matches the tag provided */
FDelegateHandle AddGameplayEventDelegate(const FGameplayTag& Tag, const FGameplayEventDelegate& Delegate);
FDelegateHandle AddGameplayEventDelegate(const FGameplayTag& Tag, FGameplayEventDelegate&& Delegate);
/** Removes previously registered delegate /
bool RemoveGameplayEventDelegate(const FGameplayTag& Tag, FDelegateHandle DelegateHandle);
/* Removes delegates with bound object for a specific tag. Returns removed count /
int32 RemoveAllGameplayEventDelegates(const FGameplayTag& Tag, const UObject BoundObject);
/** Removes delegates with bound object for any tag. Returns removed count /
int32 RemoveAllGameplayEventDelegates(const UObject BoundObject);
protected:
// Pointers to copies in stack of currently broadcasting GenericGameplayEventCallbacks. To support deletes while broadcasting
TArray<FGameplayEventMulticastDelegate*> BroadcastingGenericGameplayEventCallbacks;
// Pointers to copies in stack of currently broadcasting GameplayEventTagContainerDelegates. To support deletes while broadcasting
TArray<FGameplayEventTagMulticastDelegate*> BroadcastingGameplayEventTagContainerDelegates;`