mirror of
https://github.com/Ed94/Cog.git
synced 2026-06-27 06:01:48 -07:00
Add target acquisition in the sample
This commit is contained in:
@@ -5,3 +5,13 @@
|
||||
#ifndef USE_COG
|
||||
#define USE_COG (ENABLE_DRAW_DEBUG && !NO_LOGGING)
|
||||
#endif
|
||||
|
||||
#if !USE_COG
|
||||
|
||||
#define COG(expr) (0)
|
||||
|
||||
#else //!ENABLE_COG
|
||||
|
||||
#define COG(expr) { expr; }
|
||||
|
||||
#endif //!ENABLE_COG
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "CogSampleAttributeSet_Health.h"
|
||||
#include "CogSampleAttributeSet_Misc.h"
|
||||
#include "CogSampleCharacterMovementComponent.h"
|
||||
#include "CogSampleFunctionLibrary_Team.h"
|
||||
#include "CogSampleGameplayAbility.h"
|
||||
#include "CogSampleLogCategories.h"
|
||||
#include "CogSampleRootMotionParams.h"
|
||||
@@ -77,7 +78,7 @@ void ACogSampleCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >
|
||||
Params.Condition = COND_OwnerOnly;
|
||||
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ACogSampleCharacter, ActiveAbilityHandles, Params);
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ACogSampleCharacter, TeamID, Params);
|
||||
DOREPLIFETIME_WITH_PARAMS_FAST(ACogSampleCharacter, Team, Params);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -116,18 +117,16 @@ UAbilitySystemComponent* ACogSampleCharacter::GetAbilitySystemComponent() const
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ECogInterfacesAllegiance ACogSampleCharacter::GetAllegianceWithOtherActor(const AActor* OtherActor) const
|
||||
{
|
||||
const ACogSampleCharacter* OtherCharacter = Cast<ACogSampleCharacter>(OtherActor);
|
||||
if (OtherCharacter == nullptr)
|
||||
{
|
||||
return ECogInterfacesAllegiance::Neutral;
|
||||
}
|
||||
ECogSampleAllegiance Allegiance = UCogSampleFunctionLibrary_Team::GetActorsAllegiance(this, OtherActor);
|
||||
|
||||
if (TeamID == OtherCharacter->TeamID)
|
||||
switch (Allegiance)
|
||||
{
|
||||
return ECogInterfacesAllegiance::Friendly;
|
||||
case ECogSampleAllegiance::Enemy: return ECogInterfacesAllegiance::Enemy;
|
||||
case ECogSampleAllegiance::Friendly: return ECogInterfacesAllegiance::Friendly;
|
||||
case ECogSampleAllegiance::Neutral: return ECogInterfacesAllegiance::Neutral;
|
||||
}
|
||||
|
||||
return ECogInterfacesAllegiance::Enemy;
|
||||
|
||||
return ECogInterfacesAllegiance::Neutral;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -507,8 +506,8 @@ void ACogSampleCharacter::OnScaleAttributeChanged(const FOnAttributeChangeData&
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleCharacter::SetTeamID(int32 Value)
|
||||
{
|
||||
TeamID = Value;
|
||||
MARK_PROPERTY_DIRTY_FROM_NAME(ACogSampleCharacter, TeamID, this);
|
||||
Team = Value;
|
||||
MARK_PROPERTY_DIRTY_FROM_NAME(ACogSampleCharacter, Team, this);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -608,4 +607,16 @@ void ACogSampleCharacter::UpdateActiveAbilitySlots()
|
||||
FGameplayTag SlotTag = FCogSampleTagLibrary::ActiveAbilityCooldownTags[i];
|
||||
AbilityInstance->SetSlotTag(SlotTag);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector ACogSampleCharacter::GetTargetLocation() const
|
||||
{
|
||||
return GetActorLocation();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSampleCharacter::GetTargetCapsules(TArray<const UCapsuleComponent*>& Capsules) const
|
||||
{
|
||||
Capsules.Add(GetCapsuleComponent());
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "CogDefines.h"
|
||||
#include "CogInterfaceAllegianceActor.h"
|
||||
#include "CogInterfaceDebugFilteredActor.h"
|
||||
#include "CogSampleTargetableInterface.h"
|
||||
#include "CogSampleTeamInterface.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "GameplayAbilitySpecHandle.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
@@ -26,17 +28,6 @@ struct FCogSampleRootMotionParams;
|
||||
struct FGameplayEffectSpec;
|
||||
struct FOnAttributeChangeData;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
|
||||
enum class ECogSampleAllegianceFilter : uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
Ally = 1 << 0,
|
||||
Neutral = 1 << 1,
|
||||
Enemy = 1 << 2,
|
||||
};
|
||||
ENUM_CLASS_FLAGS(ECogSampleAllegianceFilter);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
USTRUCT(BlueprintType)
|
||||
struct FActiveAbilityInfo
|
||||
@@ -72,6 +63,8 @@ class ACogSampleCharacter : public ACharacter
|
||||
, public IAbilitySystemInterface
|
||||
, public ICogInterfacesDebugFilteredActor
|
||||
, public ICogInterfacesAllegianceActor
|
||||
, public ICogSampleTeamInterface
|
||||
, public ICogSampleTargetableInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
@@ -102,6 +95,13 @@ public:
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
ECogInterfacesAllegiance GetAllegianceWithOtherActor(const AActor* OtherActor) const override;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// ICogSampleTargetInterface overrides
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
virtual FVector GetTargetLocation() const override;
|
||||
|
||||
virtual void GetTargetCapsules(TArray<const UCapsuleComponent*>& Capsules) const override;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void OnAcknowledgePossession(APlayerController* InController);
|
||||
|
||||
@@ -181,13 +181,13 @@ public:
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
int32 GetTeamID() const { return TeamID; }
|
||||
virtual int32 GetTeam() const override { return Team; }
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void SetTeamID(int32 Value);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Team, Replicated, meta = (AllowPrivateAccess = "true"))
|
||||
int32 TeamID = 0;
|
||||
int32 Team = 0;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Root Motion
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "AbilitySystemGlobals.h"
|
||||
#include "CogSampleGameplayEffectContext.h"
|
||||
#include "CogSampleTargetableInterface.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "GameplayCueNotifyTypes.h"
|
||||
#include "GameplayEffectTypes.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "Particles/ParticleSystemComponent.h"
|
||||
#include "ScalableFloat.h"
|
||||
|
||||
@@ -108,3 +110,144 @@ int32 UCogSampleFunctionLibrary_Gameplay::GetIntValue(const FScalableFloat& Scal
|
||||
return (int32)ScalableFloat.GetValueAtLevel(Level);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FCollisionObjectQueryParams UCogSampleFunctionLibrary_Gameplay::ConfigureCollisionObjectParams(const TArray<TEnumAsByte<EObjectTypeQuery>>& ObjectTypes)
|
||||
{
|
||||
TArray<TEnumAsByte<ECollisionChannel>> CollisionObjectTraces;
|
||||
CollisionObjectTraces.AddUninitialized(ObjectTypes.Num());
|
||||
|
||||
for (auto Iter = ObjectTypes.CreateConstIterator(); Iter; ++Iter)
|
||||
{
|
||||
CollisionObjectTraces[Iter.GetIndex()] = UEngineTypes::ConvertToCollisionChannel(*Iter);
|
||||
}
|
||||
|
||||
FCollisionObjectQueryParams ObjectParams;
|
||||
for (auto Iter = CollisionObjectTraces.CreateConstIterator(); Iter; ++Iter)
|
||||
{
|
||||
const ECollisionChannel& Channel = (*Iter);
|
||||
if (FCollisionObjectQueryParams::IsValidObjectQuery(Channel))
|
||||
{
|
||||
ObjectParams.AddObjectTypesToQuery(Channel);
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectParams;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector UCogSampleFunctionLibrary_Gameplay::GetActorTargetLocation(const AActor* Actor)
|
||||
{
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
return FVector::ZeroVector;
|
||||
}
|
||||
|
||||
if (const ICogSampleTargetableInterface* Targetable = Cast<ICogSampleTargetableInterface>(Actor))
|
||||
{
|
||||
return Targetable->GetTargetLocation();
|
||||
}
|
||||
|
||||
return Actor->GetActorLocation();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float UCogSampleFunctionLibrary_Gameplay::AngleBetweenVector2D(FVector2D A, FVector2D B)
|
||||
{
|
||||
A.Normalize();
|
||||
B.Normalize();
|
||||
return FMath::RadiansToDegrees(FMath::Acos(FVector2D::DotProduct(A, B)));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogSampleFunctionLibrary_Gameplay::FindSegmentPointDistance(const FVector2D& Segment1, const FVector2D& Segment2, const FVector2D& Point, FVector2D& Projection, float& Time, float& Distance)
|
||||
{
|
||||
const float DistSquared = FVector2D::DistSquared(Segment1, Segment2);
|
||||
if (FMath::IsNearlyZero(DistSquared))
|
||||
{
|
||||
Time = 0.0f;
|
||||
Projection = Segment1;
|
||||
Distance = FVector2D::Distance(Point, Segment1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Time = FMath::Max(0.0f, FMath::Min(1.0f, FVector2D::DotProduct(Point - Segment1, Segment2 - Segment1) / DistSquared));
|
||||
Projection = Segment1 + Time * (Segment2 - Segment1);
|
||||
Distance = FVector2D::Distance(Point, Projection);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogSampleFunctionLibrary_Gameplay::FindCapsulePointDistance(const FVector2D& CapsulePoint1, const FVector2D& CapsulePoint2, const float CapsuleRadius, const FVector2D& Point, FVector2D& Projection, float& Time, float& Distance)
|
||||
{
|
||||
FindSegmentPointDistance(CapsulePoint1, CapsulePoint2, Point, Projection, Time, Distance);
|
||||
|
||||
float projectionToPointDistance = Distance;
|
||||
Distance -= CapsuleRadius;
|
||||
|
||||
if (Distance > 0.0f)
|
||||
{
|
||||
Projection = Point + ((Projection - Point) / projectionToPointDistance) * Distance;
|
||||
}
|
||||
else
|
||||
{
|
||||
Projection = Point;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D UCogSampleFunctionLibrary_Gameplay::ViewportToScreen(const FVector2D& value, const FVector2D& displaySize)
|
||||
{
|
||||
FVector2D result;
|
||||
|
||||
if (displaySize.X > displaySize.Y)
|
||||
{
|
||||
const float screenXStart = (displaySize.X - displaySize.Y) * 0.5f;
|
||||
const float screenXEnd = displaySize.X - screenXStart;
|
||||
result.X = UKismetMathLibrary::MapRangeUnclamped(value.X, -1.0f, 1.0f, screenXStart, screenXEnd);
|
||||
result.Y = UKismetMathLibrary::MapRangeUnclamped(value.Y, -1.0f, 1.0f, displaySize.Y, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float ScreenYStart = (displaySize.Y - displaySize.X) * 0.5f;
|
||||
const float ScreenYEnd = displaySize.Y - ScreenYStart;
|
||||
result.X = UKismetMathLibrary::MapRangeUnclamped(value.X, -1.0f, 1.0f, 0.0f, displaySize.X);
|
||||
result.Y = UKismetMathLibrary::MapRangeUnclamped(value.Y, -1.0f, 1.0f, ScreenYEnd, ScreenYStart);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float UCogSampleFunctionLibrary_Gameplay::ViewportToScreen(const float Value, const FVector2D& DisplaySize)
|
||||
{
|
||||
return Value * 0.5f * FMath::Min(DisplaySize.X, DisplaySize.Y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D UCogSampleFunctionLibrary_Gameplay::ScreenToViewport(const FVector2D& Value, const FVector2D& DisplaySize)
|
||||
{
|
||||
FVector2D Result;
|
||||
|
||||
if (DisplaySize.X > DisplaySize.Y)
|
||||
{
|
||||
const float screenXStart = (DisplaySize.X - DisplaySize.Y) * 0.5f;
|
||||
const float screenXEnd = DisplaySize.X - screenXStart;
|
||||
Result.X = UKismetMathLibrary::MapRangeUnclamped(Value.X, screenXStart, screenXEnd, -1.0f, 1.0f);
|
||||
Result.Y = UKismetMathLibrary::MapRangeUnclamped(Value.Y, 0.0f, DisplaySize.Y, -1.0f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float screenYStart = (DisplaySize.Y - DisplaySize.X) * 0.5f;
|
||||
const float screenYEnd = DisplaySize.Y - screenYStart;
|
||||
Result.X = UKismetMathLibrary::MapRangeUnclamped(Value.X, 0.0f, DisplaySize.X, -1.0f, 1.0f);
|
||||
Result.Y = UKismetMathLibrary::MapRangeUnclamped(Value.Y, screenYStart, screenYEnd, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
float UCogSampleFunctionLibrary_Gameplay::ScreenToViewport(const float Value, const FVector2D& DisplaySize)
|
||||
{
|
||||
return Value * 2.0f / FMath::Min(DisplaySize.X, DisplaySize.Y);
|
||||
}
|
||||
@@ -11,12 +11,14 @@ struct FGameplayAttributeData;
|
||||
struct FGameplayCueNotify_SpawnResult;
|
||||
struct FGameplayCueParameters;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
|
||||
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
|
||||
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
|
||||
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
|
||||
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(meta = (ScriptName = "CogSampleFunctionLibrary_Gameplay"))
|
||||
class UCogSampleFunctionLibrary_Gameplay : public UBlueprintFunctionLibrary
|
||||
{
|
||||
@@ -24,8 +26,6 @@ class UCogSampleFunctionLibrary_Gameplay : public UBlueprintFunctionLibrary
|
||||
|
||||
public:
|
||||
|
||||
static void AdjustAttributeForMaxChange(UAbilitySystemComponent* AbilityComponent, FGameplayAttributeData& AffectedAttribute, float OldValue, float NewMaxValue, const FGameplayAttribute& AffectedAttributeProperty);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static FVector GetActorBottomLocation(const AActor* Actor);
|
||||
|
||||
@@ -49,4 +49,28 @@ public:
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static int32 GetIntValue(const FScalableFloat& ScalableFloat, int32 Level);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static FVector GetActorTargetLocation(const AActor* Actor);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static float AngleBetweenVector2D(FVector2D A, FVector2D B);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static void FindSegmentPointDistance(const FVector2D& Segment1, const FVector2D& Segment2, const FVector2D& Point, FVector2D& Projection, float& Time, float& Distance);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static void FindCapsulePointDistance(const FVector2D& CapsulePoint1, const FVector2D& CapsulePoint2, const float CapsuleRadius, const FVector2D& Point, FVector2D& Projection, float& Time, float& Distance);
|
||||
|
||||
static void AdjustAttributeForMaxChange(UAbilitySystemComponent* AbilityComponent, FGameplayAttributeData& AffectedAttribute, float OldValue, float NewMaxValue, const FGameplayAttribute& AffectedAttributeProperty);
|
||||
|
||||
static FCollisionObjectQueryParams ConfigureCollisionObjectParams(const TArray<TEnumAsByte<EObjectTypeQuery>>& ObjectTypes);
|
||||
|
||||
static FVector2D ViewportToScreen(const FVector2D& value, const FVector2D& displaySize);
|
||||
|
||||
static float ViewportToScreen(const float value, const FVector2D& displaySize);
|
||||
|
||||
static FVector2D ScreenToViewport(const FVector2D& value, const FVector2D& displaySize);
|
||||
|
||||
static float ScreenToViewport(const float value, const FVector2D& displaySize);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "CogSampleFunctionLibrary_Team.h"
|
||||
|
||||
#include "CogSampleTeamInterface.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ECogSampleAllegiance UCogSampleFunctionLibrary_Team::GetTeamsAllegiance(int32 Team1, int32 Team2)
|
||||
{
|
||||
if (Team1 == 0 || Team2 == 0)
|
||||
{
|
||||
return ECogSampleAllegiance::Neutral;
|
||||
}
|
||||
|
||||
if (Team1 == Team2)
|
||||
{
|
||||
return ECogSampleAllegiance::Friendly;
|
||||
}
|
||||
|
||||
return ECogSampleAllegiance::Enemy;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
ECogSampleAllegiance UCogSampleFunctionLibrary_Team::GetActorsAllegiance(const AActor* Actor1, const AActor* Actor2)
|
||||
{
|
||||
const ICogSampleTeamInterface* TeamActor1 = Cast<ICogSampleTeamInterface>(Actor1);
|
||||
const ICogSampleTeamInterface* TeamActor2 = Cast<ICogSampleTeamInterface>(Actor2);
|
||||
|
||||
if (TeamActor1 == nullptr || TeamActor2 == nullptr)
|
||||
{
|
||||
return ECogSampleAllegiance::Neutral;
|
||||
}
|
||||
|
||||
const int32 Team1 = TeamActor1->GetTeam();
|
||||
const int32 Team2 = TeamActor2->GetTeam();
|
||||
const ECogSampleAllegiance Allegiance = GetTeamsAllegiance(Team1, Team2);
|
||||
|
||||
return Allegiance;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleFunctionLibrary_Team::MatchAllegiance(const AActor* Actor1, const AActor* Actor2, int32 AllegianceFilter)
|
||||
{
|
||||
const ECogSampleAllegiance Allegiance = GetActorsAllegiance(Actor1, Actor2);
|
||||
const bool Result = MatchAllegianceFilter(Allegiance, AllegianceFilter);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleFunctionLibrary_Team::MatchAllegianceFilter(ECogSampleAllegiance Allegiance, int32 AllegianceFilter)
|
||||
{
|
||||
const bool HasFriendly = (AllegianceFilter & (int)ECogSampleAllegianceFilter::Friendly) != 0;
|
||||
const bool HasNeutral = (AllegianceFilter & (int)ECogSampleAllegianceFilter::Neutral) != 0;
|
||||
const bool HasEnemy = (AllegianceFilter & (int)ECogSampleAllegianceFilter::Enemy) != 0;
|
||||
|
||||
if (Allegiance == ECogSampleAllegiance::Friendly && HasFriendly)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Allegiance == ECogSampleAllegiance::Neutral && HasNeutral)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Allegiance == ECogSampleAllegiance::Enemy && HasEnemy)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogSampleFunctionLibrary_Team.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleAllegiance : uint8
|
||||
{
|
||||
Friendly,
|
||||
Neutral,
|
||||
Enemy,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
|
||||
enum class ECogSampleAllegianceFilter : uint8
|
||||
{
|
||||
None = 0 UMETA(Hidden),
|
||||
Friendly = 1 << 0,
|
||||
Neutral = 1 << 1,
|
||||
Enemy = 1 << 2,
|
||||
};
|
||||
ENUM_CLASS_FLAGS(ECogSampleAllegianceFilter);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS(meta = (ScriptName = "CogSampleFunctionLibrary_Team"))
|
||||
class UCogSampleFunctionLibrary_Team : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static ECogSampleAllegiance GetTeamsAllegiance(int32 Team1, int32 Team2);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static ECogSampleAllegiance GetActorsAllegiance(const AActor* Actor1, const AActor* Actor2);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static bool MatchAllegiance(const AActor* Actor1, const AActor* Actor2, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
UFUNCTION(BlueprintPure)
|
||||
static bool MatchAllegianceFilter(ECogSampleAllegiance Allegiance, UPARAM(meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter")) int32 AllegianceFilter);
|
||||
|
||||
};
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "CogAbilityWindow_Tags.h"
|
||||
#include "CogAbilityWindow_Tweaks.h"
|
||||
#include "CogDebugDefines.h"
|
||||
#include "CogDebugDrawImGui.h"
|
||||
#include "CogDebugPlot.h"
|
||||
#include "CogEngineDataAsset_Collisions.h"
|
||||
#include "CogEngineDataAsset_Spawns.h"
|
||||
@@ -220,6 +221,7 @@ void ACogSampleGameState::InitializeCog()
|
||||
void ACogSampleGameState::RenderCog(float DeltaTime)
|
||||
{
|
||||
CogWindowManager->Render(DeltaTime);
|
||||
FCogDebugDrawImGui::Draw();
|
||||
}
|
||||
|
||||
#endif //USE_COG
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "CogDefines.h"
|
||||
|
||||
#if USE_COG
|
||||
#include "CogDebugLogCategoryManager.h"
|
||||
#include "CogDebugLog.h"
|
||||
#endif //USE_COG
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogCogAlways);
|
||||
@@ -15,22 +15,24 @@ DEFINE_LOG_CATEGORY(LogCogRotation);
|
||||
DEFINE_LOG_CATEGORY(LogCogControlRotation);
|
||||
DEFINE_LOG_CATEGORY(LogCogBaseAimRotation);
|
||||
DEFINE_LOG_CATEGORY(LogCogSkeleton);
|
||||
DEFINE_LOG_CATEGORY(LogCogTargetAcquisition);
|
||||
|
||||
namespace CogSampleLog
|
||||
{
|
||||
void RegiterAllLogCategories()
|
||||
{
|
||||
#if USE_COG
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogAlways, "Always", false);
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogAbilitySystem, "Ability System");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogGameplayEffects, "Gameplay Effects");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogCollision, "Collision");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogInput, "Input");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogPosition, "Position");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogRotation, "Rotation");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogControlRotation, "ControlRotation");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogBaseAimRotation, "BaseAimRotation");
|
||||
FCogDebugLogCategoryManager::AddLogCategory(LogCogSkeleton, "Skeleton");
|
||||
FCogDebugLog::AddLogCategory(LogCogAlways, "Always", false);
|
||||
FCogDebugLog::AddLogCategory(LogAbilitySystem, "Ability System");
|
||||
FCogDebugLog::AddLogCategory(LogGameplayEffects, "Gameplay Effects");
|
||||
FCogDebugLog::AddLogCategory(LogCogCollision, "Collision");
|
||||
FCogDebugLog::AddLogCategory(LogCogInput, "Input");
|
||||
FCogDebugLog::AddLogCategory(LogCogPosition, "Position");
|
||||
FCogDebugLog::AddLogCategory(LogCogRotation, "Rotation");
|
||||
FCogDebugLog::AddLogCategory(LogCogControlRotation, "ControlRotation");
|
||||
FCogDebugLog::AddLogCategory(LogCogBaseAimRotation, "BaseAimRotation");
|
||||
FCogDebugLog::AddLogCategory(LogCogSkeleton, "Skeleton");
|
||||
FCogDebugLog::AddLogCategory(LogCogTargetAcquisition, "Target Acquisition");
|
||||
#endif //USE_COG
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ DECLARE_LOG_CATEGORY_EXTERN(LogCogRotation, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogControlRotation, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogBaseAimRotation, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogSkeleton, Warning, All);
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogCogTargetAcquisition, Warning, All);
|
||||
|
||||
namespace CogSampleLog
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "CogDefines.h"
|
||||
#include "CogSampleCharacter.h"
|
||||
#include "CogSampleTargetAcquisition.h"
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
#if USE_COG
|
||||
@@ -38,4 +39,18 @@ void ACogSamplePlayerController::AcknowledgePossession(APawn* P)
|
||||
{
|
||||
PossessedCharacter->OnAcknowledgePossession(this);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void ACogSamplePlayerController::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
if (TargetAcquisition != nullptr)
|
||||
{
|
||||
TArray<AActor*> TagretToIgnore;
|
||||
FCogSampleTargetAcquisitionResult Result;
|
||||
TargetAcquisition->FindBestTarget(this, TagretToIgnore, nullptr, true, FVector2D::ZeroVector, false, Result);
|
||||
Target = Result.Target;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "CogSamplePlayerController.generated.h"
|
||||
|
||||
class UCogSampleTargetAcquisition;
|
||||
|
||||
UCLASS(config=Game)
|
||||
class ACogSamplePlayerController : public APlayerController
|
||||
{
|
||||
@@ -13,11 +15,19 @@ class ACogSamplePlayerController : public APlayerController
|
||||
public:
|
||||
|
||||
ACogSamplePlayerController();
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
virtual void AcknowledgePossession(APawn* P);
|
||||
|
||||
virtual void Tick(float DeltaSeconds);
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = TargetAcquisition, meta = (AllowPrivateAccess = "true"))
|
||||
UCogSampleTargetAcquisition* TargetAcquisition = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = TargetAcquisition, meta = (AllowPrivateAccess = "true"))
|
||||
TSoftObjectPtr<AActor> Target = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,886 @@
|
||||
#include "CogSampleTargetAcquisition.h"
|
||||
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "CogDefines.h"
|
||||
#include "CogSampleCharacter.h"
|
||||
#include "CogSampleFunctionLibrary_Gameplay.h"
|
||||
#include "CogSampleLogCategories.h"
|
||||
#include "CogSampleTargetableInterface.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
|
||||
#if USE_COG
|
||||
#include "CogDebugDraw.h"
|
||||
#include "CogDebugLog.h"
|
||||
#endif //USE_COG
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// UCogSampleTargetAcquisition_Generic
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct FCogSampleTargetCandidateEvaluationParameters
|
||||
{
|
||||
const AActor* Source;
|
||||
FVector SourceLocation;
|
||||
const APlayerController* Controller;
|
||||
TArray<AActor*> TargetsToIgnore;
|
||||
bool bWorldDistanceIgnoreZ = false;
|
||||
float MaxWorldDistance = 0.0f;
|
||||
FVector2D CrosshairPosition = FVector2D::ZeroVector;
|
||||
FVector YawDirection = FVector::ZeroVector;
|
||||
FVector CameraRight = FVector::ZeroVector;
|
||||
FMatrix ViewProjectionMatrix;
|
||||
FIntRect ViewRect;
|
||||
FCollisionObjectQueryParams BlockersParams;
|
||||
bool bUseSearchDirection = false;
|
||||
FVector2D SearchDirectionScreenOrigin = FVector2D::ZeroVector;
|
||||
FVector2D SearchDirectionNormalized = FVector2D::ZeroVector;
|
||||
bool IsDebugPersistent = false;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct FCogSampleTargetCandidateEvaluationResult
|
||||
{
|
||||
AActor* BestTarget;
|
||||
float MinScore;
|
||||
bool bFoundLocationInsideShape;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// UCogSampleTargetAcquisition_Generic
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogSampleTargetAcquisition::FindBestTargets(
|
||||
const APlayerController* Controller,
|
||||
const int32 TargetCount,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const AActor* CurrentLockedTarget,
|
||||
const bool bForceSynchronousDetection,
|
||||
const FVector2D ScreenSearchDirection,
|
||||
bool bIsDebugPersistent,
|
||||
TArray<FCogSampleTargetAcquisitionResult>& Results) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::FindBestTargets);
|
||||
|
||||
COG(FCogDebugDraw::String2D(LogCogTargetAcquisition, Controller, GetName(), FVector2D(20, 20), FColor::White, bIsDebugPersistent));
|
||||
|
||||
TArray<AActor*> TempTargetsToIgnore(TargetsToIgnore);
|
||||
|
||||
//---------------------------------------
|
||||
// Find multiple target
|
||||
//---------------------------------------
|
||||
for (int32 i = 0; i < TargetCount; i++)
|
||||
{
|
||||
FCogSampleTargetAcquisitionResult Result;
|
||||
FindBestTarget(
|
||||
Controller,
|
||||
TempTargetsToIgnore,
|
||||
CurrentLockedTarget,
|
||||
bForceSynchronousDetection,
|
||||
ScreenSearchDirection,
|
||||
bIsDebugPersistent,
|
||||
Result);
|
||||
|
||||
//---------------------------------------
|
||||
// Stop when out of valid targets
|
||||
//---------------------------------------
|
||||
if (Result.Target == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Results.Add(Result);
|
||||
TempTargetsToIgnore.Add(Result.Target);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogSampleTargetAcquisition::FindBestTarget(
|
||||
const APlayerController* Controller,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const AActor* CurrentLockedTarget,
|
||||
const bool bForceSynchronousDetection,
|
||||
const FVector2D TargetSwitchSearchDirection,
|
||||
const bool bIsDebugPersistent,
|
||||
FCogSampleTargetAcquisitionResult& Result) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::FindBestTarget);
|
||||
|
||||
ACogSampleCharacter* Character = Cast<ACogSampleCharacter>(Controller->GetPawn());
|
||||
if (Character == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FMath::IsNearlyZero(DetectionLength) && FMath::IsNearlyZero(DetectionRadius))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FMatrix ViewProjectionMatrix;
|
||||
FIntRect ViewRect;
|
||||
if (GetViewInfo(Controller, ViewProjectionMatrix, ViewRect) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FVector2D SearchDirectionScreenOrigin(ViewRect.Width() / 2.0f, ViewRect.Height() / 2.0f);
|
||||
if (CurrentLockedTarget != nullptr)
|
||||
{
|
||||
FVector CurrentLockedTargetLocation = UCogSampleFunctionLibrary_Gameplay::GetActorTargetLocation(CurrentLockedTarget);
|
||||
FSceneView::ProjectWorldToScreen(CurrentLockedTargetLocation, ViewRect, ViewProjectionMatrix, SearchDirectionScreenOrigin);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Draw the ScreenSearchDirection if valid
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
#if USE_COG
|
||||
const FVector2D SearchDirectionNormalized = (TargetSwitchSearchDirection.IsNearlyZero() == false) ? TargetSwitchSearchDirection.GetSafeNormal() : FVector2D::ZeroVector;
|
||||
if (SearchDirectionNormalized.IsNearlyZero() == false)
|
||||
{
|
||||
COG(FCogDebugDraw::Segment2D(LogCogTargetAcquisition, Controller, FVector2D::ZeroVector, FVector2D(SearchDirectionNormalized.X, -SearchDirectionNormalized.Y), FColor(255, 255, 0, 255), bIsDebugPersistent));
|
||||
}
|
||||
#endif //USE_COG
|
||||
|
||||
static const FName TraceTag(TEXT("FindLockTarget_GatherTargets"));
|
||||
FCollisionQueryParams QueryParams(TraceTag, SCENE_QUERY_STAT_ONLY(CogSampleTargetAcquisition), false);
|
||||
QueryParams.bReturnPhysicalMaterial = true;
|
||||
QueryParams.bReturnFaceIndex = false;
|
||||
QueryParams.AddIgnoredActor(Character);
|
||||
|
||||
const FCollisionObjectQueryParams ObjectParams = UCogSampleFunctionLibrary_Gameplay::ConfigureCollisionObjectParams(ObjectTypes);
|
||||
const FVector CastLocation = GetReferentialLocation(Character, DetectionLocation);
|
||||
const FRotator CastRotation = GetReferentialRotation(Character, DetectionRotation);
|
||||
const float CapsuleHalfHeight = DetectionLength * 0.5f;
|
||||
const float CapsuleRadius = DetectionRadius;
|
||||
const FVector CapsuleCenter = CastLocation + CastRotation.Vector() * CapsuleHalfHeight;
|
||||
const FQuat CapsuleRotation = (CastRotation + FRotator(90, 0, 0)).Quaternion();
|
||||
const FCollisionShape CapsuleShape = FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight);
|
||||
|
||||
COG(FCogDebugDraw::Capsule(LogCogTargetAcquisition, Controller, CapsuleCenter, CapsuleHalfHeight, CapsuleRadius, CapsuleRotation, FColor::Yellow, bIsDebugPersistent, 0));
|
||||
|
||||
//-------------------------------------------------
|
||||
// Gather targets asynchronously
|
||||
//-------------------------------------------------
|
||||
TArray<AActor*> QueriedActors;
|
||||
//if (UseAsyncDetection && bForceSynchronousDetection == false)
|
||||
//{
|
||||
// TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition_Generic::EvaluateCandidateQueryAsync);
|
||||
|
||||
// FOverlapDatum OutData;
|
||||
// if (Character->GetWorld()->QueryOverlapData(QueryHandle, OutData))
|
||||
// {
|
||||
// for (const FOverlapResult& Overlap : OutData.OutOverlaps)
|
||||
// {
|
||||
// if (AActor* Target = Overlap.GetActor())
|
||||
// {
|
||||
// QueriedActors.Add(Target);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// QueryHandle = Character->GetWorld()->AsyncOverlapByObjectType(
|
||||
// CapsuleCenter,
|
||||
// CapsuleRotation,
|
||||
// ObjectParams,
|
||||
// CapsuleShape,
|
||||
// QueryParams);
|
||||
//}
|
||||
//-------------------------------------------------
|
||||
// Gather targets synchronously
|
||||
//-------------------------------------------------
|
||||
//else
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::EvaluateCandidateQuerySync);
|
||||
|
||||
TArray<FOverlapResult> OutOverlaps;
|
||||
const bool Hit = Character->GetWorld()->OverlapMultiByObjectType(
|
||||
OutOverlaps,
|
||||
CapsuleCenter,
|
||||
CapsuleRotation,
|
||||
ObjectParams,
|
||||
CapsuleShape,
|
||||
QueryParams);
|
||||
|
||||
for (const FOverlapResult& Overlap : OutOverlaps)
|
||||
{
|
||||
if (AActor* Target = Overlap.GetActor())
|
||||
{
|
||||
QueriedActors.Add(Target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Validate actors
|
||||
//-------------------------------------------------
|
||||
TArray<AActor*> ValidCandidates;
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::EvaluateCandidateCheckValids);
|
||||
|
||||
for (AActor* Actor : QueriedActors)
|
||||
{
|
||||
if (CheckIfTargetValid(Controller, Character, Actor) == false)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, Controller, "Filter", UCogSampleFunctionLibrary_Gameplay::GetActorTargetLocation(Actor), FColor::Red, bIsDebugPersistent));
|
||||
continue;
|
||||
}
|
||||
|
||||
ValidCandidates.Add(Actor);
|
||||
}
|
||||
}
|
||||
|
||||
FindBestTargetInCandidates(Controller, TargetsToIgnore, ValidCandidates, TargetSwitchSearchDirection, SearchDirectionScreenOrigin, bIsDebugPersistent, Result);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::GetViewInfo(
|
||||
const APlayerController* Controller,
|
||||
FMatrix& viewProjectionMatrix,
|
||||
FIntRect& viewRect) const
|
||||
{
|
||||
const ULocalPlayer* localPlayer = Controller->GetLocalPlayer();
|
||||
if (localPlayer == nullptr || localPlayer->ViewportClient == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FSceneViewProjectionData projectionData;
|
||||
if (localPlayer->GetProjectionData(localPlayer->ViewportClient->Viewport, projectionData) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
viewProjectionMatrix = projectionData.ComputeViewProjectionMatrix();
|
||||
viewRect = projectionData.GetConstrainedViewRect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::EvaluateCandidate(
|
||||
AActor* CandidateTarget,
|
||||
const FCogSampleTargetCandidateEvaluationParameters& EvalParams,
|
||||
FCogSampleTargetCandidateEvaluationResult& EvalResult) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::EvaluateCandidate);
|
||||
|
||||
if (EvalParams.TargetsToIgnore.Contains(CandidateTarget))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FVector CandidateTargetLocation = UCogSampleFunctionLibrary_Gameplay::GetActorTargetLocation(CandidateTarget);
|
||||
|
||||
FVector CandidateLocationDelta = CandidateTargetLocation - EvalParams.SourceLocation;
|
||||
if (EvalParams.bWorldDistanceIgnoreZ)
|
||||
{
|
||||
CandidateLocationDelta.Z = 0.0f;
|
||||
}
|
||||
const float CandidateWorldDistance = CandidateLocationDelta.Length();
|
||||
const FVector CandidateWorldDirection = CandidateWorldDistance > 0.0f ? CandidateLocationDelta / CandidateWorldDistance : FVector::ZeroVector;
|
||||
const float ScreenMagnitude = FMath::Min(EvalParams.ViewRect.Width(), EvalParams.ViewRect.Height());
|
||||
const bool IsSearchDirectionUsed = bUseSearchDirectionScore && EvalParams.SearchDirectionNormalized.IsNearlyZero() == false;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Filter by world distance limit
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (CandidateWorldDistance > EvalParams.MaxWorldDistance)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, EvalParams.Controller, FString::Printf(TEXT("Dist: %0.2f"), CandidateWorldDistance * 0.01f), CandidateTargetLocation, FColor::Red, EvalParams.IsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Filter candidates base on yaw limit when using yaw, otherwise filter anyone behind the character
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
const FVector CandidateWorldDirectionFlat = CandidateWorldDirection.GetSafeNormal2D();
|
||||
const float CandidateDot = EvalParams.YawDirection.Dot(CandidateWorldDirectionFlat);
|
||||
const float CandidateYaw = FRotator::NormalizeAxis(FMath::RadiansToDegrees(FMath::Acos(CandidateDot)));
|
||||
if (bUseYawLimit && CandidateYaw > YawMax)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, EvalParams.Controller, FString::Printf(TEXT("Yaw: %0.2f"), CandidateYaw), CandidateTargetLocation, FColor::Red, EvalParams.IsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Find the candidate screen location. If the result distance is lower than zero, it means the crosshair is
|
||||
// inside the candidate capsules.
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
FVector2D CandidateScreenLocation;
|
||||
FVector2D CandidateClosestScreenLocation;
|
||||
float CandidateClosestScreenDistance;
|
||||
const UCapsuleComponent* CandidateBestHitZone = nullptr;
|
||||
if (!ComputeCandidateScreenLocation(CandidateTarget, EvalParams, CandidateTargetLocation, CandidateScreenLocation, CandidateClosestScreenLocation, CandidateClosestScreenDistance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Filter candidates not inside the screen distance limits.
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (bUseScreenLimit)
|
||||
{
|
||||
if (!CheckCandidateWithinScreenDistance(EvalParams.Controller, EvalParams.ViewRect, CandidateTargetLocation, CandidateClosestScreenLocation, CandidateClosestScreenDistance, EvalParams.IsDebugPersistent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Raycast to verify this target is not blocked by a collision.
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (!HasLineOfSightToTarget(EvalParams.Source, CandidateTarget, EvalParams.BlockersParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool bIsInsideCandidate = CandidateClosestScreenDistance < 0.0f;
|
||||
if (!IsSearchDirectionUsed && bPrioritizeInsideHitZones)
|
||||
{
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// We always prioritize the candidates if the crosshair is inside them. Thus if we are inside another candidate
|
||||
// but not inside this one, we discard it (unless we are switching the lock target)
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (EvalResult.bFoundLocationInsideShape && bIsInsideCandidate == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// if we are inside the capsule of this candidate, we can discard subsequent candidates that are not inside
|
||||
// but also the best previous candidate since we were not inside it.
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (bIsInsideCandidate && EvalResult.bFoundLocationInsideShape == false)
|
||||
{
|
||||
EvalResult.BestTarget = nullptr;
|
||||
EvalResult.MinScore = FLT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Compute a score based on the world distance
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
float CandidateWorldDistanceRatio = 0.0f;
|
||||
float CandidateWorldDistanceScore = 0.0f;
|
||||
if (bUseWorldDistanceScore)
|
||||
{
|
||||
CandidateWorldDistanceRatio = (WorldDistanceMax > 0.0f) ? CandidateWorldDistance / WorldDistanceMax : 0.0f;
|
||||
CandidateWorldDistanceScore = WorldDistanceScoreMultiplier * (WorldDistanceScoreCurve != nullptr ? WorldDistanceScoreCurve->GetFloatValue(CandidateWorldDistanceRatio) : CandidateWorldDistanceRatio);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Compute a score based on screen distance
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
float CandidateScreenDistanceRatio = 0.0f;
|
||||
float CandidateScreenDistanceScore = 0.0f;
|
||||
if (bUseScreenDistanceScore && IsSearchDirectionUsed == false)
|
||||
{
|
||||
CandidateScreenDistanceRatio = CandidateClosestScreenDistance / ScreenMagnitude;
|
||||
CandidateScreenDistanceScore = ScreenDistanceScoreMultiplier * (ScreenDistanceScoreCurve != nullptr ? ScreenDistanceScoreCurve->GetFloatValue(CandidateScreenDistanceRatio) : CandidateScreenDistanceRatio);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Compute a score based on yaw
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
float CandidateYawRatio = 0.0f;
|
||||
float CandidateYawScore = 0.0f;
|
||||
if (bUseYawScore)
|
||||
{
|
||||
CandidateYawRatio = YawMax > 0.0f ? CandidateYaw / YawMax : 0.0f;
|
||||
CandidateYawScore = YawScoreMultiplier * (YawScoreCurve != nullptr ? YawScoreCurve->GetFloatValue(CandidateYawRatio) : CandidateYawRatio);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Compute a score based on the search direction. (for target lock switch)
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
float SearchDirectionDistanceScore = 0.0f;
|
||||
float SearchDirectionAngleScore = 0.0f;
|
||||
float SearchDirectionDistanceRatio = 0.0f;
|
||||
float SearchDirectionAngleRatio = 0.0f;
|
||||
|
||||
if (IsSearchDirectionUsed)
|
||||
{
|
||||
const float TargetAngleWithSearchDirection = UCogSampleFunctionLibrary_Gameplay::AngleBetweenVector2D(CandidateScreenLocation - EvalParams.SearchDirectionScreenOrigin, EvalParams.SearchDirectionNormalized);
|
||||
|
||||
if (FMath::Abs(TargetAngleWithSearchDirection) > SearchDirectionMaxAngle)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, EvalParams.Controller, FString::Printf(TEXT("MaxAngle: %0.2f"), TargetAngleWithSearchDirection), CandidateTargetLocation, FColor::Red, EvalParams.IsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
|
||||
SearchDirectionDistanceRatio = FVector2D::Distance(CandidateScreenLocation, EvalParams.SearchDirectionScreenOrigin) / ScreenMagnitude;
|
||||
SearchDirectionDistanceScore = SearchDirectionDistanceScoreMultiplier * (ScreenSearchDirectionDistanceScoreCurve != nullptr ? ScreenSearchDirectionDistanceScoreCurve->GetFloatValue(SearchDirectionDistanceRatio) : SearchDirectionDistanceRatio);
|
||||
SearchDirectionAngleRatio = SearchDirectionMaxAngle > 0.0f ? TargetAngleWithSearchDirection / SearchDirectionMaxAngle : 0.0f;
|
||||
SearchDirectionAngleScore = ScreenSearchDirectionAngleScoreMultiplier * (ScreenSearchDirectionAngleScoreCurve != nullptr ? ScreenSearchDirectionAngleScoreCurve->GetFloatValue(SearchDirectionAngleRatio) : SearchDirectionAngleRatio);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Compute final score by summing all the scores. The best score is the smallest one.
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
const float TargetScore = CandidateWorldDistanceScore + CandidateScreenDistanceScore + CandidateYawScore + SearchDirectionDistanceScore + SearchDirectionAngleScore;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Draw the score of each candidate
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
#if USE_COG
|
||||
|
||||
/*
|
||||
|
||||
if (FCogDebugLog::IsLogCategoryActive(LogCogTargetAcquisition))
|
||||
{
|
||||
ImVec2 CandidateClosestViewportLocation = ImGui::ScreenToViewport(ImGui::ToImVec2(CandidateClosestScreenLocation));
|
||||
|
||||
FCogDebugDraw::Point(LogCogTargetAcquisition, EvalParams.Controller, CandidateTargetLocation, 8.0f, FColor::Blue, EvalParams.IsDebugPersistent, 0);
|
||||
|
||||
FString Text;
|
||||
if (LogCogTargetAcquisition.GetVerbosity() == ELogVerbosity::VeryVerbose)
|
||||
{
|
||||
if (bUseScreenDistanceScore)
|
||||
{
|
||||
Text.Append(FString::Printf(TEXT
|
||||
(
|
||||
"XY: %.0f %.0f \n"
|
||||
"SD: %.0f => %.0f => %.0f \n"
|
||||
),
|
||||
CandidateClosestViewportLocation.x * 100.0f, CandidateClosestViewportLocation.y * 100.0f,
|
||||
CandidateClosestScreenDistance, CandidateScreenDistanceRatio * 100, CandidateScreenDistanceScore * 100));
|
||||
}
|
||||
|
||||
if (bUseWorldDistanceScore)
|
||||
{
|
||||
Text.Append(FString::Printf(TEXT("WD: %.0f => %.0f => %.0f \n"),
|
||||
CandidateWorldDistance * 0.01f,
|
||||
CandidateWorldDistanceRatio * 100,
|
||||
CandidateWorldDistanceScore * 100));
|
||||
}
|
||||
|
||||
if (bUseYawScore)
|
||||
{
|
||||
Text.Append(FString::Printf(TEXT("Y: %.1f => %.0f => %.0f \n"),
|
||||
CandidateYaw,
|
||||
CandidateYawRatio * 100,
|
||||
CandidateYawScore * 100));
|
||||
}
|
||||
|
||||
if (bUseSearchDirectionScore)
|
||||
{
|
||||
Text.Append(FString::Printf(TEXT("VD: %.0f => %.0f \n" "VA: %.0f => %.0f \n"),
|
||||
SearchDirectionDistanceRatio * 100,
|
||||
SearchDirectionDistanceScore * 100,
|
||||
SearchDirectionAngleRatio * 100,
|
||||
SearchDirectionAngleScore * 100));
|
||||
}
|
||||
|
||||
Text.Append(FString::Printf(TEXT("==> %.0f \n"), TargetScore * 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = FString::Printf(TEXT("%0.f"), TargetScore * 100);
|
||||
}
|
||||
FCogDebugDraw::String(LogCogTargetAcquisition, EvalParams.Controller, Text, CandidateTargetLocation, FColor::White, EvalParams.IsDebugPersistent);
|
||||
}
|
||||
|
||||
*/
|
||||
#endif //USE_COG
|
||||
|
||||
if (EvalResult.MinScore < TargetScore)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EvalResult.BestTarget = CandidateTarget;
|
||||
EvalResult.MinScore = TargetScore;
|
||||
EvalResult.bFoundLocationInsideShape = EvalResult.bFoundLocationInsideShape || bIsInsideCandidate;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
void UCogSampleTargetAcquisition::FindBestTargetInCandidates(
|
||||
const APlayerController* Controller,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const TArray<AActor*>& Candidates,
|
||||
const FVector2D ScreenSearchDirection,
|
||||
const FVector2D SearchDirectionScreenOrigin,
|
||||
const bool bIsDebugPersistent,
|
||||
FCogSampleTargetAcquisitionResult& Result) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::FindBestTargetInCandidates);
|
||||
|
||||
ACogSampleCharacter* Character = Cast<ACogSampleCharacter>(Controller->GetPawn());
|
||||
if (Character == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Compute view matrix to project each candidate capsules in screen space
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
FMatrix ViewProjectionMatrix;
|
||||
FIntRect ViewRect;
|
||||
if (GetViewInfo(Controller, ViewProjectionMatrix, ViewRect) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Draw screen limits
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
FVector2D ScreenCrosshairPosition(0.5f * ViewRect.Width(), 0.5f * ViewRect.Height());
|
||||
|
||||
COG(FCogDebugDraw::Circle2D(LogCogTargetAcquisition, Controller, ScreenCrosshairPosition, 5.0f, FColor(255, 255, 255, 255), bIsDebugPersistent));
|
||||
|
||||
#if USE_COG
|
||||
//if (bUseScreenLimit)
|
||||
//{
|
||||
// if (ScreenLimitType == ECogSampleTargetAcquisitionScreenLimitType::Rectangle)
|
||||
// {
|
||||
// COG(FCogDebugDraw::Rect2D(
|
||||
// LogCogTargetAcquisition,
|
||||
// Controller,
|
||||
// FVector2D(-ScreenMaxX, -ScreenMaxY),
|
||||
// FVector2D(ScreenMaxX, ScreenMaxY),
|
||||
// FColor(255, 255, 255, 255),
|
||||
// bIsDebugPersistent));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// COG(FCogDebugDraw::Circle2D(
|
||||
// LogCogTargetAcquisition,
|
||||
// Controller,
|
||||
// ScreenCrosshairPosition,
|
||||
// ImGui::ViewportToScreen(ScreenMaxX),
|
||||
// FColor(255, 255, 255, 255),
|
||||
// bIsDebugPersistent));
|
||||
// }
|
||||
//}
|
||||
#endif //USE_COG
|
||||
|
||||
const FRotator YawRotation = GetReferentialRotation(Character, YawReferential);
|
||||
const FVector YawDirection = YawRotation.Vector();
|
||||
|
||||
FCogSampleTargetCandidateEvaluationParameters EvalParams;
|
||||
EvalParams.Source = Character;
|
||||
EvalParams.SourceLocation = Character->GetActorLocation();
|
||||
EvalParams.Controller = Controller;
|
||||
EvalParams.TargetsToIgnore = TargetsToIgnore;
|
||||
EvalParams.bWorldDistanceIgnoreZ = WorldDistanceIgnoreZ;
|
||||
EvalParams.MaxWorldDistance = WorldDistanceMax;
|
||||
EvalParams.CrosshairPosition = ScreenCrosshairPosition;
|
||||
EvalParams.YawDirection = YawDirection;
|
||||
EvalParams.CameraRight = Character->GetFollowCamera()->GetComponentQuat().GetRightVector();
|
||||
EvalParams.ViewProjectionMatrix = ViewProjectionMatrix;
|
||||
EvalParams.ViewRect = ViewRect;
|
||||
EvalParams.BlockersParams = UCogSampleFunctionLibrary_Gameplay::ConfigureCollisionObjectParams(BlockerTypes);
|
||||
EvalParams.bUseSearchDirection = ScreenSearchDirection.IsNearlyZero() == false;
|
||||
EvalParams.SearchDirectionScreenOrigin = SearchDirectionScreenOrigin;
|
||||
EvalParams.SearchDirectionNormalized = EvalParams.bUseSearchDirection ? ScreenSearchDirection.GetSafeNormal() : FVector2D::ZeroVector;
|
||||
EvalParams.IsDebugPersistent = bIsDebugPersistent;
|
||||
|
||||
FCogSampleTargetCandidateEvaluationResult EvalResult
|
||||
{
|
||||
nullptr,
|
||||
FLT_MAX,
|
||||
false
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Evaluate candidates actors
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
for (int32 i = 0; i < Candidates.Num(); ++i)
|
||||
{
|
||||
AActor* Candidate = Candidates[i];
|
||||
check(Candidate != nullptr);
|
||||
if (Candidate == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EvaluateCandidate(Candidate, EvalParams, EvalResult);
|
||||
}
|
||||
|
||||
if (EvalResult.BestTarget != nullptr)
|
||||
{
|
||||
Result.Target = EvalResult.BestTarget;
|
||||
Result.Score = EvalResult.MinScore;
|
||||
|
||||
COG(FCogDebugDraw::Point(LogCogTargetAcquisition, Controller, UCogSampleFunctionLibrary_Gameplay::GetActorTargetLocation(Result.Target), 10.0f, FColor::Green, EvalParams.IsDebugPersistent, 0));
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::ComputeCandidateScreenLocation(
|
||||
const AActor* CandidateActor,
|
||||
const FCogSampleTargetCandidateEvaluationParameters& EvalParams,
|
||||
const FVector& CandidateTargetLocation,
|
||||
FVector2D& CandidateScreenLocation,
|
||||
FVector2D& CandidateClosestScreenLocation,
|
||||
float& CandidateClosestScreenDistance) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::ComputeCandidateScreenLocation);
|
||||
|
||||
check(CandidateActor);
|
||||
|
||||
bool bFoundValidCandidate = false;
|
||||
CandidateScreenLocation = FVector2D::ZeroVector;
|
||||
CandidateClosestScreenDistance = FLT_MAX;
|
||||
|
||||
if (const ICogSampleTargetableInterface* Targetable = Cast<ICogSampleTargetableInterface>(CandidateActor))
|
||||
{
|
||||
TArray<const UCapsuleComponent*> Capsules;
|
||||
Targetable->GetTargetCapsules(Capsules);
|
||||
|
||||
for (const UCapsuleComponent* Capsule : Capsules)
|
||||
{
|
||||
const float Radius = Capsule->GetScaledCapsuleRadius();
|
||||
const float HalfHeight = Capsule->GetScaledCapsuleHalfHeight();
|
||||
|
||||
const FVector CapsuleLocation = Capsule->GetComponentLocation();
|
||||
const FVector CapsuleTop = CapsuleLocation + FVector::UpVector * (HalfHeight - Radius);
|
||||
const FVector CapsuleBottom = CapsuleLocation - FVector::UpVector * (HalfHeight - Radius);
|
||||
const FVector CapsuleRight = CapsuleLocation - EvalParams.CameraRight * Radius;
|
||||
|
||||
FVector2D CapsuleTop2D;
|
||||
FVector2D CapsuleBot2D;
|
||||
FVector2D CapsuleRight2D;
|
||||
|
||||
if (FSceneView::ProjectWorldToScreen(CapsuleTop, EvalParams.ViewRect, EvalParams.ViewProjectionMatrix, CapsuleTop2D) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FSceneView::ProjectWorldToScreen(CapsuleBottom, EvalParams.ViewRect, EvalParams.ViewProjectionMatrix, CapsuleBot2D) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FSceneView::ProjectWorldToScreen(CapsuleRight, EvalParams.ViewRect, EvalParams.ViewProjectionMatrix, CapsuleRight2D) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (Type == ECogSampleTargetAcquisitionType::Melee && CandidateCharacter != nullptr && !UCogFunctionLibrary_Targeting::IsTargetCapsuleReachableByMelee(EvalParams.Source, CandidateCharacter, Capsule))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
const FVector2D CapsuleCenter2D = CapsuleBot2D + 0.5f * (CapsuleTop2D - CapsuleBot2D);
|
||||
const float CapsuleRadius2D = FVector2D::Distance(CapsuleCenter2D, CapsuleRight2D);
|
||||
|
||||
FVector2D Projection;
|
||||
float Time;
|
||||
float ScreenCenterToCapsuleDistance;
|
||||
UCogSampleFunctionLibrary_Gameplay::FindCapsulePointDistance(CapsuleBot2D, CapsuleTop2D, CapsuleRadius2D, EvalParams.CrosshairPosition, Projection, Time, ScreenCenterToCapsuleDistance);
|
||||
|
||||
if (ScreenCenterToCapsuleDistance < CandidateClosestScreenDistance)
|
||||
{
|
||||
CandidateScreenLocation = CapsuleCenter2D;
|
||||
CandidateClosestScreenDistance = ScreenCenterToCapsuleDistance;
|
||||
CandidateClosestScreenLocation = Projection;
|
||||
bFoundValidCandidate = true;
|
||||
}
|
||||
|
||||
#if USE_COG
|
||||
const FColor CapsuleColor = (ScreenCenterToCapsuleDistance > 0.0f) ? FColor(255, 255, 255, 100) : FColor(0, 255, 0, 200);
|
||||
FCogDebugDraw::Segment2D(LogCogTargetAcquisition, CandidateActor, CapsuleBot2D + FVector2D(CapsuleRadius2D, 0), CapsuleTop2D + FVector2D(CapsuleRadius2D, 0), CapsuleColor, EvalParams.IsDebugPersistent);
|
||||
FCogDebugDraw::Segment2D(LogCogTargetAcquisition, CandidateActor, CapsuleBot2D - FVector2D(CapsuleRadius2D, 0), CapsuleTop2D - FVector2D(CapsuleRadius2D, 0), CapsuleColor, EvalParams.IsDebugPersistent);
|
||||
FCogDebugDraw::Circle2D(LogCogTargetAcquisition, CandidateActor, CapsuleTop2D, CapsuleRadius2D, CapsuleColor, EvalParams.IsDebugPersistent);
|
||||
FCogDebugDraw::Circle2D(LogCogTargetAcquisition, CandidateActor, CapsuleBot2D, CapsuleRadius2D, CapsuleColor, EvalParams.IsDebugPersistent);
|
||||
#endif //USE_COG
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FSceneView::ProjectWorldToScreen(CandidateTargetLocation, EvalParams.ViewRect, EvalParams.ViewProjectionMatrix, CandidateScreenLocation))
|
||||
{
|
||||
CandidateClosestScreenDistance = CandidateScreenLocation.Length();
|
||||
CandidateClosestScreenLocation = CandidateScreenLocation;
|
||||
bFoundValidCandidate = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_COG
|
||||
if (bFoundValidCandidate)
|
||||
{
|
||||
FCogDebugDraw::Circle2D(LogCogTargetAcquisition, CandidateActor, CandidateClosestScreenLocation, 2.0f, FColor(0, 255, 0, 255), EvalParams.IsDebugPersistent);
|
||||
}
|
||||
#endif //USE_COG
|
||||
|
||||
return bFoundValidCandidate;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::CheckCandidateWithinScreenDistance(
|
||||
const APlayerController* Controller,
|
||||
const FIntRect& ViewRect,
|
||||
const FVector& CandidateLocation,
|
||||
const FVector2D& CandidateScreenLocation,
|
||||
const float CandidateScreenDistance,
|
||||
const bool bIsDebugPersistent) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::CheckCandidateWithinScreenDistance);
|
||||
|
||||
const FVector2D ScreenSize(ViewRect.Width(), ViewRect.Height());
|
||||
const FVector2D CandidateViewportLocation = UCogSampleFunctionLibrary_Gameplay::ScreenToViewport(CandidateScreenLocation, ScreenSize);
|
||||
const float CandidateViewportDistance = UCogSampleFunctionLibrary_Gameplay::ScreenToViewport(CandidateScreenDistance, ScreenSize);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Filter by screen distance - within rectangle
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
if (ScreenLimitType == ECogSampleTargetAcquisitionScreenLimitType::Rectangle)
|
||||
{
|
||||
if (FMath::Abs(CandidateViewportLocation.X) > ScreenMaxX)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, Controller, FString::Printf(TEXT("MaxX: %0.2f"), CandidateViewportLocation.X), CandidateLocation, FColor::Red, bIsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FMath::Abs(CandidateViewportLocation.Y) > ScreenMaxY)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, Controller, FString::Printf(TEXT("MaxY: %0.2f"), CandidateViewportLocation.Y), CandidateLocation, FColor::Red, bIsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Filter by screen distance - within circle
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
else if (ScreenLimitType == ECogSampleTargetAcquisitionScreenLimitType::Circle)
|
||||
{
|
||||
if (CandidateViewportDistance > ScreenMaxX)
|
||||
{
|
||||
COG(FCogDebugDraw::String(LogCogTargetAcquisition, Controller, FString::Printf(TEXT("Max: %0.2f"), CandidateViewportDistance), CandidateLocation, FColor::Red, bIsDebugPersistent));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::CheckIfTargetValid(
|
||||
const APlayerController* Controller,
|
||||
const AActor* Source,
|
||||
const AActor* Target) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::CheckIfTargetValid);
|
||||
|
||||
if (UCogSampleFunctionLibrary_Team::MatchAllegiance(Source, Target, Allegiance) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::HasLineOfSightToTarget(
|
||||
const AActor* Source,
|
||||
const AActor* Target,
|
||||
const FCollisionObjectQueryParams& BlockersParams) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::HasLineOfSightToTarget);
|
||||
|
||||
const FVector Origin = Source->GetActorLocation();
|
||||
|
||||
static const FName BlockerTraceTag(TEXT("FindLockTarget_Blocker"));
|
||||
FCollisionQueryParams TargetQueryParams(BlockerTraceTag, SCENE_QUERY_STAT_ONLY(CogSampleTargetAcquisition), false);
|
||||
TargetQueryParams.AddIgnoredActor(Target);
|
||||
|
||||
return true;
|
||||
//return FCogHitDetectionHelper::HasLineOfSight(Source->GetWorld(), Origin, Target.GetTargetLocation(), BlockersParams, TargetQueryParams, LogCogTargetAcquisition);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool UCogSampleTargetAcquisition::HasLineOfSightToTargetBrokenForTooLong(
|
||||
const AActor* Source,
|
||||
const AActor* Target,
|
||||
const float DeltaTime,
|
||||
float& Timer) const
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::HasLineOfSightToTargetBrokenForTooLong);
|
||||
|
||||
const FCollisionObjectQueryParams BlockersParams = UCogSampleFunctionLibrary_Gameplay::ConfigureCollisionObjectParams(BlockerTypes);
|
||||
bool HasLineOfSight = HasLineOfSightToTarget(Source, Target, BlockersParams);
|
||||
if (HasLineOfSight)
|
||||
{
|
||||
Timer = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Timer += DeltaTime;
|
||||
|
||||
if (Timer > BreakLineOfSightDelay)
|
||||
{
|
||||
Timer = 0.0f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FVector UCogSampleTargetAcquisition::GetReferentialLocation(const ACogSampleCharacter* Character, ECogSampleTargetAcquisitionLocationReferential Referential)
|
||||
{
|
||||
FVector Location;
|
||||
|
||||
switch (Referential)
|
||||
{
|
||||
case ECogSampleTargetAcquisitionLocationReferential::Character:
|
||||
{
|
||||
Location = UCogSampleFunctionLibrary_Gameplay::GetActorBottomLocation(Character);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ECogSampleTargetAcquisitionLocationReferential::Camera:
|
||||
{
|
||||
Location = Character->GetFollowCamera()->GetComponentLocation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Location;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
FRotator UCogSampleTargetAcquisition::GetReferentialRotation(const ACogSampleCharacter* Character, ECogSampleTargetAcquisitionRotationReferential Referential)
|
||||
{
|
||||
FRotator Rotation;
|
||||
|
||||
switch (Referential)
|
||||
{
|
||||
case ECogSampleTargetAcquisitionRotationReferential::Character:
|
||||
{
|
||||
Rotation = Character->GetActorRotation();
|
||||
break;
|
||||
}
|
||||
|
||||
case ECogSampleTargetAcquisitionRotationReferential::MoveInput:
|
||||
{
|
||||
//const FVector WorldInput = Character->TransformInputInWorldSpace(Character->GetDesiredMoveInput());
|
||||
//if (WorldInput.IsNearlyZero())
|
||||
//{
|
||||
// Rotation = Character->GetActorRotation();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Rotation = WorldInput.GetSafeNormal().Rotation();
|
||||
//}
|
||||
//break;
|
||||
}
|
||||
|
||||
case ECogSampleTargetAcquisitionRotationReferential::Camera:
|
||||
{
|
||||
Rotation = Character->GetFollowCamera()->GetComponentRotation();
|
||||
break;
|
||||
}
|
||||
|
||||
case ECogSampleTargetAcquisitionRotationReferential::CameraFlatten:
|
||||
{
|
||||
const FVector CameraForwardFlat = Character->GetFollowCamera()->GetComponentQuat().GetForwardVector().GetSafeNormal2D();
|
||||
Rotation = CameraForwardFlat.Rotation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Rotation;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogSampleFunctionLibrary_Team.h"
|
||||
#include "Engine/DataAsset.h"
|
||||
#include "Engine/EngineTypes.h"
|
||||
#include "WorldCollision.h"
|
||||
#include "CogSampleTargetAcquisition.generated.h"
|
||||
|
||||
class ACogSampleCharacter;
|
||||
class APlayerController;
|
||||
class UCurveFloat;
|
||||
struct FCogSampleTargetCandidateEvaluationResult;
|
||||
struct FCogSampleTargetCandidateEvaluationParameters;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleTargetAcquisitionType : uint8
|
||||
{
|
||||
Melee,
|
||||
Range
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleTargetAcquisitionScreenLimitType : uint8
|
||||
{
|
||||
Rectangle,
|
||||
Circle,
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleTargetAcquisitionLocationReferential : uint8
|
||||
{
|
||||
Character,
|
||||
Camera,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleTargetAcquisitionRotationReferential : uint8
|
||||
{
|
||||
Camera,
|
||||
CameraFlatten,
|
||||
Character,
|
||||
MoveInput,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UENUM(BlueprintType)
|
||||
enum class ECogSampleTargetAcquisitionCrosshairReferential : uint8
|
||||
{
|
||||
Centered,
|
||||
Offseted,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
struct FCogSampleTargetAcquisitionResult
|
||||
{
|
||||
public:
|
||||
AActor* Target = nullptr;
|
||||
|
||||
float Score = FLT_MAX;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UCLASS()
|
||||
class UCogSampleTargetAcquisition : public UDataAsset
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// General
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> BlockerTypes;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
|
||||
float BreakLineOfSightDelay = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General", meta = (Bitmask, BitmaskEnum = "/Script/CogSample.ECogSampleAllegianceFilter"))
|
||||
int32 Allegiance = 0;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General")
|
||||
bool AcceptDead = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Detection
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Detection")
|
||||
ECogSampleTargetAcquisitionLocationReferential DetectionLocation = ECogSampleTargetAcquisitionLocationReferential::Camera;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Detection")
|
||||
ECogSampleTargetAcquisitionRotationReferential DetectionRotation = ECogSampleTargetAcquisitionRotationReferential::Camera;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Detection")
|
||||
float DetectionLength = 1000.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Detection")
|
||||
float DetectionRadius = 600.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Detection")
|
||||
bool UseAsyncDetection = true;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Screen Limit
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (ToolTip = "Limit based on the screen distance. The screen distance is computed between the crosshair and the candidate screen position"))
|
||||
bool bUseScreenLimit = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
bool bPrioritizeInsideHitZones = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
bool ScreenTestUseAspectRatio = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
ECogSampleTargetAcquisitionCrosshairReferential CrosshairReferential = ECogSampleTargetAcquisitionCrosshairReferential::Centered;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
ECogSampleTargetAcquisitionScreenLimitType ScreenLimitType = ECogSampleTargetAcquisitionScreenLimitType::Rectangle;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
float ScreenMaxX = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Screen", meta = (EditCondition = "bUseScreenLimit", EditConditionHides))
|
||||
float ScreenMaxY = 1.0f;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Yaw Limit
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Yaw", meta = (ToolTip = "Limit based on the yaw angle. The yaw angle is computed between the camera forward vector and the direction between the player character and the candidate"))
|
||||
bool bUseYawLimit = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Limit|Yaw", meta = (EditCondition = "bUseYawLimit", EditConditionHides))
|
||||
float YawMax = 90.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Limit|Yaw")
|
||||
ECogSampleTargetAcquisitionRotationReferential YawReferential = ECogSampleTargetAcquisitionRotationReferential::Camera;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// World Distance
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|World Distance", meta = (ToolTip = "The world distance is the distance between the character position and the candidate position"))
|
||||
bool bUseWorldDistanceScore = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|World Distance", meta = (EditCondition = "bUseWorldDistanceScore", EditConditionHides))
|
||||
float WorldDistanceMax = 1000.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|World Distance", meta = (EditCondition = "bUseWorldDistanceScore", EditConditionHides))
|
||||
UCurveFloat* WorldDistanceScoreCurve = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|World Distance", meta = (EditCondition = "bUseWorldDistanceScore", EditConditionHides))
|
||||
float WorldDistanceScoreMultiplier = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|World Distance", meta = (EditCondition = "bUseWorldDistanceScore", EditConditionHides))
|
||||
bool WorldDistanceIgnoreZ = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Screen Distance Score
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Screen Distance", meta = (ToolTip = "The screen distance is the distance between the crosshair and the candidate screen position"))
|
||||
bool bUseScreenDistanceScore = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Screen Distance", meta = (EditCondition = "bUseScreenDistanceScore", EditConditionHides))
|
||||
float ScreenDistanceScoreMultiplier = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Screen Distance", meta = (EditCondition = "bUseScreenDistanceScore", EditConditionHides))
|
||||
UCurveFloat* ScreenDistanceScoreCurve = nullptr;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Yaw Scoring
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Yaw", meta = (ToolTip = "The yaw angle is computed between the camera forward vector and the direction between the player character and the candidate"))
|
||||
bool bUseYawScore = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Yaw", meta = (EditCondition = "bUseYawScore", EditConditionHides))
|
||||
float YawScoreMultiplier = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Yaw", meta = (EditCondition = "bUseYawScore", EditConditionHides))
|
||||
UCurveFloat* YawScoreCurve = nullptr;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Search Direction
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (ToolTip = "The search direction is used when the player has already a locked target and request a target switch with a direction performed by the stick or the mouse"))
|
||||
bool bUseSearchDirectionScore = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (EditCondition = "bUseSearchDirectionScore", EditConditionHides))
|
||||
float SearchDirectionMaxAngle = 60.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (EditCondition = "bUseSearchDirectionScore", EditConditionHides))
|
||||
UCurveFloat* ScreenSearchDirectionAngleScoreCurve = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (EditCondition = "bUseSearchDirectionScore", EditConditionHides))
|
||||
float ScreenSearchDirectionAngleScoreMultiplier = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (EditCondition = "bUseSearchDirectionScore", EditConditionHides))
|
||||
UCurveFloat* ScreenSearchDirectionDistanceScoreCurve = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Scoring|Search Direction", meta = (EditCondition = "bUseSearchDirectionScore", EditConditionHides))
|
||||
float SearchDirectionDistanceScoreMultiplier = 1.0f;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
virtual void FindBestTargets(
|
||||
const APlayerController* Controller,
|
||||
const int32 TargetCount,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const AActor* CurrentLockedTarget,
|
||||
const bool bForceSynchronousDetection,
|
||||
const FVector2D ScreenSearchDirection,
|
||||
const bool bIsDebugPersistent,
|
||||
TArray<FCogSampleTargetAcquisitionResult>& Results) const;
|
||||
|
||||
virtual bool HasLineOfSightToTargetBrokenForTooLong(
|
||||
const AActor* Source,
|
||||
const AActor* Target,
|
||||
const float DeltaTime,
|
||||
float& Timer) const;
|
||||
|
||||
virtual bool CheckIfTargetValid(
|
||||
const APlayerController* Controller,
|
||||
const AActor* Source,
|
||||
const AActor* Target) const;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Utility
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void FindBestTargetInCandidates(
|
||||
const APlayerController* Controller,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const TArray<AActor*>& Candidates,
|
||||
const FVector2D ScreenSearchDirection,
|
||||
const FVector2D SearchDirectionViewportOrigin,
|
||||
const bool bIsDebugPersistent,
|
||||
FCogSampleTargetAcquisitionResult& Result) const;
|
||||
|
||||
void FindBestTarget(
|
||||
const APlayerController* Controller,
|
||||
const TArray<AActor*>& TargetsToIgnore,
|
||||
const AActor* CurrentLockedTarget,
|
||||
const bool bForceSynchronousDetection,
|
||||
const FVector2D ScreenSearchDirection,
|
||||
const bool bIsDebugPersistent,
|
||||
FCogSampleTargetAcquisitionResult& Result) const;
|
||||
|
||||
bool HasLineOfSightToTarget(
|
||||
const AActor* Source,
|
||||
const AActor* Target,
|
||||
const FCollisionObjectQueryParams& BlockersParams) const;
|
||||
|
||||
bool EvaluateCandidate(
|
||||
AActor* CandidateTarget,
|
||||
const FCogSampleTargetCandidateEvaluationParameters& EvaluationParameters,
|
||||
FCogSampleTargetCandidateEvaluationResult& EvaluationResult) const;
|
||||
|
||||
bool CheckCandidateWithinScreenDistance(
|
||||
const APlayerController* Controller,
|
||||
const FIntRect& viewRect,
|
||||
const FVector& candidateLocation,
|
||||
const FVector2D& candidateScreenLocation,
|
||||
const float candidateScreenDistance,
|
||||
const bool bIsDebugPersistent) const;
|
||||
|
||||
bool ComputeCandidateScreenLocation(
|
||||
const AActor* CandidateTarget,
|
||||
const FCogSampleTargetCandidateEvaluationParameters& EvalParams,
|
||||
const FVector& CandidateTargetLocation,
|
||||
FVector2D& CandidateScreenLocation,
|
||||
FVector2D& CandidateClosestScreenLocation,
|
||||
float& CandidateClosestScreenDistance) const;
|
||||
|
||||
bool GetViewInfo(
|
||||
const APlayerController* Controller,
|
||||
FMatrix& viewProjectionMatrix,
|
||||
FIntRect& viewRect) const;
|
||||
|
||||
static FVector GetReferentialLocation(const ACogSampleCharacter* Character, ECogSampleTargetAcquisitionLocationReferential Referential);
|
||||
|
||||
static FRotator GetReferentialRotation(const ACogSampleCharacter* Character, ECogSampleTargetAcquisitionRotationReferential Referential);
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogSampleTargetableInterface.generated.h"
|
||||
|
||||
class UCapsuleComponent;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UINTERFACE(MinimalAPI, Blueprintable)
|
||||
class UCogSampleTargetableInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class ICogSampleTargetableInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual FVector GetTargetLocation() const { return FVector::ZeroVector; }
|
||||
|
||||
virtual void GetTargetCapsules(TArray<const UCapsuleComponent*>& Capsules) const { }
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CogSampleTeamInterface.generated.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
UINTERFACE(MinimalAPI, Blueprintable)
|
||||
class UCogSampleTeamInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class ICogSampleTeamInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
virtual int32 GetTeam() const { return 0; }
|
||||
};
|
||||
Reference in New Issue
Block a user