In my game, i wanted to grab Gameplay Tags from the source object if possible, and apply them into the captured tags of the Gameplay Effect Spec. With this in mind, i went searching through the system, and found the following function gets called UGameplayAbility::ApplyAbilityTagsToGameplayEffectSpec. I was like great that is exactly what i need, so i went and overrode this function.
void UKaosGameplayAbility::ApplyAbilityTagsToGameplayEffectSpec(FGameplayEffectSpec& Spec, FGameplayAbilitySpec* AbilitySpec) const
{
FGameplayTagContainer& CapturedSourceTags = Spec.CapturedSourceTags.GetSpecTags();
CapturedSourceTags.AppendTags(AbilityTags);
const UKaosWorldItemDefinition* SourceObjAsItemDefinition = GetCurrentSourceItemDefinition();
if (SourceObjAsItemDefinition)
{
FGameplayTagContainer ItemDefTags;
SourceObjAsItemDefinition->GetOwnedGameplayTags(ItemDefTags);
CapturedSourceTags.AppendTags(ItemDefTags);
}
// Allow the source object of the ability to propagate tags along as well
if (AbilitySpec)
{
CapturedSourceTags.AppendTags(AbilitySpec->DynamicAbilityTags);
const IGameplayTagAssetInterface* SourceObjAsTagInterface = Cast<IGameplayTagAssetInterface>(AbilitySpec->SourceObject);
if (SourceObjAsTagInterface)
{
FGameplayTagContainer SourceObjTags;
SourceObjAsTagInterface->GetOwnedGameplayTags(SourceObjTags);
CapturedSourceTags.AppendTags(SourceObjTags);
}
// Copy SetByCallerMagnitudes
Spec.MergeSetByCallerMagnitudes(AbilitySpec->SetByCallerTagMagnitudes);
}
}
The relevant lines to take note of is
const UKaosWorldItemDefinition* SourceObjAsItemDefinition = GetCurrentSourceItemDefinition();
if (SourceObjAsItemDefinition)
{
FGameplayTagContainer ItemDefTags;
SourceObjAsItemDefinition->GetOwnedGameplayTags(ItemDefTags);
CapturedSourceTags.AppendTags(ItemDefTags);
}
With this, i grab the current source items definition. This is purely for my games purpose, but it shows that you can grab tags from anywhere, but what you are really interested in is pulling it from the SourceObject that would implement the IGameplayTagAssetInterface. This is seen in the first code block under the if (AbilitySpec), the relevant code is here:
const IGameplayTagAssetInterface* SourceObjAsTagInterface = Cast<IGameplayTagAssetInterface>(AbilitySpec->SourceObject);
if (SourceObjAsTagInterface)
{
FGameplayTagContainer SourceObjTags;
SourceObjAsTagInterface->GetOwnedGameplayTags(SourceObjTags);
CapturedSourceTags.AppendTags(SourceObjTags);
}
So what the above does, is gets the SourceObject from the AbilitySpec, then casts it to the IGameplayTagAssetInterface. If this is successful, we can literally grab the Owned GameplayTags and populate our CapturedSourceTags.
And there you have it, a nice way to capture tags from Source Objects, and automatically get them applied to your GameplayEffect when used in an ability with that Source Object.