Making a custom Ability Actor Info

When you start getting into the power of the Gameplay Ability System, it may be needed that you want to access stuff easily in your Actor Info. The guys at Epic made this really easy to override and implement but there is a few steps. The first step that is mandatory is setting up your own Game specific UAbilitySystemGlobals. You can read that post here: https://www.thegames.dev/?p=52

With that out of the way, let us start.

The first thing you want to do is create a AbilityTypes class to hold your structs/enums you will use in your ability system if you do not have one. In my example i have a KaosAbilityTypes.cpp and KaosAbilityTypes.h file.

Next we need to create our own AbilityActorInfo derived from FGameplayAbilityActorInfo in our AbilityTypes header file:

USTRUCT(BlueprintType)
struct FKaosGameplayAbilityActorInfo : public FGameplayAbilityActorInfo
{
	GENERATED_USTRUCT_BODY()
	
		typedef Super FGameplayAbilityActorInfo;
	
	virtual ~FKaosGameplayAbilityActorInfo()
	{
	}

	//Our KaosAbilitySystemComponent. Should NEVER be null.
	UPROPERTY(BlueprintReadOnly, Category = "ActorInfo")
	TWeakObjectPtr<class UKaosAbilitySystemComponent> KaosAbilitySystemComponent;

	//Our KaosPawn. Often nullptr.
	UPROPERTY(BlueprintReadOnly, Category = "ActorInfo")
	TWeakObjectPtr<class AKaosPawn> KaosPawn;

	//Our Kaos Player Pawn. Often nullptr
	UPROPERTY(BlueprintReadOnly, Category = "ActorInfo")
	TWeakObjectPtr<class AKaosPlayerPawn> KaosPlayerPawn;

	//Our Kaos Player Controller. Often nullptr.
	UPROPERTY(BlueprintReadOnly, Category = "ActorInfo")
	TWeakObjectPtr<class AKaosPlayerController> KaosPlayerController;

	//Our Kaos Player State. Often nullptr.
	UPROPERTY(BlueprintReadOnly, Category = "ActorInfo")
	TWeakObjectPtr<class AKaosPlayerState> KaosPlayerState;

	virtual void InitFromActor(AActor* OwnerActor, AActor* AvatarActor, UAbilitySystemComponent* InAbilitySystemComponent) override;

	virtual void SetAvatarActor(AActor* AvatarActor) override;

	virtual void ClearActorInfo() override;

	//Gets the Kaos Pawn. This is often nullptr.
	class AKaosPawn* GetKaosPawn() const;

	//Gets the Kaos Player Pawn. This is often nullptr.
	class AKaosPlayerPawn* GetKaosPlayerPawn() const;

	//Gets the Kaos Player Controller. This is often nullptr.
	class AKaosPlayerController* GetKaosPlayerController() const;

	//Gets the Kaos Player State. This is often nullptr.
	class AKaosPlayerState* GetKaosPlayerState() const;
};

As you can see with the above, i want to easily get my game specific Controllers, Pawn(Character) and PlayerState from the Actor Info. We have to override a few things to achieve this. We also put a typedef there so we can call Super::InitFromActor and keep it consistent with UE4 code.

Now in our AbilityTypes.cpp we can start grabbing and setting our properties, as well as defining the functions we declared in our header.

void FKaosGameplayAbilityActorInfo::InitFromActor(AActor* InOwnerActor, AActor* InAvatarActor, UAbilitySystemComponent* InAbilitySystemComponent)
{
	Super::InitFromActor(InOwnerActor, InAvatarActor, InAbilitySystemComponent);

	KaosAbilitySystemComponent = Cast<UKaosAbilitySystemComponent>(InAbilitySystemComponent);
	
        KaosPawn = Cast<AKaosPawn>(InAvatarActor);
	KaosPlayerPawn = Cast<AKaosPlayerPawn>(InAvatarActor);

	if (PlayerController.IsValid())
	{
		KaosPlayerController = Cast<AKaosPlayerController>(PlayerController.Get());
		KaosPlayerState = PlayerController->GetPlayerState<AKaosPlayerState>();
	}
	else if (KaosPawn.IsValid())
	{
		KaosAIController = KaosPawn->GetController<AKaosAIController>();
	}


}

