void AGameModeBase::InitSeamlessTravelPlayer(AController* NewController)
{
	APlayerController* NewPC = Cast<APlayerController>(NewController);
	// Find a start spot
	AActor* StartSpot = FindPlayerStart(NewController);

	if (StartSpot == nullptr)
	{
		UE_LOG(LogGameMode, Warning, TEXT("Could not find a starting spot"));
	}
	else
	{
		FRotator StartRotation(0, StartSpot->GetActorRotation().Yaw, 0);
		NewController->SetInitialLocationAndRotation(StartSpot->GetActorLocation(), StartRotation);
	}

	NewController->StartSpot = StartSpot;

	if (NewPC != nullptr)
	{
		NewPC->PostSeamlessTravel();

		if (MustSpectate(NewPC))
		{
			NewPC->StartSpectatingOnly();
		}
		else
		{
			NewPC->bPlayerIsWaiting = true;
			NewPC->ChangeState(NAME_Spectating);
			NewPC->ClientGotoState(NAME_Spectating);
		}
	}
}
FString AGameModeBase::InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal)
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
	// Try calling deprecated version first
	FString DeprecatedError = InitNewPlayer(NewPlayerController, UniqueId.GetUniqueNetId(), Options, Portal);
	if (DeprecatedError != TEXT("DEPRECATED"))
	{
		// This means it was implemented in subclass
		return DeprecatedError;
	}
