2021-11-24 04:26:12 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-05-02 09:15:14 -04:00
# include "Components/StateTreeComponent.h"
2021-11-24 04:26:12 -05:00
# include "GameplayTasksComponent.h"
2023-01-16 17:04:48 -05:00
# include "StateTreeExecutionContext.h"
2021-11-24 04:26:12 -05:00
# include "VisualLogger/VisualLogger.h"
# include "AIController.h"
2022-08-29 14:47:43 -04:00
# include "Components/StateTreeComponentSchema.h"
2022-07-07 11:38:21 -04:00
# include "Engine/World.h"
2023-01-16 17:04:48 -05:00
# include "Tasks/AITask.h"
2021-11-24 04:26:12 -05:00
# define STATETREE_LOG(Verbosity, Format, ...) UE_VLOG(GetOwner(), LogStateTree, Verbosity, Format, ##__VA_ARGS__)
# define STATETREE_CLOG(Condition, Verbosity, Format, ...) UE_CVLOG((Condition), GetOwner(), LogStateTree, Verbosity, Format, ##__VA_ARGS__)
//////////////////////////////////////////////////////////////////////////
2022-05-02 09:15:14 -04:00
// UStateTreeComponent
2021-11-24 04:26:12 -05:00
2022-05-02 09:15:14 -04:00
UStateTreeComponent : : UStateTreeComponent ( const FObjectInitializer & ObjectInitializer )
2021-11-24 04:26:12 -05:00
: Super ( ObjectInitializer )
{
bWantsInitializeComponent = true ;
bIsRunning = false ;
bIsPaused = false ;
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : InitializeComponent ( )
2021-11-24 04:26:12 -05:00
{
2022-08-29 14:47:43 -04:00
if ( ! StateTreeRef . IsValid ( ) )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Error , TEXT ( " %s: StateTree asset is not set, cannot initialize. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
2022-09-23 20:02:42 -04:00
const FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
if ( ! Context . IsValid ( ) )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Error , TEXT ( " %s: Failed to init StateTreeContext. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
}
}
2022-07-22 05:33:11 -04:00
# if WITH_EDITOR
void UStateTreeComponent : : PostLoad ( )
{
Super : : PostLoad ( ) ;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if ( StateTree_DEPRECATED ! = nullptr )
{
2022-08-29 14:47:43 -04:00
StateTreeRef . SetStateTree ( StateTree_DEPRECATED ) ;
2022-07-22 05:33:11 -04:00
StateTreeRef . SyncParameters ( ) ;
StateTree_DEPRECATED = nullptr ;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
# endif //WITH_EDITOR
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : UninitializeComponent ( )
2021-11-24 04:26:12 -05:00
{
}
2022-09-23 20:02:42 -04:00
bool UStateTreeComponent : : SetContextRequirements ( FStateTreeExecutionContext & Context , bool bLogErrors )
2021-11-24 04:26:12 -05:00
{
2022-09-23 20:02:42 -04:00
if ( ! Context . IsValid ( ) )
2021-11-24 04:26:12 -05:00
{
return false ;
}
2022-04-06 10:04:05 -04:00
const UWorld * World = GetWorld ( ) ;
2021-11-24 04:26:12 -05:00
if ( World = = nullptr )
{
return false ;
}
2022-09-23 20:02:42 -04:00
for ( const FStateTreeExternalDataDesc & ItemDesc : Context . GetExternalDataDescs ( ) )
2021-11-24 04:26:12 -05:00
{
if ( ItemDesc . Struct ! = nullptr )
{
if ( ItemDesc . Struct - > IsChildOf ( UWorldSubsystem : : StaticClass ( ) ) )
{
2022-07-22 15:06:06 -04:00
UWorldSubsystem * Subsystem = World - > GetSubsystemBase ( Cast < UClass > ( const_cast < UStruct * > ( ToRawPtr ( ItemDesc . Struct ) ) ) ) ;
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( Subsystem ) ) ;
2021-11-24 04:26:12 -05:00
}
else if ( ItemDesc . Struct - > IsChildOf ( UActorComponent : : StaticClass ( ) ) )
{
2022-07-22 15:06:06 -04:00
UActorComponent * Component = GetOwner ( ) - > FindComponentByClass ( Cast < UClass > ( const_cast < UStruct * > ( ToRawPtr ( ItemDesc . Struct ) ) ) ) ;
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( Component ) ) ;
2021-11-24 04:26:12 -05:00
}
else if ( ItemDesc . Struct - > IsChildOf ( APawn : : StaticClass ( ) ) )
{
2022-04-06 10:04:05 -04:00
APawn * OwnerPawn = ( AIOwner ! = nullptr ) ? AIOwner - > GetPawn ( ) : Cast < APawn > ( GetOwner ( ) ) ;
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( OwnerPawn ) ) ;
2021-11-24 04:26:12 -05:00
}
else if ( ItemDesc . Struct - > IsChildOf ( AAIController : : StaticClass ( ) ) )
{
2022-04-06 10:04:05 -04:00
AAIController * OwnerController = ( AIOwner ! = nullptr ) ? AIOwner . Get ( ) : Cast < AAIController > ( GetOwner ( ) ) ;
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( OwnerController ) ) ;
2022-04-06 10:04:05 -04:00
}
else if ( ItemDesc . Struct - > IsChildOf ( AActor : : StaticClass ( ) ) )
{
AActor * OwnerActor = ( AIOwner ! = nullptr ) ? AIOwner - > GetPawn ( ) : GetOwner ( ) ;
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( OwnerActor ) ) ;
2021-11-24 04:26:12 -05:00
}
}
}
2022-08-29 14:47:43 -04:00
// Make sure the actor matches one required.
AActor * ContextActor = nullptr ;
2022-09-23 20:02:42 -04:00
const UStateTreeComponentSchema * Schema = Cast < UStateTreeComponentSchema > ( Context . GetStateTree ( ) - > GetSchema ( ) ) ;
2022-08-29 14:47:43 -04:00
if ( Schema )
{
if ( AAIController * OwnerController = ( AIOwner ! = nullptr ) ? AIOwner . Get ( ) : Cast < AAIController > ( GetOwner ( ) ) )
{
if ( OwnerController & & OwnerController - > IsA ( Schema - > GetContextActorClass ( ) ) )
{
ContextActor = OwnerController ;
}
}
if ( ContextActor = = nullptr )
{
if ( AActor * OwnerActor = ( AIOwner ! = nullptr ) ? AIOwner - > GetPawn ( ) : GetOwner ( ) )
{
if ( OwnerActor & & OwnerActor - > IsA ( Schema - > GetContextActorClass ( ) ) )
{
ContextActor = OwnerActor ;
}
}
}
if ( ContextActor = = nullptr & & bLogErrors )
{
STATETREE_LOG ( Error , TEXT ( " %s: Could not find context actor of type %s. StateTree will not update. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) , * GetNameSafe ( Schema - > GetContextActorClass ( ) ) ) ;
}
}
else if ( bLogErrors )
{
STATETREE_LOG ( Error , TEXT ( " %s: Expected StateTree asset to contain StateTreeComponentSchema. StateTree will not update. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
}
const FName ActorName ( TEXT ( " Actor " ) ) ;
2022-09-23 20:02:42 -04:00
for ( const FStateTreeExternalDataDesc & ItemDesc : Context . GetContextDataDescs ( ) )
2022-08-29 14:47:43 -04:00
{
if ( ItemDesc . Name = = ActorName )
{
2022-09-23 20:02:42 -04:00
Context . SetExternalData ( ItemDesc . Handle , FStateTreeDataView ( ContextActor ) ) ;
2022-08-29 14:47:43 -04:00
}
}
2022-09-23 20:02:42 -04:00
bool bResult = Context . AreExternalDataViewsValid ( ) ;
2022-08-29 14:47:43 -04:00
if ( ! bResult & & bLogErrors )
{
STATETREE_LOG ( Error , TEXT ( " %s: Missing external data requirements. StateTree will not update. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
}
return bResult ;
}
void UStateTreeComponent : : BeginPlay ( )
{
Super : : BeginPlay ( ) ;
if ( AIOwner = = nullptr & & bStartLogicAutomatically )
{
StartLogic ( ) ;
}
2021-11-24 04:26:12 -05:00
}
2023-03-17 09:41:07 -04:00
void UStateTreeComponent : : EndPlay ( const EEndPlayReason : : Type EndPlayReason )
{
StopLogic ( UEnum : : GetValueAsString ( EndPlayReason ) ) ;
Super : : EndPlay ( EndPlayReason ) ;
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : TickComponent ( float DeltaTime , enum ELevelTick TickType , FActorComponentTickFunction * ThisTickFunction )
2021-11-24 04:26:12 -05:00
{
Super : : TickComponent ( DeltaTime , TickType , ThisTickFunction ) ;
if ( ! bIsRunning | | bIsPaused )
{
return ;
}
2022-12-15 15:56:52 -05:00
if ( ! StateTreeRef . IsValid ( ) )
{
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to tick State Tree component with invalid asset. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
2022-09-23 20:02:42 -04:00
FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
if ( SetContextRequirements ( Context ) )
2021-11-24 04:26:12 -05:00
{
2023-02-03 08:41:48 -05:00
Context . SetParameters ( StateTreeRef . GetParameters ( ) ) ;
2022-12-16 05:45:13 -05:00
const EStateTreeRunStatus PreviousRunStatus = Context . GetStateTreeRunStatus ( ) ;
const EStateTreeRunStatus CurrentRunStatus = Context . Tick ( DeltaTime ) ;
if ( CurrentRunStatus ! = PreviousRunStatus )
{
OnStateTreeRunStatusChanged . Broadcast ( CurrentRunStatus ) ;
}
2021-11-24 04:26:12 -05:00
}
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : StartLogic ( )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Log , TEXT ( " %s: Start Logic " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2022-12-15 15:56:52 -05:00
if ( ! StateTreeRef . IsValid ( ) )
{
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to start State Tree component with invalid asset. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
2022-09-23 20:02:42 -04:00
FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
if ( SetContextRequirements ( Context ) )
2021-11-24 04:26:12 -05:00
{
2022-09-23 20:02:42 -04:00
Context . SetParameters ( StateTreeRef . GetParameters ( ) ) ;
2022-12-16 05:45:13 -05:00
const EStateTreeRunStatus PreviousRunStatus = Context . GetStateTreeRunStatus ( ) ;
const EStateTreeRunStatus CurrentRunStatus = Context . Start ( ) ;
2021-11-24 04:26:12 -05:00
bIsRunning = true ;
2022-12-16 05:45:13 -05:00
if ( CurrentRunStatus ! = PreviousRunStatus )
{
OnStateTreeRunStatusChanged . Broadcast ( CurrentRunStatus ) ;
}
2021-11-24 04:26:12 -05:00
}
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : RestartLogic ( )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Log , TEXT ( " %s: Restart Logic " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2022-12-15 15:56:52 -05:00
if ( ! StateTreeRef . IsValid ( ) )
{
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to restart State Tree component with invalid asset. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
2022-09-23 20:02:42 -04:00
FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
if ( SetContextRequirements ( Context ) )
2021-11-24 04:26:12 -05:00
{
2022-09-23 20:02:42 -04:00
Context . SetParameters ( StateTreeRef . GetParameters ( ) ) ;
2022-12-16 05:45:13 -05:00
const EStateTreeRunStatus PreviousRunStatus = Context . GetStateTreeRunStatus ( ) ;
const EStateTreeRunStatus CurrentRunStatus = Context . Start ( ) ;
2021-11-24 04:26:12 -05:00
bIsRunning = true ;
2022-12-16 05:45:13 -05:00
if ( CurrentRunStatus ! = PreviousRunStatus )
{
OnStateTreeRunStatusChanged . Broadcast ( CurrentRunStatus ) ;
}
2021-11-24 04:26:12 -05:00
}
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : StopLogic ( const FString & Reason )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Log , TEXT ( " %s: Stopping, reason: \' %s \' " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) , * Reason ) ;
2022-12-15 15:56:52 -05:00
if ( ! bIsRunning )
{
return ;
}
if ( ! StateTreeRef . IsValid ( ) )
{
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to stop State Tree component with invalid asset. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
2022-09-23 20:02:42 -04:00
FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , InstanceData ) ;
if ( SetContextRequirements ( Context ) )
2021-11-24 04:26:12 -05:00
{
2023-02-03 08:41:48 -05:00
Context . SetParameters ( StateTreeRef . GetParameters ( ) ) ;
2022-12-16 05:45:13 -05:00
const EStateTreeRunStatus PreviousRunStatus = Context . GetStateTreeRunStatus ( ) ;
const EStateTreeRunStatus CurrentRunStatus = Context . Stop ( ) ;
2021-11-24 04:26:12 -05:00
bIsRunning = false ;
2022-12-16 05:45:13 -05:00
if ( CurrentRunStatus ! = PreviousRunStatus )
{
OnStateTreeRunStatusChanged . Broadcast ( CurrentRunStatus ) ;
}
2021-11-24 04:26:12 -05:00
}
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : Cleanup ( )
2021-11-24 04:26:12 -05:00
{
2023-03-17 09:41:07 -04:00
StopLogic ( TEXT ( " Cleanup " ) ) ;
2021-11-24 04:26:12 -05:00
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : PauseLogic ( const FString & Reason )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Log , TEXT ( " %s: Execution updates: PAUSED (%s) " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) , * Reason ) ;
bIsPaused = true ;
}
2022-05-02 09:15:14 -04:00
EAILogicResuming : : Type UStateTreeComponent : : ResumeLogic ( const FString & Reason )
2021-11-24 04:26:12 -05:00
{
STATETREE_LOG ( Log , TEXT ( " %s: Execution updates: RESUMED (%s) " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) , * Reason ) ;
const EAILogicResuming : : Type SuperResumeResult = Super : : ResumeLogic ( Reason ) ;
if ( ! ! bIsPaused )
{
bIsPaused = false ;
if ( SuperResumeResult = = EAILogicResuming : : Continue )
{
// Nop
}
else if ( SuperResumeResult = = EAILogicResuming : : RestartedInstead )
{
RestartLogic ( ) ;
}
}
return SuperResumeResult ;
}
2022-05-02 09:15:14 -04:00
bool UStateTreeComponent : : IsRunning ( ) const
2021-11-24 04:26:12 -05:00
{
return bIsRunning ;
}
2022-05-02 09:15:14 -04:00
bool UStateTreeComponent : : IsPaused ( ) const
2021-11-24 04:26:12 -05:00
{
return bIsPaused ;
}
2022-05-02 09:15:14 -04:00
UGameplayTasksComponent * UStateTreeComponent : : GetGameplayTasksComponent ( const UGameplayTask & Task ) const
2021-11-24 04:26:12 -05:00
{
const UAITask * AITask = Cast < const UAITask > ( & Task ) ;
return ( AITask & & AITask - > GetAIController ( ) ) ? AITask - > GetAIController ( ) - > GetGameplayTasksComponent ( Task ) : Task . GetGameplayTasksComponent ( ) ;
}
2022-05-02 09:15:14 -04:00
AActor * UStateTreeComponent : : GetGameplayTaskOwner ( const UGameplayTask * Task ) const
2021-11-24 04:26:12 -05:00
{
if ( Task = = nullptr )
{
return GetAIOwner ( ) ;
}
const UAITask * AITask = Cast < const UAITask > ( Task ) ;
if ( AITask )
{
return AITask - > GetAIController ( ) ;
}
const UGameplayTasksComponent * TasksComponent = Task - > GetGameplayTasksComponent ( ) ;
return TasksComponent ? TasksComponent - > GetGameplayTaskOwner ( Task ) : nullptr ;
}
2022-05-02 09:15:14 -04:00
AActor * UStateTreeComponent : : GetGameplayTaskAvatar ( const UGameplayTask * Task ) const
2021-11-24 04:26:12 -05:00
{
if ( Task = = nullptr )
{
return GetAIOwner ( ) ? GetAIOwner ( ) - > GetPawn ( ) : nullptr ;
}
const UAITask * AITask = Cast < const UAITask > ( Task ) ;
if ( AITask )
{
return AITask - > GetAIController ( ) ? AITask - > GetAIController ( ) - > GetPawn ( ) : nullptr ;
}
const UGameplayTasksComponent * TasksComponent = Task - > GetGameplayTasksComponent ( ) ;
return TasksComponent ? TasksComponent - > GetGameplayTaskAvatar ( Task ) : nullptr ;
}
2022-05-02 09:15:14 -04:00
uint8 UStateTreeComponent : : GetGameplayTaskDefaultPriority ( ) const
2021-11-24 04:26:12 -05:00
{
return static_cast < uint8 > ( EAITaskPriority : : AutonomousAI ) ;
}
2022-05-02 09:15:14 -04:00
void UStateTreeComponent : : OnGameplayTaskInitialized ( UGameplayTask & Task )
2021-11-24 04:26:12 -05:00
{
const UAITask * AITask = Cast < const UAITask > ( & Task ) ;
if ( AITask & & ( AITask - > GetAIController ( ) = = nullptr ) )
{
// this means that the task has either been created without specifying
// UAITAsk::OwnerController's value (like via BP's Construct Object node)
// or it has been created in C++ with inappropriate function
UE_LOG ( LogStateTree , Error , TEXT ( " Missing AIController in AITask %s " ) , * AITask - > GetName ( ) ) ;
}
}
2022-12-15 15:55:44 -05:00
void UStateTreeComponent : : SetStartLogicAutomatically ( const bool bInStartLogicAutomatically )
{
bStartLogicAutomatically = bInStartLogicAutomatically ;
}
2022-09-01 09:06:53 -04:00
void UStateTreeComponent : : SendStateTreeEvent ( const FStateTreeEvent & Event )
2022-11-01 15:11:19 -04:00
{
SendStateTreeEvent ( Event . Tag , Event . Payload , Event . Origin ) ;
}
void UStateTreeComponent : : SendStateTreeEvent ( const FGameplayTag Tag , const FConstStructView Payload , const FName Origin )
2022-09-01 09:06:53 -04:00
{
if ( ! bIsRunning )
{
2022-12-15 15:56:52 -05:00
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to send event to a State Tree that is not started yet. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
return ;
}
if ( ! StateTreeRef . IsValid ( ) )
{
STATETREE_LOG ( Warning , TEXT ( " %s: Trying to send event to State Tree component with invalid asset. " ) , ANSI_TO_TCHAR ( __FUNCTION__ ) ) ;
2022-09-01 09:06:53 -04:00
return ;
}
2023-01-12 09:00:45 -05:00
InstanceData . GetMutableEventQueue ( ) . SendEvent ( this , Tag , Payload , Origin ) ;
2022-09-01 09:06:53 -04:00
}
2022-12-16 05:45:13 -05:00
EStateTreeRunStatus UStateTreeComponent : : GetStateTreeRunStatus ( ) const
{
2023-01-12 09:00:45 -05:00
if ( const FStateTreeExecutionState * Exec = InstanceData . GetExecutionState ( ) )
2022-12-16 05:45:13 -05:00
{
2023-01-12 09:00:45 -05:00
return Exec - > TreeRunStatus ;
2022-12-16 05:45:13 -05:00
}
2023-01-12 09:00:45 -05:00
return EStateTreeRunStatus : : Failed ;
2022-12-16 05:45:13 -05:00
}
2022-09-01 09:06:53 -04:00
2021-11-24 04:26:12 -05:00
# if WITH_GAMEPLAY_DEBUGGER
2022-05-02 09:15:14 -04:00
FString UStateTreeComponent : : GetDebugInfoString ( ) const
2021-11-24 04:26:12 -05:00
{
2022-09-23 20:02:42 -04:00
FStateTreeExecutionContext Context ( * GetOwner ( ) , * StateTreeRef . GetStateTree ( ) , const_cast < FStateTreeInstanceData & > ( InstanceData ) ) ;
return Context . GetDebugInfoString ( ) ;
2021-11-24 04:26:12 -05:00
}
# endif // WITH_GAMEPLAY_DEBUGGER
# undef STATETREE_LOG
# undef STATETREE_CLOG