176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LyraPlayerBotController.h"
|
|
#include "GameModes/LyraGameMode.h"
|
|
#include "Engine/World.h"
|
|
#include "AbilitySystemGlobals.h"
|
|
#include "AbilitySystemComponent.h"
|
|
#include "GameFramework/PlayerState.h"
|
|
#include "LyraLogChannels.h"
|
|
|
|
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();
|
|
}
|