332 lines
9.2 KiB
C++
332 lines
9.2 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#include "UnrealProject.h"
|
|
#include "DefaultGameInstance.h"
|
|
#include "MenuController.h"
|
|
#include "SplashScreen.h"
|
|
#include "LobbyMenu.h"
|
|
#include "CharacterSettings.h"
|
|
#include "StartPromptScreen.h"
|
|
#include "PlayerStateBase.h"
|
|
#include "GameStateBase.h"
|
|
#include "SessionManager.h"
|
|
#include "TransitionScreen.h"
|
|
#include "ScreenOverlay.h"
|
|
#include "SkillTreeWidget.h"
|
|
#include "DefaultPlayerController.h"
|
|
#include "MenuScreen.h"
|
|
#include "MenuGameMode.h"
|
|
|
|
static UClass* menuWidgetClass = nullptr;
|
|
static UClass* lobbyWidgetClass = nullptr;
|
|
static UClass* splashScreenClass = nullptr;
|
|
static UClass* startScreenClass = nullptr;
|
|
static UClass* skillTreeClass = nullptr;
|
|
static TSubclassOf<UMenuPanel> mainSubMenuClass;
|
|
|
|
AMenuController::AMenuController(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
{
|
|
menuWidgetClass = ConstructorHelpers::FClassFinder<UMenuScreen>(TEXT("/Game/Assets/GUI/WEEGEE_Menu")).Class;
|
|
lobbyWidgetClass = ConstructorHelpers::FClassFinder<ULobbyMenu>(TEXT("/Game/Assets/GUI/WEEGEE_Lobby")).Class;
|
|
splashScreenClass = ConstructorHelpers::FClassFinder<USplashScreen>(TEXT("/Game/Assets/GUI/WEEGEE_Splash")).Class;
|
|
startScreenClass = ConstructorHelpers::FClassFinder<UStartPromptScreen>(TEXT("/Game/Assets/GUI/WEEGEE_StartPrompt")).Class;
|
|
skillTreeClass = ConstructorHelpers::FClassFinder<USkillTreeWidget>(TEXT("/Game/Assets/GUI/WEEGEE_SkillTree")).Class;
|
|
mainSubMenuClass = ConstructorHelpers::FClassFinder<UMenuPanel>(TEXT("/Game/Assets/GUI/Menus/WEEGEE_MainSubMenu")).Class;
|
|
|
|
this->bShowMouseCursor = true;
|
|
m_inLobby = false;
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
}
|
|
|
|
void AMenuController::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
if(IsLocalController())
|
|
{
|
|
// Create skill tree widget
|
|
skillTree = CreateWidget<USkillTreeWidget>(GetWorld(), skillTreeClass);
|
|
skillTree->AddToViewport(5);
|
|
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
UWorld* world = GetWorld();
|
|
bool showSplash = !inst->splashScreenShown;
|
|
if(world->WorldType == EWorldType::PIE)
|
|
showSplash = false;
|
|
if(inst->sessionManager->HasNetConnection())
|
|
showSplash = false;
|
|
|
|
if(showSplash)
|
|
{
|
|
m_splash = CreateWidget<USplashScreen>(this, splashScreenClass);
|
|
m_splash->onDone.AddDynamic(this, &AMenuController::m_OnSplashScreenEnded);
|
|
check(m_splash);
|
|
m_splash->AddToViewport();
|
|
}
|
|
else
|
|
{
|
|
m_OnStartPromptClosed();
|
|
}
|
|
|
|
inst->splashScreenShown = true;
|
|
|
|
inst->sessionManager->onAcceptInvite.AddUObject(this, &AMenuController::m_OnInviteAccepted);
|
|
}
|
|
}
|
|
void AMenuController::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
inst->sessionManager->onAcceptInvite.RemoveAll(this);
|
|
}
|
|
|
|
void AMenuController::NotifyLoadedWorld(FName WorldPackageName, bool bFinalDest)
|
|
{
|
|
Super::NotifyLoadedWorld(WorldPackageName, bFinalDest);
|
|
if(bFinalDest)
|
|
{
|
|
GPRINT("Final level loaded for player controller " + GetName());
|
|
if(transitionScreen)
|
|
{
|
|
// Hide transition screen
|
|
transitionScreen->OnHide();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AMenuController::Destroyed()
|
|
{
|
|
GPRINT("Menu controller destroyed " + GetName());
|
|
Super::Destroyed();
|
|
}
|
|
|
|
void AMenuController::PreClientTravel(const FString& PendingURL, ETravelType TravelType, bool bIsSeamlessTravel)
|
|
{
|
|
if(bIsSeamlessTravel)
|
|
{
|
|
// Hide lobby UI
|
|
if(lobbyMenu)
|
|
lobbyMenu->OnHide();
|
|
|
|
// Close all the menu
|
|
if(m_splash)
|
|
m_splash->RemoveFromViewport();
|
|
if(m_startScreen)
|
|
m_startScreen->RemoveFromViewport();
|
|
if(lobbyMenu)
|
|
lobbyMenu->RemoveFromViewport();
|
|
if(mainMenu)
|
|
mainMenu->RemoveFromViewport();
|
|
if(skillTree)
|
|
skillTree->RemoveFromViewport();
|
|
mainMenu = nullptr;
|
|
lobbyMenu = nullptr;
|
|
skillTree = nullptr;
|
|
m_startScreen = nullptr;
|
|
m_splash = nullptr;
|
|
|
|
// Show transition screen
|
|
transitionScreen->OnShow();
|
|
|
|
GPRINT("Seamless travel on player " + GetName() + " to \"" + PendingURL + "\"");
|
|
}
|
|
else
|
|
{
|
|
GPRINT("Regular travel on player to " + GetName() + " to \"" + PendingURL + "\"");
|
|
}
|
|
Super::PreClientTravel(PendingURL, TravelType, bIsSeamlessTravel);
|
|
}
|
|
|
|
void AMenuController::SeamlessTravelFrom(class APlayerController* OldPC)
|
|
{
|
|
Super::SeamlessTravelFrom(OldPC);
|
|
GPRINT("Seamless travel to menu [" + GetName() + "]<-[" + OldPC->GetName() + "]");
|
|
}
|
|
void AMenuController::SeamlessTravelTo(class APlayerController* NewPC)
|
|
{
|
|
Super::SeamlessTravelTo(NewPC);
|
|
GPRINT("Seamless travel to game level [" + GetName() + "]->[" + NewPC->GetName() + "]");
|
|
APlayerStateBase* pcbn = Cast<APlayerStateBase>(NewPC->PlayerState);
|
|
APlayerStateBase* pcbo = GetPlayerState<APlayerStateBase>();
|
|
|
|
check(pcbn && pcbo);
|
|
pcbn->Transfer(pcbo);
|
|
|
|
ADefaultPlayerController* newDPC = Cast<ADefaultPlayerController>(NewPC);
|
|
if(newDPC)
|
|
{
|
|
newDPC->setupState = setupState;
|
|
}
|
|
}
|
|
|
|
void AMenuController::OnLearnSkill(class UBaseSkillObject* object)
|
|
{
|
|
}
|
|
void AMenuController::OnUnlearnSkill(class UBaseSkillObject* object)
|
|
{
|
|
}
|
|
|
|
void AMenuController::OnEnterLobby()
|
|
{
|
|
if(m_inLobby)
|
|
return;
|
|
|
|
if(mainMenu && lobbyMenu)
|
|
{
|
|
mainMenu->OnHide();
|
|
lobbyMenu->OnShow();
|
|
lobbyMenu->OnLobbyEnter();
|
|
m_inLobby = true;
|
|
OnRep_PlayerState();
|
|
}
|
|
else
|
|
{
|
|
GERROR("wat");
|
|
}
|
|
|
|
// Set Default character slot
|
|
/// TODO: Add selector widget
|
|
//UCharacterSettings* settings = Cast<UDefaultGameInstance>(GetGameInstance())->GetCharacterSettings();
|
|
//if(settings->characterSaves.Num() > 0)
|
|
//{
|
|
// const FCharacterSave& save = settings->characterSaves[0];
|
|
// FPlayerSetupState pss;
|
|
// pss.customizations = save.characterCustomization;
|
|
// pss.skills = save.skillTreeState;
|
|
// pss.characterClass = save.characterClass;
|
|
// SetSetupState(pss);
|
|
//}
|
|
}
|
|
|
|
/// TODO, validate skill tree / customization here
|
|
bool AMenuController::SetSetupState_Validate(const FPlayerSetupState& state)
|
|
{
|
|
return true;
|
|
}
|
|
void AMenuController::SetSetupState_Implementation(const FPlayerSetupState& state)
|
|
{
|
|
setupState = state;
|
|
|
|
// Resync the lobby
|
|
UWorld* const world = GetWorld();
|
|
if (IsValid(world))
|
|
{
|
|
AGameStateBase* const gameState = Cast<AGameStateBase>(GetWorld()->GetGameState());
|
|
if (IsValid(gameState))
|
|
gameState->OnPlayerStateChange.Broadcast(this);
|
|
}
|
|
}
|
|
|
|
void AMenuController::OnRep_PlayerState()
|
|
{
|
|
// Request a team if we're in a lobby
|
|
if(m_inLobby)
|
|
{
|
|
m_AutoRequestTeam();
|
|
}
|
|
|
|
// Send to the server that we got our player state
|
|
m_OnClientInitialized();
|
|
}
|
|
|
|
void AMenuController::SwitchToMenu()
|
|
{
|
|
mainMenu->OnShow();
|
|
lobbyMenu->OnHide();
|
|
m_inLobby = false;
|
|
}
|
|
|
|
bool AMenuController::m_OnClientInitialized_Validate()
|
|
{
|
|
return true;
|
|
}
|
|
void AMenuController::m_OnClientInitialized_Implementation()
|
|
{
|
|
AMenuGameMode* gm = Cast<AMenuGameMode>(GetWorld()->GetAuthGameMode());
|
|
if(gm)
|
|
{
|
|
gm->onPlayerJoined.Broadcast(this);
|
|
}
|
|
}
|
|
|
|
void AMenuController::m_OnInviteAccepted(bool success, const FOnlineSessionSearchResult& result)
|
|
{
|
|
if(success)
|
|
{
|
|
GPRINT("Accepted an invite");
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
|
|
inst->sessionManager->onJoinSessionComplete.AddUObject(this, &AMenuController::m_OnSessionJoined);
|
|
inst->sessionManager->JoinSession(result);
|
|
}
|
|
}
|
|
void AMenuController::m_OnSessionJoined(int32 result)
|
|
{
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
|
|
inst->sessionManager->onJoinSessionComplete.RemoveAll(this);
|
|
|
|
if(result == EOnJoinSessionCompleteResult::Success)
|
|
{
|
|
ClientTravel(inst->sessionManager->joinConnectionString, ETravelType::TRAVEL_Absolute);
|
|
}
|
|
else
|
|
{
|
|
TArray<FString> options;
|
|
options.Add("OK");
|
|
overlay->ShowMessageBox("Error", FString("Failed to accept invite (") + FString::FromInt(result) + ")", options);
|
|
GERROR("Failed to join session invite");
|
|
SwitchToMenu();
|
|
}
|
|
}
|
|
|
|
void AMenuController::m_AutoRequestTeam()
|
|
{
|
|
UWorld* world = GetWorld();
|
|
APlayerStateBase* state = GetPlayerState<APlayerStateBase>();
|
|
if(state)
|
|
{
|
|
state->AutoAssignTeam();
|
|
if(world->IsPlayInEditor())
|
|
state->SetReadyState(true);
|
|
//GetWorld()->GetTimerManager().ClearTimer(m_teamRequestTimer);
|
|
}
|
|
}
|
|
void AMenuController::m_OnSplashScreenEnded()
|
|
{
|
|
m_splash = nullptr;
|
|
|
|
// Create start prompt
|
|
m_startScreen = CreateWidget<UStartPromptScreen>(this, startScreenClass);
|
|
check(m_startScreen);
|
|
m_startScreen->onClosed.AddUObject(this, &AMenuController::m_OnStartPromptClosed);
|
|
m_startScreen->AddToViewport();
|
|
}
|
|
void AMenuController::m_OnStartPromptClosed()
|
|
{
|
|
m_startScreen = nullptr;
|
|
|
|
// Open main menu
|
|
lobbyMenu = CreateWidget<ULobbyMenu>(this, lobbyWidgetClass);
|
|
lobbyMenu->AddToViewport();
|
|
mainMenu = CreateWidget<UMenuScreen>(this, menuWidgetClass);
|
|
mainMenu->AddToViewport();
|
|
mainMenu->OnShow();
|
|
mainMenu->OpenScreenMenu(mainSubMenuClass);
|
|
|
|
// Enter lobby when initially connected
|
|
UWorld* world = GetWorld();
|
|
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(world->GetGameInstance());
|
|
if(inst->sessionManager->HasNetConnection())
|
|
{
|
|
OnEnterLobby();
|
|
}
|
|
}
|
|
|
|
bool AMenuController::WorldIsPIE() const
|
|
{
|
|
UWorld* const world = GetWorld();
|
|
if (!IsValid(world)) return false;
|
|
return world->WorldType == EWorldType::PIE;
|
|
} |