2024-04-12 16:55:34 -07:00
|
|
|
|
#include "GasaGameMode.h"
|
|
|
|
|
|
2024-04-22 22:10:02 -07:00
|
|
|
|
#include "GasaGameInstance.h"
|
|
|
|
|
#include "GasaGameState.h"
|
|
|
|
|
#include "GasaPlayerController.h"
|
|
|
|
|
#include "GasaPlayerState.h"
|
|
|
|
|
#include "Engine/Player.h"
|
|
|
|
|
#include "GameFramework/GameSession.h"
|
|
|
|
|
#include "GameFramework/GameState.h"
|
|
|
|
|
#include "GameFramework/PlayerState.h"
|
|
|
|
|
#include "OnlineSubsystem.h"
|
|
|
|
|
using namespace Gasa;
|
|
|
|
|
|
|
|
|
|
#pragma region Game Framework
|
|
|
|
|
void AGasaGameMode::OnGameFrameworkInitialized()
|
|
|
|
|
{
|
|
|
|
|
NetLog("OnGameFrameworkInitialized");
|
|
|
|
|
|
|
|
|
|
BP_OnGameFrameworkInitialized();
|
|
|
|
|
if (MatchState == MatchState::WaitingToStart && ReadyToStartMatch())
|
|
|
|
|
StartMatch();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::OwningClient_OnGameFrameworkInitialized(AGasaPlayerController* PC)
|
|
|
|
|
{
|
|
|
|
|
NetLog("OwningClient_OnGameFrameworkInitialized");
|
|
|
|
|
HandleStartingNewPlayer(PC);
|
|
|
|
|
}
|
|
|
|
|
#pragma endregion Game Framework
|
|
|
|
|
|
|
|
|
|
#pragma region GameMode
|
|
|
|
|
void AGasaGameMode::HandleStartingNewPlayer_Implementation(APlayerController* NewPlayer)
|
|
|
|
|
{
|
|
|
|
|
Super::HandleStartingNewPlayer_Implementation(NewPlayer);
|
|
|
|
|
if (NewPlayer)
|
|
|
|
|
NewPlayer->bBlockInput = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AGasaGameMode::ReadyToStartMatch_Implementation()
|
|
|
|
|
{
|
|
|
|
|
if ( ! GetGameInstance<UGasaGameInstance>()->IsGameFrameworkInitialized())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Super::ReadyToStartMatch();
|
|
|
|
|
{
|
|
|
|
|
// If bDelayed Start is set, wait for a manual match start
|
|
|
|
|
if (bDelayedStart)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// By default start when we have > 0 players
|
|
|
|
|
if (GetMatchState() == MatchState::WaitingToStart)
|
|
|
|
|
{
|
|
|
|
|
if (NumPlayers + NumBots > 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#pragma endregion GameMode
|
|
|
|
|
|
|
|
|
|
#pragma region GameModeBase
|
|
|
|
|
void AGasaGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
|
|
|
{
|
|
|
|
|
Super::EndPlay(EndPlayReason);
|
|
|
|
|
NetLog("EndPlay");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::GenericPlayerInitialization(AController* C)
|
|
|
|
|
{
|
|
|
|
|
NetLog("GenericPlayerInitialization: " + C->GetName());
|
|
|
|
|
|
|
|
|
|
// AGameMode::GenericPlayerInitialization(C);
|
|
|
|
|
{
|
|
|
|
|
APlayerController* PC = Cast<APlayerController>(C);
|
|
|
|
|
if (PC != nullptr)
|
|
|
|
|
{
|
|
|
|
|
// Moved to: void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn)
|
|
|
|
|
// InitializeHUDForPlayer(Cast<APlayerController>(C));
|
|
|
|
|
|
|
|
|
|
// Notify the game that we can now be muted and mute others
|
|
|
|
|
UpdateGameplayMuteList(PC);
|
|
|
|
|
|
|
|
|
|
if (GameSession != nullptr)
|
|
|
|
|
{
|
|
|
|
|
// Tell the player to enable voice by default or use the push to talk method
|
|
|
|
|
PC->ClientEnableNetworkVoice(!GameSession->RequiresPushToTalk());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReplicateStreamingStatus(PC);
|
|
|
|
|
|
|
|
|
|
bool HidePlayer = false, HideHUD = false, DisableMovement = false, DisableTurning = false;
|
|
|
|
|
|
|
|
|
|
// Check to see if we should start in cinematic mode (matinee movie capture)
|
|
|
|
|
if (ShouldStartInCinematicMode(PC, HidePlayer, HideHUD, DisableMovement, DisableTurning))
|
|
|
|
|
{
|
|
|
|
|
PC->SetCinematicMode(true, HidePlayer, HideHUD, DisableMovement, DisableTurning);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TSubclassOf<APlayerController> AGasaGameMode::GetPlayerControllerClassToSpawnForSeamlessTravel(APlayerController* PreviousPlayerController)
|
|
|
|
|
{
|
|
|
|
|
NetLog("GetPlayerControllerClassToSpawnForSeamlessTravel: " + PreviousPlayerController->GetName());
|
|
|
|
|
return Super::GetPlayerControllerClassToSpawnForSeamlessTravel(PreviousPlayerController);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::HandleSeamlessTravelPlayer(AController*& Controller)
|
|
|
|
|
{
|
|
|
|
|
NetLog("HandleSeamlessTravelPlayer: " + Controller->GetName());
|
|
|
|
|
|
|
|
|
|
// Super::HandleSeamlessTravelPlayer( C );
|
|
|
|
|
|
|
|
|
|
UE_LOG(LogGameMode, Log, TEXT(">> GameMode::HandleSeamlessTravelPlayer: %s "), * Controller->GetName());
|
|
|
|
|
|
|
|
|
|
APlayerController* PC = Cast<APlayerController>(Controller);
|
|
|
|
|
UClass* PCClassToSpawn = GetPlayerControllerClassToSpawnForSeamlessTravel(PC);
|
|
|
|
|
// FUniqueNetIdRepl StoredNativePlatformUniqueNetId = C->GetPlayerState<AGasaPlayerState>()->NativePlatformUniqueNetId;
|
|
|
|
|
|
|
|
|
|
if (PC && PC->GetClass() != PCClassToSpawn)
|
|
|
|
|
{
|
|
|
|
|
if (PC->Player != nullptr)
|
|
|
|
|
{
|
|
|
|
|
// We need to spawn a new PlayerController to replace the old one
|
|
|
|
|
APlayerController* const NewPC = SpawnPlayerControllerCommon(PC->IsLocalPlayerController()
|
|
|
|
|
? ROLE_SimulatedProxy
|
|
|
|
|
: ROLE_AutonomousProxy, PC->GetFocalLocation(), PC->GetControlRotation(), PCClassToSpawn);
|
|
|
|
|
if (NewPC == nullptr)
|
|
|
|
|
{
|
|
|
|
|
NetLog(FString::Printf(
|
|
|
|
|
TEXT("Failed to spawn new PlayerController for %s (old class %s)"), *PC->GetHumanReadableName(), *PC->GetClass()->GetName())
|
|
|
|
|
, ELogV::Warning
|
|
|
|
|
);
|
|
|
|
|
PC->Destroy();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
PC->SeamlessTravelTo(NewPC);
|
|
|
|
|
NewPC->SeamlessTravelFrom(PC);
|
|
|
|
|
SwapPlayerControllers(PC, NewPC);
|
|
|
|
|
PC = NewPC;
|
|
|
|
|
Controller = NewPC;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
PC->Destroy();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// clear out data that was only for the previous game
|
|
|
|
|
Controller->PlayerState->Reset();
|
|
|
|
|
// create a new PlayerState and copy over info; this is necessary because the old GameMode may have used a different PlayerState class
|
|
|
|
|
APlayerState* OldPlayerState = Controller->PlayerState;
|
|
|
|
|
Controller->InitPlayerState();
|
|
|
|
|
OldPlayerState->SeamlessTravelTo( Controller->PlayerState);
|
|
|
|
|
// we don"t need the old PlayerState anymore
|
|
|
|
|
//@fixme: need a way to replace PlayerStates that doesn't cause incorrect "player left the game"/"player entered the game" messages
|
|
|
|
|
OldPlayerState->Destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InitSeamlessTravelPlayer(Controller);
|
|
|
|
|
|
|
|
|
|
// Initialize hud and other player details, shared with PostLogin
|
|
|
|
|
GenericPlayerInitialization(Controller);
|
|
|
|
|
|
|
|
|
|
if (AGasaGameState* GS = GetGameState<AGasaGameState>())
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
|
|
|
|
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
|
|
|
|
int32 NumConnections = GI->SessionSettings.bPublicGame
|
|
|
|
|
? GI->SessionSettings.PublicConnections
|
|
|
|
|
: GI->SessionSettings.PrivateConnections;
|
|
|
|
|
if (GS->OnlinePlayers.Num() < NumConnections)
|
|
|
|
|
GS->OnlinePlayers.Init( nullptr, NumConnections );
|
|
|
|
|
|
|
|
|
|
for (AGasaPlayerState* & PS : GS->OnlinePlayers)
|
|
|
|
|
{
|
|
|
|
|
if (PS == nullptr)
|
|
|
|
|
{
|
|
|
|
|
PS = C->GetPlayerState<ASlipgatePlayerState>();
|
|
|
|
|
PS->SgID = GS->OnlinePlayers.Find( PS );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Controller->GetPlayerState<AGasaPlayerState>()->NativePlatformUniqueNetId = StoredNativePlatformUniqueNetId;
|
|
|
|
|
NetLog(FString::Printf(TEXT("HandleSeamlessTravelPlayer: %s"), * Controller->GetName()) );
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (PC)
|
|
|
|
|
PC->Event_NetOwner_OnGameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::InitializeHUDForPlayer_Implementation(APlayerController* NewPlayer)
|
|
|
|
|
{
|
|
|
|
|
// Super::InitializeHUDForPlayer_Implementation(NewPlayer);
|
|
|
|
|
NewPlayer->ClientSetHUD(HUDClass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::InitSeamlessTravelPlayer(AController* NewController)
|
|
|
|
|
{
|
|
|
|
|
if (NewController)
|
|
|
|
|
NewController->bBlockInput = true;
|
|
|
|
|
|
|
|
|
|
// GameMode::InitSeamlessTravelPlayer(NewController);
|
|
|
|
|
{
|
|
|
|
|
// AGameModeBase::InitSeamlessTravelPlayer(NewController);
|
|
|
|
|
{
|
|
|
|
|
APlayerController* NewPC = Cast<APlayerController>(NewController);
|
|
|
|
|
|
|
|
|
|
FString ErrorMessage;
|
|
|
|
|
if (!UpdatePlayerStartSpot(NewController, TEXT(""), ErrorMessage))
|
|
|
|
|
NetLog(FString::Printf( TEXT("InitSeamlessTravelPlayer: %s"), *ErrorMessage), ELogV::Warning);
|
|
|
|
|
|
|
|
|
|
if (NewPC != nullptr)
|
|
|
|
|
{
|
|
|
|
|
NewPC->PostSeamlessTravel();
|
|
|
|
|
|
|
|
|
|
if (MustSpectate(NewPC))
|
|
|
|
|
{
|
|
|
|
|
NewPC->StartSpectatingOnly();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NewPC->bPlayerIsWaiting = true;
|
|
|
|
|
NewPC->ChangeState(NAME_Spectating);
|
|
|
|
|
NewPC->ClientGotoState(NAME_Spectating);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APlayerController* NewPC = Cast<APlayerController>(NewController);
|
|
|
|
|
|
|
|
|
|
if (NewPC != nullptr)
|
|
|
|
|
{
|
|
|
|
|
SetSeamlessTravelViewTarget(NewPC);
|
|
|
|
|
|
|
|
|
|
if (!MustSpectate(NewPC))
|
|
|
|
|
{
|
|
|
|
|
NumPlayers++;
|
|
|
|
|
NumTravellingPlayers--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NumBots++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NetLog("InitSeamlessTravelPlayer: " + NewController->GetName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::HandleMatchAborted()
|
|
|
|
|
{
|
|
|
|
|
Super::HandleMatchAborted();
|
|
|
|
|
NetLog("HandleMatchAborted");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::Logout(AController* Exiting)
|
|
|
|
|
{
|
|
|
|
|
Super::Logout(Exiting);
|
|
|
|
|
|
|
|
|
|
Event_OnLogout.Broadcast(Cast<AGasaPlayerController>(Exiting));
|
|
|
|
|
NetLog("User Logged out: " + Exiting->GetName());
|
|
|
|
|
|
|
|
|
|
if (AGasaGameState* GS = Cast<AGasaGameState>(GetWorld()->GetGameState()))
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
|
|
|
|
int32 Index = GS->OnlinePlayers.Find(Exiting->GetPlayerState<AGasaGameState>());
|
|
|
|
|
if (Index == INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
NetLog("Could not find exiting player state in online players!", ELogV::Error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
GS->OnlinePlayers[Index] = nullptr;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
IOnlineSessionPtr const SessionInterface = Online::GetSessionInterface(GetWorld());
|
|
|
|
|
if ( ! SessionInterface.IsValid())
|
|
|
|
|
{
|
|
|
|
|
NetLog("DestoryCurrentSession: Could not get the session interface.", ELogV::Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
|
|
|
|
|
{
|
|
|
|
|
Super::PreLogin(Options, Address, UniqueId, ErrorMessage);
|
|
|
|
|
// TODO(Ed): Refuse players if the server is full.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::PostLogin(APlayerController* NewPlayer)
|
|
|
|
|
{
|
|
|
|
|
// AGameMode::PostLogin(NewPlayer);
|
|
|
|
|
{
|
|
|
|
|
UWorld* World = GetWorld();
|
|
|
|
|
|
|
|
|
|
// Update player count
|
|
|
|
|
if (MustSpectate(NewPlayer))
|
|
|
|
|
NumSpectators++;
|
|
|
|
|
else if (World->IsInSeamlessTravel() || NewPlayer->HasClientLoadedCurrentWorld())
|
|
|
|
|
NumPlayers++;
|
|
|
|
|
else
|
|
|
|
|
NumTravellingPlayers++;
|
|
|
|
|
|
|
|
|
|
// Save network address for re-associating with reconnecting player, after stripping out port number
|
|
|
|
|
FString Address = NewPlayer->GetPlayerNetworkAddress();
|
|
|
|
|
int32 Pos = Address.Find(TEXT(":"), ESearchCase::CaseSensitive);
|
|
|
|
|
|
|
|
|
|
NewPlayer->PlayerState->SavedNetworkAddress = (Pos > 0) ? Address.Left(Pos) : Address;
|
|
|
|
|
|
|
|
|
|
// Check if this player is reconnecting and already has PlayerState
|
|
|
|
|
FindInactivePlayer(NewPlayer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AGameModeBase::PostLogin(NewPlayer)
|
|
|
|
|
{
|
|
|
|
|
// Runs shared initialization that can happen during seamless travel as well
|
|
|
|
|
GenericPlayerInitialization(NewPlayer);
|
|
|
|
|
|
|
|
|
|
// Perform initialization that only happens on initially joining a server
|
|
|
|
|
NewPlayer->ClientCapBandwidth(NewPlayer->Player->CurrentNetSpeed);
|
|
|
|
|
|
|
|
|
|
if (MustSpectate(NewPlayer))
|
|
|
|
|
{
|
|
|
|
|
NewPlayer->ClientGotoState(NAME_Spectating);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If NewPlayer is not only a spectator and has a valid ID, add him as a user to the replay.
|
|
|
|
|
FUniqueNetIdRepl const&
|
|
|
|
|
NewPlayerStateUniqueId = NewPlayer->PlayerState->GetUniqueId();
|
|
|
|
|
if (NewPlayerStateUniqueId.IsValid())
|
|
|
|
|
{
|
|
|
|
|
GetGameInstance()->AddUserToReplay(NewPlayerStateUniqueId.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GameSession)
|
|
|
|
|
{
|
|
|
|
|
GameSession->PostLogin(NewPlayer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (AGasaGameState* GS = GetGameState<AGasaGameState>())
|
|
|
|
|
{
|
|
|
|
|
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
|
|
|
|
|
|
|
|
|
// int32 numconnections = gi->sessionsettings.bpublicgame
|
|
|
|
|
// ? GI->SessionSettings.PublicConnections : GI->SessionSettings.PrivateConnections;
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
if (GS->OnlinePlayers.Num() < NumConnections)
|
|
|
|
|
{
|
|
|
|
|
GS->OnlinePlayers.Init( nullptr, NumConnections );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (AGasaPlayerState* & PS : GS->OnlinePlayers)
|
|
|
|
|
{
|
|
|
|
|
if (PS == nullptr)
|
|
|
|
|
{
|
|
|
|
|
PS = NewPlayer->GetPlayerState<AGasaPlayerState>();
|
|
|
|
|
PS->GasaID = GS->OnlinePlayers.Find( PS );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cont. AGameModeBase::PostLogin(NewPlayer)
|
|
|
|
|
{
|
|
|
|
|
// Notify Blueprints that a new player has logged in. Calling it here, because this is the first time that the PlayerController can take RPCs
|
|
|
|
|
DispatchPostLogin(NewPlayer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AGasaPlayerController* PC = Cast<AGasaPlayerController>(NewPlayer);
|
|
|
|
|
// if (PC)
|
|
|
|
|
// PC->Event_OnNetOwner_GameplayFrameworkInitialized.AddDynamic(this, &ThisClass::OwningClient_OnGameFrameworkInitialized);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::PostSeamlessTravel()
|
|
|
|
|
{
|
|
|
|
|
Super::PostSeamlessTravel();
|
|
|
|
|
NetLog("PostSeamlessTravel");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::SetPlayerDefaults(APawn* PlayerPawn)
|
|
|
|
|
{
|
|
|
|
|
InitializeHUDForPlayer(Cast<APlayerController>(PlayerPawn->GetController()));
|
|
|
|
|
|
|
|
|
|
// Super::SetPlayerDefaults(PlayerPawn);
|
|
|
|
|
{
|
|
|
|
|
PlayerPawn->SetPlayerDefaults();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::SetSeamlessTravelViewTarget(APlayerController* PC)
|
|
|
|
|
{
|
|
|
|
|
Super::SetSeamlessTravelViewTarget(PC);
|
|
|
|
|
NetLog("SetSeamlessTravelViewTarget");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::StartPlay()
|
|
|
|
|
{
|
|
|
|
|
if (MatchState == MatchState::EnteringMap)
|
|
|
|
|
SetMatchState(MatchState::WaitingToStart);
|
|
|
|
|
|
|
|
|
|
// Start match is deferred until the framework is considered initialized.
|
|
|
|
|
NetLog("StartPlay");
|
|
|
|
|
|
|
|
|
|
UGasaGameInstance* GI = GetGameInstance<UGasaGameInstance>();
|
|
|
|
|
GI->Event_OnGameFrameworkInitialized.AddDynamic(this, &ThisClass::OnGameFrameworkInitialized);
|
|
|
|
|
GI->NotifyGameFrameworkClassReady(EGameFrameworkClassFlag::GameMode);
|
|
|
|
|
|
|
|
|
|
// Not called yet, will wait for initialization of the framework.
|
|
|
|
|
//Super::StartPlay();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::StartToLeaveMap()
|
|
|
|
|
{
|
|
|
|
|
NetLog("StartToLeaveMap");
|
|
|
|
|
Super::StartToLeaveMap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AGasaGameMode::SwapPlayerControllers(APlayerController* OldPC, APlayerController* NewPC)
|
|
|
|
|
{
|
|
|
|
|
NetLog("SwapPlayerControllers");
|
|
|
|
|
NetLog("Old: " + OldPC->GetName());
|
|
|
|
|
NetLog("New: " + NewPC->GetName());
|
|
|
|
|
|
|
|
|
|
Super::SwapPlayerControllers(OldPC, NewPC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APlayerController* AGasaGameMode::SpawnPlayerControllerCommon(ENetRole InRemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation,
|
|
|
|
|
TSubclassOf<APlayerController> InPlayerControllerClass)
|
|
|
|
|
{
|
|
|
|
|
NetLog("SpawnPlayerControllerCommon");
|
|
|
|
|
return Super::SpawnPlayerControllerCommon(InRemoteRole, SpawnLocation, SpawnRotation, InPlayerControllerClass);
|
|
|
|
|
}
|
|
|
|
|
#pragma endregion GameModeBase
|