document.write("
// Fill out your copyright notice in the Description page of Project Settings. 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); }