Skip to content

Commit

Permalink
Add option to enable / disable sticky feeling behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
mklabs committed Jun 18, 2020
1 parent c10cd36 commit dc158b5
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 47 deletions.
99 changes: 60 additions & 39 deletions TargetSystem/Source/TargetSystem/Private/TargetSystemComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2018-2019 Mickael Daniel. All Rights Reserved.

#include "TargetSystemComponent.h"
#include "TargetSystemLockOnWidget.h"
#include "TargetSystemTargetableInterface.h"
#include "Engine/World.h"
#include "Engine/Public/TimerManager.h"
Expand All @@ -24,13 +23,14 @@ UTargetSystemComponent::UTargetSystemComponent()
bIsBreakingLineOfSight = false;
bShouldControlRotation = true;
StartRotatingThreshold = 1.5f;
// StartRotatingThreshold = 0.3f;
StartRotatingStack = 0.0f;
bIsSwitchingTarget = false;
bShouldDrawLockedOnWidget = true;
LockedOnWidgetParentSocket = FName("spine_03");
bAdjustPitchBasedOnDistanceToTarget = true;
bDesireToSwitch = false;
AxisMultiplier = 1.0f;
StickyRotationThreshold = 30.0f;

LockedOnWidgetClass = StaticLoadClass(UObject::StaticClass(), nullptr, TEXT("/TargetSystem/UI/WBP_LockOn.WBP_LockOn_C"));

Expand Down Expand Up @@ -112,45 +112,21 @@ void UTargetSystemComponent::TargetActor()
}
}

void UTargetSystemComponent::TargetActorWithAxisInput(const float AxisValue, const float Delta)
void UTargetSystemComponent::TargetActorWithAxisInput(const float AxisValue)
{
StartRotatingStack += (AxisValue != 0) ? AxisValue * Delta : (StartRotatingStack > 0 ? -Delta : Delta);

if (AxisValue == 0 && FMath::Abs(StartRotatingStack) <= Delta)
{
StartRotatingStack = 0.0f;
}

// If Axis value does not exceeds configured threshold, do nothing
if (FMath::Abs(StartRotatingStack) < StartRotatingThreshold)
// If we're not locked on, do nothing
if (!bTargetLocked)
{
bDesireToSwitch = false;
return;
}
else
{
//Sticky when switching target.
if (StartRotatingStack * AxisValue > 0)
{
StartRotatingStack = StartRotatingStack > 0 ? StartRotatingThreshold : -StartRotatingThreshold;
}
else if (StartRotatingStack * AxisValue < 0)
{
StartRotatingStack = StartRotatingStack * -1.0f;

}

bDesireToSwitch = true;
}


// If we're not locked on, do nothing
if (!bTargetLocked)
if (!LockedOnTargetActor)
{
return;
}

if (!LockedOnTargetActor)
// If we're not allowed to switch target, do nothing
if (!ShouldSwitchTargetActor(AxisValue))
{
return;
}
Expand Down Expand Up @@ -304,6 +280,52 @@ void UTargetSystemComponent::ResetIsSwitchingTarget()
bDesireToSwitch = false;
}

bool UTargetSystemComponent::ShouldSwitchTargetActor(const float AxisValue)
{
if (AxisValue != 0)
{
UE_LOG(LogTemp, Log, TEXT("TargetSystem: ShouldSwitchTargetActor() AxisValue: %f, Stack: %f, Threshold: %f || %f"), AxisValue, StartRotatingStack, StartRotatingThreshold, StickyRotationThreshold);
}

// Sticky feeling computation
if (bEnableStickyTarget)
{
StartRotatingStack += (AxisValue != 0) ? AxisValue * AxisMultiplier : (StartRotatingStack > 0 ? -AxisMultiplier : AxisMultiplier);

if (AxisValue == 0 && FMath::Abs(StartRotatingStack) <= AxisMultiplier)
{

StartRotatingStack = 0.0f;
}

// If Axis value does not exceeds configured threshold, do nothing
if (FMath::Abs(StartRotatingStack) < StickyRotationThreshold)
{
bDesireToSwitch = false;
return false;
}

UE_LOG(LogTemp, Log, TEXT("TargetSystem: StartRotatingStack value exceeds -> StartRotatingStack: %f"), StartRotatingStack);
//Sticky when switching target.
if (StartRotatingStack * AxisValue > 0)
{
StartRotatingStack = StartRotatingStack > 0 ? StickyRotationThreshold : -StickyRotationThreshold;
}
else if (StartRotatingStack * AxisValue < 0)
{
StartRotatingStack = StartRotatingStack * -1.0f;

}

bDesireToSwitch = true;

return true;
}

// Non Sticky feeling, check Axis value exceeds threshold
return FMath::Abs(AxisValue) > StartRotatingThreshold;
}

