FHitResult AGameplayAbilityTargetActor_GroundTrace::PerformTrace(AActor* InSourceActor)
{
    static const FName LineTraceSingleName(TEXT("AGameplayAbilityTargetActor_GroundTrace"));
    bool bTraceComplex = false;

    FCollisionQueryParams Params(LineTraceSingleName, bTraceComplex);
    Params.bReturnPhysicalMaterial = true;
    Params.bTraceAsyncScene = true;
    Params.AddIgnoredActor(InSourceActor);

    FVector TraceStart = StartLocation.GetTargetingTransform().GetLocation();// InSourceActor->GetActorLocation();
    FVector TraceEnd;
    AimWithPlayerController(InSourceActor, Params, TraceStart, TraceEnd);		//Effective on server and launching client only

    // ------------------------------------------------------

    FHitResult ReturnHitResult;
    //Use a line trace initially to see where the player is actually pointing
    LineTraceWithFilter(ReturnHitResult, InSourceActor->GetWorld(), Filter, TraceStart, TraceEnd, TraceProfile.Name, Params);
    //Default to end of trace line if we don't hit anything.
    if (!ReturnHitResult.bBlockingHit)
    {
        ReturnHitResult.Location = TraceEnd;
    }

    //Second trace, straight down. Consider using InSourceActor->GetWorld()->NavigationSystem->ProjectPointToNavigation() instead of just going straight down in the case of movement abilities (flag/bool).
    TraceStart = ReturnHitResult.Location - (TraceEnd - TraceStart).GetSafeNormal();		//Pull back very slightly to avoid scraping down walls
    TraceEnd = TraceStart;
    TraceStart.Z += CollisionHeightOffset;
    TraceEnd.Z -= 99999.0f;
    LineTraceWithFilter(ReturnHitResult, InSourceActor->GetWorld(), Filter, TraceStart, TraceEnd, TraceProfile.Name, Params);
    //if (!ReturnHitResult.bBlockingHit) then our endpoint may be off the map. Hopefully this is only possible in debug maps.

    bLastTraceWasGood = true;		//So far, we're good. If we need a ground spot and can't find one, we'll come back.

    //Use collision shape to find a valid ground spot, if appropriate
    if (CollisionShape.ShapeType != ECollisionShape::Line)
    {
        ReturnHitResult.Location.Z += CollisionHeightOffset;		//Rise up out of the ground
        TraceStart = InSourceActor->GetActorLocation();
        TraceEnd = ReturnHitResult.Location;
        TraceStart.Z += CollisionHeightOffset;
        bLastTraceWasGood = AdjustCollisionResultForShape(TraceStart, TraceEnd, Params, ReturnHitResult);
        if (bLastTraceWasGood)
        {
            ReturnHitResult.Location.Z -= CollisionHeightOffset;	//Undo the artificial height adjustment
        }
    }

    if (AGameplayAbilityWorldReticle* LocalReticleActor = ReticleActor.Get())
    {
        LocalReticleActor->SetIsTargetValid(bLastTraceWasGood);
        LocalReticleActor->SetActorLocation(ReturnHitResult.Location);
    }

    // Reset the trace start so the target data uses the correct origin
    ReturnHitResult.TraceStart = StartLocation.GetTargetingTransform().GetLocation();

    return ReturnHitResult;
}
FHitResult AGameplayAbilityTargetActor_SingleLineTrace::PerformTrace(AActor* InSourceActor)
{
	static const FName LineTraceSingleName(TEXT("AGameplayAbilityTargetActor_SingleLineTrace"));
	bool bTraceComplex = false;
	TArray<AActor*> ActorsToIgnore;

	ActorsToIgnore.Add(InSourceActor);

	FCollisionQueryParams Params(LineTraceSingleName, bTraceComplex);
	Params.bReturnPhysicalMaterial = true;
	Params.bTraceAsyncScene = true;
	Params.AddIgnoredActors(ActorsToIgnore);

	FVector TraceStart = StartLocation.GetTargetingTransform().GetLocation();// InSourceActor->GetActorLocation();
	FVector TraceEnd;
	AimWithPlayerController(InSourceActor, Params, TraceStart, TraceEnd);		//Effective on server and launching client only

	// ------------------------------------------------------

	FHitResult ReturnHitResult;
	LineTraceWithFilter(ReturnHitResult, InSourceActor->GetWorld(), Filter, TraceStart, TraceEnd, TraceProfile.Name, Params);
	//Default to end of trace line if we don't hit anything.
	if (!ReturnHitResult.bBlockingHit)
	{
		ReturnHitResult.Location = TraceEnd;
	}
	if (AGameplayAbilityWorldReticle* LocalReticleActor = ReticleActor.Get())
	{
		LocalReticleActor->SetActorLocation(ReturnHitResult.Location);
		LocalReticleActor->SetIsTargetAnActor(ReturnHitResult.bBlockingHit && (ReturnHitResult.Actor != NULL));
	}

	if (bDebug)
	{
		DrawDebugLine(GetWorld(), TraceStart, TraceEnd, FColor::Green);
		DrawDebugSphere(GetWorld(), TraceEnd, 100.0f, 16, FColor::Green);
	}
	return ReturnHitResult;
}