AbilitySystemComponent : How to know if an ability can be activated (by class)?

Hi,

Is there bloody anything in the AbilitySystemComponent (ASC ) that would return true/false if an ability can be activated? Ideally passing an ability class.

There’s a method “TryActivateAbilityByClass” that does exactly that and returns true if successful. I want that without activating the ability. I just want to know if its possible.
ie.:

  • Does the ASC have the ability?
  • Is the ability on CD?
  • Are there any blocking tags?
  • Is check cost valid?
  • etc …

I tried reading the .cpp file for AbilitySystemComponent, and tho the method appears in the .h, its nowhere to be found in the .cpp …!?

I want this method to expose it in a Behaviour Tree Task ‘CanAbilityBeUsed’ and then ‘UseAbility’.

Thanks <3

1 Like

Hello!

I, too, found this hard to track down exactly how the sequence of events worked.

CanActivateAbility() can be found in GameplayAbility.h at line 285 for me. This is not exposed to BP so you will have to do that yourself.
You can see how the TryActivateAbilityByClass() is used in AbilitySystemComponent_Abilities.cpp at line 1309 and remove the portions that try to activate the ability replacing it with the CanActivateAbility() to get a return. It’s used in that implementation at line 1387 in AbilitySystemComponent_Abilities.cpp

2 Likes

Lost me on this one. I’ll try to remember to come back if I do find something. Sorry!

Ok, now I got it!
I deleted my previous post to avoid cluttering.
Turns out I dont need to set-up ‘SourceTags’, ‘TargetTags’ nor even ‘OptionalRelevantTags’.

This works respecting tag requirements, cooldowns and costs.
Based on the guidelines you gave me the code looks like this:

// fyi: look class UAbilitySystemComponent_Abilities.cpp : TryActivateAbilityByClass
bool UAbilitySystemComponent_Crow::CanAbilityBeActivated(TSubclassOf<UGameplayAbility> AbilityClass) const
{
	// Try find ability by class
	const UGameplayAbility* const abilityCDO = AbilityClass.GetDefaultObject();
	FGameplayAbilitySpec abilitySpec;
	FGameplayAbilitySpecHandle handle;
	for (const FGameplayAbilitySpec& iSpec : ActivatableAbilities.Items)
	{
		if (iSpec.Ability == abilityCDO)
		{
			abilitySpec = iSpec;
			handle = abilitySpec.Handle;
			break;
		}
	}

	// If we have an instanced ability, call CanActivateAbility on it.
	// Otherwise we always do a non instanced CanActivateAbility check using the CDO of the Ability.
	UGameplayAbility* ability = abilitySpec.GetPrimaryInstance();
	if (ability == nullptr)
	{
		ability = abilitySpec.Ability;
		if (ability == nullptr)
		{
			return false;
		}
	}

	if (ability == false)
	{
		return false;
	}

	const FGameplayAbilityActorInfo* actorInfo = AbilityActorInfo.Get();
	// make sure the ActorInfo and then Actor on that FGameplayAbilityActorInfo are valid, if not bail out.
	if (actorInfo == nullptr || !actorInfo->OwnerActor.IsValid() || !actorInfo->AvatarActor.IsValid())
	{
		return false;
	}
	
	return ability->CanActivateAbility(handle, actorInfo, nullptr, nullptr, nullptr);
}

Thanks for your help <3

2 Likes