document.write("
// Fill out your copyright notice in the Description page of Project Settings.
#include "InputActionGameplayAbility.h"
#include "EnhancedInputComponent.h"
#include "Dandelion/Sandbox/Input/InputActionGameplayAbilityMappings.h"
#include "Dandelion/Sandbox/Pawns/DandelionPlayerCharacter.h"
UInputActionGameplayAbility::UInputActionGameplayAbility()
{
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalOnly;
}
void UInputActionGameplayAbility::OnGiveAbility(
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilitySpec& Spec
)
{
Super::OnGiveAbility(ActorInfo, Spec);
DandelionPlayerCharacter = Cast<ADandelionPlayerCharacter>(ActorInfo->AvatarActor);
if (!ensure(IsValid(DandelionPlayerCharacter)))
{
UE_LOG(
LogGameplayAbility,
Error,
TEXT("%s: Tried to GiveAbility without a valid DandelionPlayerCharacter."),
*GetFullNameSafe(this)
)
}
}
void UInputActionGameplayAbility::ActivateAbility(
const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData
)
{
constexpr bool bReplicateCancelAbility = true;
EnhancedInputComponent = Cast<UEnhancedInputComponent>(DandelionPlayerCharacter->InputComponent);
if (!ensure(IsValid(EnhancedInputComponent)))
{
UE_LOG(
LogGameplayAbility,
Error,
TEXT("%s: Tried to ActivateAbility without a valid UEnhancedInputComponent."),
*GetFullNameSafe(this)
)
CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancelAbility);
return;
}
const UInputActionGameplayAbilityMappings* InputActionGameplayAbilityMappings =
DandelionPlayerCharacter->GetInputActionGameplayAbilityMappings();
if (!IsValid(InputActionGameplayAbilityMappings))
{
UE_LOG(
LogGameplayAbility,
Warning,
TEXT(
"%s: Tried to ActivateAbility on an InputActionGameplayAbility without a valid UInputActionGameplayAbilityMappings."
),
*GetFullNameSafe(this)
)
CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancelAbility);
return;
}
// TODO: Probably cache the InputAction value in OnGiveAbility? No particularly great reason to be looking this up
// every time the ability is activated. Only the actual binding part needs to be done here.
const TSet<FInputActionGameplayAbilityMappingData>& Mappings = InputActionGameplayAbilityMappings->GetMappings();
for (const FInputActionGameplayAbilityMappingData& Mapping : Mappings)
{
// Only watch for InputAction trigger if this GA activates off of Starting the IA, not Triggering it.
if (!Mapping.IsValid() ||
Mapping.GameplayAbilityClass != GetClass() ||
Mapping.TriggerType != ETriggerEvent::Started) { continue; }
const FEnhancedInputActionEventBinding& TriggeredEventBinding = EnhancedInputComponent->BindAction(
Mapping.InputAction,
ETriggerEvent::Triggered,
this,
&ThisClass::InvokeTriggeredInputAction
);
const uint32 TriggeredEventHandle = TriggeredEventBinding.GetHandle();
TriggeredEventHandles.AddUnique(TriggeredEventHandle);
}
if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
{
UE_LOG(
LogGameplayAbility,
Verbose,
TEXT(
"%s: Failed CommitAbility checks when trying to ActivateAbility."
),
*GetFullNameSafe(this)
)
CancelAbility(Handle, ActorInfo, ActivationInfo, bReplicateCancelAbility);
}
}
void UInputActionGameplayAbility::EndAbility(
const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
bool bReplicateEndAbility,
bool bWasCancelled
)
{
if (!IsValid(EnhancedInputComponent))
{
// Hard to tell if this will occur just to normal stuff like players clicking off the screen or if this is
// actually catastrophic.
UE_LOG(
LogGameplayAbility,
Warning,
TEXT("%s: Tried to EndAbility without cancelling with an invalid UEnhancedInputComponent."),
*GetFullNameSafe(this)
)
TriggeredEventHandles.Reset();
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
return;
}
if (TriggeredEventHandles.IsEmpty())
{
EnhancedInputComponent = nullptr;
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
return;
}
for (const uint32 EventHandle : TriggeredEventHandles)
{
EnhancedInputComponent->RemoveBindingByHandle(EventHandle);
}
EnhancedInputComponent = nullptr;
TriggeredEventHandles.Reset();
Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
}
void UInputActionGameplayAbility::InputPressed(
const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo
)
{
switch (ResponseOnInputPressed)
{
case EInputActionGameplayAbilityResponse::None: { break; }
case EInputActionGameplayAbilityResponse::EndAbility:
{
if (!IsActive())
{
UE_LOG(
LogGameplayAbility,
Warning,
TEXT("%s: Attempted to handle InputPressed with EndAbility mode and an inactive GA."),
*GetFullNameSafe(this)
);
break;
}
RestartAbility(Handle, ActorInfo, ActivationInfo, true, false, true);
break;
}
case EInputActionGameplayAbilityResponse::CancelAbility:
{
if (!IsActive())
{
UE_LOG(
LogGameplayAbility,
Warning,
TEXT("%s: Attempted to handle InputPressed with EndAbility mode and an inactive GA."),
*GetFullNameSafe(this)
);
break;
}
RestartAbility(Handle, ActorInfo, ActivationInfo, true, true, true);
break;
}
case EInputActionGameplayAbilityResponse::Custom:
{
HandleInputPressed(Handle, *ActorInfo, ActivationInfo);
break;
}
}
Super::InputPressed(Handle, ActorInfo, ActivationInfo);
}
void UInputActionGameplayAbility::InputReleased(
const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo
)
{
switch (ResponseOnInputReleased)
{
case EInputActionGameplayAbilityResponse::None: { break; }
case EInputActionGameplayAbilityResponse::EndAbility:
{
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
break;
}
case EInputActionGameplayAbilityResponse::CancelAbility:
{
CancelAbility(Handle, ActorInfo, ActivationInfo, true);
break;
}
case EInputActionGameplayAbilityResponse::Custom:
{
HandleInputReleased(Handle, *ActorInfo, ActivationInfo);
break;
}
}
Super::InputReleased(Handle, ActorInfo, ActivationInfo);
}
void UInputActionGameplayAbility::HandleInputPressed_Implementation(
const FGameplayAbilitySpecHandle& Handle,
const FGameplayAbilityActorInfo& ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo
)
{
UE_LOG(
LogGameplayAbility,
Warning,
TEXT(
"%s: Used Custom response mode when OnInputPressed but did not override base behavior."
),
*GetFullNameSafe(this)
)
}
void UInputActionGameplayAbility::HandleInputReleased_Implementation(
const FGameplayAbilitySpecHandle& Handle,
const FGameplayAbilityActorInfo& ActorInfo,
const FGameplayAbilityActivationInfo& ActivationInfo
)
{
UE_LOG(
LogGameplayAbility,
Warning,
TEXT(
"%s: Used Custom response mode when OnInputReleased but did not override base behavior. Likely will result in a dangling GA."
),
*GetFullNameSafe(this)
)
}
void UInputActionGameplayAbility::InvokeTriggeredInputAction(const FInputActionValue& Value)
{
OnTriggeredInputAction.Broadcast(Value);
OnTriggeredInputAction_BP.Broadcast(Value);
}
DandelionGameplayAbility.cpp - Snippet hosted by \"Cacher\"
");