RealtimeStyleTransferRuntime/Source/LyraGame/Interaction/Abilities/LyraGameplayAbility_Interac...

129 lines
5.2 KiB
C++
Raw Permalink Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraGameplayAbility_Interact.h"
2022-09-13 07:18:28 +00:00
#include "Abilities/GameplayAbilityTypes.h"
2022-05-23 18:41:30 +00:00
#include "AbilitySystemComponent.h"
2022-09-13 07:18:28 +00:00
#include "Containers/EnumAsByte.h"
#include "Engine/EngineTypes.h"
#include "GameFramework/Actor.h"
#include "GameplayTagContainer.h"
2022-05-23 18:41:30 +00:00
#include "Interaction/IInteractableTarget.h"
#include "Interaction/InteractionStatics.h"
#include "Interaction/Tasks/AbilityTask_GrantNearbyInteraction.h"
#include "NativeGameplayTags.h"
#include "Player/LyraPlayerController.h"
#include "UI/IndicatorSystem/IndicatorDescriptor.h"
2022-09-13 07:18:28 +00:00
#include "UI/IndicatorSystem/LyraIndicatorManagerComponent.h"
#include "UObject/NameTypes.h"
#include "UObject/ObjectPtr.h"
#include "UObject/ScriptInterface.h"
class UUserWidget;
2022-05-23 18:41:30 +00:00
UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Ability_Interaction_Activate, "Ability.Interaction.Activate");
UE_DEFINE_GAMEPLAY_TAG(TAG_INTERACTION_DURATION_MESSAGE, "Ability.Interaction.Duration.Message");
ULyraGameplayAbility_Interact::ULyraGameplayAbility_Interact(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
ActivationPolicy = ELyraAbilityActivationPolicy::OnSpawn;
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;
}
void ULyraGameplayAbility_Interact::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
UAbilitySystemComponent* AbilitySystem = GetAbilitySystemComponentFromActorInfo();
if (AbilitySystem && AbilitySystem->GetOwnerRole() == ROLE_Authority)
{
UAbilityTask_GrantNearbyInteraction* Task = UAbilityTask_GrantNearbyInteraction::GrantAbilitiesForNearbyInteractors(this, InteractionScanRange, InteractionScanRate);
Task->ReadyForActivation();
}
}
void ULyraGameplayAbility_Interact::UpdateInteractions(const TArray<FInteractionOption>& InteractiveOptions)
{
if (ALyraPlayerController* PC = GetLyraPlayerControllerFromActorInfo())
{
if (ULyraIndicatorManagerComponent* IndicatorManager = ULyraIndicatorManagerComponent::GetComponent(PC))
{
for (UIndicatorDescriptor* Indicator : Indicators)
{
IndicatorManager->RemoveIndicator(Indicator);
}
Indicators.Reset();
for (const FInteractionOption& InteractionOption : InteractiveOptions)
{
AActor* InteractableTargetActor = UInteractionStatics::GetActorFromInteractableTarget(InteractionOption.InteractableTarget);
TSoftClassPtr<UUserWidget> InteractionWidgetClass =
InteractionOption.InteractionWidgetClass.IsNull() ? DefaultInteractionWidgetClass : InteractionOption.InteractionWidgetClass;
UIndicatorDescriptor* Indicator = NewObject<UIndicatorDescriptor>();
Indicator->SetDataObject(InteractableTargetActor);
Indicator->SetSceneComponent(InteractableTargetActor->GetRootComponent());
Indicator->SetIndicatorClass(InteractionWidgetClass);
IndicatorManager->AddIndicator(Indicator);
Indicators.Add(Indicator);
}
}
else
{
//TODO This should probably be a noisy warning. Why are we updating interactions on a PC that can never do anything with them?
}
}
CurrentOptions = InteractiveOptions;
}
void ULyraGameplayAbility_Interact::TriggerInteraction()
{
if (CurrentOptions.Num() == 0)
{
return;
}
UAbilitySystemComponent* AbilitySystem = GetAbilitySystemComponentFromActorInfo();
if (AbilitySystem)
{
const FInteractionOption& InteractionOption = CurrentOptions[0];
AActor* Instigator = GetAvatarActorFromActorInfo();
AActor* InteractableTargetActor = UInteractionStatics::GetActorFromInteractableTarget(InteractionOption.InteractableTarget);
// Allow the target to customize the event data we're about to pass in, in case the ability needs custom data
// that only the actor knows.
FGameplayEventData Payload;
Payload.EventTag = TAG_Ability_Interaction_Activate;
Payload.Instigator = Instigator;
Payload.Target = InteractableTargetActor;
// If needed we allow the interactable target to manipulate the event data so that for example, a button on the wall
// may want to specify a door actor to execute the ability on, so it might choose to override Target to be the
// door actor.
InteractionOption.InteractableTarget->CustomizeInteractionEventData(TAG_Ability_Interaction_Activate, Payload);
// Grab the target actor off the payload we're going to use it as the 'avatar' for the interaction, and the
// source InteractableTarget actor as the owner actor.
2022-09-13 07:18:28 +00:00
AActor* TargetActor = const_cast<AActor*>(ToRawPtr(Payload.Target));
2022-05-23 18:41:30 +00:00
// The actor info needed for the interaction.
FGameplayAbilityActorInfo ActorInfo;
ActorInfo.InitFromActor(InteractableTargetActor, TargetActor, InteractionOption.TargetAbilitySystem);
// Trigger the ability using event tag.
const bool bSuccess = InteractionOption.TargetAbilitySystem->TriggerAbilityFromGameplayEvent(
InteractionOption.TargetInteractionAbilityHandle,
&ActorInfo,
TAG_Ability_Interaction_Activate,
&Payload,
*InteractionOption.TargetAbilitySystem
);
}
}