document.write("
// Fill out your copyright notice in the Description page of Project Settings.
#include "AbilityTask_FollowCursor.h"
#include "GameplayCueNotify_Actor.h"
#include "GameplayCueNotify_Static.h"
#include "Dandelion/Sandbox/Abilities/DandelionGameplayAbility.h"
#include "Dandelion/Sandbox/PlayerControllers/DandelionPlayerController.h"
UAbilityTask_FollowCursor::UAbilityTask_FollowCursor() { bTickingTask = true; }
UAbilityTask_FollowCursor* UAbilityTask_FollowCursor::FollowCursor(
UDandelionGameplayAbility* OwningAbility,
const FName TaskInstanceName,
const float StopDistance
)
{
UAbilityTask_FollowCursor* NewTaskInstance =
NewAbilityTask<UAbilityTask_FollowCursor>(OwningAbility, TaskInstanceName);
NewTaskInstance->TargetLocation = FVector::ZeroVector;
if (StopDistance < 0.f)
{
UE_LOG(
LogGameplayTasks,
Warning,
TEXT("%s: Tried to instantiate a new MoveToCursorTask with an invalid StopDistance: %f."),
*GetFullNameSafe(NewTaskInstance),
StopDistance
)
}
NewTaskInstance->StopDistance = FMath::Max(0.f, StopDistance);
APawn* AvatarPawn = OwningAbility->TryCastAvatarActorFromActorInfo<APawn>();
if (!ensure(IsValid(AvatarPawn)))
{
UE_LOG(
LogGameplayTasks,
Error,
TEXT("%s: Tried to instantiate a new MoveToCursorTask without a valid avatar Pawn."),
*GetFullNameSafe(NewTaskInstance)
)
return NewTaskInstance;
}
NewTaskInstance->PlayerPawn = AvatarPawn;
ADandelionPlayerController* AvatarController = AvatarPawn->GetController<ADandelionPlayerController>();
if (!ensure(IsValid(AvatarController)))
{
UE_LOG(
LogGameplayTasks,
Error,
TEXT("%s: Tried to instantiate a new MoveTo task without a valid avatar PlayerController."),
*GetFullNameSafe(NewTaskInstance)
)
return NewTaskInstance;
}
NewTaskInstance->PlayerController = AvatarController;
return NewTaskInstance;
}
void UAbilityTask_FollowCursor::ExternalCancel()
{
if (IsValid(PlayerController)) { PlayerController->StopMovement(); }
Super::ExternalCancel();
}
void UAbilityTask_FollowCursor::Activate()
{
if (!IsValid(PlayerController))
{
UE_LOG(
LogGameplayTasks,
Warning,
TEXT("%s: Tried to Activate with an invalid avatar PlayerController."),
*GetFullNameSafe(this)
)
return;
}
PlayerController->StopMovement();
Super::Activate();
}
void UAbilityTask_FollowCursor::TickTask(const float DeltaTime)
{
if (!IsValid(PlayerPawn))
{
UE_LOG(
LogGameplayTasks,
Warning,
TEXT("%s: Tried to TickTask with an invalid avatar Pawn."),
*GetFullNameSafe(this)
)
EndTask();
return;
}
UpdateTargetLocation();
const float XYDistance = FVector::DistXY(TargetLocation, PlayerPawn->GetActorLocation());
const FVector WorldDisplacement = TargetLocation - PlayerPawn->GetActorLocation();
if (XYDistance < StopDistance + UE_SMALL_NUMBER)
{
OnMoveComplete.Broadcast();
EndTask();
return;
}
PlayerPawn->AddMovementInput(WorldDisplacement.GetSafeNormal(), 1.0, false);
Super::TickTask(DeltaTime);
}
void UAbilityTask_FollowCursor::UpdateTargetLocation()
{
FHitResult Hit;
if (!PlayerController->GetHitResultUnderCursor(ECC_Visibility, true, Hit))
{
UE_LOG(
LogGameplayTasks,
VeryVerbose,
TEXT("%s: Failed to register a hit under cursor in GetTargetLocation. Using CachedDestination: %s"),
*GetFullNameSafe(this),
*TargetLocation.ToString()
);
return;
}
TargetLocation = Hit.Location;
}
AbilityTask_FollowCursor.cpp - Snippet hosted by \"Cacher\"
");