2022-05-23 18:41:30 +00:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
#include "AbilityTask_GrantNearbyInteraction.h"
|
2022-09-13 07:18:28 +00:00
|
|
|
|
|
|
|
#include "Abilities/GameplayAbility.h"
|
|
|
|
#include "AbilitySystemComponent.h"
|
|
|
|
#include "CollisionQueryParams.h"
|
|
|
|
#include "CollisionShape.h"
|
|
|
|
#include "Containers/Array.h"
|
|
|
|
#include "Delegates/Delegate.h"
|
|
|
|
#include "Engine/OverlapResult.h"
|
|
|
|
#include "Engine/World.h"
|
2022-05-23 18:41:30 +00:00
|
|
|
#include "GameFramework/Actor.h"
|
2022-09-13 07:18:28 +00:00
|
|
|
#include "GameFramework/Controller.h"
|
|
|
|
#include "GameplayAbilitySpec.h"
|
2022-05-23 18:41:30 +00:00
|
|
|
#include "Interaction/IInteractableTarget.h"
|
2022-09-13 07:18:28 +00:00
|
|
|
#include "Interaction/InteractionOption.h"
|
2022-05-23 18:41:30 +00:00
|
|
|
#include "Interaction/InteractionQuery.h"
|
2022-09-13 07:18:28 +00:00
|
|
|
#include "Interaction/InteractionStatics.h"
|
|
|
|
#include "Math/Quat.h"
|
|
|
|
#include "Physics/LyraCollisionChannels.h"
|
|
|
|
#include "Stats/Stats2.h"
|
|
|
|
#include "Templates/Casts.h"
|
|
|
|
#include "Templates/SubclassOf.h"
|
2022-05-23 18:41:30 +00:00
|
|
|
#include "TimerManager.h"
|
2022-09-13 07:18:28 +00:00
|
|
|
#include "UObject/ObjectKey.h"
|
|
|
|
#include "UObject/ScriptInterface.h"
|
|
|
|
#include "UObject/WeakObjectPtr.h"
|
|
|
|
#include "UObject/WeakObjectPtrTemplates.h"
|
2022-05-23 18:41:30 +00:00
|
|
|
|
|
|
|
UAbilityTask_GrantNearbyInteraction::UAbilityTask_GrantNearbyInteraction(const FObjectInitializer& ObjectInitializer)
|
|
|
|
: Super(ObjectInitializer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
UAbilityTask_GrantNearbyInteraction* UAbilityTask_GrantNearbyInteraction::GrantAbilitiesForNearbyInteractors(UGameplayAbility* OwningAbility, float InteractionScanRange, float InteractionScanRate)
|
|
|
|
{
|
|
|
|
UAbilityTask_GrantNearbyInteraction* MyObj = NewAbilityTask<UAbilityTask_GrantNearbyInteraction>(OwningAbility);
|
|
|
|
MyObj->InteractionScanRange = InteractionScanRange;
|
|
|
|
MyObj->InteractionScanRate = InteractionScanRate;
|
|
|
|
return MyObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAbilityTask_GrantNearbyInteraction::Activate()
|
|
|
|
{
|
|
|
|
SetWaitingOnAvatar();
|
|
|
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
World->GetTimerManager().SetTimer(QueryTimerHandle, this, &ThisClass::QueryInteractables, InteractionScanRate, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAbilityTask_GrantNearbyInteraction::OnDestroy(bool AbilityEnded)
|
|
|
|
{
|
|
|
|
Super::OnDestroy(AbilityEnded);
|
|
|
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
World->GetTimerManager().ClearTimer(QueryTimerHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UAbilityTask_GrantNearbyInteraction::QueryInteractables()
|
|
|
|
{
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
AActor* ActorOwner = GetAvatarActor();
|
|
|
|
|
|
|
|
if (World && ActorOwner)
|
|
|
|
{
|
|
|
|
FCollisionQueryParams Params(SCENE_QUERY_STAT(UAbilityTask_GrantNearbyInteraction), false);
|
|
|
|
|
|
|
|
TArray<FOverlapResult> OverlapResults;
|
|
|
|
World->OverlapMultiByChannel(OUT OverlapResults, ActorOwner->GetActorLocation(), FQuat::Identity, Lyra_TraceChannel_Interaction, FCollisionShape::MakeSphere(InteractionScanRange), Params);
|
|
|
|
|
|
|
|
if (OverlapResults.Num() > 0)
|
|
|
|
{
|
|
|
|
TArray<TScriptInterface<IInteractableTarget>> InteractableTargets;
|
|
|
|
UInteractionStatics::AppendInteractableTargetsFromOverlapResults(OverlapResults, OUT InteractableTargets);
|
|
|
|
|
|
|
|
FInteractionQuery InteractionQuery;
|
|
|
|
InteractionQuery.RequestingAvatar = ActorOwner;
|
|
|
|
InteractionQuery.RequestingController = Cast<AController>(ActorOwner->GetOwner());
|
|
|
|
|
|
|
|
TArray<FInteractionOption> Options;
|
|
|
|
for (TScriptInterface<IInteractableTarget>& InteractiveTarget : InteractableTargets)
|
|
|
|
{
|
|
|
|
FInteractionOptionBuilder InteractionBuilder(InteractiveTarget, Options);
|
|
|
|
InteractiveTarget->GatherInteractionOptions(InteractionQuery, InteractionBuilder);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if any of the options need to grant the ability to the user before they can be used.
|
|
|
|
for (FInteractionOption& Option : Options)
|
|
|
|
{
|
|
|
|
if (Option.InteractionAbilityToGrant)
|
|
|
|
{
|
|
|
|
// Grant the ability to the GAS, otherwise it won't be able to do whatever the interaction is.
|
|
|
|
FObjectKey ObjectKey(Option.InteractionAbilityToGrant);
|
|
|
|
if (!InteractionAbilityCache.Find(ObjectKey))
|
|
|
|
{
|
|
|
|
FGameplayAbilitySpec Spec(Option.InteractionAbilityToGrant, 1, INDEX_NONE, this);
|
|
|
|
FGameplayAbilitySpecHandle Handle = AbilitySystemComponent->GiveAbility(Spec);
|
|
|
|
InteractionAbilityCache.Add(ObjectKey, Handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|