Hello,
I’m learning GAS and I’m creating a Toggle Openable ability to open/close things.
Here is what I’ve come up with:
code
// Fill out your copyright notice in the Description page of Project Settings.
include “Abilities/Capabilities/EdenGameplayAbility_ToggleOpenable.h”
include “AbilitySystemComponent.h”
include “AbilitySystemGlobals.h”
include “EdenGameplayTags.h”
include “Effects/State/EdenGameplayEffect_Close.h”
include “Effects/State/EdenGameplayEffect_Open.h”
UEdenGameplayAbility_ToggleOpenable::UEdenGameplayAbility_ToggleOpenable()
{
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
TargetRequiredTags.AddTag(EdenGameplayTags::Eden_Gameplay_Capability_Openable);
TargetBlockedTags.AddTag(EdenGameplayTags::Eden_Gameplay_State_Locked);
}
void UEdenGameplayAbility_ToggleOpenable::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
// Figure out the target door from event data (passed in when triggering)
const AActor\* TargetActor = nullptr;
if (TriggerEventData && TriggerEventData->Target)
{
TargetActor = const_cast<AActor\*>(TriggerEventData->Target.Get());
}
if (!TargetActor)
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
UAbilitySystemComponent\* TargetAsc = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(TargetActor);
if (!TargetAsc)
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
return;
}
FGameplayEffectContextHandle Context = TargetAsc->MakeEffectContext();
Context.AddSourceObject(this);
if (TargetAsc->HasMatchingGameplayTag(EdenGameplayTags::Eden_Gameplay_State_Opened))
{
// Door is open → close it
if (const FGameplayEffectSpecHandle SpecHandle = TargetAsc->MakeOutgoingSpec(UEdenGameplayEffect_Close::StaticClass(), 1, Context); SpecHandle.IsValid())
{
TargetAsc->ApplyGameplayEffectSpecToSelf(\*SpecHandle.Data.Get());
}
}
else if (TargetAsc->HasMatchingGameplayTag(EdenGameplayTags::Eden_Gameplay_State_Closed))
{
// Door is closed → open it
if (const FGameplayEffectSpecHandle SpecHandle = TargetAsc->MakeOutgoingSpec(UEdenGameplayEffect_Open::StaticClass(), 1, Context); SpecHandle.IsValid())
{
TargetAsc->ApplyGameplayEffectSpecToSelf(\*SpecHandle.Data.Get());
}
}
EndAbility(Handle, ActorInfo, ActivationInfo, false, false);
}
Is it a good approach?
I’m now looking on how to provide user an interaction indicator text and I’m wondering how I could somehow return a text from my ability “Open” when it targets an openable actor and “Close” when it targets a closable actor. Any idea?