RealtimeStyleTransferRuntime/Source/LyraGame/Player/LyraPlayerController.cpp

436 lines
12 KiB
C++
Raw Permalink Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraPlayerController.h"
#include "LyraLogChannels.h"
#include "GameModes/LyraGameMode.h"
#include "LyraCheatManager.h"
#include "LyraPlayerState.h"
#include "Camera/LyraPlayerCameraManager.h"
#include "UI/LyraHUD.h"
#include "Character/LyraPawnData.h"
#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "EngineUtils.h"
#include "LyraGameplayTags.h"
#include "GameFramework/Pawn.h"
#include "AbilitySystemGlobals.h"
#include "CommonInputSubsystem.h"
2022-11-02 10:42:10 +00:00
#include "LevelEditorSubsystem.h"
2022-05-23 18:41:30 +00:00
#include "LyraLocalPlayer.h"
2022-11-02 10:42:10 +00:00
#include "Character/LyraCharacter.h"
2022-05-23 18:41:30 +00:00
#include "Settings/LyraSettingsShared.h"
#include "Development/LyraDeveloperSettings.h"
ALyraPlayerController::ALyraPlayerController(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
PlayerCameraManagerClass = ALyraPlayerCameraManager::StaticClass();
#if USING_CHEAT_MANAGER
CheatClass = ULyraCheatManager::StaticClass();
#endif // #if USING_CHEAT_MANAGER
}
void ALyraPlayerController::PreInitializeComponents()
{
Super::PreInitializeComponents();
}
void ALyraPlayerController::BeginPlay()
{
Super::BeginPlay();
SetActorHiddenInGame(false);
}
void ALyraPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
}
2022-11-02 10:42:10 +00:00
void ALyraPlayerController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
ULevelEditorSubsystem* LevelEditorSubsystem = GEditor->GetEditorSubsystem<ULevelEditorSubsystem>();
AActor* ActorToPilot = LevelEditorSubsystem->GetPilotLevelActor();
if (Cast<ALyraCharacter>(ActorToPilot))
return;
for (ALyraCharacter* LyraCharacter : TActorRange<ALyraCharacter>(GetWorld()))
{
if(Cast<ALyraPlayerController>(LyraCharacter->GetController()))
continue;
ActorToPilot = LyraCharacter;
break;
}
if (!IsValid(ActorToPilot))
return;
LevelEditorSubsystem->PilotLevelActor(ActorToPilot);
}
2022-05-23 18:41:30 +00:00
void ALyraPlayerController::ReceivedPlayer()
{
Super::ReceivedPlayer();
}
void ALyraPlayerController::PlayerTick(float DeltaTime)
{
Super::PlayerTick(DeltaTime);
// If we are auto running then add some player input
if (GetIsAutoRunning())
{
if (APawn* CurrentPawn = GetPawn())
{
const FRotator MovementRotation(0.0f, GetControlRotation().Yaw, 0.0f);
const FVector MovementDirection = MovementRotation.RotateVector(FVector::ForwardVector);
CurrentPawn->AddMovementInput(MovementDirection, 1.0f);
}
}
}
ALyraPlayerState* ALyraPlayerController::GetLyraPlayerState() const
{
return CastChecked<ALyraPlayerState>(PlayerState, ECastCheckedType::NullAllowed);
}
ULyraAbilitySystemComponent* ALyraPlayerController::GetLyraAbilitySystemComponent() const
{
const ALyraPlayerState* LyraPS = GetLyraPlayerState();
return (LyraPS ? LyraPS->GetLyraAbilitySystemComponent() : nullptr);
}
ALyraHUD* ALyraPlayerController::GetLyraHUD() const
{
return CastChecked<ALyraHUD>(GetHUD(), ECastCheckedType::NullAllowed);
}
void ALyraPlayerController::OnPlayerStateChangedTeam(UObject* TeamAgent, int32 OldTeam, int32 NewTeam)
{
ConditionalBroadcastTeamChanged(this, IntegerToGenericTeamId(OldTeam), IntegerToGenericTeamId(NewTeam));
}
void ALyraPlayerController::OnPlayerStateChanged()
{
// Empty, place for derived classes to implement without having to hook all the other events
}
void ALyraPlayerController::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 ALyraPlayerController::InitPlayerState()
{
Super::InitPlayerState();
BroadcastOnPlayerStateChanged();
}
void ALyraPlayerController::CleanupPlayerState()
{
Super::CleanupPlayerState();
BroadcastOnPlayerStateChanged();
}
void ALyraPlayerController::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
BroadcastOnPlayerStateChanged();
}
void ALyraPlayerController::SetPlayer(UPlayer* InPlayer)
{
Super::SetPlayer(InPlayer);
if (const ULyraLocalPlayer* LyraLocalPlayer = Cast<ULyraLocalPlayer>(InPlayer))
{
ULyraSettingsShared* UserSettings = LyraLocalPlayer->GetSharedSettings();
UserSettings->OnSettingChanged.AddUObject(this, &ThisClass::OnSettingsChanged);
OnSettingsChanged(UserSettings);
}
}
void ALyraPlayerController::OnSettingsChanged(ULyraSettingsShared* InSettings)
{
bForceFeedbackEnabled = InSettings->GetForceFeedbackEnabled();
}
void ALyraPlayerController::AddCheats(bool bForce)
{
#if USING_CHEAT_MANAGER
Super::AddCheats(true);
#else //#if USING_CHEAT_MANAGER
Super::AddCheats(bForce);
#endif // #else //#if USING_CHEAT_MANAGER
}
void ALyraPlayerController::ServerCheat_Implementation(const FString& Msg)
{
#if USING_CHEAT_MANAGER
if (CheatManager)
{
UE_LOG(LogLyra, Warning, TEXT("ServerCheat: %s"), *Msg);
ClientMessage(ConsoleCommand(Msg));
}
#endif // #if USING_CHEAT_MANAGER
}
bool ALyraPlayerController::ServerCheat_Validate(const FString& Msg)
{
return true;
}
void ALyraPlayerController::ServerCheatAll_Implementation(const FString& Msg)
{
#if USING_CHEAT_MANAGER
if (CheatManager)
{
UE_LOG(LogLyra, Warning, TEXT("ServerCheatAll: %s"), *Msg);
for (TActorIterator<ALyraPlayerController> It(GetWorld()); It; ++It)
{
ALyraPlayerController* LyraPC = (*It);
if (LyraPC)
{
LyraPC->ClientMessage(LyraPC->ConsoleCommand(Msg));
}
}
}
#endif // #if USING_CHEAT_MANAGER
}
bool ALyraPlayerController::ServerCheatAll_Validate(const FString& Msg)
{
return true;
}
void ALyraPlayerController::PreProcessInput(const float DeltaTime, const bool bGamePaused)
{
Super::PreProcessInput(DeltaTime, bGamePaused);
}
void ALyraPlayerController::PostProcessInput(const float DeltaTime, const bool bGamePaused)
{
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
{
LyraASC->ProcessAbilityInput(DeltaTime, bGamePaused);
}
Super::PostProcessInput(DeltaTime, bGamePaused);
}
void ALyraPlayerController::OnCameraPenetratingTarget()
{
bHideViewTargetPawnNextFrame = true;
}
void ALyraPlayerController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
#if WITH_SERVER_CODE && WITH_EDITOR
if (GIsEditor && (InPawn != nullptr) && (GetPawn() == InPawn))
{
for (const FLyraCheatToRun& CheatRow : GetDefault<ULyraDeveloperSettings>()->CheatsToRun)
{
if (CheatRow.Phase == ECheatExecutionTime::OnPlayerPawnPossession)
{
ConsoleCommand(CheatRow.Cheat, /*bWriteToLog=*/ true);
}
}
}
#endif
SetIsAutoRunning(false);
}
void ALyraPlayerController::SetIsAutoRunning(const bool bEnabled)
{
const bool bIsAutoRunning = GetIsAutoRunning();
if (bEnabled != bIsAutoRunning)
{
if (!bEnabled)
{
OnEndAutoRun();
}
else
{
OnStartAutoRun();
}
}
}
bool ALyraPlayerController::GetIsAutoRunning() const
{
bool bIsAutoRunning = false;
if (const ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
{
bIsAutoRunning = LyraASC->GetTagCount(FLyraGameplayTags::Get().Status_AutoRunning) > 0;
}
return bIsAutoRunning;
}
void ALyraPlayerController::OnStartAutoRun()
{
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
{
LyraASC->SetLooseGameplayTagCount(FLyraGameplayTags::Get().Status_AutoRunning, 1);
K2_OnStartAutoRun();
}
}
void ALyraPlayerController::OnEndAutoRun()
{
if (ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent())
{
LyraASC->SetLooseGameplayTagCount(FLyraGameplayTags::Get().Status_AutoRunning, 0);
K2_OnEndAutoRun();
}
}
void ALyraPlayerController::UpdateForceFeedback(IInputInterface* InputInterface, const int32 ControllerId)
{
if (bForceFeedbackEnabled)
{
if (const UCommonInputSubsystem* CommonInputSubsystem = UCommonInputSubsystem::Get(GetLocalPlayer()))
{
const ECommonInputType CurrentInputType = CommonInputSubsystem->GetCurrentInputType();
if (CurrentInputType == ECommonInputType::Gamepad || CurrentInputType == ECommonInputType::Touch)
{
InputInterface->SetForceFeedbackChannelValues(ControllerId, ForceFeedbackValues);
return;
}
}
}
InputInterface->SetForceFeedbackChannelValues(ControllerId, FForceFeedbackValues());
}
void ALyraPlayerController::UpdateHiddenComponents(const FVector& ViewLocation, TSet<FPrimitiveComponentId>& OutHiddenComponents)
{
Super::UpdateHiddenComponents(ViewLocation, OutHiddenComponents);
if (bHideViewTargetPawnNextFrame)
{
AActor* const ViewTargetPawn = PlayerCameraManager ? Cast<AActor>(PlayerCameraManager->GetViewTarget()) : nullptr;
if (ViewTargetPawn)
{
// internal helper func to hide all the components
auto AddToHiddenComponents = [&OutHiddenComponents](const TInlineComponentArray<UPrimitiveComponent*>& InComponents)
{
// add every component and all attached children
for (UPrimitiveComponent* Comp : InComponents)
{
if (Comp->IsRegistered())
{
OutHiddenComponents.Add(Comp->ComponentId);
for (USceneComponent* AttachedChild : Comp->GetAttachChildren())
{
static FName NAME_NoParentAutoHide(TEXT("NoParentAutoHide"));
UPrimitiveComponent* AttachChildPC = Cast<UPrimitiveComponent>(AttachedChild);
if (AttachChildPC && AttachChildPC->IsRegistered() && !AttachChildPC->ComponentTags.Contains(NAME_NoParentAutoHide))
{
OutHiddenComponents.Add(AttachChildPC->ComponentId);
}
}
}
}
};
//TODO Solve with an interface. Gather hidden components or something.
//TODO Hiding isn't awesome, sometimes you want the effect of a fade out over a proximity, needs to bubble up to designers.
// hide pawn's components
TInlineComponentArray<UPrimitiveComponent*> PawnComponents;
ViewTargetPawn->GetComponents(PawnComponents);
AddToHiddenComponents(PawnComponents);
//// hide weapon too
//if (ViewTargetPawn->CurrentWeapon)
//{
// TInlineComponentArray<UPrimitiveComponent*> WeaponComponents;
// ViewTargetPawn->CurrentWeapon->GetComponents(WeaponComponents);
// AddToHiddenComponents(WeaponComponents);
//}
}
// we consumed it, reset for next frame
bHideViewTargetPawnNextFrame = false;
}
}
void ALyraPlayerController::SetGenericTeamId(const FGenericTeamId& NewTeamID)
{
UE_LOG(LogLyraTeams, Error, TEXT("You can't set the team ID on a player controller (%s); it's driven by the associated player state"), *GetPathNameSafe(this));
}
FGenericTeamId ALyraPlayerController::GetGenericTeamId() const
{
if (const ILyraTeamAgentInterface* PSWithTeamInterface = Cast<ILyraTeamAgentInterface>(PlayerState))
{
return PSWithTeamInterface->GetGenericTeamId();
}
return FGenericTeamId::NoTeam;
}
FOnLyraTeamIndexChangedDelegate* ALyraPlayerController::GetOnTeamIndexChangedDelegate()
{
return &OnTeamChangedDelegate;
}
void ALyraPlayerController::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();
}
//////////////////////////////////////////////////////////////////////
// ALyraReplayPlayerController
void ALyraReplayPlayerController::SetPlayer(UPlayer* InPlayer)
{
Super::SetPlayer(InPlayer);
}