void FKaosGameplayAbilityActorInfo::SetAvatarActor(AActor* InAvatarActor)
{
	Super::SetAvatarActor(InAvatarActor);
}

void FKaosGameplayAbilityActorInfo::ClearActorInfo()
{
	Super::ClearActorInfo();

	KaosPawn = nullptr;
	KaosPlayerPawn = nullptr;
	KaosPlayerState = nullptr;
	KaosPlayerController = nullptr;
	KaosAbilitySystemComponent = nullptr;
}

class UKaosAbilitySystemComponent* FKaosGameplayAbilityActorInfo::GetKaosAbilitySystemComponent() const
{
	return KaosAbilitySystemComponent.IsValid() ? KaosAbilitySystemComponent.Get() : nullptr;
}

class AKaosPawn* FKaosGameplayAbilityActorInfo::GetKaosPawn() const
{
	return KaosPawn.IsValid() ? KaosPawn.Get() : nullptr;
}

class AKaosPlayerPawn* FKaosGameplayAbilityActorInfo::GetKaosPlayerPawn() const
{
	return KaosPlayerPawn.IsValid() ? KaosPlayerPawn.Get() : nullptr;
}

class AKaosPlayerController* FKaosGameplayAbilityActorInfo::GetKaosPlayerController() const
{
	return KaosPlayerController.IsValid() ? KaosPlayerController.Get() : nullptr;
}

class AKaosPlayerState* FKaosGameplayAbilityActorInfo::GetKaosPlayerState() const
{
	return KaosPlayerState.IsValid() ? KaosPlayerState.Get() : nullptr;
}

class AKaosWeapon* FKaosGameplayAbilityActorInfo::GetKaosWeapon() const
{
	return GetKaosPawn() ? GetKaosPawn()->GetCurrentWeapon() : nullptr;
}

class AKaosWeaponRanged* FKaosGameplayAbilityActorInfo::GetKaosWeaponRanged() const
{
	return GetKaosPawn() ? Cast<AKaosWeaponRanged>(GetKaosPawn()->GetCurrentWeapon()) : nullptr;
}

The main bulk of the stuff, is the overridden functions, we needed to override InitActorInfo to grab the actor info required. We also overrode ClearActorInfo, so we can clear everything we had set in InitAbilityActorInfo/SetAvatarActor.

Now we need to tell the Gameplay Ability System we want to use this new Actor Info. Open your game specific AbilitySystemGlobals class header, and override the following function:

	virtual FGameplayAbilityActorInfo* AllocAbilityActorInfo() const override;

and in the cpp file of your game specific AbilitySystemGlobals, we need to define this like so:

FGameplayAbilityActorInfo* UKaosAbilitySystemGlobals::AllocAbilityActorInfo() const
{
	return new FKaosGameplayAbilityActorInfo();
}

Remember to replace the names with your projects names, ie FMyGameplayAbilityActorInfo, etc.

To access your newly created AbilityActorInfo from within abilities, etc, you need to cast. I have shown an example below:

const FKaosGameplayAbilityActorInfo* UKaosGameplayAbility::GetKaosActorInfo(const FGameplayAbilityActorInfo* InInfo)
{
	return static_cast<const FKaosGameplayAbilityActorInfo*>(InInfo);
}

with the above function, which is a little wrapper, i can access specific stuff i want, like this function:

AKaosPawn* UKaosGameplayAbility::GetKaosPawnFromAvatar(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const
{
	const FKaosGameplayAbilityActorInfo* KaosActorInfo = GetKaosActorInfo(ActorInfo);
	return KaosActorInfo ? KaosActorInfo->GetKaosPawn() : nullptr;
}

I hope this helps, and you find it useful.

That is all for now 🙂