Last active
May 17, 2022 07:25
-
-
Save Mikea15/1de0dd7d4956b37d0b3b3cce10dabf2e to your computer and use it in GitHub Desktop.
Pseudo-Untested-Modular-Target-Selection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) Michael Adaixo - 2022 | |
#pragma once | |
#include "CoreMinimal.h" | |
#include "ITargetSelector.generated.h" | |
/* | |
* Base TS Filter object | |
*/ | |
UCLASS(ClassGroup = TargetSelector, abstract, EditInlineNew) | |
class UTSFilter : public UObject | |
{ | |
GENERATED_BODY() | |
public: | |
virtual bool PassesFilters(const AActor* Querier, const AActor* Perceived) { return true; } | |
}; | |
/* | |
* Affinity TS Filter | |
*/ | |
UCLASS(meta = (DisplayName = "Target Selector | Filter | Affinity")) | |
class UTSFilter_Affinity : public UTSFilter | |
{ | |
GENERATED_BODY() | |
public: | |
bool PassesFilters(const AActor* Querier, const AActor* Perceived) override { /* if then bla */ return true; } | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool AcceptFriendly; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool AcceptHostile; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool AcceptNeutral; | |
}; | |
/* | |
* ZHeight TS Filter | |
*/ | |
UCLASS(meta = (DisplayName = "Target Selector | Filter | ZHeight")) | |
class UTSFilter_ZDist : public UTSFilter | |
{ | |
GENERATED_BODY() | |
public: | |
bool PassesFilters(const AActor* Querier, const AActor* Perceived) override { /* if then bla */ return true; } | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
float HeightMarginOfError = 500.0f; | |
}; | |
/* | |
* Base TS Weight object | |
*/ | |
UCLASS(ClassGroup = TargetSelector, abstract, EditInlineNew) | |
class UTSWeight : public UObject | |
{ | |
GENERATED_BODY() | |
public: | |
virtual float ApplyWeight(const AActor* Querier, const AActor* Perceived) { return 1.0f; } | |
float MaybeClamp(float Weight) | |
{ | |
if (!bClampWeight) { return Weight; } | |
return FMath::Clamp(Weight, MinClamp, MaxClamp); | |
} | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool bClampWeight = false; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (EditCondition = "bClampWeight", EditConditionHides)) | |
float MinClamp; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (EditCondition = "bClampWeight", EditConditionHides)) | |
float MaxClamp; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool bNormalizeValues = false; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (EditCondition = "bNormalizeValues", EditConditionHides)) | |
float MinValue; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (EditCondition = "bNormalizeValues", EditConditionHides)) | |
float MaxValue; | |
}; | |
/* | |
* Distance TS Weight | |
*/ | |
UCLASS(meta = (DisplayName = "Target Selector | Weight | Distance")) | |
class UTSWeight_Distance : public UTSWeight | |
{ | |
GENERATED_BODY() | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (UIMin = 0.0, ClampMin = 0.0)) | |
float MaxDistance; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
bool IsInvincible; | |
}; | |
/* | |
* ThreatLevel TS Weight | |
*/ | |
UCLASS(meta = (DisplayName = "Target Selector | Weight | Threat Level")) | |
class UTSWeight_ThreatLevel : public UTSWeight | |
{ | |
GENERATED_BODY() | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (UIMin = 0.0, ClampMin = 0.0)) | |
float MaxThreat; | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
int ExampleOption2; | |
}; | |
/* | |
* SameTarget TS Weight | |
*/ | |
UCLASS(meta = (DisplayName = "Target Selector | Weight | SameTarget")) | |
class UTSWeight_SameTarget : public UTSWeight | |
{ | |
GENERATED_BODY() | |
public: | |
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) | |
float Multiplier; | |
}; | |
/* | |
* Main TargetSelector | |
*/ | |
UCLASS(Blueprintable, abstract, ClassGroup = TargetSelector, EditInlineNew) | |
class UTargetSelector : public UObject | |
{ | |
GENERATED_BODY() | |
public: | |
UFUNCTION(BlueprintCallable, Category = "Target Selector") | |
AActor* SelectTarget(const AActor* SelfActor, TArray<AActor*> PerceivedActor); | |
public: | |
UPROPERTY(EditDefaultsOnly, Instanced, Category = "Target Selector") | |
TArray<TObjectPtr<UTSFilter>> Filters; | |
UPROPERTY(EditDefaultsOnly, Instanced, Category = "Target Selector") | |
TArray<TObjectPtr<UTSWeight>> Weights; | |
}; | |
// .cpp | |
AActor* UTargetSelector::SelectTarget(const AActor* SelfActor, TArray<AActor*> PerceivedActor) | |
{ | |
AActor* BestActor = nullptr; | |
float BestScore = -FLT_MAX; | |
for (AActor* Perceived : PerceivedActor) | |
{ | |
bool bPassedFilters = false; | |
for (const TObjectPtr<UTSFilter>& Filter : Filters) | |
{ | |
bPassedFilters = Filter->PassesFilters(SelfActor, Perceived); | |
if (!bPassedFilters) | |
{ | |
break; | |
} | |
} | |
if (!bPassedFilters) | |
{ | |
continue; | |
} | |
float Score = 1.0f; | |
for (const TObjectPtr<UTSWeight>& Weight : Weights) | |
{ | |
const float TempWeight = Weight->ApplyWeight(SelfActor, Perceived); | |
Score *= Weight->MaybeClamp(TempWeight); | |
if (Score <= 0.0f) | |
{ | |
break; | |
} | |
} | |
if (Score > BestScore) | |
{ | |
BestScore = Score; | |
BestActor = Perceived; | |
} | |
} | |
return BestActor; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment