RealtimeStyleTransferRuntime/Source/LyraGame/Player/LyraPlayerBotController.cpp

192 lines
5.2 KiB
C++
Raw Normal View History

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();
}