Gameplay Abilities: TryActivateAbilityByClass results error

So… here is the problem:

I have dedicated server.

  1. Server creates actor
  2. Server gives ability to actor
  3. Player connects and possesses actor.
  4. Trying activate ability.
  5. Getting error:

Warning: Can’t activate LocalOnly or LocalPredicted ability Default__GA_BasicMeleeAtack_C when not local! Net Execution Policy is 0.

and ability doesn’t work.

(btw. dedicated server doesn’t have sessions set up, client connects by IP)

After some digging i found:

        if (Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalOnly || (Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalPredicted && !InPredictionKey.IsValidKey()))
        {
            // If we have a valid prediction key, the ability was started on the local client so it's okay

            ABILITY_LOG(Warning, TEXT("Can't activate LocalOnly or LocalPredicted ability %s when not local! Net Execution Policy is %d. "), *Ability->GetName(), (int32)Ability->GetNetExecutionPolicy());

            if (NetworkFailTag.IsValid())
            {
                InternalTryActivateAbilityFailureTags.AddTag(NetworkFailTag);
                NotifyAbilityFailed(Handle, Ability, InternalTryActivateAbilityFailureTags);
            }

            return false;
        }

Net Execution Policy is Local Predicted.

So i think something wrong with PredictionKey… and my skills not enough to find out whats wrong…

so i added to plugin this:

ABILITY_LOG(Warning, TEXT("InPredictionKey = %s"), (InPredictionKey.IsValidKey() ? TEXT("True") : TEXT("False")));

and getting false.

So how to fix this key stuff?


This is how ability is acquired:

void ACharacterRoot::XAquireAbility(TSubclassOf<UGameplayAbility> wAbilityToAquire)
{      
    if (AbilitySystemComponentas)
    {
        if (HasAuthority() && wAbilityToAquire)
        {
            AbilitySystemComponentas->GiveAbility(FGameplayAbilitySpec(wAbilityToAquire, 1, 0));
        }
        AbilitySystemComponentas->InitAbilityActorInfo(this, this);
    }
}

Also i overridet PossessedBy so after possession information is refreshed:

void ACharacterRoot::PossessedBy(AController * NewController)
{
	Super::PossessedBy(NewController);

	if (AbilitySystemComponentas)
	{
		AbilitySystemComponentas->RefreshAbilityActorInfo();
	}
}

well… i dont know what to do :frowning: so i’m messing around…

when i’m using TryActivateAbilityByClass then in chain reaction this function is called:

	/** Attempts to activate the given ability, will only work if called from the correct client/server context */
	bool InternalTryActivateAbility(FGameplayAbilitySpecHandle AbilityToActivate, FPredictionKey InPredictionKey = FPredictionKey(), UGameplayAbility ** OutInstancedAbility = nullptr, FOnGameplayAbilityEnded::FDelegate* OnGameplayAbilityEndedDelegate = nullptr, const FGameplayEventData* TriggerEventData = nullptr);

So… InternalTryActivateAbility have FPredictionKey InPredictionKey = FPredictionKey() with default value… and by default it getting not valid key…

so in fileGameplayPrediction.h i writed line with log:

	FPredictionKey()
	: Current(0), Base(0), PredictiveConnection(nullptr), bIsStale(false), bIsServerInitiated(false)
	{
    		UE_LOG(LogTemp, Display, TEXT(" STEP D5. FPredictionKey() !!!!!!!!!!!!!!!!!!!"));
	}

but what is strange… now i’m getting log full message. even if i comment:

	// Construc component
	//AbilitySystemComponentas = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComponentas");

who the hell generating FPredictionKey() ???link text

Could you share the advanced category properties on you blueprint ?

right now i suppose it’s a local one, and you try to call “Trying activate ability” from the server, you should try to activate it on the client side ( or change the settings) ability system take care of activating it on the server side

Ability system is not easy to understand and take in hand, no much ressources on that

Well there mine blueprints…

A’m activating ability with HasAuthority so it is called on client… i think…
BTW… before line which prints out error i added another to log
InPredictionKey.IsValidKey() and i’m getting false…
So i think mine local client dont generate keys… or local client thinks that it is server…

But then you should put local only as your ability is not replicated

Found it !
you call AbilitySystem->InitAbilityActorInfo(this, this); only on the server, put it in begin play !

because your client has no actor infos, so when it try to look if it’s a local player, it’s can’t know ( so it answer false )

I changed net execution policy to LocalOnly
resultat:

[ 66]LogAbilitySystem: Warning: Can’t activate LocalOnly or LocalPredicted ability Default__GA_BasicMeleeAtack_C when not local! Net Execution Policy is 1.

same…

I even added check for IsDedicated server. Well i’m getting false… So i’m trying to run on client locally…

just before the line you posted
if (Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalOnly || (Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalPredicted && !InPredictionKey.IsValidKey()))

the is a line

bool bIsLocal = AbilityActorInfo->IsLocallyControlled();

it currently return false ( but should return true )
but a breakpoint and check what’s happening in there
also put a breakpoint on you blueprint when you try to activate ability and check if it’s on server or client !

AbilitySystem->InitAbilityActorInfo(this, this) is called in function ACharacterRoot::XAquireAbility

And function XAquireAbility is called from BeginPlay in blueprint…

and PossessedBy is overriden and when controller possesses actor with ability, AbilitySystemComponentas->RefreshAbilityActorInfo() is called.

on the controler, override the method on playerControler " virtual void ClientRestart_Implementation(class APawn* NewPawn) override;" ( and get pawn + cast to your pawn class and call it from there )

well…

in guides i red that you need to refresh actor info after possession and override PossessedBy function…
But problem is that PossessedBy is called only on server… So i tried refresh actor info before activate ability on client and ability STARTED to work.
Last thing for me… decide where exactly to put RefreshActorInfo so it will be called on server and on client…

Well its working… I’ve done what you told me…

Thank you for your time… and help…

@Firefly74 Thank you so much! Just been smashing my head against the desk trying to figure out what I was doing wrong - but overriding ClientRestart_Implementation as suggested to trigger RefreshActorInfo on Posessed Pawn’s AbilitySystemComponent worked.

1 Like