2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "LyraPlayerBotController.h"
2022-09-13 07:18:28 +00:00
2022-05-23 18:41:30 +00:00
# include "AbilitySystemComponent.h"
2022-09-13 07:18:28 +00:00
# include "AbilitySystemGlobals.h"
# include "Containers/UnrealString.h"
# include "Delegates/Delegate.h"
# include "Engine/EngineBaseTypes.h"
# include "Engine/World.h"
# include "GameFramework/Pawn.h"
2022-05-23 18:41:30 +00:00
# include "GameFramework/PlayerState.h"
2022-09-13 07:18:28 +00:00
# include "GameModes/LyraGameMode.h"
# include "Logging/LogCategory.h"
# include "Logging/LogMacros.h"
2022-05-23 18:41:30 +00:00
# include "LyraLogChannels.h"
2022-09-13 07:18:28 +00:00
# include "Misc/AssertionMacros.h"
# include "Perception/AIPerceptionComponent.h"
# include "Templates/Casts.h"
# include "Trace/Detail/Channel.h"
# include "UObject/ObjectPtr.h"
# include "UObject/UObjectBaseUtility.h"
# include "UObject/UnrealNames.h"
class UObject ;
2022-05-23 18:41:30 +00:00
ALyraPlayerBotController : : ALyraPlayerBotController ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
{
bWantsPlayerState = true ;
bStopAILogicOnUnposses = false ;
}
void ALyraPlayerBotController : : OnPlayerStateChangedTeam ( UObject * TeamAgent , int32 OldTeam , int32 NewTeam )
{
ConditionalBroadcastTeamChanged ( this , IntegerToGenericTeamId ( OldTeam ) , IntegerToGenericTeamId ( NewTeam ) ) ;
}
void ALyraPlayerBotController : : OnPlayerStateChanged ( )
{
// Empty, place for derived classes to implement without having to hook all the other events
}
void ALyraPlayerBotController : : BroadcastOnPlayerStateChanged ( )
{
OnPlayerStateChanged ( ) ;
// Unbind from the old player state, if any
FGenericTeamId OldTeamID = FGenericTeamId : : NoTeam ;
if ( LastSeenPlayerState ! = nullptr )
{
if ( ILyraTeamAgentInterface * PlayerStateTeamInterface = Cast < ILyraTeamAgentInterface > ( LastSeenPlayerState ) )
{
OldTeamID = PlayerStateTeamInterface - > GetGenericTeamId ( ) ;
PlayerStateTeamInterface - > GetTeamChangedDelegateChecked ( ) . RemoveAll ( this ) ;
}
}
// Bind to the new player state, if any
FGenericTeamId NewTeamID = FGenericTeamId : : NoTeam ;
if ( PlayerState ! = nullptr )
{
if ( ILyraTeamAgentInterface * PlayerStateTeamInterface = Cast < ILyraTeamAgentInterface > ( PlayerState ) )
{
NewTeamID = PlayerStateTeamInterface - > GetGenericTeamId ( ) ;
PlayerStateTeamInterface - > GetTeamChangedDelegateChecked ( ) . AddDynamic ( this , & ThisClass : : OnPlayerStateChangedTeam ) ;
}
}
// Broadcast the team change (if it really has)
ConditionalBroadcastTeamChanged ( this , OldTeamID , NewTeamID ) ;
LastSeenPlayerState = PlayerState ;
}
void ALyraPlayerBotController : : InitPlayerState ( )
{
Super : : InitPlayerState ( ) ;
BroadcastOnPlayerStateChanged ( ) ;
}
void ALyraPlayerBotController : : CleanupPlayerState ( )
{
Super : : CleanupPlayerState ( ) ;
BroadcastOnPlayerStateChanged ( ) ;
}
void ALyraPlayerBotController : : OnRep_PlayerState ( )
{
Super : : OnRep_PlayerState ( ) ;
BroadcastOnPlayerStateChanged ( ) ;
}
void ALyraPlayerBotController : : SetGenericTeamId ( const FGenericTeamId & NewTeamID )
{
UE_LOG ( LogLyraTeams , Error , TEXT ( " You can't set the team ID on a player bot controller (%s); it's driven by the associated player state " ) , * GetPathNameSafe ( this ) ) ;
}
FGenericTeamId ALyraPlayerBotController : : GetGenericTeamId ( ) const
{
if ( ILyraTeamAgentInterface * PSWithTeamInterface = Cast < ILyraTeamAgentInterface > ( PlayerState ) )
{
return PSWithTeamInterface - > GetGenericTeamId ( ) ;
}
return FGenericTeamId : : NoTeam ;
}
FOnLyraTeamIndexChangedDelegate * ALyraPlayerBotController : : GetOnTeamIndexChangedDelegate ( )
{
return & OnTeamChangedDelegate ;
}
void ALyraPlayerBotController : : ServerRestartController ( )
{
if ( GetNetMode ( ) = = NM_Client )
{
return ;
}
ensure ( ( GetPawn ( ) = = nullptr ) & & IsInState ( NAME_Inactive ) ) ;
if ( IsInState ( NAME_Inactive ) | | ( IsInState ( NAME_Spectating ) ) )
{
ALyraGameMode * const GameMode = GetWorld ( ) - > GetAuthGameMode < ALyraGameMode > ( ) ;
if ( ( GameMode = = nullptr ) | | ! GameMode - > ControllerCanRestart ( this ) )
{
return ;
}
// If we're still attached to a Pawn, leave it
if ( GetPawn ( ) ! = nullptr )
{
UnPossess ( ) ;
}
// Re-enable input, similar to code in ClientRestart
ResetIgnoreInputFlags ( ) ;
GameMode - > RestartPlayer ( this ) ;
}
}
ETeamAttitude : : Type ALyraPlayerBotController : : GetTeamAttitudeTowards ( const AActor & Other ) const
{
if ( const APawn * OtherPawn = Cast < APawn > ( & Other ) ) {
if ( const ILyraTeamAgentInterface * TeamAgent = Cast < ILyraTeamAgentInterface > ( OtherPawn - > GetController ( ) ) )
{
FGenericTeamId OtherTeamID = TeamAgent - > GetGenericTeamId ( ) ;
//Checking Other pawn ID to define Attitude
if ( OtherTeamID . GetId ( ) ! = GetGenericTeamId ( ) . GetId ( ) )
{
return ETeamAttitude : : Hostile ;
}
else
{
return ETeamAttitude : : Friendly ;
}
}
}
return ETeamAttitude : : Neutral ;
}
void ALyraPlayerBotController : : UpdateTeamAttitude ( UAIPerceptionComponent * AIPerception )
{
if ( AIPerception )
{
AIPerception - > RequestStimuliListenerUpdate ( ) ;
}
}
void ALyraPlayerBotController : : OnUnPossess ( )
{
// Make sure the pawn that is being unpossessed doesn't remain our ASC's avatar actor
if ( APawn * PawnBeingUnpossessed = GetPawn ( ) )
{
if ( UAbilitySystemComponent * ASC = UAbilitySystemGlobals : : GetAbilitySystemComponentFromActor ( PlayerState ) )
{
if ( ASC - > GetAvatarActor ( ) = = PawnBeingUnpossessed )
{
ASC - > SetAvatarActor ( nullptr ) ;
}
}
}
Super : : OnUnPossess ( ) ;
}