diff --git a/Content/Characters/Children/Creature1/BP_Creature1.uasset b/Content/Characters/Children/Creature1/BP_Creature1.uasset index 750342d..925af2e 100644 Binary files a/Content/Characters/Children/Creature1/BP_Creature1.uasset and b/Content/Characters/Children/Creature1/BP_Creature1.uasset differ diff --git a/Content/Characters/Children/Creature2/BP_Creature2.uasset b/Content/Characters/Children/Creature2/BP_Creature2.uasset index 454bd1d..7ef86d7 100644 Binary files a/Content/Characters/Children/Creature2/BP_Creature2.uasset and b/Content/Characters/Children/Creature2/BP_Creature2.uasset differ diff --git a/Content/Characters/Children/Hero1/Attributes/CT_Hero1_Attributes.uasset b/Content/Characters/Children/Hero1/Attributes/CT_Hero1_Attributes.uasset index 1e35364..14824e4 100644 Binary files a/Content/Characters/Children/Hero1/Attributes/CT_Hero1_Attributes.uasset and b/Content/Characters/Children/Hero1/Attributes/CT_Hero1_Attributes.uasset differ diff --git a/Content/Characters/Children/Hero1/BP_Hero1.uasset b/Content/Characters/Children/Hero1/BP_Hero1.uasset index 25029fe..3503d97 100644 Binary files a/Content/Characters/Children/Hero1/BP_Hero1.uasset and b/Content/Characters/Children/Hero1/BP_Hero1.uasset differ diff --git a/Content/Characters/Children/Hero2/BP_Hero2.uasset b/Content/Characters/Children/Hero2/BP_Hero2.uasset index 46edd7a..ebf411e 100644 Binary files a/Content/Characters/Children/Hero2/BP_Hero2.uasset and b/Content/Characters/Children/Hero2/BP_Hero2.uasset differ diff --git a/Content/Core/GameModes/BP_PlayerController.uasset b/Content/Core/GameModes/BP_PlayerController.uasset new file mode 100644 index 0000000..4e0091a Binary files /dev/null and b/Content/Core/GameModes/BP_PlayerController.uasset differ diff --git a/Content/Core/GameModes/DA_TargetAcquisition.uasset b/Content/Core/GameModes/DA_TargetAcquisition.uasset new file mode 100644 index 0000000..a12e0d1 Binary files /dev/null and b/Content/Core/GameModes/DA_TargetAcquisition.uasset differ diff --git a/Content/Core/GameModes/GM_CogSample.uasset b/Content/Core/GameModes/GM_CogSample.uasset index caa842f..8237ce8 100644 Binary files a/Content/Core/GameModes/GM_CogSample.uasset and b/Content/Core/GameModes/GM_CogSample.uasset differ diff --git a/Content/__ExternalActors__/Maps/L_Default/5/88/NDHUEK1ROBM2RCW7ZU51MM.uasset b/Content/__ExternalActors__/Maps/L_Default/5/88/NDHUEK1ROBM2RCW7ZU51MM.uasset index 165bcb7..92c176e 100644 Binary files a/Content/__ExternalActors__/Maps/L_Default/5/88/NDHUEK1ROBM2RCW7ZU51MM.uasset and b/Content/__ExternalActors__/Maps/L_Default/5/88/NDHUEK1ROBM2RCW7ZU51MM.uasset differ diff --git a/Content/__ExternalActors__/Maps/L_Default/6/U3/6O7DJ03I0JB041XHH0L21L.uasset b/Content/__ExternalActors__/Maps/L_Default/6/U3/6O7DJ03I0JB041XHH0L21L.uasset index 68bcb71..83504b5 100644 Binary files a/Content/__ExternalActors__/Maps/L_Default/6/U3/6O7DJ03I0JB041XHH0L21L.uasset and b/Content/__ExternalActors__/Maps/L_Default/6/U3/6O7DJ03I0JB041XHH0L21L.uasset differ diff --git a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugDraw.cpp b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugDraw.cpp index 88f3bd9..01a03a5 100644 --- a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugDraw.cpp +++ b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugDraw.cpp @@ -5,7 +5,7 @@ #include "CogDebugHelper.h" #include "CogDebugDrawImGui.h" #include "CogImguiHelper.h" -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" #include "CogDebugModule.h" #include "CogDebugReplicator.h" #include "Engine/SkeletalMesh.h" @@ -16,7 +16,7 @@ //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::String2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector2D& Location, const FColor& Color, bool Persistent) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { FCogDebugDrawImGui::AddText( FCogImguiHelper::ToImVec2(Location), @@ -31,7 +31,7 @@ void FCogDebugDraw::String2D(const FLogCategoryBase& LogCategory, const UObject* //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Segment2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& SegmentStart, const FVector2D& SegmentEnd, const FColor& Color, bool Persistent) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { FCogDebugDrawImGui::AddLine( FCogImguiHelper::ToImVec2(SegmentStart), @@ -46,7 +46,7 @@ void FCogDebugDraw::Segment2D(const FLogCategoryBase& LogCategory, const UObject //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Circle2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Location, float Radius, const FColor& Color, bool Persistent) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { FCogDebugDrawImGui::AddCircle( FCogImguiHelper::ToImVec2(Location), @@ -63,7 +63,7 @@ void FCogDebugDraw::Circle2D(const FLogCategoryBase& LogCategory, const UObject* void FCogDebugDraw::Rect2D(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Min, const FVector2D& Max, const FColor& Color, bool Persistent) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const ImVec2 ImMin = FCogImguiHelper::ToImVec2(Min); const ImVec2 ImMax = FCogImguiHelper::ToImVec2(Max); @@ -82,7 +82,7 @@ void FCogDebugDraw::Rect2D(const FLogCategoryBase& LogCategory, const UObject* W //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::String(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FString& Text, const FVector& Location, const FColor& Color, const bool Persistent) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_LOCATION(WorldContextObject, LogCategory, Verbose, Location, 10.0f, NewColor, TEXT("%s"), *Text); @@ -102,7 +102,7 @@ void FCogDebugDraw::String(const FLogCategoryBase& LogCategory, const UObject* W //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Point(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, const float Size, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); ::DrawDebugPoint( @@ -121,7 +121,7 @@ void FCogDebugDraw::Point(const FLogCategoryBase& LogCategory, const UObject* Wo //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Segment(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_SEGMENT(WorldContextObject, LogCategory, Verbose, SegmentStart, SegmentEnd, NewColor, TEXT_EMPTY); @@ -142,7 +142,7 @@ void FCogDebugDraw::Segment(const FLogCategoryBase& LogCategory, const UObject* //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Bone(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& BoneLocation, const FVector& ParentLocation, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_SEGMENT(WorldContextObject, LogCategory, Verbose, BoneLocation, ParentLocation, NewColor, TEXT_EMPTY); @@ -173,7 +173,7 @@ void FCogDebugDraw::Bone(const FLogCategoryBase& LogCategory, const UObject* Wor //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Arrow(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& SegmentStart, const FVector& SegmentEnd, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, SegmentStart, SegmentEnd, NewColor, TEXT_EMPTY); @@ -195,7 +195,7 @@ void FCogDebugDraw::Arrow(const FLogCategoryBase& LogCategory, const UObject* Wo //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Axis(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& AxisLoc, const FRotator& AxisRot, float Scale, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { FRotationMatrix R(AxisRot); UE_VLOG_ARROW(WorldContextObject, LogCategory, Verbose, AxisLoc, AxisLoc + R.GetScaledAxis(EAxis::X) * Scale, FColor::Red, TEXT_EMPTY); @@ -218,7 +218,7 @@ void FCogDebugDraw::Axis(const FLogCategoryBase& LogCategory, const UObject* Wor //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Circle(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float Radius, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); const FVector Center = Matrix.GetOrigin(); @@ -243,7 +243,7 @@ void FCogDebugDraw::Circle(const FLogCategoryBase& LogCategory, const UObject* W //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::CircleArc(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, float InnerRadius, float OuterRadius, float Angle, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); @@ -269,7 +269,7 @@ void FCogDebugDraw::CircleArc(const FLogCategoryBase& LogCategory, const UObject //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::FlatCapsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector2D& Start, const FVector2D& End, const float Radius, const float Z, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); // TODO : Add VLOG @@ -294,7 +294,7 @@ void FCogDebugDraw::FlatCapsule(const FLogCategoryBase& LogCategory, const UObje //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Sphere(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Location, float Radius, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_CAPSULE(WorldContextObject, LogCategory, Verbose, Location, 0.0f, Radius, FQuat::Identity, NewColor, TEXT_EMPTY); @@ -316,7 +316,7 @@ void FCogDebugDraw::Sphere(const FLogCategoryBase& LogCategory, const UObject* W //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Box(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_OBOX(WorldContextObject, LogCategory, Verbose, FBox(-Extent, Extent), FQuatRotationTranslationMatrix::Make(Rotation, Center), NewColor, TEXT_EMPTY); @@ -339,7 +339,7 @@ void FCogDebugDraw::Box(const FLogCategoryBase& LogCategory, const UObject* Worl //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::SolidBox(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const FVector& Extent, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_OBOX(WorldContextObject, LogCategory, Verbose, FBox(-Extent, Extent), FQuatRotationTranslationMatrix::Make(Rotation, Center), NewColor, TEXT_EMPTY); @@ -366,7 +366,7 @@ void FCogDebugDraw::SolidBox(const FLogCategoryBase& LogCategory, const UObject* //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Frustrum(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FMatrix& Matrix, const float Angle, const float AspectRatio, const float NearPlane, const float FarPlane, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); @@ -390,7 +390,7 @@ void FCogDebugDraw::Frustrum(const FLogCategoryBase& LogCategory, const UObject* //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Capsule(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const FVector& Center, const float HalfHeight, const float Radius, const FQuat& Rotation, const FColor& Color, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FColor NewColor = FCogDebugSettings::ModulateDebugColor(WorldContextObject->GetWorld(), Color, Persistent); UE_VLOG_CAPSULE(WorldContextObject, LogCategory, Verbose, Center, HalfHeight, Radius, FQuat::Identity, NewColor, TEXT_EMPTY); @@ -414,7 +414,7 @@ void FCogDebugDraw::Capsule(const FLogCategoryBase& LogCategory, const UObject* //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Points(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray& Points, float Radius, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { int32 index = 0; for (const FVector& Point : Points) @@ -429,7 +429,7 @@ void FCogDebugDraw::Points(const FLogCategoryBase& LogCategory, const UObject* W //-------------------------------------------------------------------------------------------------------------------------- void FCogDebugDraw::Path(const FLogCategoryBase& LogCategory, const UObject* WorldContextObject, const TArray& Points, float PointSize, const FColor& StartColor, const FColor& EndColor, const bool Persistent, const uint8 DepthPriority) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { if (Points.Num() == 0) { @@ -465,7 +465,7 @@ void FCogDebugDraw::Skeleton(const FLogCategoryBase& LogCategory, const USkeleta return; } - if (FCogDebugLogCategoryManager::IsLogCategoryActive(LogCategory)) + if (FCogDebugLog::IsLogCategoryActive(LogCategory)) { const FReferenceSkeleton& ReferenceSkeleton = Skeleton->GetSkeletalMeshAsset()->GetRefSkeleton(); const FTransform WorldTransform = Skeleton->GetComponentTransform(); diff --git a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategoryManager.cpp b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLog.cpp similarity index 77% rename from Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategoryManager.cpp rename to Plugins/CogDebug/Source/CogDebug/Private/CogDebugLog.cpp index dc88dea..1fe1f6a 100644 --- a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategoryManager.cpp +++ b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLog.cpp @@ -1,4 +1,4 @@ -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" #include "CogDebugModule.h" #include "CogDebugReplicator.h" @@ -10,7 +10,7 @@ DEFINE_LOG_CATEGORY(LogCogNone); DEFINE_LOG_CATEGORY(LogCogServerDebug); -TMap FCogDebugLogCategoryManager::LogCategories; +TMap FCogDebugLog::LogCategories; //-------------------------------------------------------------------------------------------------------------------------- @@ -34,7 +34,7 @@ FString FCogDebugLogCategoryInfo::GetDisplayName() const //-------------------------------------------------------------------------------------------------------------------------- // FCogDebugLogCategoryManager //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::AddLogCategory(FLogCategoryBase& LogCategory, const FString& DisplayName, bool bVisible) +void FCogDebugLog::AddLogCategory(FLogCategoryBase& LogCategory, const FString& DisplayName, bool bVisible) { LogCategories.Add(LogCategory.GetCategoryName(), FCogDebugLogCategoryInfo @@ -47,19 +47,19 @@ void FCogDebugLogCategoryManager::AddLogCategory(FLogCategoryBase& LogCategory, } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogDebugLogCategoryManager::IsVerbosityActive(ELogVerbosity::Type Verbosity) +bool FCogDebugLog::IsVerbosityActive(ELogVerbosity::Type Verbosity) { return Verbosity >= ELogVerbosity::Verbose; } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogDebugLogCategoryManager::IsLogCategoryActive(const FLogCategoryBase& LogCategory) +bool FCogDebugLog::IsLogCategoryActive(const FLogCategoryBase& LogCategory) { return IsVerbosityActive(LogCategory.GetVerbosity()); } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogDebugLogCategoryManager::IsLogCategoryActive(FName CategoryName) +bool FCogDebugLog::IsLogCategoryActive(FName CategoryName) { if (FLogCategoryBase* LogCategory = FindLogCategory(CategoryName)) { @@ -70,13 +70,13 @@ bool FCogDebugLogCategoryManager::IsLogCategoryActive(FName CategoryName) } //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::SetLogCategoryActive(FLogCategoryBase& LogCategory, bool Value) +void FCogDebugLog::SetLogCategoryActive(FLogCategoryBase& LogCategory, bool Value) { LogCategory.SetVerbosity(Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning); } //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::OnServerVerbosityChanged(FName CategoryName, ELogVerbosity::Type Verbosity) +void FCogDebugLog::OnServerVerbosityChanged(FName CategoryName, ELogVerbosity::Type Verbosity) { if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName)) { @@ -85,7 +85,7 @@ void FCogDebugLogCategoryManager::OnServerVerbosityChanged(FName CategoryName, E } //-------------------------------------------------------------------------------------------------------------------------- -ELogVerbosity::Type FCogDebugLogCategoryManager::GetServerVerbosity(FName CategoryName) +ELogVerbosity::Type FCogDebugLog::GetServerVerbosity(FName CategoryName) { if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName)) { @@ -96,7 +96,7 @@ ELogVerbosity::Type FCogDebugLogCategoryManager::GetServerVerbosity(FName Catego } //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::SetServerVerbosity(UWorld& World, FName CategoryName, ELogVerbosity::Type Verbosity) +void FCogDebugLog::SetServerVerbosity(UWorld& World, FName CategoryName, ELogVerbosity::Type Verbosity) { if (ACogDebugReplicator* Replicator = FCogDebugModule::Get().GetLocalReplicator(World)) { @@ -105,25 +105,25 @@ void FCogDebugLogCategoryManager::SetServerVerbosity(UWorld& World, FName Catego } //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::SetServerVerbosityActive(UWorld& World, FName CategoryName, bool Value) +void FCogDebugLog::SetServerVerbosityActive(UWorld& World, FName CategoryName, bool Value) { SetServerVerbosity(World, CategoryName, Value ? ELogVerbosity::Verbose : ELogVerbosity::Warning); } //-------------------------------------------------------------------------------------------------------------------------- -bool FCogDebugLogCategoryManager::IsServerVerbosityActive(FName CategoryName) +bool FCogDebugLog::IsServerVerbosityActive(FName CategoryName) { return IsVerbosityActive(GetServerVerbosity(CategoryName)); } //-------------------------------------------------------------------------------------------------------------------------- -FCogDebugLogCategoryInfo* FCogDebugLogCategoryManager::FindLogCategoryInfo(FName CategoryName) +FCogDebugLogCategoryInfo* FCogDebugLog::FindLogCategoryInfo(FName CategoryName) { return LogCategories.Find(CategoryName); } //-------------------------------------------------------------------------------------------------------------------------- -FLogCategoryBase* FCogDebugLogCategoryManager::FindLogCategory(FName CategoryName) +FLogCategoryBase* FCogDebugLog::FindLogCategory(FName CategoryName) { if (FCogDebugLogCategoryInfo* LogCategoryInfo = FindLogCategoryInfo(CategoryName)) { @@ -138,7 +138,7 @@ FLogCategoryBase* FCogDebugLogCategoryManager::FindLogCategory(FName CategoryNam } //-------------------------------------------------------------------------------------------------------------------------- -void FCogDebugLogCategoryManager::DeactivateAllLogCateories(UWorld& World) +void FCogDebugLog::DeactivateAllLogCateories(UWorld& World) { FString ToggleStr = TEXT("Log LogCogNone Only"); GEngine->Exec(&World, *ToggleStr); diff --git a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogBlueprint.cpp b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogBlueprint.cpp index 5c56a70..5c30c93 100644 --- a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogBlueprint.cpp +++ b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogBlueprint.cpp @@ -1,6 +1,6 @@ #include "CogDebugLogBlueprint.h" -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" #include "CogDebugLogMacros.h" //-------------------------------------------------------------------------------------------------------------------------- @@ -35,7 +35,7 @@ bool UCogDebugLogBlueprint::IsLogActive(const UObject* WorldContextObject, FCogL if (const FLogCategoryBase* LogCategoryPtr = LogCategory.GetLogCategory()) { - if (FCogDebugLogCategoryManager::IsLogCategoryActive(*LogCategoryPtr) == false) + if (FCogDebugLog::IsLogCategoryActive(*LogCategoryPtr) == false) { return false; } diff --git a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategory.cpp b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategory.cpp index 30a36ce..2e5fd51 100644 --- a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategory.cpp +++ b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugLogCategory.cpp @@ -1,6 +1,6 @@ #include "CogDebugLogCategory.h" -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" //-------------------------------------------------------------------------------------------------------------------------- FLogCategoryBase* FCogLogCategory::GetLogCategory() const @@ -18,7 +18,7 @@ FLogCategoryBase* FCogLogCategory::GetLogCategory() const if (LogCategory == nullptr) { - if (FCogDebugLogCategoryInfo* CategoryInfo = FCogDebugLogCategoryManager::GetLogCategories().Find(Name)) + if (FCogDebugLogCategoryInfo* CategoryInfo = FCogDebugLog::GetLogCategories().Find(Name)) { LogCategory = CategoryInfo->LogCategory; } diff --git a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugReplicator.cpp b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugReplicator.cpp index 6a51d48..4647c9f 100644 --- a/Plugins/CogDebug/Source/CogDebug/Private/CogDebugReplicator.cpp +++ b/Plugins/CogDebug/Source/CogDebug/Private/CogDebugReplicator.cpp @@ -181,7 +181,7 @@ void ACogDebugReplicator::Server_SetCategoryVerbosity_Implementation(FName LogCa ENetMode NetMode = GetWorld()->GetNetMode(); if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer) { - if (FCogDebugLogCategoryInfo* LogCategoryInfo = FCogDebugLogCategoryManager::FindLogCategoryInfo(LogCategoryName)) + if (FCogDebugLogCategoryInfo* LogCategoryInfo = FCogDebugLog::FindLogCategoryInfo(LogCategoryName)) { LogCategoryInfo->LogCategory->SetVerbosity((ELogVerbosity::Type)Verbosity); @@ -203,7 +203,7 @@ void ACogDebugReplicator::NetMulticast_SendCategoriesVerbosity_Implementation(co { for (const FCogServerCategoryData& Category : Categories) { - FCogDebugLogCategoryManager::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity); + FCogDebugLog::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity); } } @@ -219,7 +219,7 @@ void ACogDebugReplicator::Client_SendCategoriesVerbosity_Implementation(const TA { for (const FCogServerCategoryData& Category : Categories) { - FCogDebugLogCategoryManager::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity); + FCogDebugLog::OnServerVerbosityChanged(Category.LogCategoryName, (ELogVerbosity::Type)Category.Verbosity); } } @@ -235,7 +235,7 @@ void ACogDebugReplicator::Server_RequestAllCategoriesVerbosity_Implementation() if (NetMode == NM_DedicatedServer || NetMode == NM_ListenServer) { TArray CategoriesData; - for (auto& Entry : FCogDebugLogCategoryManager::GetLogCategories()) + for (auto& Entry : FCogDebugLog::GetLogCategories()) { FCogDebugLogCategoryInfo& CategoryInfo = Entry.Value; if (CategoryInfo.LogCategory != nullptr) diff --git a/Plugins/CogDebug/Source/CogDebug/Public/CogDebugDrawImGui.h b/Plugins/CogDebug/Source/CogDebug/Public/CogDebugDrawImGui.h index 493f35a..e871e11 100644 --- a/Plugins/CogDebug/Source/CogDebug/Public/CogDebugDrawImGui.h +++ b/Plugins/CogDebug/Source/CogDebug/Public/CogDebugDrawImGui.h @@ -3,7 +3,7 @@ #include "CoreMinimal.h" #include "imgui.h" -class FCogDebugDrawImGui +class COGDEBUG_API FCogDebugDrawImGui { public: static void AddLine(const ImVec2& P1, const ImVec2& P2, ImU32 Color, float Thickness = 1.0f, float Duration = 0.0f, bool FadeColor = false); diff --git a/Plugins/CogDebug/Source/CogDebug/Public/CogDebugLogCategoryManager.h b/Plugins/CogDebug/Source/CogDebug/Public/CogDebugLog.h similarity index 97% rename from Plugins/CogDebug/Source/CogDebug/Public/CogDebugLogCategoryManager.h rename to Plugins/CogDebug/Source/CogDebug/Public/CogDebugLog.h index 0d69d65..eb7a858 100644 --- a/Plugins/CogDebug/Source/CogDebug/Public/CogDebugLogCategoryManager.h +++ b/Plugins/CogDebug/Source/CogDebug/Public/CogDebugLog.h @@ -20,7 +20,7 @@ struct COGDEBUG_API FCogDebugLogCategoryInfo }; //-------------------------------------------------------------------------------------------------------------------------- -struct COGDEBUG_API FCogDebugLogCategoryManager +struct COGDEBUG_API FCogDebugLog { static void AddLogCategory(FLogCategoryBase& LogCategory, const FString& DisplayName = "", bool bVisible = true); diff --git a/Plugins/CogDebug/Source/CogDebugEditor/Private/CogDebugLogCategoryDetails.cpp b/Plugins/CogDebug/Source/CogDebugEditor/Private/CogDebugLogCategoryDetails.cpp index 2ba2883..fd0ef1e 100644 --- a/Plugins/CogDebug/Source/CogDebugEditor/Private/CogDebugLogCategoryDetails.cpp +++ b/Plugins/CogDebug/Source/CogDebugEditor/Private/CogDebugLogCategoryDetails.cpp @@ -1,7 +1,7 @@ #include "CogDebugLogCategoryDetails.h" #include "CogDebugLogCategory.h" -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" #include "DetailWidgetRow.h" #include "Editor.h" #include "IPropertyUtilities.h" @@ -27,7 +27,7 @@ void FCogLogCategoryDetails::CustomizeHeader(TSharedRef StructP PropertyOptions.Empty(); PropertyOptions.Add(MakeShareable(new FString("None"))); - for (auto& Entry : FCogDebugLogCategoryManager::GetLogCategories()) + for (auto& Entry : FCogDebugLog::GetLogCategories()) { PropertyOptions.Add(MakeShareable(new FString(Entry.Value.LogCategory->GetCategoryName().ToString()))); } diff --git a/Plugins/CogDebug/Source/CogDebugEditor/Private/SCogDebugLogCategoryWidget.cpp b/Plugins/CogDebug/Source/CogDebugEditor/Private/SCogDebugLogCategoryWidget.cpp index 8b8e1e5..add566b 100644 --- a/Plugins/CogDebug/Source/CogDebugEditor/Private/SCogDebugLogCategoryWidget.cpp +++ b/Plugins/CogDebug/Source/CogDebugEditor/Private/SCogDebugLogCategoryWidget.cpp @@ -247,7 +247,7 @@ TSharedPtr SLogCategoryListWidget::UpdatePropertyOptions PropertyOptions.Add(InitiallySelected); // Gather all ULogCategory classes - for (auto& Entry : FCogDebugLogCategoryManager::GetLogCategories()) + for (auto& Entry : FCogDebugLog::GetLogCategories()) { // if we have a search string and this doesn't match, don't show it if (LogCategoryTextFilter.IsValid() && !LogCategoryTextFilter->PassesFilter(Entry.Value.LogCategory->GetCategoryName())) diff --git a/Plugins/CogEngine/Source/CogEngine/Private/CogEngineWindow_LogCategories.cpp b/Plugins/CogEngine/Source/CogEngine/Private/CogEngineWindow_LogCategories.cpp index fed1ada..78523ad 100644 --- a/Plugins/CogEngine/Source/CogEngine/Private/CogEngineWindow_LogCategories.cpp +++ b/Plugins/CogEngine/Source/CogEngine/Private/CogEngineWindow_LogCategories.cpp @@ -2,7 +2,7 @@ #include "CogDebugHelper.h" #include "CogWindowWidgets.h" -#include "CogDebugLogCategoryManager.h" +#include "CogDebugLog.h" //-------------------------------------------------------------------------------------------------------------------------- void UCogEngineWindow_LogCategories::RenderHelp() @@ -49,7 +49,7 @@ void UCogEngineWindow_LogCategories::RenderContent() if (ImGui::MenuItem("Reset")) { - FCogDebugLogCategoryManager::DeactivateAllLogCateories(*World); + FCogDebugLog::DeactivateAllLogCateories(*World); } if (ImGui::IsItemHovered()) @@ -77,7 +77,7 @@ void UCogEngineWindow_LogCategories::RenderContent() ImGuiStyle& Style = ImGui::GetStyle(); int Index = 0; - for (const auto& Entry : FCogDebugLogCategoryManager::GetLogCategories()) + for (const auto& Entry : FCogDebugLog::GetLogCategories()) { FName CategoryName = Entry.Key; const FCogDebugLogCategoryInfo& CategoryInfo = Entry.Value; @@ -96,8 +96,8 @@ void UCogEngineWindow_LogCategories::RenderContent() const bool IsControlDown = ImGui::GetIO().KeyCtrl; if (IsClient) { - ELogVerbosity::Type Verbosity = FCogDebugLogCategoryManager::GetServerVerbosity(CategoryName); - bool IsActive = FCogDebugLogCategoryManager::IsVerbosityActive(Verbosity); + ELogVerbosity::Type Verbosity = FCogDebugLog::GetServerVerbosity(CategoryName); + bool IsActive = FCogDebugLog::IsVerbosityActive(Verbosity); if (Verbosity == ELogVerbosity::VeryVerbose) { @@ -107,7 +107,7 @@ void UCogEngineWindow_LogCategories::RenderContent() if (ImGui::Checkbox("##Server", &IsActive)) { ELogVerbosity::Type NewVerbosity = IsActive ? (IsControlDown ? ELogVerbosity::VeryVerbose : ELogVerbosity::Verbose) : ELogVerbosity::Warning; - FCogDebugLogCategoryManager::SetServerVerbosity(*World, CategoryName, NewVerbosity); + FCogDebugLog::SetServerVerbosity(*World, CategoryName, NewVerbosity); } if (Verbosity == ELogVerbosity::VeryVerbose) @@ -128,7 +128,7 @@ void UCogEngineWindow_LogCategories::RenderContent() { ELogVerbosity::Type Verbosity = Category->GetVerbosity(); - bool IsActive = FCogDebugLogCategoryManager::IsVerbosityActive(Verbosity); + bool IsActive = FCogDebugLog::IsVerbosityActive(Verbosity); if (Verbosity == ELogVerbosity::VeryVerbose) { @@ -162,7 +162,7 @@ void UCogEngineWindow_LogCategories::RenderContent() { if (IsClient) { - ELogVerbosity::Type CurrentVerbosity = FCogDebugLogCategoryManager::GetServerVerbosity(CategoryName); + ELogVerbosity::Type CurrentVerbosity = FCogDebugLog::GetServerVerbosity(CategoryName); FCogWindowWidgets::SetNextItemToShortWidth(); if (ImGui::BeginCombo("##Server", FCogDebugHelper::VerbosityToString(CurrentVerbosity))) { @@ -173,7 +173,7 @@ void UCogEngineWindow_LogCategories::RenderContent() if (ImGui::Selectable(FCogDebugHelper::VerbosityToString(Verbosity), IsSelected)) { - FCogDebugLogCategoryManager::SetServerVerbosity(*World, CategoryName, Verbosity); + FCogDebugLog::SetServerVerbosity(*World, CategoryName, Verbosity); } } ImGui::EndCombo(); diff --git a/Source/CogSample/CogDefines.h b/Source/CogSample/CogDefines.h index ad566e8..45a03a2 100644 --- a/Source/CogSample/CogDefines.h +++ b/Source/CogSample/CogDefines.h @@ -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 diff --git a/Source/CogSample/CogSampleCharacter.cpp b/Source/CogSample/CogSampleCharacter.cpp index 7a8bc77..ead5ef2 100644 --- a/Source/CogSample/CogSampleCharacter.cpp +++ b/Source/CogSample/CogSampleCharacter.cpp @@ -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(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& Capsules) const +{ + Capsules.Add(GetCapsuleComponent()); } \ No newline at end of file diff --git a/Source/CogSample/CogSampleCharacter.h b/Source/CogSample/CogSampleCharacter.h index 4b0ac15..3f8048a 100644 --- a/Source/CogSample/CogSampleCharacter.h +++ b/Source/CogSample/CogSampleCharacter.h @@ -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& 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 diff --git a/Source/CogSample/CogSampleFunctionLibrary_Gameplay.cpp b/Source/CogSample/CogSampleFunctionLibrary_Gameplay.cpp index 70fcc7d..42bc85b 100644 --- a/Source/CogSample/CogSampleFunctionLibrary_Gameplay.cpp +++ b/Source/CogSample/CogSampleFunctionLibrary_Gameplay.cpp @@ -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>& ObjectTypes) +{ + TArray> 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(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); +} \ No newline at end of file diff --git a/Source/CogSample/CogSampleFunctionLibrary_Gameplay.h b/Source/CogSample/CogSampleFunctionLibrary_Gameplay.h index 29a58ac..7974fc8 100644 --- a/Source/CogSample/CogSampleFunctionLibrary_Gameplay.h +++ b/Source/CogSample/CogSampleFunctionLibrary_Gameplay.h @@ -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>& 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); }; diff --git a/Source/CogSample/CogSampleFunctionLibrary_Team.cpp b/Source/CogSample/CogSampleFunctionLibrary_Team.cpp new file mode 100644 index 0000000..c5b06ac --- /dev/null +++ b/Source/CogSample/CogSampleFunctionLibrary_Team.cpp @@ -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(Actor1); + const ICogSampleTeamInterface* TeamActor2 = Cast(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; +} \ No newline at end of file diff --git a/Source/CogSample/CogSampleFunctionLibrary_Team.h b/Source/CogSample/CogSampleFunctionLibrary_Team.h new file mode 100644 index 0000000..69ad7ae --- /dev/null +++ b/Source/CogSample/CogSampleFunctionLibrary_Team.h @@ -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); + +}; diff --git a/Source/CogSample/CogSampleGameState.cpp b/Source/CogSample/CogSampleGameState.cpp index 313c9ce..cb1ca49 100644 --- a/Source/CogSample/CogSampleGameState.cpp +++ b/Source/CogSample/CogSampleGameState.cpp @@ -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 diff --git a/Source/CogSample/CogSampleLogCategories.cpp b/Source/CogSample/CogSampleLogCategories.cpp index 53da048..0cd8556 100644 --- a/Source/CogSample/CogSampleLogCategories.cpp +++ b/Source/CogSample/CogSampleLogCategories.cpp @@ -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 } } diff --git a/Source/CogSample/CogSampleLogCategories.h b/Source/CogSample/CogSampleLogCategories.h index c85f12b..8d8da8e 100644 --- a/Source/CogSample/CogSampleLogCategories.h +++ b/Source/CogSample/CogSampleLogCategories.h @@ -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 { diff --git a/Source/CogSample/CogSamplePlayerController.cpp b/Source/CogSample/CogSamplePlayerController.cpp index 4fc271c..6ce3d86 100644 --- a/Source/CogSample/CogSamplePlayerController.cpp +++ b/Source/CogSample/CogSamplePlayerController.cpp @@ -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 TagretToIgnore; + FCogSampleTargetAcquisitionResult Result; + TargetAcquisition->FindBestTarget(this, TagretToIgnore, nullptr, true, FVector2D::ZeroVector, false, Result); + Target = Result.Target; + } } \ No newline at end of file diff --git a/Source/CogSample/CogSamplePlayerController.h b/Source/CogSample/CogSamplePlayerController.h index f071173..89cc44b 100644 --- a/Source/CogSample/CogSamplePlayerController.h +++ b/Source/CogSample/CogSamplePlayerController.h @@ -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 Target = nullptr; }; diff --git a/Source/CogSample/CogSampleTargetAcquisition.cpp b/Source/CogSample/CogSampleTargetAcquisition.cpp new file mode 100644 index 0000000..4ba3299 --- /dev/null +++ b/Source/CogSample/CogSampleTargetAcquisition.cpp @@ -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 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& TargetsToIgnore, + const AActor* CurrentLockedTarget, + const bool bForceSynchronousDetection, + const FVector2D ScreenSearchDirection, + bool bIsDebugPersistent, + TArray& Results) const +{ + TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::FindBestTargets); + + COG(FCogDebugDraw::String2D(LogCogTargetAcquisition, Controller, GetName(), FVector2D(20, 20), FColor::White, bIsDebugPersistent)); + + TArray 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& 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(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 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 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 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& TargetsToIgnore, + const TArray& Candidates, + const FVector2D ScreenSearchDirection, + const FVector2D SearchDirectionScreenOrigin, + const bool bIsDebugPersistent, + FCogSampleTargetAcquisitionResult& Result) const +{ + TRACE_CPUPROFILER_EVENT_SCOPE(UCogSampleTargetAcquisition::FindBestTargetInCandidates); + + ACogSampleCharacter* Character = Cast(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(CandidateActor)) + { + TArray 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; +} diff --git a/Source/CogSample/CogSampleTargetAcquisition.h b/Source/CogSample/CogSampleTargetAcquisition.h new file mode 100644 index 0000000..20af702 --- /dev/null +++ b/Source/CogSample/CogSampleTargetAcquisition.h @@ -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> ObjectTypes; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "General") + TArray> 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& TargetsToIgnore, + const AActor* CurrentLockedTarget, + const bool bForceSynchronousDetection, + const FVector2D ScreenSearchDirection, + const bool bIsDebugPersistent, + TArray& 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& TargetsToIgnore, + const TArray& Candidates, + const FVector2D ScreenSearchDirection, + const FVector2D SearchDirectionViewportOrigin, + const bool bIsDebugPersistent, + FCogSampleTargetAcquisitionResult& Result) const; + + void FindBestTarget( + const APlayerController* Controller, + const TArray& 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); +}; \ No newline at end of file diff --git a/Source/CogSample/CogSampleTargetableInterface.h b/Source/CogSample/CogSampleTargetableInterface.h new file mode 100644 index 0000000..c361a21 --- /dev/null +++ b/Source/CogSample/CogSampleTargetableInterface.h @@ -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& Capsules) const { } +}; diff --git a/Source/CogSample/CogSampleTeamInterface.h b/Source/CogSample/CogSampleTeamInterface.h new file mode 100644 index 0000000..748a622 --- /dev/null +++ b/Source/CogSample/CogSampleTeamInterface.h @@ -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; } +};