void UTargetSystemComponent::TargetLockOn(AActor* TargetToLockOn)
{
if (TargetToLockOn)
Expand Down Expand Up @@ -356,16 +378,15 @@ void UTargetSystemComponent::TargetLockOff()

void UTargetSystemComponent::CreateAndAttachTargetLockedOnWidgetComponent(AActor* TargetActor)
{
TargetLockedOnWidgetComponent = NewObject<UWidgetComponent>(TargetActor, FName("TargetLockOn"));
if (LockedOnWidgetClass)
{
TargetLockedOnWidgetComponent->SetWidgetClass(LockedOnWidgetClass);
}
else
if (!LockedOnWidgetClass)
{
TargetLockedOnWidgetComponent->SetWidgetClass(UTargetSystemLockOnWidget::StaticClass());
UE_LOG(LogTemp, Error, TEXT("TargetSystemComponent: Cannot get LockedOnWidgetClass, please ensure it is a valid reference in the Component Properties."));
return;
}

TargetLockedOnWidgetComponent = NewObject<UWidgetComponent>(TargetActor, FName("TargetLockOn"));
TargetLockedOnWidgetComponent->SetWidgetClass(LockedOnWidgetClass);

UMeshComponent* MeshComponent = TargetActor->FindComponentByClass<UMeshComponent>();
USceneComponent* ParentComponent = MeshComponent && LockedOnWidgetParentSocket != NAME_None ? MeshComponent : TargetActor->GetRootComponent();

Expand Down
54 changes: 46 additions & 8 deletions TargetSystem/Source/TargetSystem/Public/TargetSystemComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
float BreakLineOfSightDelay;

// Lower this value is, easier it will be to switch new target on right or left.
//
// When using Sticky Feeling feature, it has no effect (see StickyRotationThreshold)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target System")
float StartRotatingThreshold;

Expand Down Expand Up @@ -99,6 +101,24 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target System|Pitch Offset")
float PitchMax = -20.0f;

// Set it to true / false whether you want a sticky feeling when switching target
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target System|Sticky Feeling on Target Switch")
bool bEnableStickyTarget;

// This value gets multiplied to the AxisValue to check against StickyRotationThreshold.
//
// Only used when Sticky Target is enabled.
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target System|Sticky Feeling on Target Switch")
float AxisMultiplier;

// Lower this value is, easier it will be to switch new target on right or left.
//
// This is similar to StartRotatingThreshold, but you should set this to a much higher value.
//
// Only used when Sticky Target is enabled.
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Target System|Sticky Feeling on Target Switch")
float StickyRotationThreshold;

// Function to call to target a new actor.
UFUNCTION(BlueprintCallable, Category = "Target System")
void TargetActor();
Expand All @@ -114,7 +134,7 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
* @param Delta This value and AxisValue are multiplied before being checked against StartRotatingThreshold
*/
UFUNCTION(BlueprintCallable, Category = "Target System")
void TargetActorWithAxisInput(float AxisValue, float Delta = 1.0f);
void TargetActorWithAxisInput(float AxisValue);

// Called when a target is locked off, either if it is out of reach (based on MinimumDistanceToEnable) or behind an Object.
UPROPERTY(BlueprintAssignable, Category = "Target System")
Expand Down Expand Up @@ -164,26 +184,44 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
bool bDesireToSwitch;
float StartRotatingStack;

/** Actors search / trace */

TArray<AActor*> GetAllActorsOfClass(TSubclassOf<AActor> ActorClass) const;
TArray<AActor*> FindTargetsInRange(TArray<AActor*> ActorsToLook, float RangeMin, float RangeMax) const;

AActor* FindNearestTarget(TArray<AActor*> Actors) const;

bool LineTrace(FHitResult& HitResult, AActor* OtherActor, TArray<AActor*> ActorsToIgnore = TArray<AActor*>()) const;
bool LineTraceForActor(AActor* OtherActor, TArray<AActor*> ActorsToIgnore = TArray<AActor*>()) const;
FRotator GetControlRotationOnTarget(AActor* OtherActor) const;
void SetControlRotationOnTarget(AActor* TargetActor) const;
void CreateAndAttachTargetLockedOnWidgetComponent(AActor* TargetActor);

bool ShouldBreakLineOfSight() const;
void BreakLineOfSight();
void ControlRotation(bool ShouldControlRotation) const;
bool IsInViewport(AActor* TargetActor) const;

void TargetLockOn(AActor* TargetToLockOn);
bool IsInViewport(AActor* TargetActor) const;

float GetDistanceFromCharacter(AActor* OtherActor) const;
TArray<AActor*> FindTargetsInRange(TArray<AActor*> ActorsToLook, float RangeMin, float RangeMax) const;


/** Actor rotation */

FRotator GetControlRotationOnTarget(AActor* OtherActor) const;
void SetControlRotationOnTarget(AActor* TargetActor) const;
void ControlRotation(bool ShouldControlRotation) const;

float GetAngleUsingCameraRotation(AActor* ActorToLook) const;
float GetAngleUsingCharacterRotation(AActor* ActorToLook) const;

static FRotator FindLookAtRotation(const FVector Start, const FVector Target);

/** Widget */

void CreateAndAttachTargetLockedOnWidgetComponent(AActor* TargetActor);

/** Targeting */

void TargetLockOn(AActor* TargetToLockOn);
void ResetIsSwitchingTarget();
bool ShouldSwitchTargetActor(float AxisValue);

static bool TargetIsTargetable(AActor* Actor);

Expand Down

0 comments on commit dc158b5

Please sign in to comment.