PRAGMA_ENABLE_DEPRECATION_WARNINGS

	check(NewPlayerController);

	FString ErrorMessage;

	// Register the player with the session
	GameSession->RegisterPlayer(NewPlayerController, UniqueId.GetUniqueNetId(), UGameplayStatics::HasOption(Options, TEXT("bIsFromInvite")));

	// Find a starting spot
	AActor* const StartSpot = FindPlayerStart(NewPlayerController, Portal);
	if (StartSpot != nullptr)
	{
		// Set the player controller / camera in this new location
		FRotator InitialControllerRot = StartSpot->GetActorRotation();
		InitialControllerRot.Roll = 0.f;
		NewPlayerController->SetInitialLocationAndRotation(StartSpot->GetActorLocation(), InitialControllerRot);
		NewPlayerController->StartSpot = StartSpot;
	}
	else
	{
		ErrorMessage = FString::Printf(TEXT("Failed to find PlayerStart"));
	}

	// Set up spectating
	bool bSpectator = FCString::Stricmp(*UGameplayStatics::ParseOption(Options, TEXT("SpectatorOnly")), TEXT("1")) == 0;
	if (bSpectator || MustSpectate(NewPlayerController))
	{
		NewPlayerController->StartSpectatingOnly();
	}

	// Init player's name
	FString InName = UGameplayStatics::ParseOption(Options, TEXT("Name")).Left(20);
	if (InName.IsEmpty())
	{
		InName = FString::Printf(TEXT("%s%i"), *DefaultPlayerName.ToString(), NewPlayerController->PlayerState->PlayerId);
	}

	ChangeName(NewPlayerController, InName, false);

	return ErrorMessage;
}
void ABerserkGameMode::RestartPlayer(AController* newPlayer)
{
	const auto startSpot = FindPlayerStart(newPlayer);
	if (startSpot != nullptr)
	{
		InitStartSpot(startSpot, newPlayer);

		const auto newPlayerController = Cast<ABerserkPlayerController>(newPlayer);
		if (newPlayerController != nullptr)
			newPlayerController->SetInitialLocationAndRotation(startSpot->GetActorLocation(), startSpot->GetActorRotation());
	}
	else LogWarning("Player start not found, failed to restart player.");
}
void AProjectTapGameMode::StartPlay()
{
    Super::StartPlay();
    auto gameState = GetGameState<AProjectTapGameState>();
    ABallPawn* ball = nullptr;
    if ( UWorld* world = GetWorld() )
    {
        AActor* playerStart = FindPlayerStart( 0 , FString( "Player" ) );
        FTransform playerTransform = playerStart->GetTransform();
        if ( ABallPlayerStart* realPlayerStart = Cast<ABallPlayerStart>( playerStart ) )
        {
            auto possibleCamera = realPlayerStart->camera == nullptr ? nullptr : Cast<UProjectTapCameraComponent>( realPlayerStart->camera->GetComponentByClass( UProjectTapCameraComponent::StaticClass() ) );
            FActorSpawnParameters params;
            ball = world->SpawnActor<ABallPawn>(
                       ABallPawn::StaticClass() ,
                       playerTransform.GetTranslation() ,
                       FRotator( playerTransform.GetRotation() ) ,
                       params );

            if ( ball != nullptr )
            {
                ball->AddVelocity( realPlayerStart->initialVelocity , realPlayerStart->GetActorLocation() );
                if ( possibleCamera != nullptr && realPlayerStart->followPlayer )
                {
                    ball->setCamera( realPlayerStart );
                    possibleCamera = ball->GetCamera();
                }
            }
            gameState->SetCamera( possibleCamera );
            isMenu = realPlayerStart->GameMode == CustomGameMode::GAME_MODE_MAIN_MENU;
            if ( realPlayerStart->music != nullptr )musicPlayer->SetSound( realPlayerStart->music );
        }
        else
        {
            FActorSpawnParameters params;
            ball = world->SpawnActor<ABallPawn>( ABallPawn::StaticClass() , playerTransform.GetTranslation() , FRotator( playerTransform.GetRotation() ) , params );
        }

        gameState->SetPlayer(ball);
    }
    musicPlayer->Play();
    musicPlayer->SetVolumeMultiplier( 0 );

    gameState->SetGameState( CustomGameState::GAME_STATE_PLAYING );
    if ( isMenu ) gameState->SetGameMode( CustomGameMode::GAME_MODE_MAIN_MENU );
}
void AGameModeBase::RestartPlayer(AController* NewPlayer)
{
	if (NewPlayer == nullptr || NewPlayer->IsPendingKillPending())
	{
		return;
	}

	AActor* StartSpot = FindPlayerStart(NewPlayer);

	// If a start spot wasn't found,
	if (StartSpot == nullptr)
	{
		// Check for a previously assigned spot
		if (NewPlayer->StartSpot != nullptr)
		{
			StartSpot = NewPlayer->StartSpot.Get();
			UE_LOG(LogGameMode, Warning, TEXT("Player start not found, using last start spot"));
		}	
	}

	RestartPlayerAtPlayerStart(NewPlayer, StartSpot);
}
void Application::OnStart(int argc, char **argv, bool vrMode)
{
    m_VREnabled = vrMode;   
    glEnable(GL_MULTISAMPLE);

    Q3BspLoader loader;
    // assume the parameter with a string ".bsp" is the map we want to load
    for (int i = 1; i < argc; ++i)
    {
        if (std::string(argv[i]).find(".bsp") != std::string::npos)
        {
            m_q3map = loader.Load(argv[i]);
            break;
        }
    }

    Math::Vector3f startPos;

    if (m_q3map)
    {
        m_q3map->Init();
        m_q3map->ToggleRenderFlag(Q3RenderUseLightmaps);

        // try to locate the first info_player_deathmatch entity and place the camera there
        startPos = FindPlayerStart(static_cast<Q3BspMap *>(m_q3map)->entities.ents);
    }

    g_cameraDirector.AddCamera(startPos / Q3BspMap::s_worldScale,
                               Math::Vector3f(0.f, 0.f, 1.f),
                               Math::Vector3f(1.f, 0.f, 0.f),
                               Math::Vector3f(0.f, 1.f, 0.f));

    // set to "clean" perspective matrix
    g_cameraDirector.GetActiveCamera()->SetMode(Camera::CAM_FPS);

    m_q3stats = new Q3StatsUI(m_q3map);
}
AActor* AGameModeBase::K2_FindPlayerStart(AController* Player, const FString& IncomingName)
{
	return FindPlayerStart(Player, IncomingName);
}