2021-09-28 13:33:17 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "AITestsCommon.h"
2023-07-18 08:42:51 -04:00
# include "Engine/World.h"
2022-03-02 13:25:37 -05:00
# include "GameplayTagsManager.h"
2021-09-28 13:33:17 -04:00
# include "SmartObjectComponent.h"
# include "SmartObjectTestTypes.h"
2023-01-18 10:52:51 -05:00
# include "WorldConditions/SmartObjectWorldConditionObjectTagQuery.h"
2021-09-28 13:33:17 -04:00
# define LOCTEXT_NAMESPACE "AITestSuite_SmartObjectsTest"
namespace FSmartObjectTest
{
2022-11-07 09:57:31 -05:00
const FVector QueryExtent = FVector ( 5000.f ) ;
const FBox QueryBounds = FBox ( EForceInit : : ForceInit ) . ExpandBy ( QueryExtent , QueryExtent ) ;
// Helper struct to define some test tags
struct FNativeGameplayTags : public FGameplayTagNativeAdder
{
FGameplayTag TestTag1 ;
FGameplayTag TestTag2 ;
FGameplayTag TestTag3 ;
virtual void AddTags ( ) override
2022-03-02 13:25:37 -05:00
{
2022-11-07 09:57:31 -05:00
UGameplayTagsManager & Manager = UGameplayTagsManager : : Get ( ) ;
TestTag1 = Manager . AddNativeGameplayTag ( TEXT ( " Test.SmartObject.Tag1 " ) ) ;
TestTag2 = Manager . AddNativeGameplayTag ( TEXT ( " Test.SmartObject.Tag2 " ) ) ;
TestTag3 = Manager . AddNativeGameplayTag ( TEXT ( " Test.SmartObject.Tag3 " ) ) ;
}
2022-03-02 13:25:37 -05:00
2022-11-07 09:57:31 -05:00
FORCEINLINE static const FNativeGameplayTags & Get ( )
{
return StaticInstance ;
}
static FNativeGameplayTags StaticInstance ;
} ;
FNativeGameplayTags FNativeGameplayTags : : StaticInstance ;
2022-03-02 13:25:37 -05:00
2021-09-28 13:33:17 -04:00
struct FSmartObjectTestBase : FAITestBase
{
2023-02-02 18:43:13 -05:00
FSmartObjectActorUserData TestContextData ;
2021-09-28 13:33:17 -04:00
FSmartObjectRequestFilter TestFilter ;
2022-03-02 13:25:37 -05:00
USmartObjectDefinition * Definition = nullptr ;
2022-11-07 09:57:31 -05:00
USmartObjectTestSubsystem * Subsystem = nullptr ;
2021-09-28 13:33:17 -04:00
TArray < USmartObjectComponent * > SOList ;
2022-03-02 13:25:37 -05:00
int32 NumCreatedSlots = 0 ;
/** Callback that derived classes can override to tweak the SmartObjectDefinition before the runtime gets initialized */
virtual bool SetupDefinition ( ) { return true ; }
2021-09-28 13:33:17 -04:00
virtual bool SetUp ( ) override
{
UWorld * World = FAITestHelpers : : GetWorld ( ) ;
2022-11-07 09:57:31 -05:00
Subsystem = NewAutoDestroyObject < USmartObjectTestSubsystem > ( World ) ;
2021-09-28 13:33:17 -04:00
if ( Subsystem = = nullptr )
{
return false ;
}
2022-01-19 14:16:16 -05:00
// Setup main definition
2022-03-02 13:25:37 -05:00
Definition = NewAutoDestroyObject < USmartObjectDefinition > ( ) ;
// Set activity tags
Definition - > SetActivityTags ( FGameplayTagContainer ( FNativeGameplayTags : : Get ( ) . TestTag1 ) ) ;
2022-01-31 18:52:49 -05:00
FSmartObjectSlotDefinition & FirstSlot = Definition - > DebugAddSlot ( ) ;
FSmartObjectSlotDefinition & SecondSlot = Definition - > DebugAddSlot ( ) ;
2022-03-02 13:25:37 -05:00
FSmartObjectSlotDefinition & ThirdSlot = Definition - > DebugAddSlot ( ) ;
2022-01-19 14:16:16 -05:00
// Add some test behavior definition
2022-01-31 18:52:49 -05:00
FirstSlot . BehaviorDefinitions . Add ( NewAutoDestroyObject < USmartObjectTestBehaviorDefinition > ( ) ) ;
SecondSlot . BehaviorDefinitions . Add ( NewAutoDestroyObject < USmartObjectTestBehaviorDefinition > ( ) ) ;
2022-03-02 13:25:37 -05:00
ThirdSlot . BehaviorDefinitions . Add ( NewAutoDestroyObject < USmartObjectTestBehaviorDefinition > ( ) ) ;
2022-01-19 14:16:16 -05:00
// Add some test slot definition data
FSmartObjectSlotTestDefinitionData DefinitionData ;
DefinitionData . SomeSharedFloat = 123.456f ;
2023-08-29 07:48:32 -04:00
2023-12-04 07:36:52 -05:00
FirstSlot . DefinitionData . Add ( FSmartObjectDefinitionDataProxy : : Make ( DefinitionData ) ) ;
SecondSlot . DefinitionData . Add ( FSmartObjectDefinitionDataProxy : : Make ( DefinitionData ) ) ;
ThirdSlot . DefinitionData . Add ( FSmartObjectDefinitionDataProxy : : Make ( DefinitionData ) ) ;
2021-09-28 13:33:17 -04:00
// Setup filter
2022-09-08 19:27:10 -04:00
TestFilter . BehaviorDefinitionClasses = { USmartObjectTestBehaviorDefinition : : StaticClass ( ) } ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Allow derived classes to tweak the definitions before we initialize the runtime
2022-11-07 09:57:31 -05:00
const bool DefinitionSetUp = SetupDefinition ( ) ;
if ( ! DefinitionSetUp )
2022-03-02 13:25:37 -05:00
{
return false ;
}
2021-09-28 13:33:17 -04:00
// Create some smart objects
SOList =
{
NewAutoDestroyObject < USmartObjectComponent > ( World ) ,
NewAutoDestroyObject < USmartObjectComponent > ( World )
} ;
// Register all to the subsystem
for ( USmartObjectComponent * SO : SOList )
{
if ( SO ! = nullptr )
{
2021-11-26 09:52:13 -05:00
SO - > SetDefinition ( Definition ) ;
2021-09-28 13:33:17 -04:00
Subsystem - > RegisterSmartObject ( * SO ) ;
2022-03-02 13:25:37 -05:00
NumCreatedSlots + = Definition - > GetSlots ( ) . Num ( ) ;
2021-09-28 13:33:17 -04:00
}
}
2023-07-18 08:42:51 -04:00
Subsystem - > RebuildAndInitializeForTesting ( ) ;
2022-01-19 14:16:16 -05:00
2021-09-28 13:33:17 -04:00
return true ;
}
virtual void TearDown ( ) override
{
2022-11-07 09:57:31 -05:00
if ( Subsystem ! = nullptr )
2021-09-28 13:33:17 -04:00
{
# if WITH_SMARTOBJECT_DEBUG
2022-11-07 09:57:31 -05:00
// Force removal from the runtime simulation
Subsystem - > DebugCleanupRuntime ( ) ;
2021-09-28 13:33:17 -04:00
# endif
2022-11-07 09:57:31 -05:00
// Unregister all from the current test
for ( USmartObjectComponent * SO : SOList )
2021-09-28 13:33:17 -04:00
{
2022-11-07 09:57:31 -05:00
if ( SO ! = nullptr )
{
Subsystem - > UnregisterSmartObject ( * SO ) ;
}
2021-09-28 13:33:17 -04:00
}
}
FAITestBase : : TearDown ( ) ;
}
} ;
struct FFindSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult FindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , FindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , FindResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FFindSmartObject , " System.AI.SmartObjects.Find " ) ;
2022-01-31 18:52:49 -05:00
struct FFindMultipleSmartObjects : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-01-31 18:52:49 -05:00
2022-03-02 13:25:37 -05:00
// Find all candidates
2022-01-31 18:52:49 -05:00
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( Request , Results ) ;
2022-03-02 13:25:37 -05:00
AITEST_EQUAL ( " Results.Num() " , Results . Num ( ) , NumCreatedSlots ) ;
2022-01-31 18:52:49 -05:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FFindMultipleSmartObjects , " System.AI.SmartObjects.Find multiple " ) ;
2021-09-28 13:33:17 -04:00
struct FClaimAndReleaseSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult FirstFindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , FirstFindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , FirstFindResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Gather all available candidates before claiming
TArray < FSmartObjectSlotHandle > ResultsBeforeClaim ;
Subsystem - > FindSlots ( FirstFindResult . SmartObjectHandle , TestFilter , ResultsBeforeClaim ) ;
// Claim candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle ClaimHandle = Subsystem - > MarkSlotAsClaimed ( FirstFindResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() " , ClaimHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Gather remaining available candidates
TArray < FSmartObjectSlotHandle > ResultsAfterClaim ;
Subsystem - > FindSlots ( FirstFindResult . SmartObjectHandle , TestFilter , ResultsAfterClaim ) ;
AITEST_NOT_EQUAL ( " Number of available slots before and after a claim " , ResultsBeforeClaim . Num ( ) , ResultsAfterClaim . Num ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Release claimed candidate
2023-06-08 10:34:40 -04:00
const bool bSuccess = Subsystem - > MarkSlotAsFree ( ClaimHandle ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Release() return status " , bSuccess ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Gather all available candidates after releasing
TArray < FSmartObjectSlotHandle > ResultsAfterRelease ;
Subsystem - > FindSlots ( FirstFindResult . SmartObjectHandle , TestFilter , ResultsAfterRelease ) ;
AITEST_EQUAL ( " Number of available slots before claiming and after releasing " , ResultsBeforeClaim . Num ( ) , ResultsAfterRelease . Num ( ) ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FClaimAndReleaseSmartObject , " System.AI.SmartObjects.Claim & Release " ) ;
struct FFindAfterClaimSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find first candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult FirstFindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , FirstFindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , FirstFindResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim first candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle FirstClaimHandle = Subsystem - > MarkSlotAsClaimed ( FirstFindResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() after first find result " , FirstClaimHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find second candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult SecondFindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , SecondFindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , SecondFindResult . SmartObjectHandle . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SlotHandle.IsValid() " , SecondFindResult . SlotHandle . IsValid ( ) ) ;
AITEST_NOT_EQUAL ( " Result is expected to point to a different slot since first slot was claimed " , FirstFindResult . SlotHandle , SecondFindResult . SlotHandle ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FFindAfterClaimSmartObject , " System.AI.SmartObjects.Find after Claim " ) ;
struct FDoubleClaimSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult PreClaimResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , PreClaimResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , PreClaimResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim first candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle FirstHdl = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() after first claim " , FirstHdl . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim first candidate again
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle SecondHdl = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_FALSE ( " ClaimHandle.IsValid() after second claim " , SecondHdl . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FDoubleClaimSmartObject , " System.AI.SmartObjects.Double Claim " ) ;
2023-11-30 02:26:33 -05:00
struct FOverrideClaimSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
TArray < FSmartObjectRequestResult > PostClaimResults ;
// Find candidate
const FSmartObjectRequestResult PreClaimResult = Subsystem - > FindSmartObject ( Request ) ;
AITEST_TRUE ( " Result.IsValid() " , PreClaimResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , PreClaimResult . SmartObjectHandle . IsValid ( ) ) ;
// Claim slot the first time with Normal priority, should succeed.
const FSmartObjectClaimHandle FirstHandle = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
AITEST_TRUE ( " FirstHandle.IsValid() after first claim " , FirstHandle . IsValid ( ) ) ;
// Try to claim slot again with Low priority, should fail.
const FSmartObjectClaimHandle SecondHandle = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Low ) ;
AITEST_FALSE ( " SecondHandle.IsValid() after second claim " , SecondHandle . IsValid ( ) ) ;
// Try to claim slot again with High priority, should succeed.
const FSmartObjectClaimHandle ThirdHandle = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : High ) ;
AITEST_TRUE ( " ThirdHandle.IsValid() after third claim " , ThirdHandle . IsValid ( ) ) ;
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FOverrideClaimSmartObject , " System.AI.SmartObjects.Override Claim " ) ;
struct FFindClaimPrioritySmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
TArray < FSmartObjectRequestResult > PostClaimResults ;
// Find candidate
const FSmartObjectRequestResult PreClaimResult = Subsystem - > FindSmartObject ( Request ) ;
AITEST_TRUE ( " Result.IsValid() " , PreClaimResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , PreClaimResult . SmartObjectHandle . IsValid ( ) ) ;
// Claim first candidate
const FSmartObjectClaimHandle FirstHdl = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
AITEST_TRUE ( " ClaimHandle.IsValid() after first claim " , FirstHdl . IsValid ( ) ) ;
// Find candidate should not contain the first result on "normal" claim priority.
Request . Filter . ClaimPriority = ESmartObjectClaimPriority : : Normal ;
PostClaimResults . Reset ( ) ;
Subsystem - > FindSmartObjects ( Request , PostClaimResults ) ;
const bool bContainsClaimedNormal = PostClaimResults . Contains ( PreClaimResult ) ;
AITEST_FALSE ( " bContainsClaimed " , bContainsClaimedNormal ) ;
// Find candidate should contain the first result on "high" claim priority.
Request . Filter . ClaimPriority = ESmartObjectClaimPriority : : High ;
PostClaimResults . Reset ( ) ;
Subsystem - > FindSmartObjects ( Request , PostClaimResults ) ;
const bool bContainsClaimedHigh = PostClaimResults . Contains ( PreClaimResult ) ;
AITEST_TRUE ( " bContainsClaimed " , bContainsClaimedHigh ) ;
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FFindClaimPrioritySmartObject , " System.AI.SmartObjects.Find Claim Priority " ) ;
2021-09-28 13:33:17 -04:00
struct FUseAndReleaseSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult PreClaimResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , PreClaimResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , PreClaimResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim & Use candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle Hdl = Subsystem - > MarkSlotAsClaimed ( PreClaimResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() " , Hdl . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Use specific behavior
2023-06-08 10:34:40 -04:00
const USmartObjectBehaviorDefinition * BehaviorDefinition = Subsystem - > MarkSlotAsOccupied < USmartObjectBehaviorDefinition > ( Hdl ) ;
2022-03-02 13:25:37 -05:00
AITEST_NOT_NULL ( " Behavior definition pointer " , BehaviorDefinition ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Release candidate
2023-06-08 10:34:40 -04:00
const bool bSuccess = Subsystem - > MarkSlotAsFree ( Hdl ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Release() return status " , bSuccess ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FUseAndReleaseSmartObject , " System.AI.SmartObjects.Use & Release " ) ;
struct FFindAfterUseSmartObject : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2021-09-28 13:33:17 -04:00
2022-01-19 14:16:16 -05:00
constexpr uint32 ExpectedNumRegisteredObjects = 2 ;
2022-03-02 13:25:37 -05:00
AITEST_EQUAL ( " Number of registerd smart objects " , SOList . Num ( ) , ExpectedNumRegisteredObjects ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find first candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult FirstFindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , FirstFindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , FirstFindResult . SmartObjectHandle . IsValid ( ) ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim & Use first candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle FirstClaimHandle = Subsystem - > MarkSlotAsClaimed ( FirstFindResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() after first claim " , FirstClaimHandle . IsValid ( ) ) ;
2023-06-08 10:34:40 -04:00
const USmartObjectBehaviorDefinition * FirstDefinition = Subsystem - > MarkSlotAsOccupied < USmartObjectBehaviorDefinition > ( FirstClaimHandle ) ;
2022-03-02 13:25:37 -05:00
AITEST_NOT_NULL ( " Behavior definition pointer " , FirstDefinition ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Find second candidate
2021-09-28 13:33:17 -04:00
const FSmartObjectRequestResult SecondFindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , SecondFindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , SecondFindResult . SmartObjectHandle . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SlotHandle.IsValid() " , SecondFindResult . SlotHandle . IsValid ( ) ) ;
AITEST_NOT_EQUAL ( " Result is expected to point to a different slot since first slot was claimed " , FirstFindResult . SlotHandle , SecondFindResult . SlotHandle ) ;
2021-09-28 13:33:17 -04:00
2022-03-02 13:25:37 -05:00
// Claim & use second candidate
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle SecondClaimHandle = Subsystem - > MarkSlotAsClaimed ( SecondFindResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() after second claim " , SecondClaimHandle . IsValid ( ) ) ;
2023-06-08 10:34:40 -04:00
const USmartObjectBehaviorDefinition * SecondDefinition = Subsystem - > MarkSlotAsOccupied < USmartObjectBehaviorDefinition > ( SecondClaimHandle ) ;
2022-03-02 13:25:37 -05:00
AITEST_NOT_NULL ( " Behavior definition pointer " , SecondDefinition ) ;
2021-09-28 13:33:17 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FFindAfterUseSmartObject , " System.AI.SmartObjects.Find after Use " ) ;
2022-01-19 14:16:16 -05:00
struct FSlotCustomData : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest Request ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-01-19 14:16:16 -05:00
// Find an object
const FSmartObjectRequestResult FindResult = Subsystem - > FindSmartObject ( Request ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " Result.IsValid() " , FindResult . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SmartObjectHandle.IsValid() " , FindResult . SmartObjectHandle . IsValid ( ) ) ;
AITEST_TRUE ( " Result.SlotHandle.IsValid() " , FindResult . SlotHandle . IsValid ( ) ) ;
2022-01-19 14:16:16 -05:00
2022-03-16 03:47:02 -04:00
const FSmartObjectSlotView SlotView = Subsystem - > GetSlotView ( FindResult . SlotHandle ) ;
AITEST_TRUE ( " SlotView.IsValid() " , SlotView . IsValid ( ) ) ;
AITEST_TRUE ( " SlotView.SlotHandle.IsValid() " , SlotView . GetSlotHandle ( ) . IsValid ( ) ) ;
2022-01-19 14:16:16 -05:00
const FSmartObjectSlotTestDefinitionData * DefinitionData = SlotView . GetDefinitionDataPtr < FSmartObjectSlotTestDefinitionData > ( ) ;
2022-03-02 13:25:37 -05:00
AITEST_NOT_NULL ( " Data definition pointer (for cooldown) " , DefinitionData ) ;
2022-01-19 14:16:16 -05:00
const FSmartObjectSlotTestRuntimeData * RuntimeData = SlotView . GetStateDataPtr < FSmartObjectSlotTestRuntimeData > ( ) ;
2022-03-02 13:25:37 -05:00
AITEST_NULL ( " Runtime data pointer " , RuntimeData ) ;
2022-01-19 14:16:16 -05:00
// Claim
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle ClaimHandle = Subsystem - > MarkSlotAsClaimed ( FindResult . SlotHandle , ESmartObjectClaimPriority : : Normal ) ;
2022-03-02 13:25:37 -05:00
AITEST_TRUE ( " ClaimHandle.IsValid() after first claim " , ClaimHandle . IsValid ( ) ) ;
2022-01-19 14:16:16 -05:00
// Add new data, note that this will invalidate the view...
FSmartObjectSlotTestRuntimeData NewRuntimeData ;
constexpr float SomeFloatConstant = 654.321f ;
NewRuntimeData . SomePerInstanceSharedFloat = SomeFloatConstant ;
2023-07-18 08:42:51 -04:00
Subsystem - > AddSlotData ( ClaimHandle , FConstStructView : : Make ( NewRuntimeData ) ) ;
2022-01-19 14:16:16 -05:00
// Fetch a fresh slot view
2022-03-16 03:47:02 -04:00
const FSmartObjectSlotView SlotViewAfter = Subsystem - > GetSlotView ( ClaimHandle . SlotHandle ) ;
2022-01-19 14:16:16 -05:00
const FSmartObjectSlotTestRuntimeData * RuntimeDataAfter = SlotViewAfter . GetStateDataPtr < FSmartObjectSlotTestRuntimeData > ( ) ;
2022-03-02 13:25:37 -05:00
AITEST_NOT_NULL ( " Runtime data pointer " , RuntimeDataAfter ) ;
AITEST_EQUAL ( " Runtime data float from SlotView " , RuntimeDataAfter - > SomePerInstanceSharedFloat , SomeFloatConstant ) ;
2022-01-19 14:16:16 -05:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FSlotCustomData , " System.AI.SmartObjects.Slot custom data " ) ;
2023-05-26 12:48:38 -04:00
struct FDebugUnregister : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
for ( const USmartObjectComponent * SmartObjectComponent : SOList )
{
AITEST_TRUE ( " SmartObjectComponent is initially bound to simulation " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
2023-05-26 16:30:18 -04:00
# if WITH_SMARTOBJECT_DEBUG
2023-05-26 12:48:38 -04:00
Subsystem - > DebugUnregisterAllSmartObjects ( ) ;
for ( const USmartObjectComponent * SmartObjectComponent : SOList )
{
AITEST_FALSE ( " SmartObjectComponent is not bound to simulation after calling RemoveComponentFromSimulation " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
2023-05-26 16:30:18 -04:00
# endif // WITH_SMARTOBJECT_DEBUG
2023-05-26 12:48:38 -04:00
// Simulate a call to EndPlay by calling UnregisterSmartObject after using DebugUnregisterAllSmartObjects
for ( USmartObjectComponent * SmartObjectComponent : SOList )
{
Subsystem - > UnregisterSmartObject ( * SmartObjectComponent ) ;
AITEST_FALSE ( " SmartObjectComponent is not bound to simulation after calling UnregisterSmartObject " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FDebugUnregister , " System.AI.SmartObjects.Debug Unregister " ) ;
struct FBoundToSimulation : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
for ( const USmartObjectComponent * SmartObjectComponent : SOList )
{
AITEST_TRUE ( " SmartObjectComponent is initially bound to simulation " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
2023-05-26 16:30:18 -04:00
# if WITH_SMARTOBJECT_DEBUG
2023-05-26 12:48:38 -04:00
Subsystem - > DebugUnregisterAllSmartObjects ( ) ;
for ( const USmartObjectComponent * SmartObjectComponent : SOList )
{
AITEST_FALSE ( " SmartObjectComponent is not bound to simulation after calling RemoveComponentFromSimulation " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
Subsystem - > DebugRegisterAllSmartObjects ( ) ;
for ( const USmartObjectComponent * SmartObjectComponent : SOList )
{
AITEST_TRUE ( " SmartObjectComponent is bound to simulation after calling AddComponentToSimulation " , SmartObjectComponent - > IsBoundToSimulation ( ) ) ;
}
2023-05-26 16:30:18 -04:00
# endif // WITH_SMARTOBJECT_DEBUG
2023-05-26 12:48:38 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FBoundToSimulation , " System.AI.SmartObjects.Add to/Remove from simulation " ) ;
2023-11-29 11:23:11 -05:00
struct FEnabledReasons : FSmartObjectTestBase
{
virtual bool InstantTest ( ) override
{
const USmartObjectComponent * SmartObjectComponent = SOList [ 0 ] ;
const FSmartObjectHandle Handle = SmartObjectComponent - > GetRegisteredHandle ( ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabled ( Handle , false ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , UE : : SmartObject : : EnabledReason : : Gameplay ) ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag1 ) ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag2 ) ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag3 ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag1 , false ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag1 ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag2 , false ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag2 ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag3 , false ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag3 ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabled ( Handle , true ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag1 , true ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag1 ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag2 , true ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag2 ) ) ;
AITEST_FALSE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
Subsystem - > SetEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag3 , true ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabledForReason ( Handle , FNativeGameplayTags : : Get ( ) . TestTag3 ) ) ;
AITEST_TRUE ( " SmartObjectComponent is enabled " , Subsystem - > IsEnabled ( Handle ) ) ;
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FEnabledReasons , " System.AI.SmartObjects.Enabled Reasons " ) ;
2022-03-02 22:33:53 -05:00
struct FActivityTagsMergingPolicy : FSmartObjectTestBase
2022-03-02 13:25:37 -05:00
{
virtual bool SetupDefinition ( ) override
{
2022-03-31 17:42:26 -04:00
const TArrayView < FSmartObjectSlotDefinition > Slots = Definition - > GetMutableSlots ( ) ;
constexpr int32 NumRequiredSlots = 2 ;
if ( ! ensureMsgf ( Slots . Num ( ) > = NumRequiredSlots , TEXT ( " Expecting at least %d slots " ) , NumRequiredSlots ) )
2022-03-02 13:25:37 -05:00
{
return false ;
}
// Tags setup looks like:
// Object: ActivityTags: TestTag1
// Slot1: ActivityTags: TestTag2
// Slot2: ActivityTags: TestTag1, TestTag2
// Slot3: ActivityTags: ---
2022-03-31 17:42:26 -04:00
FSmartObjectSlotDefinition & FirstSlot = Slots [ 0 ] ;
FSmartObjectSlotDefinition & SecondSlot = Slots [ 1 ] ;
2022-03-02 13:25:37 -05:00
FirstSlot . ActivityTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 ) ;
SecondSlot . ActivityTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 ) ;
SecondSlot . ActivityTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 ) ;
return true ;
}
} ;
2022-03-02 22:33:53 -05:00
struct FActivityTagsMergingPolicyCombine : FActivityTagsMergingPolicy
2022-03-02 13:25:37 -05:00
{
virtual bool SetupDefinition ( ) override
{
2022-03-02 22:33:53 -05:00
if ( ! FActivityTagsMergingPolicy : : SetupDefinition ( ) )
2022-03-02 13:25:37 -05:00
{
return false ;
}
2022-03-02 22:33:53 -05:00
Definition - > SetActivityTagsMergingPolicy ( ESmartObjectTagMergingPolicy : : Combine ) ;
2022-03-02 13:25:37 -05:00
return true ;
}
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-02 13:25:37 -05:00
{
// No activity requirements, should return registered slots
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( DefaultRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with an empty query " , Results . Num ( ) , NumCreatedSlots ) ;
}
{
// Adding activity requirements to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . ActivityRequirements = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. NoTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// All slots inherit TestTag1 from parent object, so all invalid
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with NoMatch(TestTag1) " , Results . Num ( ) , 0 ) ;
}
{
// Adding activity requirements to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . ActivityRequirements = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. AnyTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 )
) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 1 & 2 & 3) = 3 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with AnyMatch(TestTag1, TestTag2) " , Results . Num ( ) , SOList . Num ( ) * 3 ) ;
}
{
// Adding activity requirements to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . ActivityRequirements = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. AllTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 )
) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 1 & 2) = 2 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with AllMatch(TestTag1, TestTag2) " , Results . Num ( ) , SOList . Num ( ) * 2 ) ;
}
return true ;
}
} ;
2022-03-02 22:33:53 -05:00
IMPLEMENT_AI_INSTANT_TEST ( FActivityTagsMergingPolicyCombine , " System.AI.SmartObjects.Merging policy 'Combine' on ActivityTags " ) ;
2022-03-02 13:25:37 -05:00
2022-03-02 22:33:53 -05:00
struct FActivityTagsMergingPolicyOverride : FActivityTagsMergingPolicy
2022-03-02 13:25:37 -05:00
{
virtual bool SetupDefinition ( ) override
{
2022-03-02 22:33:53 -05:00
if ( ! FActivityTagsMergingPolicy : : SetupDefinition ( ) )
2022-03-02 13:25:37 -05:00
{
return false ;
}
2022-03-02 22:33:53 -05:00
Definition - > SetActivityTagsMergingPolicy ( ESmartObjectTagMergingPolicy : : Override ) ;
2022-03-02 13:25:37 -05:00
return true ;
}
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-02 13:25:37 -05:00
{
// No activity requirements, should return registered slots
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( DefaultRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() using 'Override' policy with an empty query " , Results . Num ( ) , NumCreatedSlots ) ;
}
{
// Adding activity requirements to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . ActivityRequirements = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. NoTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// Slot 1 only has TestTag2 (Slot 2 has TestTag1 in override and Slot 3 inherits from parent) = 1 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with NoMatch(TestTag1) " , Results . Num ( ) , SOList . Num ( ) * 1 ) ;
}
{
// Adding activity requirements to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . ActivityRequirements = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. AllTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 )
) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 2) = 1 matching slot / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with AllMatch(TestTag1, TestTag2) " , Results . Num ( ) , SOList . Num ( ) * 1 ) ;
}
return true ;
}
} ;
2022-03-02 22:33:53 -05:00
IMPLEMENT_AI_INSTANT_TEST ( FActivityTagsMergingPolicyOverride , " System.AI.SmartObjects.Merging policy 'Override' on ActivityTags " ) ;
2022-03-02 13:25:37 -05:00
struct FUserTagsFilterPolicy : FSmartObjectTestBase
{
virtual bool SetupDefinition ( ) override
{
2022-03-31 17:42:26 -04:00
const TArrayView < FSmartObjectSlotDefinition > Slots = Definition - > GetMutableSlots ( ) ;
constexpr int32 NumRequiredSlots = 2 ;
if ( ! ensureMsgf ( Slots . Num ( ) > = NumRequiredSlots , TEXT ( " Expecting at least %d slots " ) , NumRequiredSlots ) )
2022-03-02 13:25:37 -05:00
{
return false ;
}
// Tags setup looks like:
// Object: UserTagFilter: Match(TestTag1)
// Slot1: UserTagFilter: NoMatch(TestTag2)
// Slot2: UserTagFilter: AnyMatch(TestTag1, TestTag2, TestTag3)
2022-03-31 17:42:26 -04:00
FSmartObjectSlotDefinition & FirstSlot = Slots [ 0 ] ;
FSmartObjectSlotDefinition & SecondSlot = Slots [ 1 ] ;
2022-03-02 13:25:37 -05:00
// Set first slot user tag filter
FirstSlot . UserTagFilter = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. NoTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 )
) ;
// Set second slot user tag filter
SecondSlot . UserTagFilter = FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. AnyTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag3 )
) ;
// Set user tag filter
Definition - > SetUserTagFilter ( FGameplayTagQuery : : BuildQuery (
FGameplayTagQueryExpression ( )
. AllTagsMatch ( )
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 )
) ) ;
return true ;
}
} ;
struct FUserTagsFilterPolicyNoFilter : FUserTagsFilterPolicy
{
virtual bool SetupDefinition ( ) override
{
if ( ! FUserTagsFilterPolicy : : SetupDefinition ( ) )
{
return false ;
}
2022-03-02 22:33:53 -05:00
Definition - > SetUserTagsFilteringPolicy ( ESmartObjectTagFilteringPolicy : : NoFilter ) ;
2022-03-02 13:25:37 -05:00
return true ;
}
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-02 13:25:37 -05:00
{
// Providing user tags to the query
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() using 'NoFilter' policy with user tags = TestTag2 " , Results . Num ( ) , NumCreatedSlots ) ;
}
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FUserTagsFilterPolicyNoFilter , " System.AI.SmartObjects.Filter policy 'NoFilter' on UserTags " ) ;
struct FUserTagsFilterPolicyCombine : FUserTagsFilterPolicy
{
virtual bool SetupDefinition ( ) override
{
if ( ! FUserTagsFilterPolicy : : SetupDefinition ( ) )
{
return false ;
}
2022-03-02 22:33:53 -05:00
Definition - > SetUserTagsFilteringPolicy ( ESmartObjectTagFilteringPolicy : : Combine ) ;
2022-03-02 13:25:37 -05:00
return true ;
}
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-02 13:25:37 -05:00
{
// User tags are empty so none should be found
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( DefaultRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with an empty query " , Results . Num ( ) , 0 ) ;
}
{
// Add TestTag1 to user tags
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 1 & 2 & 3) = 3 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with user tags = TestTag1 " , Results . Num ( ) , SOList . Num ( ) * 3 ) ;
// Add TestTag2 to User tags so first slot should match
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 ) ;
Results . Reset ( ) ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 2 & 3) = 2 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with user tags = TestTag1, TestTag2 " , Results . Num ( ) , SOList . Num ( ) * 2 ) ;
}
{
// Add TestTag3 to User tags so first slot should match
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag3 ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() using 'Combine' policy with user tags = TestTag3 " , Results . Num ( ) , 0 ) ;
}
2022-03-16 03:47:02 -04:00
2022-03-02 13:25:37 -05:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FUserTagsFilterPolicyCombine , " System.AI.SmartObjects.Filter policy 'Combine' on UserTags " ) ;
struct FUserTagsFilterPolicyOverride : FUserTagsFilterPolicy
{
virtual bool SetupDefinition ( ) override
{
if ( ! FUserTagsFilterPolicy : : SetupDefinition ( ) )
{
return false ;
}
2022-03-02 22:33:53 -05:00
Definition - > SetUserTagsFilteringPolicy ( ESmartObjectTagFilteringPolicy : : Override ) ;
2022-03-02 13:25:37 -05:00
return true ;
}
virtual bool InstantTest ( ) override
{
2022-11-07 09:57:31 -05:00
FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-02 13:25:37 -05:00
{
// User tags are empty
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( DefaultRequest , Results ) ;
// (Slot 1) = 1 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with an empty query " , Results . Num ( ) , SOList . Num ( ) * 1 ) ;
}
{
// Add TestTag1 to user tags
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 1 & 2 & 3) = 3 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with user tags = TestTag1 " , Results . Num ( ) , SOList . Num ( ) * 3 ) ;
// Add TestTag2 to User tags so first slot should match
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag2 ) ;
Results . Reset ( ) ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 2 & 3) = 2 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with user tags = TestTag1, TestTag2 " , Results . Num ( ) , SOList . Num ( ) * 2 ) ;
}
{
// Add TestTag3 to User tags so first slot should match
FSmartObjectRequest ModifiedRequest = DefaultRequest ;
ModifiedRequest . Filter . UserTags . AddTag ( FNativeGameplayTags : : Get ( ) . TestTag3 ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( ModifiedRequest , Results ) ;
// (Slot 1 & 2) = 2 matching slots / object
AITEST_EQUAL ( " Results.Num() using 'Override' policy with user tags = TestTag3 " , Results . Num ( ) , SOList . Num ( ) * 2 ) ;
}
2022-03-16 03:47:02 -04:00
2022-03-02 13:25:37 -05:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FUserTagsFilterPolicyOverride , " System.AI.SmartObjects.Filter policy 'Override' on UserTags " ) ;
2022-03-16 03:47:02 -04:00
struct FInstanceTagsFilter : FSmartObjectTestBase
{
2023-01-18 10:52:51 -05:00
virtual bool SetupDefinition ( ) override
2022-03-16 03:47:02 -04:00
{
2023-01-18 10:52:51 -05:00
if ( ! FSmartObjectTestBase : : SetupDefinition ( ) )
2022-03-16 03:47:02 -04:00
{
return false ;
}
// Tags setup looks like:
2023-01-18 10:52:51 -05:00
// Object: FSmartObjectWorldConditionObjectTagQuery: NoMatch(TestTag1)
2022-03-16 03:47:02 -04:00
2023-01-18 10:52:51 -05:00
FWorldConditionQueryDefinition & ConditionQueryDefinition = Definition - > GetMutablePreconditions ( ) ;
FSmartObjectWorldConditionObjectTagQuery NewCondition ;
NewCondition . TagQuery = FGameplayTagQuery : : BuildQuery (
2022-03-16 03:47:02 -04:00
FGameplayTagQueryExpression ( )
. NoTagsMatch ( )
2023-01-18 10:52:51 -05:00
. AddTag ( FNativeGameplayTags : : Get ( ) . TestTag1 ) ) ;
2023-03-02 12:12:47 -05:00
ConditionQueryDefinition . Initialize ( Definition , Definition - > GetWorldConditionSchemaClass ( ) ,
2023-01-26 06:15:02 -05:00
{
FWorldConditionEditable ( 0 , EWorldConditionOperator : : And , FConstStructView : : Make ( NewCondition ) )
} ) ;
2022-03-16 03:47:02 -04:00
return true ;
}
virtual bool InstantTest ( ) override
{
2023-02-02 18:43:13 -05:00
const FConstStructView ConditionsUserData = FConstStructView : : Make ( TestContextData ) ;
2022-11-07 09:57:31 -05:00
const FSmartObjectRequest DefaultRequest ( FSmartObjectTest : : QueryBounds , TestFilter ) ;
2022-03-16 03:47:02 -04:00
FSmartObjectRequestResult SingleResult = Subsystem - > FindSmartObject ( DefaultRequest ) ;
AITEST_TRUE ( " SingleResult.IsValid() " , SingleResult . IsValid ( ) ) ;
TArray < FSmartObjectRequestResult > Results ;
Subsystem - > FindSmartObjects ( DefaultRequest , Results ) ;
AITEST_EQUAL ( " Results.Num() for objects without instance tags " , Results . Num ( ) , NumCreatedSlots ) ;
AITEST_NOT_EQUAL ( " Num results " , Results . Num ( ) , 0 ) ;
2023-02-02 18:43:13 -05:00
const FSmartObjectHandle ObjectToDisableByTag = Results . Top ( ) . SmartObjectHandle ;
2022-03-16 03:47:02 -04:00
// Find candidate slots
TArray < FSmartObjectSlotHandle > SlotHandles ;
2023-02-02 18:43:13 -05:00
Subsystem - > FindSlots ( ObjectToDisableByTag , TestFilter , SlotHandles , ConditionsUserData ) ;
2022-03-16 03:47:02 -04:00
AITEST_TRUE ( " Num slot handles " , SlotHandles . Num ( ) > = 3 ) ;
// Claim first slot
2023-11-30 02:26:33 -05:00
const FSmartObjectClaimHandle FirstClaimHandle = Subsystem - > MarkSlotAsClaimed ( SlotHandles [ 0 ] , ESmartObjectClaimPriority : : Normal ) ;
2022-03-16 03:47:02 -04:00
AITEST_TRUE ( " FirstClaimHandle.IsValid() " , FirstClaimHandle . IsValid ( ) ) ;
// Use First slot
2023-06-08 10:34:40 -04:00
const USmartObjectBehaviorDefinition * BehaviorDefinition = Subsystem - > MarkSlotAsOccupied < USmartObjectBehaviorDefinition > ( FirstClaimHandle ) ;
2022-03-16 03:47:02 -04:00
AITEST_NOT_NULL ( " Behavior definition pointer for first slot before activation " , BehaviorDefinition ) ;
2023-02-02 18:43:13 -05:00
// Apply tag that will cause preconditions to fail for some results
AITEST_TRUE ( " Result should pass selection conditions " , Subsystem - > EvaluateSelectionConditions ( SingleResult . SlotHandle , ConditionsUserData ) ) ;
Subsystem - > AddTagToInstance ( ObjectToDisableByTag , FNativeGameplayTags : : Get ( ) . TestTag1 ) ;
AITEST_FALSE ( " Result should fail selection conditions " , Subsystem - > EvaluateSelectionConditions ( SingleResult . SlotHandle , ConditionsUserData ) ) ;
2022-03-16 03:47:02 -04:00
2023-02-02 18:43:13 -05:00
// Find new list of candidates that should exclude all slots from 'ObjectToDisableByTag'
2022-03-16 03:47:02 -04:00
TArray < FSmartObjectRequestResult > ResultsAfter ;
Subsystem - > FindSmartObjects ( DefaultRequest , ResultsAfter ) ;
// (Slot 1 & 2 & 3) = 3 matching slots / object
2023-02-02 18:43:13 -05:00
AITEST_EQUAL ( " Results.Num() for 1 object with instance tags (InstanceTags=TestTag1) " , ResultsAfter . Num ( ) , ( SOList . Num ( ) - 1 ) * 3 ) ;
2022-03-16 03:47:02 -04:00
2023-01-18 10:52:51 -05:00
// Find candidate slots from deactivated object
2022-03-16 03:47:02 -04:00
TArray < FSmartObjectSlotHandle > SlotHandlesAfter ;
2023-02-02 18:43:13 -05:00
Subsystem - > FindSlots ( ObjectToDisableByTag , TestFilter , SlotHandlesAfter , ConditionsUserData ) ;
2022-03-16 03:47:02 -04:00
AITEST_EQUAL ( " Num slot handles from deactivated object " , SlotHandlesAfter . Num ( ) , 0 ) ;
2023-02-02 18:43:13 -05:00
// Validate that 3rd slot with previously valid stored results can not be claimed or used
const bool bThirdClaimPossible = Subsystem - > EvaluateSelectionConditions ( SlotHandles [ 2 ] , ConditionsUserData ) ;
AITEST_FALSE ( " bThirdClaimPossible " , bThirdClaimPossible ) ;
2022-03-16 03:47:02 -04:00
// Release all valid claim handles
2023-06-08 10:34:40 -04:00
const bool bFirstSlotReleaseSuccess = Subsystem - > MarkSlotAsFree ( FirstClaimHandle ) ;
2022-11-07 09:57:31 -05:00
AITEST_TRUE ( " bFirstSlotReleaseSuccess " , bFirstSlotReleaseSuccess ) ;
2022-03-16 03:47:02 -04:00
// Remove tag
2023-02-02 18:43:13 -05:00
Subsystem - > RemoveTagFromInstance ( ObjectToDisableByTag , FNativeGameplayTags : : Get ( ) . TestTag1 ) ;
2022-03-16 03:47:02 -04:00
return true ;
}
} ;
IMPLEMENT_AI_INSTANT_TEST ( FInstanceTagsFilter , " System.AI.SmartObjects.Filter policy on InstanceTags " ) ;
2021-09-28 13:33:17 -04:00
} // namespace FSmartObjectTest
# undef LOCTEXT_NAMESPACE