aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Client/mod/scripts/vscripts
diff options
context:
space:
mode:
authorRoyalBlue <11448698+RoyalBlue1@users.noreply.github.com>2023-05-12 00:02:08 +0200
committerRoyalBlue <11448698+RoyalBlue1@users.noreply.github.com>2023-05-12 00:02:08 +0200
commit71ab870841c4ed048887289e9ad3ed9ff0c25c35 (patch)
tree516483c9a172cedadfd3716e250c65cc8b4ae910 /Northstar.Client/mod/scripts/vscripts
parentdd457ef265f440bbcb4ff6f07bfc76ea1661d40b (diff)
parentd205d4440ffbf0947ca5cf4a2705157ba2d873e2 (diff)
downloadNorthstarMods-71ab870841c4ed048887289e9ad3ed9ff0c25c35.tar.gz
NorthstarMods-71ab870841c4ed048887289e9ad3ed9ff0c25c35.zip
Merge remote-tracking branch 'upsteam/main' into gamemode_fd
Diffstat (limited to 'Northstar.Client/mod/scripts/vscripts')
-rw-r--r--Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut2
-rw-r--r--Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut43
-rw-r--r--Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut95
-rw-r--r--Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut42
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/_menus.nut2004
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut693
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut2
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut3
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut3
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut270
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut4
11 files changed, 2935 insertions, 226 deletions
diff --git a/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut
index 277ed030..db4865ee 100644
--- a/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut
+++ b/Northstar.Client/mod/scripts/vscripts/_custom_codecallbacks_client.gnut
@@ -23,7 +23,7 @@ struct {
void function OnReceivedMessage(ClClient_MessageStruct localMessage) {
- if ( IsWatchingReplay() )
+ if ( IsWatchingReplay() && localMessage.player == null )
return
if (localMessage.player != null)
diff --git a/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut
new file mode 100644
index 00000000..2a2ed3db
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/cl_northstar_client_init.nut
@@ -0,0 +1,43 @@
+global struct GameStateStruct {
+
+ string map
+ string mapDisplayname
+
+ string playlist
+ string playlistDisplayname
+
+ int currentPlayers
+ int maxPlayers
+ int ownScore
+ int otherHighestScore
+ int maxScore
+ float timeEnd
+}
+
+global struct UIPresenceStruct {
+ bool isLoading
+ bool isLobby
+ string loadingLevel
+ string loadedLevel
+}
+
+global struct RequiredModInfo
+{
+ string name
+ string version
+}
+
+global struct ServerInfo
+{
+ int index
+ string id
+ string name
+ string description
+ string map
+ string playlist
+ int playerCount
+ int maxPlayerCount
+ bool requiresPassword
+ string region
+ array< RequiredModInfo > requiredMods
+}
diff --git a/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut
index 755396e3..c8a8274a 100644
--- a/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut
+++ b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut
@@ -1,60 +1,45 @@
untyped
globalize_all_functions
-struct {
- int highestScore = 0
- int secondHighestScore = 0
-} file
-
-void function OnPrematchStart()
-{
- if ( GetServerVar( "roundBased" ) )
- NSUpdateTimeInfo( level.nv.roundEndTime - Time() )
- else
- NSUpdateTimeInfo( level.nv.gameEndTime - Time() )
-}
-
-void function NSUpdateGameStateClientStart()
-{
- #if MP
- AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart )
- #endif
-
- thread NSUpdateGameStateLoopClient()
- OnPrematchStart()
-}
-
-void function NSUpdateGameStateLoopClient()
-{
- while ( true )
+void function NorthstarCodeCallback_GenerateGameState() {
+
+ GameStateStruct gs
+
+ int highestScore = 0
+ int secondHighest = 0
+
+ foreach ( player in GetPlayerArray() )
{
- if ( IsSingleplayer() )
- {
- NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), 1, 1, 1, GetServerVar( "roundBased" ), 1 )
- wait 1.0
- }
- else
- {
- foreach ( player in GetPlayerArray() )
- {
- if ( GameRules_GetTeamScore( player.GetTeam() ) >= file.highestScore )
- {
- file.highestScore = GameRules_GetTeamScore( player.GetTeam() )
- }
- else if ( GameRules_GetTeamScore( player.GetTeam() ) > file.secondHighestScore )
- {
- file.secondHighestScore = GameRules_GetTeamScore( player.GetTeam() )
- }
- }
-
- int ourScore = 0
- if ( IsValid( GetLocalClientPlayer() ) )
- ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() )
-
- int limit = IsRoundBased() ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 )
- NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), ourScore, file.secondHighestScore, file.highestScore, GetServerVar( "roundBased" ), limit )
- OnPrematchStart()
- wait 1.0
- }
+ if ( GameRules_GetTeamScore( player.GetTeam() ) >= highestScore )
+ {
+ highestScore = GameRules_GetTeamScore( player.GetTeam() )
+ }
+ else if ( GameRules_GetTeamScore( player.GetTeam() ) > secondHighest )
+ {
+ secondHighest = GameRules_GetTeamScore( player.GetTeam() )
+ }
}
-}
+
+ gs.map = GetMapName()
+ gs.mapDisplayname = Localize(GetMapDisplayName(GetMapName()))
+
+ gs.playlist = GetCurrentPlaylistName()
+ gs.playlistDisplayname = Localize(GetCurrentPlaylistVarString("name", GetCurrentPlaylistName()))
+
+ gs.currentPlayers = GetPlayerArray().len()
+ gs.maxPlayers = GetCurrentPlaylistVarInt( "maxPlayers", -1 )
+
+ if ( IsValid( GetLocalClientPlayer() ) )
+ gs.ownScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() )
+
+ gs.otherHighestScore = gs.ownScore == highestScore ? secondHighest : highestScore
+
+ gs.maxScore = IsRoundBased() ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 )
+
+ if ( GetServerVar( "roundBased" ) )
+ gs.timeEnd = expect float(level.nv.roundEndTime - Time())
+ else
+ gs.timeEnd = expect float(level.nv.gameEndTime - Time())
+
+ NSPushGameStateData(gs)
+} \ No newline at end of file
diff --git a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut
index 1e381989..cdf1c981 100644
--- a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut
+++ b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut
@@ -1,38 +1,12 @@
untyped
globalize_all_functions
-void function NSUpdateGameStateUIStart()
-{
- thread NSUpdateGameStateLoopUI()
-}
+void function NorthstarCodeCallback_GenerateUIPresence() {
+ UIPresenceStruct uis
-void function NSUpdateGameStateLoopUI()
-{
- while ( true )
- {
- wait 1.0
-
- if ( uiGlobal.loadedLevel == "" )
- {
- if ( uiGlobal.isLoading )
- NSSetLoading( true )
- else
- {
- NSSetLoading( false )
- NSUpdateGameStateUI( "", "", "", "", true, false )
- }
-
- continue
- }
-
- NSSetLoading( false )
- if( GetConVarString( "mp_gamemode" ) == "solo" )
- {
- NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() + "_CAMPAIGN_NAME" ) ), "Campaign", "Campaign", IsFullyConnected(), false )
- }
- else
- {
- NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString( "mp_gamemode" ) ) ), IsFullyConnected(), false )
- }
- }
-}
+ uis.isLoading = uiGlobal.isLoading
+ uis.isLobby = IsLobby()
+ uis.loadingLevel = uiGlobal.loadingLevel
+ uis.loadedLevel = uiGlobal.loadedLevel
+ NSPushUIPresence(uis)
+} \ No newline at end of file
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut b/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut
new file mode 100644
index 00000000..c83381fd
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/ui/_menus.nut
@@ -0,0 +1,2004 @@
+untyped
+
+global const bool EDIT_LOADOUT_SELECTS = true
+global const string PURCHASE_SUCCESS_SOUND = "UI_Menu_Store_Purchase_Success"
+
+global function UICodeCallback_CloseAllMenus
+global function UICodeCallback_ActivateMenus
+global function UICodeCallback_LevelInit
+global function UICodeCallback_LevelLoadingStarted
+global function UICodeCallback_LevelLoadingFinished
+global function UICodeCallback_LevelShutdown
+global function UICodeCallback_OnConnected
+global function UICodeCallback_OnFocusChanged
+global function UICodeCallback_NavigateBack
+global function UICodeCallback_ToggleInGameMenu
+global function UICodeCallback_TryCloseDialog
+global function UICodeCallback_UpdateLoadingLevelName
+global function UICodeCallback_ConsoleKeyboardClosed
+global function UICodeCallback_ErrorDialog
+global function UICodeCallback_AcceptInvite
+global function UICodeCallback_OnDetenteDisplayed
+global function UICodeCallback_OnSpLogDisplayed
+global function UICodeCallback_EntitlementsChanged
+global function UICodeCallback_StoreTransactionCompleted
+global function UICodeCallback_GamePurchased
+global function UICodeCallback_PartyUpdated
+global function UICodeCallback_KeyBindOverwritten
+
+global function AdvanceMenu
+global function OpenSubmenu // REMOVE
+global function CloseSubmenu // REMOVE
+global function CloseActiveMenu
+global function CloseActiveMenuNoParms
+global function CloseAllMenus
+global function CloseAllInGameMenus
+global function CloseAllDialogs
+global function CloseAllToTargetMenu
+global function PrintMenuStack
+global function CleanupInGameMenus
+global function GetActiveMenu
+global function GetMenu
+global function GetPanel
+global function GetAllMenuPanels
+global function InitGamepadConfigs
+global function InitMenus
+global function AdvanceMenuEventHandler
+global function PCSwitchTeamsButton_Activate
+global function PCToggleSpectateButton_Activate
+global function AddMenuElementsByClassname
+global function FocusDefault
+global function SetPanelDefaultFocus
+global function PanelFocusDefault
+global function OpenMenuWrapper
+global function CloseMenuWrapper
+global function IsLevelMultiplayer
+global function AddMenuEventHandler
+global function AddPanelEventHandler
+global function AddButtonEventHandler
+global function AddEventHandlerToButton
+global function AddEventHandlerToButtonClass
+global function DisableMusic
+global function EnableMusic
+global function PlayMusic
+global function StopMusic
+global function IsMenuInMenuStack
+global function GetTopNonDialogMenu
+global function IsDialog
+global function IsDialogActive
+global function IsDialogOnlyActiveMenu
+global function SetNavUpDown
+global function SetNavLeftRight
+global function IsTrialPeriodActive
+global function LaunchGamePurchaseOrDLCStore
+global function SetMenuThinkFunc
+
+global function PCBackButton_Activate
+
+global function RegisterMenuVarInt
+global function GetMenuVarInt
+global function SetMenuVarInt
+global function RegisterMenuVarBool
+global function GetMenuVarBool
+global function SetMenuVarBool
+global function RegisterMenuVarVar
+global function GetMenuVarVar
+global function SetMenuVarVar
+global function AddMenuVarChangeHandler
+
+global function InviteFriends
+
+global function HACK_DelayedSetFocus_BecauseWhy
+
+#if DURANGO_PROG
+ global function OpenXboxPartyApp
+ global function OpenXboxHelp
+#endif // DURANGO_PROG
+
+global function OpenReviewTermsDialog
+global function ClassicMusic_OnChange
+global function IsClassicMusicAvailable
+
+
+void function UICodeCallback_CloseAllMenus()
+{
+ printt( "UICodeCallback_CloseAllMenus" )
+ CloseAllMenus()
+ // This is usually followed by a call to UICodeCallback_ActivateMenus().
+}
+
+// Bringing up the console will cause this, and it probably shouldn't
+void function UICodeCallback_ActivateMenus()
+{
+ if ( IsConnected() )
+ return
+
+ printt( "UICodeCallback_ActivateMenus:", uiGlobal.activeMenu && Hud_GetHudName( uiGlobal.activeMenu ) )
+
+ if ( uiGlobal.menuStack.len() == 0 )
+ {
+ AdvanceMenu( GetMenu( "MainMenu" ) )
+ }
+
+ if ( uiGlobal.activeMenu == GetMenu( "MainMenu" ) )
+ Signal( uiGlobal.signalDummy, "OpenErrorDialog" )
+
+ PlayMusic()
+
+ #if DURANGO_PROG
+ Durango_LeaveParty()
+ #endif // DURANGO_PROG
+}
+
+void function UICodeCallback_ToggleInGameMenu()
+{
+ if ( !IsFullyConnected() )
+ return
+
+ var activeMenu = uiGlobal.activeMenu
+ bool isMP = IsLevelMultiplayer( GetActiveLevel() )
+ bool isLobby = IsLobby()
+
+ var ingameMenu
+ if ( isMP )
+ {
+ ingameMenu = GetMenu( "InGameMPMenu" )
+ }
+ else
+ {
+ // Disable this callback for this special case menu so players can't skip it.
+ var spTitanTutorialMenu = GetMenu( "SPTitanLoadoutTutorialMenu" )
+ if ( activeMenu == spTitanTutorialMenu )
+ return
+
+ ingameMenu = GetMenu( "InGameSPMenu" )
+ }
+
+ if ( IsDialog( uiGlobal.activeMenu ) )
+ {
+ // Do nothing if a dialog is showing
+ }
+ else if ( TeamTitanSelectMenuIsOpen() )
+ {
+ if ( uiGlobal.activeMenu == GetMenu( "TeamTitanSelectMenu" ) )
+ {
+ // Do nothing here either
+ }
+ else
+ {
+ CloseActiveMenu()
+ }
+ }
+ else if ( ( isMP && !isLobby ) || !isMP )
+ {
+ if ( !activeMenu )
+ AdvanceMenu( ingameMenu )
+ else
+ CloseAllInGameMenus()
+ }
+}
+
+// Return true to show load screen, false to not show load screen.
+// levelname can be "" because the level to load isn't always known when the load screen starts
+bool function UICodeCallback_LevelLoadingStarted( string levelname )
+{
+ printt( "UICodeCallback_LevelLoadingStarted: " + levelname )
+
+ CloseAllDialogs()
+
+ uiGlobal.loadingLevel = levelname
+ uiGlobal.isLoading = true
+
+ StopMusic()
+
+ if ( uiGlobal.playingVideo )
+ Signal( uiGlobal.signalDummy, "PlayVideoEnded" )
+
+ if ( uiGlobal.playingCredits )
+ Signal( uiGlobal.signalDummy, "PlayingCreditsDone" )
+
+ // kill lingering postgame summary since persistent data may not be available at this point
+ Signal( uiGlobal.signalDummy, "PGDisplay" )
+
+#if CONSOLE_PROG
+ if ( !Console_IsSignedIn() )
+ return false
+#endif
+
+ return true
+}
+
+// Return true to show load screen, false to not show load screen.
+bool function UICodeCallback_UpdateLoadingLevelName( string levelname )
+{
+ printt( "UICodeCallback_UpdateLoadingLevelName: " + levelname )
+
+#if CONSOLE_PROG
+ if ( !Console_IsSignedIn() )
+ return false
+#endif
+
+ return true
+}
+
+void function UICodeCallback_LevelLoadingFinished( bool error )
+{
+ printt( "UICodeCallback_LevelLoadingFinished: " + uiGlobal.loadingLevel + " (" + error + ")" )
+
+ if ( !IsLobby() )
+ {
+ HudChat_ClearTextFromAllChatPanels()
+ ResetActiveChatroomLastModified()
+ }
+ else
+ {
+ uiGlobal.lobbyFromLoadingScreen = true
+ }
+
+ uiGlobal.loadingLevel = ""
+ uiGlobal.isLoading = false
+ Signal( uiGlobal.signalDummy, "LevelFinishedLoading" )
+}
+
+void function UICodeCallback_LevelInit( string levelname )
+{
+ Assert( IsConnected() )
+
+ StopVideo()
+
+ uiGlobal.loadedLevel = levelname
+
+ printt( "UICodeCallback_LevelInit: " + uiGlobal.loadedLevel )
+
+ if ( !uiGlobal.loadoutsInitialized )
+ {
+ string gameModeString = GetConVarString( "mp_gamemode" )
+ if ( gameModeString != "solo" )
+ {
+ InitStatsTables()
+ }
+ }
+
+ InitItems()
+
+ if ( IsMultiplayer() )
+ {
+ ShWeaponXP_Init()
+ ShTitanXP_Init()
+ ShFactionXP_Init()
+ }
+ else
+ {
+ SPObjectiveStringsInit()
+ }
+
+ #if DEV
+ UpdatePrecachedSPWeapons()
+ #endif
+
+
+ if ( !uiGlobal.loadoutsInitialized )
+ {
+ string gameModeString = GetConVarString( "mp_gamemode" )
+ if ( gameModeString != "solo" )
+ {
+ DeathHints_Init()
+ InitDefaultLoadouts()
+ CreateChallenges()
+ uiGlobal.loadoutsInitialized = true
+ }
+ }
+
+ if ( IsLevelMultiplayer( levelname ) || IsLobbyMapName( levelname ) )
+ {
+ thread UpdateCachedLoadouts()
+ thread UpdateCachedNewItems()
+ thread InitUISpawnLoadoutIndexes()
+
+ if ( !uiGlobal.eventHandlersAdded )
+ {
+ uiGlobal.eventHandlersAdded = true
+ }
+
+ UI_GetAllChallengesProgress()
+
+ bool isLobby = IsLobbyMapName( levelname )
+
+ string gameModeString = GetConVarString( "mp_gamemode" )
+ if ( gameModeString == "" )
+ gameModeString = "<null>"
+
+ Assert( gameModeString == GetConVarString( "mp_gamemode" ) )
+ Assert( gameModeString != "" )
+
+ int gameModeId = GameMode_GetGameModeId( gameModeString )
+
+ int mapId = eMaps.invalid
+ if ( levelname in getconsttable().eMaps )
+ {
+ mapId = expect int( getconsttable().eMaps[ levelname ] )
+ }
+ else
+ {
+ // Don't worry about this until we have to consider R2 Durango TCRs (10/2015)
+ //if ( !IsTestMap() )
+ // CodeWarning( "No map named '" + levelname + "' exists in eMaps, all shipping maps should be in this enum" )
+ }
+
+ int difficultyLevelId = 0
+ int roundId = 0
+
+ if ( isLobby )
+ Durango_OnLobbySessionStart( gameModeId, difficultyLevelId )
+ else
+ Durango_OnMultiplayerRoundStart( gameModeId, mapId, difficultyLevelId, roundId, 0 )
+ }
+ else
+ {
+ // SP loadout stuff
+ UI_GetAllChallengesProgress() // TODO: Can this be moved so we don't call it twice? It's called above.
+
+ SP_ResetObjectiveStringIndex() // Since this persists thru level load, we need to explicitely clear it.
+ }
+
+ if ( IsMultiplayer() )
+ {
+ foreach ( callbackFunc in uiGlobal.onLevelInitCallbacks )
+ {
+ thread callbackFunc()
+ }
+
+ }
+ thread UpdateMenusOnConnect( levelname )
+
+ uiGlobal.previousLevel = uiGlobal.loadedLevel
+ uiGlobal.previousPlaylist = GetCurrentPlaylistName()
+}
+
+void function UICodeCallback_LevelShutdown()
+{
+ Signal( uiGlobal.signalDummy, "LevelShutdown" )
+
+ printt( "UICodeCallback_LevelShutdown: " + uiGlobal.loadedLevel )
+
+ StopVideo()
+
+ if ( uiGlobal.loadedLevel != "" )
+ CleanupInGameMenus()
+
+ uiGlobal.loadedLevel = ""
+ uiGlobal.mapSupportsMenuModelsUpdated = false
+ uiGlobal.sp_showAlternateMissionLog = false
+}
+
+void function UICodeCallback_NavigateBack()
+{
+ if ( uiGlobal.activeMenu == null )
+ return
+
+ if ( IsDialog( uiGlobal.activeMenu ) )
+ {
+ if ( uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.noChoice ||
+ uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.forceChoice ||
+ Time() < uiGlobal.dialogInputEnableTime )
+ return
+ }
+
+ Assert( uiGlobal.activeMenu in uiGlobal.menuData )
+ if ( uiGlobal.menuData[ uiGlobal.activeMenu ].navBackFunc != null )
+ {
+ thread uiGlobal.menuData[ uiGlobal.activeMenu ].navBackFunc()
+ return
+ }
+
+ if ( uiGlobal.activeMenu.GetType() == "submenu" ) // REMOVE
+ {
+ CloseSubmenu()
+ return
+ }
+
+ CloseActiveMenu( true )
+}
+
+// Called when IsConnected() will start returning true.
+void function UICodeCallback_OnConnected()
+{
+
+}
+
+void function UICodeCallback_OnFocusChanged( var oldFocusedPanel, var newFocusedPanel )
+{
+
+}
+
+// Accepting an origin invite closes dialogs, or aborts if they can't be closed
+bool function UICodeCallback_TryCloseDialog()
+{
+ if ( !IsDialog( uiGlobal.activeMenu ) )
+ return true
+
+ if ( uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData.forceChoice )
+ return false
+
+ CloseAllDialogs()
+ Assert( !IsDialog( uiGlobal.activeMenu ) )
+ return true
+}
+
+void function UICodeCallback_ConsoleKeyboardClosed()
+{
+ switch ( uiGlobal.activeMenu )
+ {
+ case GetMenu( "EditPilotLoadoutMenu" ):
+ string oldName = GetPilotLoadoutName( GetCachedPilotLoadout( uiGlobal.editingLoadoutIndex ) )
+ string newName = GetPilotLoadoutRenameText()
+
+ // strip doesn't work on UTF-8 strings
+ // newName = strip( newName ) // Remove leading/trailing whitespace
+ if ( newName == "" ) // If all whitespace entered reset to previous name
+ newName = oldName
+
+ SetPilotLoadoutName( newName )
+ SelectPilotLoadoutRenameText()
+ if ( newName != oldName )
+ EmitUISound( "Menu.Accept" ) // No callback when cancelled so for now assume name was changed
+ break
+
+ default:
+ break
+ }
+}
+
+void function UICodeCallback_OnDetenteDisplayed()
+{
+// thread PlayDetentSound()
+//}
+//
+//void function PlayDetentSound()
+//{
+// WaitFrame() // otherwise gets killed off by code pause
+// WaitFrame() // otherwise gets killed off by code pause
+// EmitUISound( "Pilot_Killed_Indicator" )
+}
+
+void function UICodeCallback_OnSpLogDisplayed()
+{
+}
+
+void function UICodeCallback_ErrorDialog( string errorDetails )
+{
+ printt( "UICodeCallback_ErrorDialog: " + errorDetails )
+ thread OpenErrorDialog( errorDetails )
+}
+
+void function UICodeCallback_AcceptInviteThread( string accesstoken )
+{
+ printt( "UICodeCallback_AcceptInviteThread '" + accesstoken + "'")
+
+ #if PS4_PROG
+ if ( !Ps4_PSN_Is_Loggedin() )
+ {
+ Ps4_LoginDialog_Schedule();
+ while( Ps4_LoginDialog_Running() )
+ WaitFrame()
+ if ( !Ps4_PSN_Is_Loggedin() )
+ return;
+ }
+
+ if( Ps4_CheckPlus_Schedule() )
+ {
+ while( Ps4_CheckPlus_Running() )
+ WaitFrame()
+ if( !Ps4_CheckPlus_Allowed() )
+ {
+ if( Ps4_CheckPlus_GetLastRequestResults() != 0 )
+ {
+ return
+ }
+
+ if( Ps4_ScreenPlusDialog_Schedule() )
+ {
+ while( Ps4_ScreenPlusDialog_Running() )
+ WaitFrame()
+ if( !Ps4_ScreenPlusDialog_Allowed() )
+ return;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+ #endif // #if PS4_PROG
+
+ SubscribeToChatroomPartyChannel( accesstoken );
+
+}
+
+
+void function UICodeCallback_AcceptInvite( string accesstoken )
+{
+ printt( "UICodeCallback_AcceptInvite '" + accesstoken + "'")
+ thread UICodeCallback_AcceptInviteThread( accesstoken )
+}
+
+// TODO: replaceCurrent should not be an option. It should be a different function.
+void function AdvanceMenu( var menu, bool replaceCurrent = false )
+{
+ //foreach ( index, menu in uiGlobal.menuStack )
+ //{
+ // if ( menu != null )
+ // printt( "menu index " + index + " is named " + menu.GetDisplayName() )
+ //}
+
+ if ( uiGlobal.activeMenu )
+ {
+ // Don't open the same menu again if it's already open
+ if ( uiGlobal.activeMenu == menu )
+ return
+
+ // Opening a normal menu while a dialog is open
+ Assert( !IsDialog( uiGlobal.activeMenu ), "Tried opening menu: " + Hud_GetHudName( menu ) + " when uiGlobal.activeMenu was: " + Hud_GetHudName( uiGlobal.activeMenu ) )
+ }
+
+ if ( uiGlobal.activeMenu && !IsDialog( menu ) ) // Dialogs show on top so don't close existing menu when opening them
+ {
+ SetBlurEnabled( false )
+
+ if ( replaceCurrent )
+ {
+ CloseMenuWrapper( uiGlobal.activeMenu )
+ uiGlobal.menuStack.pop()
+ }
+ else
+ {
+ CloseMenu( uiGlobal.activeMenu )
+ printt( Hud_GetHudName( uiGlobal.activeMenu ), "menu closed" )
+ }
+ }
+
+ if ( IsDialog( menu ) && uiGlobal.activeMenu )
+ SetFooterPanelVisibility( uiGlobal.activeMenu, false )
+
+ uiGlobal.menuStack.push( menu )
+ uiGlobal.activeMenu = menu
+
+ uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD
+
+ if ( uiGlobal.activeMenu )
+ {
+ if ( !IsLobby() && !uiGlobal.mapSupportsMenuModels )
+ SetBlurEnabled( true )
+
+ OpenMenuWrapper( uiGlobal.activeMenu, true )
+ }
+
+ Signal( uiGlobal.signalDummy, "ActiveMenuChanged" )
+}
+
+void function SetFooterPanelVisibility( var menu, bool visible )
+{
+ if ( !Hud_HasChild( menu, "FooterButtons" ) )
+ return
+
+ var panel = Hud_GetChild( menu, "FooterButtons" )
+ Hud_SetVisible( panel, visible )
+}
+
+void function OpenSubmenu( var menu, bool updateMenuPos = true )
+{
+ Assert( menu )
+ Assert( menu.GetType() == "submenu" )
+
+ if ( uiGlobal.activeMenu )
+ {
+ // Don't open the same menu again if it's already open
+ if ( uiGlobal.activeMenu == menu )
+ return
+ }
+
+ local submenuPos = Hud_GetAbsPos( GetFocus() )
+
+ uiGlobal.menuStack.push( menu )
+ uiGlobal.activeMenu = menu
+
+ OpenMenuWrapper( uiGlobal.activeMenu, true )
+
+ if ( updateMenuPos )
+ {
+ var vguiButtonFrame = Hud_GetChild( uiGlobal.activeMenu, "ButtonFrame" )
+ Hud_SetPos( vguiButtonFrame, submenuPos[0], submenuPos[1] )
+ }
+
+ uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD
+
+ Signal( uiGlobal.signalDummy, "ActiveMenuChanged" )
+}
+
+void function CloseSubmenu( bool openStackMenu = true )
+{
+ if ( !uiGlobal.activeMenu )
+ return
+
+ if ( uiGlobal.activeMenu.GetType() != "submenu" )
+ return
+
+ CloseMenuWrapper( uiGlobal.activeMenu )
+ uiGlobal.menuStack.pop()
+
+ uiGlobal.lastMenuNavDirection = MENU_NAV_FORWARD
+
+ if ( uiGlobal.menuStack.len() )
+ {
+ uiGlobal.activeMenu = uiGlobal.menuStack.top()
+
+ // This runs any OnOpen function for the menu and sets focus, but doesn't actually open the menu because it is already open
+ if ( openStackMenu )
+ OpenMenuWrapper( uiGlobal.activeMenu, false )
+ }
+ else
+ {
+ uiGlobal.activeMenu = null
+ }
+
+ Signal( uiGlobal.signalDummy, "ActiveMenuChanged" )
+}
+
+void function CloseActiveMenuNoParms()
+{
+ CloseActiveMenu()
+}
+
+void function CloseActiveMenu( bool cancelled = false, bool openStackMenu = true )
+{
+ bool updateBlur = true
+ bool wasDialog = false
+
+ if ( uiGlobal.activeMenu )
+ {
+ if ( IsDialog( uiGlobal.activeMenu ) )
+ {
+ updateBlur = false
+ wasDialog = true
+ uiGlobal.dialogInputEnableTime = 0.0
+
+ if ( uiGlobal.dialogCloseCallback )
+ {
+ uiGlobal.dialogCloseCallback( cancelled )
+ uiGlobal.dialogCloseCallback = null
+ }
+ }
+
+ if ( updateBlur )
+ SetBlurEnabled( false )
+
+ CloseMenuWrapper( uiGlobal.activeMenu )
+ }
+
+ uiGlobal.menuStack.pop()
+ if ( uiGlobal.menuStack.len() )
+ uiGlobal.activeMenu = uiGlobal.menuStack.top()
+ else
+ uiGlobal.activeMenu = null
+
+ uiGlobal.lastMenuNavDirection = MENU_NAV_BACK
+
+ if ( wasDialog )
+ {
+ if ( uiGlobal.activeMenu )
+ SetFooterPanelVisibility( uiGlobal.activeMenu, true )
+
+ if ( IsDialog( uiGlobal.activeMenu ) )
+ openStackMenu = true
+ else
+ openStackMenu = false
+ }
+
+ if ( uiGlobal.activeMenu )
+ {
+ if ( uiGlobal.activeMenu.GetType() == "submenu" )
+ {
+ Hud_SetFocused( uiGlobal.menuData[ uiGlobal.activeMenu ].lastFocus )
+ }
+ else if ( openStackMenu )
+ {
+ OpenMenuWrapper( uiGlobal.activeMenu, false )
+
+ if ( updateBlur && !IsLobby() && !uiGlobal.mapSupportsMenuModels )
+ SetBlurEnabled( true )
+ }
+ }
+
+ Signal( uiGlobal.signalDummy, "ActiveMenuChanged" )
+}
+
+void function CloseAllMenus()
+{
+ if ( IsDialog( uiGlobal.activeMenu ) )
+ CloseActiveMenu( true )
+
+ if ( uiGlobal.activeMenu && uiGlobal.activeMenu.GetType() == "submenu" )
+ CloseSubmenu( false )
+
+ if ( uiGlobal.activeMenu )
+ {
+ SetBlurEnabled( false )
+ CloseMenuWrapper( uiGlobal.activeMenu )
+ }
+
+ uiGlobal.menuStack = []
+ uiGlobal.activeMenu = null
+
+ uiGlobal.lastMenuNavDirection = MENU_NAV_BACK
+
+ Signal( uiGlobal.signalDummy, "ActiveMenuChanged" )
+}
+
+void function CloseAllInGameMenus()
+{
+ while ( uiGlobal.activeMenu )
+ {
+ if ( uiGlobal.activeMenu.GetType() == "submenu" )
+ CloseSubmenu( false )
+
+ CloseActiveMenu( true, false )
+ }
+}
+
+void function CloseAllDialogs()
+{
+ while ( IsDialog( uiGlobal.activeMenu ) )
+ CloseActiveMenu( true )
+}
+
+void function CloseAllToTargetMenu( var targetMenu )
+{
+ while ( uiGlobal.activeMenu != targetMenu )
+ CloseActiveMenu( true, false )
+}
+
+void function PrintMenuStack()
+{
+ array<var> stack = clone uiGlobal.menuStack
+ stack.reverse()
+
+ printt( "MENU STACK:" )
+
+ foreach ( menu in stack )
+ {
+ if ( menu )
+ printt( " ", Hud_GetHudName( menu ) )
+ else
+ printt( " null" )
+ }
+}
+
+// Happens on any level load
+void function UpdateMenusOnConnect( string levelname )
+{
+ EndSignal( uiGlobal.signalDummy, "LevelShutdown" ) // HACK fix because UICodeCallback_LevelInit() incorrectly runs when disconnected by client error. Test with "script_error_client" while a level is loaded.
+
+ CloseAllDialogs()
+
+ var mainMenu = GetMenu( "MainMenu" )
+ if ( IsMenuInMenuStack( mainMenu ) && !IsMenuInMenuStack( null ) )
+ CloseAllToTargetMenu( mainMenu )
+
+ Assert( uiGlobal.activeMenu != null || uiGlobal.menuStack.len() == 0 )
+
+ AdvanceMenu( null )
+
+ // TODO: The order things are called in should be predictable so this isn't needed
+ while ( !uiGlobal.mapSupportsMenuModelsUpdated )
+ {
+ //printt( Time(), "beginning waitframe, uiGlobal.mapSupportsMenuModelsUpdated is:", uiGlobal.mapSupportsMenuModelsUpdated )
+ WaitFrame()
+ //printt( Time(), "ended waitframe, uiGlobal.mapSupportsMenuModelsUpdated is:", uiGlobal.mapSupportsMenuModelsUpdated )
+ }
+
+ if ( IsLevelMultiplayer( levelname ) )
+ {
+ bool isLobby = IsLobbyMapName( levelname )
+
+ if ( isLobby )
+ {
+ if ( IsPrivateMatch() )
+ {
+ AdvanceMenu( GetMenu( "PrivateLobbyMenu" ) )
+ }
+ else
+ {
+ AdvanceMenu( GetMenu( "LobbyMenu" ) )
+ }
+
+ thread UpdateAnnouncementDialog()
+ }
+ else
+ {
+ UI_SetPresentationType( ePresentationType.INACTIVE )
+ }
+ }
+}
+
+bool function IsMenuInMenuStack( var searchMenu )
+{
+ foreach ( menu in uiGlobal.menuStack )
+ {
+ // loading a map pushes a null sentinel onto the menu stack
+ if ( !menu )
+ continue
+
+ if ( menu == searchMenu )
+ return true
+ }
+
+ return false
+}
+
+var function GetTopNonDialogMenu()
+{
+ array<var> menuArray = clone uiGlobal.menuStack
+ menuArray.reverse()
+
+ foreach ( menu in menuArray )
+ {
+ if ( menu == null || IsDialog( menu ) )
+ continue
+
+ return menu
+ }
+
+ return null
+}
+
+void function CleanupInGameMenus()
+{
+ Signal( uiGlobal.signalDummy, "CleanupInGameMenus" )
+
+ CloseAllInGameMenus()
+ Assert( uiGlobal.activeMenu == null )
+ if ( uiGlobal.menuStack.len() )
+ {
+ if ( uiGlobal.loadingLevel == "" )
+ CloseActiveMenu() // Disconnected. Remove stack null and open main menu.
+ else
+ CloseActiveMenu( true, false ) // Level to level transition. Remove stack null and DON'T open main menu.
+ }
+}
+
+var function GetActiveMenu()
+{
+ return uiGlobal.activeMenu
+}
+
+var function GetMenu( string menuName )
+{
+ return uiGlobal.menus[ menuName ]
+}
+
+var function GetPanel( string panelName )
+{
+ return uiGlobal.panels[ panelName ]
+}
+
+array<var> function GetAllMenuPanels( var menu )
+{
+ array<var> menuPanels
+
+ foreach ( panel in uiGlobal.allPanels )
+ {
+ if ( Hud_GetParent( panel ) == menu )
+ menuPanels.append( panel )
+ }
+
+ return menuPanels
+}
+
+void function InitGamepadConfigs()
+{
+ uiGlobal.buttonConfigs = [ { orthodox = "gamepad_button_layout_default.cfg", southpaw = "gamepad_button_layout_default_southpaw.cfg" } ]
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_bumper_jumper.cfg", southpaw = "gamepad_button_layout_bumper_jumper_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_bumper_jumper_alt.cfg", southpaw = "gamepad_button_layout_bumper_jumper_alt_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_pogo_stick.cfg", southpaw = "gamepad_button_layout_pogo_stick_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_button_kicker.cfg", southpaw = "gamepad_button_layout_button_kicker_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_circle.cfg", southpaw = "gamepad_button_layout_circle_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_ninja.cfg", southpaw = "gamepad_button_layout_ninja_southpaw.cfg" } )
+ uiGlobal.buttonConfigs.append( { orthodox = "gamepad_button_layout_custom.cfg", southpaw = "gamepad_button_layout_custom.cfg" } )
+
+ uiGlobal.stickConfigs = []
+ uiGlobal.stickConfigs.append( "gamepad_stick_layout_default.cfg" )
+ uiGlobal.stickConfigs.append( "gamepad_stick_layout_southpaw.cfg" )
+ uiGlobal.stickConfigs.append( "gamepad_stick_layout_legacy.cfg" )
+ uiGlobal.stickConfigs.append( "gamepad_stick_layout_legacy_southpaw.cfg" )
+
+ foreach ( key, val in uiGlobal.buttonConfigs )
+ {
+ VPKNotifyFile( "cfg/" + val.orthodox )
+ VPKNotifyFile( "cfg/" + val.southpaw )
+ }
+
+ foreach ( key, val in uiGlobal.stickConfigs )
+ VPKNotifyFile( "cfg/" + val )
+
+ ExecCurrentGamepadButtonConfig()
+ ExecCurrentGamepadStickConfig()
+
+ SetStandardAbilityBindingsForPilot( GetLocalClientPlayer() )
+}
+
+void function InitMenus()
+{
+ InitGlobalMenuVars()
+ SpShWeaponsInit()
+
+ AddMenu( "MainMenu", $"resource/ui/menus/main.menu", InitMainMenu, "#MAIN" )
+ AddPanel( GetMenu( "MainMenu" ), "EstablishUserPanel", InitEstablishUserPanel )
+ AddPanel( GetMenu( "MainMenu" ), "MainMenuPanel", InitMainMenuPanel )
+
+ AddMenu( "PlayVideoMenu", $"resource/ui/menus/play_video.menu", InitPlayVideoMenu )
+ AddMenu( "LobbyMenu", $"resource/ui/menus/lobby.menu", InitLobbyMenu, "#LOBBY" )
+
+ AddMenu( "FDMenu", $"resource/ui/menus/playlist_fd.menu", InitFDPlaylistMenu )
+ AddMenu( "TeamTitanSelectMenu", $"resource/ui/menus/team_titan_select.menu", InitTeamTitanSelectMenu )
+ AddMenu( "PlaylistMenu", $"resource/ui/menus/playlist.menu", InitPlaylistMenu )
+ AddMenu( "PlaylistMixtapeMenu", $"resource/ui/menus/playlist_mixtape.menu", InitPlaylistMixtapeMenu )
+ AddMenu( "PlaylistMixtapeChecklistMenu", $"resource/ui/menus/playlist_mixtape_checklist.menu", InitPlaylistMixtapeChecklistMenu )
+
+ AddMenu( "SinglePlayerDevMenu", $"resource/ui/menus/singleplayer_dev.menu", InitSinglePlayerDevMenu, "SINGLE PLAYER DEV" )
+ AddMenu( "SinglePlayerMenu", $"resource/ui/menus/singleplayer.menu", InitSinglePlayerMenu, "SINGLE PLAYER" )
+
+ AddMenu( "SearchMenu", $"resource/ui/menus/search.menu", InitSearchMenu )
+
+ AddMenu( "GammaMenu", $"resource/ui/menus/gamma.menu", InitGammaMenu, "#BRIGHTNESS" )
+
+ AddMenu( "CommunitiesMenu", $"resource/ui/menus/community.menu", InitCommunitiesMenu )
+ AddMenu( "Notifications", $"resource/ui/menus/notifications.menu", InitNotificationsMenu )
+ AddMenu( "MyNetworks", $"resource/ui/menus/communities_mine.menu", InitMyNetworksMenu )
+ AddMenu( "InboxFrontMenu", $"resource/ui/menus/inbox_front.menu", InitInboxFrontMenu )
+ AddMenu( "Inbox", $"resource/ui/menus/inbox.menu", InitInboxMenu )
+ AddMenu( "BrowseCommunities", $"resource/ui/menus/communities_browse.menu" )
+ AddMenu( "CommunityEditMenu", $"resource/ui/menus/community_edit.menu" )
+ AddMenu( "CommunityAdminSendMessage", $"resource/ui/menus/community_sendMessage.menu" )
+ AddMenu( "CommunityAdminInviteRequestMenu", $"resource/ui/menus/community_inviteRequest.menu" )
+#if NETWORK_INVITE
+ AddMenu( "InviteFriendsToNetworkMenu", $"resource/ui/menus/invite_friends.menu", InitInviteFriendsToNetworkMenu )
+#endif
+
+ AddMenu( "InGameMPMenu", $"resource/ui/menus/ingame_mp.menu", InitInGameMPMenu )
+ AddMenu( "InGameSPMenu", $"resource/ui/menus/ingame_sp.menu", InitInGameSPMenu )
+
+ AddMenu( "Dialog", $"resource/ui/menus/dialog.menu", InitDialogMenu )
+ AddMenu( "AnnouncementDialog", $"resource/ui/menus/dialog_announcement.menu", InitAnnouncementDialog )
+ AddMenu( "ConnectingDialog", $"resource/ui/menus/dialog_connecting.menu", InitConnectingDialog )
+ AddMenu( "DataCenterDialog", $"resource/ui/menus/dialog_datacenter.menu", InitDataCenterDialogMenu )
+ AddMenu( "EULADialog", $"resource/ui/menus/dialog_eula.menu", InitEULADialog )
+ AddMenu( "ReviewTermsDialog", $"resource/ui/menus/dialog_review_terms.menu", InitReviewTermsDialog )
+ AddMenu( "RegistrationDialog", $"resource/ui/menus/dialog_registration.menu", InitRegistrationDialog )
+ AddMenu( "AdvocateGiftDialog", $"resource/ui/menus/dialog_advocate_gift.menu", InitAdvocateGiftDialog )
+
+ AddMenu( "ControlsMenu", $"resource/ui/menus/controls.menu", InitControlsMenu, "#CONTROLS" )
+ AddMenu( "ControlsAdvancedLookMenu", $"resource/ui/menus/controls_advanced_look.menu", InitControlsAdvancedLookMenu, "#CONTROLS_ADVANCED_LOOK" )
+ AddMenu( "GamepadLayoutMenu", $"resource/ui/menus/gamepadlayout.menu", InitGamepadLayoutMenu )
+#if PC_PROG
+ AddMenu_WithCreateFunc( "MouseKeyboardBindingsMenu", $"resource/ui/menus/mousekeyboardbindings.menu", InitMouseKeyboardMenu, CreateKeyBindingMenu )
+ AddMenu( "AudioMenu", $"resource/ui/menus/audio.menu", InitAudioMenu, "#AUDIO" )
+ AddMenu_WithCreateFunc( "VideoMenu", $"resource/ui/menus/video.menu", InitVideoMenu, CreateVideoOptionsMenu )
+#elseif CONSOLE_PROG
+ AddMenu( "AudioVideoMenu", $"resource/ui/menus/audio_video.menu", InitAudioVideoMenu, "#AUDIO_VIDEO" )
+#endif
+
+ AddMenu( "AdvancedHudMenu", $"resource/ui/menus/advanced_hud.menu", InitAdvancedHudMenu, "#ADVANCED_HUD" )
+
+ AddMenu( "PilotLoadoutsMenu", $"resource/ui/menus/pilotloadouts.menu", InitPilotLoadoutsMenu )
+ AddMenu( "TitanLoadoutsMenu", $"resource/ui/menus/titanloadouts.menu", InitTitanLoadoutsMenu )
+ AddMenu( "EditPilotLoadoutsMenu", $"resource/ui/menus/pilotloadouts.menu", InitEditPilotLoadoutsMenu )
+ AddMenu( "EditTitanLoadoutsMenu", $"resource/ui/menus/titanloadouts.menu", InitEditTitanLoadoutsMenu )
+ AddMenu( "EditPilotLoadoutMenu", $"resource/ui/menus/editpilotloadout.menu", InitEditPilotLoadoutMenu )
+ AddMenu( "EditTitanLoadoutMenu", $"resource/ui/menus/edittitanloadout.menu", InitEditTitanLoadoutMenu )
+
+ AddMenu( "SPTitanLoadoutMenu", $"resource/ui/menus/sptitanloadout.menu", InitSPTitanLoadoutMenu )
+ AddMenu( "SPTitanLoadoutTutorialMenu", $"resource/ui/menus/sptitanloadout_tutorial.menu", InitSPTitanLoadoutTutorialMenu )
+
+ AddMenu( "SuitSelectMenu", $"resource/ui/menus/suitselect.menu", InitSuitSelectMenu )
+ AddMenu( "WeaponSelectMenu", $"resource/ui/menus/weaponselect.menu", InitWeaponSelectMenu )
+ AddMenu( "CategorySelectMenu", $"resource/ui/menus/categoryselect.menu", InitCategorySelectMenu )
+ AddMenu( "AbilitySelectMenu", $"resource/ui/menus/abilityselect.menu", InitAbilitySelectMenu )
+ AddMenu( "PassiveSelectMenu", $"resource/ui/menus/passiveselect.menu", InitPassiveSelectMenu )
+ AddSubmenu( "ModSelectMenu", $"resource/ui/menus/modselect.menu", InitModSelectMenu )
+ AddMenu( "CamoSelectMenu", $"resource/ui/menus/camoselect.menu", InitCamoSelectMenu )
+ AddMenu( "NoseArtSelectMenu", $"resource/ui/menus/noseartselect.menu", InitNoseArtSelectMenu )
+ AddMenu( "CallsignCardSelectMenu", $"resource/ui/menus/callsigncardselect.menu", InitCallsignCardSelectMenu )
+ AddMenu( "CallsignIconSelectMenu", $"resource/ui/menus/callsigniconselect.menu", InitCallsignIconSelectMenu )
+ AddMenu( "BoostStoreMenu", $"resource/ui/menus/booststore.menu", InitBoostStoreMenu )
+
+ AddMenu( "PrivateLobbyMenu", $"resource/ui/menus/private_lobby.menu", InitPrivateMatchMenu, "#PRIVATE_MATCH" )
+ AddMenu( "MapsMenu", $"resource/ui/menus/map_select.menu", InitMapsMenu )
+ AddMenu( "ModesMenu", $"resource/ui/menus/mode_select.menu", InitModesMenu )
+ AddMenu( "MatchSettingsMenu", $"resource/ui/menus/match_settings.menu", InitMatchSettingsMenu )
+
+ AddMenu( "Advocate_Letter", $"resource/ui/menus/advocate_letter.menu", InitAdvocateLetterMenu )
+ AddMenu( "Generation_Respawn", $"resource/ui/menus/generation_respawn.menu", InitGenerationRespawnMenu )
+ AddMenu( "ChallengesMenu", $"resource/ui/menus/challenges.menu", InitChallengesMenu )
+
+ AddMenu( "ViewStatsMenu", $"resource/ui/menus/viewstats.menu", InitViewStatsMenu, "#PERSONAL_STATS" )
+ AddMenu( "ViewStats_Overview_Menu", $"resource/ui/menus/viewstats_overview.menu", InitViewStatsOverviewMenu )
+ //AddMenu( "ViewStats_Kills_Menu", $"resource/ui/menus/viewstats_kills.menu", InitViewStatsKillsMenu )
+ AddMenu( "ViewStats_Time_Menu", $"resource/ui/menus/viewstats_time.menu", InitViewStatsTimeMenu )
+ //AddMenu( "ViewStats_Distance_Menu", $"resource/ui/menus/viewstats_distance.menu", InitViewStatsDistanceMenu )
+ AddMenu( "ViewStats_Weapons_Menu", $"resource/ui/menus/viewstats_weapons.menu", InitViewStatsWeaponsMenu )
+ AddMenu( "ViewStats_Titans_Menu", $"resource/ui/menus/viewstats_titans.menu", InitViewStatsTitansMenu )
+ AddMenu( "ViewStats_Misc_Menu", $"resource/ui/menus/viewstats_misc.menu", InitViewStatsMiscMenu )
+ AddMenu( "ViewStats_Maps_Menu", $"resource/ui/menus/viewstats_maps.menu", InitViewStatsMapsMenu )
+
+ AddMenu( "PostGameMenu", $"resource/ui/menus/postgame.menu", InitPostGameMenu )
+ AddMenu( "EOG_XP", $"resource/ui/menus/eog_xp.menu", InitEOG_XPMenu )
+ AddMenu( "EOG_Coins", $"resource/ui/menus/eog_coins.menu", InitEOG_CoinsMenu )
+ AddMenu( "EOG_Challenges", $"resource/ui/menus/eog_challenges.menu", InitEOG_ChallengesMenu )
+ AddMenu( "EOG_Unlocks", $"resource/ui/menus/eog_unlocks.menu", InitEOG_UnlocksMenu )
+ AddMenu( "EOG_Scoreboard", $"resource/ui/menus/eog_scoreboard.menu", InitEOG_ScoreboardMenu )
+
+ AddMenu( "CreditsMenu", $"resource/ui/menus/credits.menu", InitCreditsMenu, "#CREDITS" )
+
+ AddMenu( "BurnCardMenu", $"resource/ui/menus/burn_cards.menu", InitBurnCardMenu, "#MENU_BURNCARD_MENU" )
+ AddMenu( "FactionChoiceMenu", $"resource/ui/menus/faction_choice.menu", InitFactionChoiceMenu, "#FACTION_CHOICE_MENU" )
+ AddMenu( "ArmoryMenu", $"resource/ui/menus/armory.menu", InitArmoryMenu, "#ARMORY_MENU" )
+
+ AddMenu( "StoreMenu", $"resource/ui/menus/store.menu", InitStoreMenu, "#STORE_MENU" )
+ AddMenu( "StoreMenu_NewReleases", $"resource/ui/menus/store_new_releases.menu", InitStoreMenuNewReleases, "#STORE_NEW_RELEASES" )
+ AddMenu( "StoreMenu_Limited", $"resource/ui/menus/store_limited.menu", InitStoreMenuLimited, "#STORE_LIMITED" )
+ AddMenu( "StoreMenu_Sales", $"resource/ui/menus/store_bundles.menu", InitStoreMenuSales, "#STORE_BUNDLES" )
+ AddMenu( "StoreMenu_Titans", $"resource/ui/menus/store_prime_titans.menu", InitStoreMenuTitans, "#STORE_TITANS" ) // reusing store_prime_titans.menu
+ AddMenu( "StoreMenu_PrimeTitans", $"resource/ui/menus/store_prime_titans.menu", InitStoreMenuPrimeTitans, "#STORE_PRIME_TITANS" )
+ //AddMenu( "StoreMenu_WeaponSelect", $"resource/ui/menus/store_weapon_select.menu", InitStoreMenuWeaponSelect )
+ //AddMenu( "StoreMenu_WeaponSkinPreview", $"resource/ui/menus/store_weapon_skin_preview.menu", InitStoreMenuWeaponSkinPreview )
+ AddMenu( "StoreMenu_WeaponSkinBundles", $"resource/ui/menus/store_weapon_skin_bundles.menu", InitStoreMenuWeaponSkinBundles )
+ AddMenu( "StoreMenu_WeaponSkins", $"resource/ui/menus/store_weapons.menu", InitStoreMenuWeaponSkins )
+ AddMenu( "StoreMenu_Customization", $"resource/ui/menus/store_customization.menu", InitStoreMenuCustomization, "#STORE_CUSTOMIZATION_PACKS" )
+ AddMenu( "StoreMenu_CustomizationPreview", $"resource/ui/menus/store_customization_preview.menu", InitStoreMenuCustomizationPreview, "#STORE_CUSTOMIZATION_PACKS" )
+ AddMenu( "StoreMenu_Camo", $"resource/ui/menus/store_camo.menu", InitStoreMenuCamo, "#STORE_CAMO_PACKS" )
+ AddMenu( "StoreMenu_CamoPreview", $"resource/ui/menus/store_camo_preview.menu", InitStoreMenuCamoPreview, "#STORE_CAMO_PACKS" )
+ AddMenu( "StoreMenu_Callsign", $"resource/ui/menus/store_callsign.menu", InitStoreMenuCallsign, "#STORE_CALLSIGN_PACKS" )
+ AddMenu( "StoreMenu_CallsignPreview", $"resource/ui/menus/store_callsign_preview.menu", InitStoreMenuCallsignPreview, "#STORE_CALLSIGN_PACKS" )
+
+ AddMenu( "KnowledgeBaseMenu", $"resource/ui/menus/knowledgebase.menu", InitKnowledgeBaseMenu )
+ AddMenu( "KnowledgeBaseMenuSubMenu", $"resource/ui/menus/knowledgebase_submenu.menu", InitKnowledgeBaseMenuSubMenu )
+
+ AddMenu( "DevMenu", $"resource/ui/menus/dev.menu", InitDevMenu, "Dev" )
+ InitSharedStartPoints()
+
+ foreach ( menu in uiGlobal.allMenus )
+ {
+ if ( uiGlobal.menuData[ menu ].initFunc != null )
+ uiGlobal.menuData[ menu ].initFunc()
+
+ array<var> elems = GetElementsByClassname( menu, "TabsCommonClass" )
+ if ( elems.len() )
+ uiGlobal.menuData[ menu ].hasTabs = true
+
+ elems = GetElementsByClassname( menu, "EnableKeyBindingIcons" )
+ foreach ( elem in elems )
+ Hud_EnableKeyBindingIcons( elem )
+ }
+
+ InitTabs()
+
+ var tabbedMenu = GetMenu( "PostGameMenu" )
+ AddPanel( tabbedMenu, "PVEPanel", InitPVEPanel )
+ AddPanel( tabbedMenu, "SummaryPanel", InitSummaryPanel )
+ AddPanel( tabbedMenu, "FDAwardsPanel", InitFDAwardsPanel )
+
+ AddPanel( tabbedMenu, "ScoreboardPanel", InitScoreboardPanel )
+
+ foreach ( panel in uiGlobal.allPanels )
+ {
+ if ( uiGlobal.panelData[ panel ].initFunc != null )
+ uiGlobal.panelData[ panel ].initFunc()
+ }
+
+ // A little weird, but GetElementsByClassname() uses menu scope rather than parent scope.
+ foreach ( menu in uiGlobal.allMenus )
+ {
+ array<var> buttons = GetElementsByClassname( menu, "DefaultFocus" )
+ foreach ( button in buttons )
+ {
+ var panel = Hud_GetParent( button )
+
+ //Assert( elems.len() == 1, "More than 1 panel element set as DefaultFocus!" )
+ Assert( panel != null, "no parent panel found for button " + Hud_GetHudName( button ) )
+ Assert( panel in uiGlobal.panelData, "panel " + Hud_GetHudName( panel ) + " isn't in uiGlobal.panelData, but button " + Hud_GetHudName( button ) + " has defaultFocus set!" )
+ uiGlobal.panelData[ panel ].defaultFocus = button
+ //printt( "Found DefaultFocus, button was:", Hud_GetHudName( button ), "panel was:", Hud_GetHudName( panel ) )
+ }
+ }
+
+ InitFooterOptions()
+
+ #if DEV
+ if ( Dev_CommandLineHasParm( "-autoprecache_all" ) )
+ {
+ // repreache all levels
+ ExecuteLoadingClientCommands_SetStartPoint( "sp_training" )
+ ClientCommand( "map sp_training" )
+ CloseAllMenus()
+ }
+ #endif
+}
+
+void functionref( var ) function AdvanceMenuEventHandler( var menu )
+{
+ return void function( var item ) : ( menu )
+ {
+ if ( Hud_IsLocked( item ) )
+ return
+
+ AdvanceMenu( menu )
+ }
+}
+
+void function PCBackButton_Activate( var button )
+{
+ UICodeCallback_NavigateBack()
+}
+
+void function PCSwitchTeamsButton_Activate( var button )
+{
+ ClientCommand( "PrivateMatchSwitchTeams" )
+}
+
+void function PCToggleSpectateButton_Activate( var button )
+{
+ ClientCommand( "PrivateMatchToggleSpectate" )
+}
+
+void function ToggleButtonStates( var button )
+{
+ for ( ;; )
+ {
+ Hud_SetEnabled( button, true )
+ wait 1
+ Hud_SetSelected( button, true )
+ wait 1
+ Hud_SetLocked( button, true )
+ wait 1
+ Hud_SetNew( button, true )
+ wait 1
+ Hud_SetNew( button, false )
+ wait 1
+ Hud_SetLocked( button, false )
+ wait 1
+ Hud_SetSelected( button, false )
+ wait 1
+ Hud_SetEnabled( button, false )
+ wait 1
+ }
+}
+
+void function AddMenuElementsByClassname( var menu, string classname )
+{
+ array<var> elements = GetElementsByClassname( menu, classname )
+
+ if ( !(classname in menu.classElements) )
+ menu.classElements[classname] <- []
+
+ menu.classElements[classname].extend( elements )
+}
+
+void function FocusDefault( var menu )
+{
+ if (
+ menu == GetMenu( "MainMenu" ) ||
+ menu == GetMenu( "CategorySelectMenu" ) ||
+ menu == GetMenu( "AbilitySelectMenu" ) ||
+ menu == GetMenu( "PassiveSelectMenu" ) ||
+ menu == GetMenu( "WeaponSelectMenu" ) ||
+ menu == GetMenu( "SuitSelectMenu" ) ||
+ menu == GetMenu( "CamoSelectMenu" ) ||
+ menu == GetMenu( "NoseArtSelectMenu" ) ||
+ menu == GetMenu( "FactionChoiceMenu" ) ||
+ menu == GetMenu( "BurnCardMenu" ) ||
+ menu == GetMenu( "CallsignCardSelectMenu" ) ||
+ menu == GetMenu( "CallsignIconSelectMenu" ) )
+ {
+ }
+ else
+ {
+ //printt( "FocusDefaultMenuItem() called" )
+ FocusDefaultMenuItem( menu )
+ }
+}
+
+void function SetPanelDefaultFocus( var panel, var button )
+{
+ uiGlobal.panelData[ panel ].defaultFocus = button
+}
+
+void function PanelFocusDefault( var panel )
+{
+ //printt( "PanelFocusDefault called" )
+ if ( uiGlobal.panelData[ panel ].defaultFocus )
+ {
+ Hud_SetFocused( uiGlobal.panelData[ panel ].defaultFocus )
+ //printt( "PanelFocusDefault if passed,", Hud_GetHudName( uiGlobal.panelData[ panel ].defaultFocus ), "focused" )
+ }
+}
+
+void function SetMenuThinkFunc( var menu, void functionref() func )
+{
+ Assert( uiGlobal.menuData[ menu ].thinkFunc == null )
+ uiGlobal.menuData[ menu ].thinkFunc = func
+}
+
+void function AddMenuEventHandler( var menu, int event, void functionref() func )
+{
+ if ( event == eUIEvent.MENU_OPEN )
+ {
+ Assert( uiGlobal.menuData[ menu ].openFunc == null )
+ uiGlobal.menuData[ menu ].openFunc = func
+ }
+ else if ( event == eUIEvent.MENU_CLOSE )
+ {
+ Assert( uiGlobal.menuData[ menu ].closeFunc == null )
+ uiGlobal.menuData[ menu ].closeFunc = func
+ }
+ else if ( event == eUIEvent.MENU_SHOW )
+ {
+ Assert( uiGlobal.menuData[ menu ].showFunc == null )
+ uiGlobal.menuData[ menu ].showFunc = func
+ }
+ else if ( event == eUIEvent.MENU_HIDE )
+ {
+ Assert( uiGlobal.menuData[ menu ].hideFunc == null )
+ uiGlobal.menuData[ menu ].hideFunc = func
+ }
+ else if ( event == eUIEvent.MENU_NAVIGATE_BACK )
+ {
+ Assert( uiGlobal.menuData[ menu ].navBackFunc == null )
+ uiGlobal.menuData[ menu ].navBackFunc = func
+ }
+ else if ( event == eUIEvent.MENU_TAB_CHANGED )
+ {
+ Assert( uiGlobal.menuData[ menu ].tabChangedFunc == null )
+ uiGlobal.menuData[ menu ].tabChangedFunc = func
+ }
+ else if ( event == eUIEvent.MENU_ENTITLEMENTS_CHANGED )
+ {
+ Assert( uiGlobal.menuData[ menu ].entitlementsChangedFunc == null )
+ uiGlobal.menuData[ menu ].entitlementsChangedFunc = func
+ }
+ else if ( event == eUIEvent.MENU_INPUT_MODE_CHANGED )
+ {
+ Assert( uiGlobal.menuData[ menu ].inputModeChangedFunc == null )
+ uiGlobal.menuData[ menu ].inputModeChangedFunc = func
+ }
+}
+
+void function AddPanelEventHandler( var panel, int event, void functionref() func )
+{
+ if ( event == eUIEvent.PANEL_SHOW )
+ uiGlobal.panelData[ panel ].showFunc = func
+ else if ( event == eUIEvent.PANEL_HIDE )
+ uiGlobal.panelData[ panel ].hideFunc = func
+}
+
+// TODO: Get a real on open event from code?
+void function OpenMenuWrapper( var menu, bool focusDefault )
+{
+ OpenMenu( menu )
+ printt( Hud_GetHudName( menu ), "menu opened" )
+
+ Assert( menu in uiGlobal.menuData )
+ if ( uiGlobal.menuData[ menu ].openFunc != null )
+ {
+ thread uiGlobal.menuData[ menu ].openFunc()
+ //printt( "Called openFunc for:", menu.GetHudName() )
+ }
+
+ if ( focusDefault )
+ FocusDefault( menu )
+
+ //UpdateMenuTabs()
+ UpdateFooterOptions()
+}
+
+void function CloseMenuWrapper( var menu )
+{
+ CloseMenu( menu )
+ printt( Hud_GetHudName( menu ), "menu closed" )
+
+ Assert( menu in uiGlobal.menuData )
+ if ( uiGlobal.menuData[ menu ].closeFunc != null )
+ {
+ thread uiGlobal.menuData[ menu ].closeFunc()
+ //printt( "Called closeFunc for:", Hud_GetHudName( menu ) )
+ }
+}
+
+bool function IsLevelMultiplayer( string levelname )
+{
+ return levelname.find( "mp_" ) == 0
+}
+
+void function AddButtonEventHandler( var button, int event, void functionref( var ) func )
+{
+ Hud_AddEventHandler( button, event, func )
+}
+
+void function AddEventHandlerToButton( var menu, string buttonName, int event, void functionref( var ) func )
+{
+ var button = Hud_GetChild( menu, buttonName )
+ Hud_AddEventHandler( button, event, func )
+}
+
+void function AddEventHandlerToButtonClass( var menu, string classname, int event, void functionref( var ) func )
+{
+ array<var> buttons = GetElementsByClassname( menu, classname )
+
+ foreach ( button in buttons )
+ {
+ //printt( "button name:", Hud_GetHudName( button ) )
+ Hud_AddEventHandler( button, event, func )
+ }
+}
+
+// Added slight delay to main menu music to work around a hitch caused when the game first starts up
+void function PlayMusicAfterDelay()
+{
+ wait MAINMENU_MUSIC_DELAY
+ if ( uiGlobal.playingMusic )
+ EmitUISound( "MainMenu_Music" )
+}
+
+void function DisableMusic()
+{
+ EmitUISound( "Movie_MuteAllGameSound" )
+}
+
+void function EnableMusic()
+{
+ StopUISoundByName( "Movie_MuteAllGameSound" )
+}
+
+void function PlayMusic()
+{
+ if ( !uiGlobal.playingMusic && !uiGlobal.playingVideo && !uiGlobal.playingCredits )
+ {
+ //printt( "PlayMusic() called. Playing: MainMenu_Music. uiGlobal.playingMusic:", uiGlobal.playingMusic, "uiGlobal.playingVideo:", uiGlobal.playingVideo, "uiGlobal.playingCredits:", uiGlobal.playingCredits )
+ uiGlobal.playingMusic = true
+ thread PlayMusicAfterDelay()
+ }
+ else
+ {
+ //printt( "PlayMusic() called, but doing nothing. uiGlobal.playingMusic:", uiGlobal.playingMusic, "uiGlobal.playingVideo:", uiGlobal.playingVideo, "uiGlobal.playingCredits:", uiGlobal.playingCredits )
+ }
+}
+
+void function StopMusic()
+{
+ //printt( "StopMusic() called. Stopping: MainMenu_Music" )
+ StopUISound( "MainMenu_Music" )
+ uiGlobal.playingMusic = false
+}
+
+void function RegisterMenuVarInt( string varName, int value )
+{
+ table<string, int> intVars = uiGlobal.intVars
+
+ Assert( !( varName in intVars ) )
+
+ intVars[varName] <- value
+}
+
+void function RegisterMenuVarBool( string varName, bool value )
+{
+ table<string, bool> boolVars = uiGlobal.boolVars
+
+ Assert( !( varName in boolVars ) )
+
+ boolVars[varName] <- value
+}
+
+void function RegisterMenuVarVar( string varName, var value )
+{
+ table<string, var> varVars = uiGlobal.varVars
+
+ Assert( !( varName in varVars ) )
+
+ varVars[varName] <- value
+}
+
+int function GetMenuVarInt( string varName )
+{
+ table<string, int> intVars = uiGlobal.intVars
+
+ Assert( varName in intVars )
+
+ return intVars[varName]
+}
+
+bool function GetMenuVarBool( string varName )
+{
+ table<string, bool> boolVars = uiGlobal.boolVars
+
+ Assert( varName in boolVars )
+
+ return boolVars[varName]
+}
+
+var function GetMenuVarVar( string varName )
+{
+ table<string, var> varVars = uiGlobal.varVars
+
+ Assert( varName in varVars )
+
+ return varVars[varName]
+}
+
+void function SetMenuVarInt( string varName, int value )
+{
+ table<string, int> intVars = uiGlobal.intVars
+
+ Assert( varName in intVars )
+
+ if ( intVars[varName] == value )
+ return
+
+ intVars[varName] = value
+
+ table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs
+
+ if ( varName in varChangeFuncs )
+ {
+ foreach ( func in varChangeFuncs[varName] )
+ {
+ //printt( varName, "changed, calling changeFunc:", string( func ) )
+ func()
+ }
+ }
+}
+
+void function SetMenuVarBool( string varName, bool value )
+{
+ table<string, bool> boolVars = uiGlobal.boolVars
+
+ Assert( varName in boolVars )
+
+ if ( boolVars[varName] == value )
+ return
+
+ boolVars[varName] = value
+
+ table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs
+
+ if ( varName in varChangeFuncs )
+ {
+ foreach ( func in varChangeFuncs[varName] )
+ {
+ //printt( varName, "changed, calling changeFunc:", string( func ) )
+ func()
+ }
+ }
+}
+
+void function SetMenuVarVar( string varName, var value )
+{
+ table<string, var> varVars = uiGlobal.varVars
+
+ Assert( varName in varVars )
+
+ if ( varVars[varName] == value )
+ return
+
+ varVars[varName] = value
+
+ table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs
+
+ if ( varName in varChangeFuncs )
+ {
+ foreach ( func in varChangeFuncs[varName] )
+ {
+ //printt( varName, "changed, calling changeFunc:", string( func ) )
+ func()
+ }
+ }
+}
+
+void function AddMenuVarChangeHandler( string varName, void functionref() func )
+{
+ table<string, array<void functionref()> > varChangeFuncs = uiGlobal.varChangeFuncs
+
+ if ( !( varName in varChangeFuncs ) )
+ varChangeFuncs[varName] <- []
+
+ // TODO: Verify we're not duplicating an existing func
+ varChangeFuncs[varName].append( func )
+}
+
+// These are common menu statuses that trigger menu logic any time they change
+// They should become code callbacks, so script doesn't poll
+void function InitGlobalMenuVars()
+{
+ RegisterMenuVarVar( "focus", null )
+ RegisterMenuVarBool( "isConnected", false )
+ RegisterMenuVarBool( "isFullyConnected", false )
+ RegisterMenuVarBool( "isPartyLeader", false )
+ RegisterMenuVarBool( "isPrivateMatch", false )
+ RegisterMenuVarBool( "isGamepadActive", IsControllerModeActive() )
+
+ #if CONSOLE_PROG
+ RegisterMenuVarBool( "CONSOLE_isOnline", false )
+ RegisterMenuVarBool( "CONSOLE_isSignedIn", false )
+ #endif // CONSOLE_PROG
+
+ #if DURANGO_PROG
+ RegisterMenuVarBool( "DURANGO_isGameFullyInstalled", false )
+ RegisterMenuVarBool( "DURANGO_canInviteFriends", false )
+ RegisterMenuVarBool( "DURANGO_isJoinable", false )
+ #elseif PS4_PROG
+ RegisterMenuVarBool( "PS4_canInviteFriends", false)
+ #elseif PC_PROG
+ RegisterMenuVarBool( "ORIGIN_isEnabled", false )
+ RegisterMenuVarBool( "ORIGIN_isJoinable", false )
+ #endif
+
+ thread UpdateFocus()
+ thread UpdateIsConnected()
+ thread UpdateIsFullyConnected()
+ thread UpdateAmIPartyLeader()
+ thread UpdateIsPrivateMatch()
+ thread UpdateActiveMenuThink()
+
+ #if CONSOLE_PROG
+ thread UpdateConsole_IsOnline()
+ thread UpdateConsole_IsSignedIn()
+ #endif // CONSOLE_PROG
+
+ #if DURANGO_PROG
+ thread UpdateDurango_IsGameFullyInstalled()
+ thread UpdateDurango_CanInviteFriends()
+ thread UpdateDurango_IsJoinable()
+ #elseif PS4_PROG
+ thread UpdatePS4_CanInviteFriends()
+ #elseif PC_PROG
+ thread UpdateOrigin_IsEnabled()
+ thread UpdateOrigin_IsJoinable()
+ thread UpdateIsGamepadActive()
+ #endif
+}
+
+void function UpdateFocus()
+{
+ while ( true )
+ {
+ SetMenuVarVar( "focus", GetFocus() )
+ WaitFrame()
+ }
+}
+
+void function UpdateActiveMenuThink()
+{
+ while ( true )
+ {
+ var menu = GetActiveMenu()
+ if ( menu )
+ {
+ Assert( menu in uiGlobal.menuData )
+ if ( uiGlobal.menuData[ menu ].thinkFunc != null )
+ uiGlobal.menuData[ menu ].thinkFunc()
+ }
+
+ WaitFrame()
+ }
+}
+
+void function UpdateIsConnected()
+{
+ while ( true )
+ {
+ SetMenuVarBool( "isConnected", IsConnected() )
+ WaitFrame()
+ }
+}
+
+void function UpdateIsFullyConnected()
+{
+ while ( true )
+ {
+ SetMenuVarBool( "isFullyConnected", IsFullyConnected() )
+ WaitFrame()
+ }
+}
+
+void function UpdateAmIPartyLeader()
+{
+ while ( true )
+ {
+ SetMenuVarBool( "isPartyLeader", AmIPartyLeader() )
+ WaitFrame()
+ }
+}
+
+void function UpdateIsPrivateMatch()
+{
+ while ( true )
+ {
+ SetMenuVarBool( "isPrivateMatch", IsPrivateMatch() )
+ WaitFrame()
+ }
+}
+
+#if CONSOLE_PROG
+ void function UpdateConsole_IsOnline()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "CONSOLE_isOnline", Console_IsOnline() )
+ WaitFrame()
+ }
+ }
+
+ void function UpdateConsole_IsSignedIn()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "CONSOLE_isSignedIn", Console_IsSignedIn() )
+ WaitFrame()
+ }
+ }
+#endif // CONSOLE_PROG
+
+
+#if PS4_PROG
+ void function UpdatePS4_CanInviteFriends()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "PS4_canInviteFriends", PS4_canInviteFriends() )
+ WaitFrame()
+ }
+ }
+#endif // PS4_PROG
+
+
+
+#if DURANGO_PROG
+ void function UpdateDurango_IsGameFullyInstalled()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "DURANGO_isGameFullyInstalled", IsGameFullyInstalled() )
+ wait 1 // Poll less frequent
+ }
+ }
+
+ void function UpdateDurango_CanInviteFriends()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "DURANGO_canInviteFriends", Durango_CanInviteFriends() )
+ WaitFrame()
+ }
+ }
+
+ void function UpdateDurango_IsJoinable()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "DURANGO_isJoinable", Durango_IsJoinable() )
+ WaitFrame()
+ }
+ }
+#endif // DURANGO_PROG
+
+#if PC_PROG
+ void function UpdateOrigin_IsEnabled()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "ORIGIN_isEnabled", Origin_IsEnabled() )
+ WaitFrame()
+ }
+ }
+
+ void function UpdateOrigin_IsJoinable()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "ORIGIN_isJoinable", Origin_IsJoinable() )
+ WaitFrame()
+ }
+ }
+
+ void function UpdateIsGamepadActive()
+ {
+ while ( true )
+ {
+ SetMenuVarBool( "isGamepadActive", IsControllerModeActive() )
+ WaitFrame()
+ }
+ }
+#endif // PC_PROG
+
+void function InviteFriends( var button )
+{
+ //AdvanceMenu( GetMenu( "InviteFriendsToPartyMenu" ) )
+
+ #if DURANGO_PROG
+ Durango_InviteFriends()
+ #elseif PS4_PROG
+ ClientCommand("session_debug_invite");
+ #elseif PC_PROG
+ Assert( Origin_IsEnabled() )
+ Assert( Origin_IsJoinable() )
+
+ Origin_ShowInviteFriendsDialog()
+ #endif
+}
+
+#if DURANGO_PROG
+void function OpenXboxPartyApp( var button )
+{
+ Durango_OpenPartyApp()
+}
+
+void function OpenXboxHelp( var button )
+{
+ Durango_ShowHelpWindow()
+}
+#endif // DURANGO_PROG
+
+void function OpenReviewTermsDialog( var button )
+{
+ AdvanceMenu( GetMenu( "ReviewTermsDialog" ) )
+}
+
+void function OpenErrorDialog( string errorDetails )
+{
+ DialogData dialogData
+ dialogData.header = "#ERROR"
+ dialogData.message = errorDetails
+ dialogData.image = $"ui/menu/common/dialog_error"
+
+#if PC_PROG
+ AddDialogButton( dialogData, "#DISMISS" )
+
+ AddDialogFooter( dialogData, "#A_BUTTON_SELECT" )
+#endif // PC_PROG
+ AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" )
+
+ while ( uiGlobal.activeMenu != GetMenu( "MainMenu" ) )
+ {
+ WaitSignal( uiGlobal.signalDummy, "OpenErrorDialog", "ActiveMenuChanged" )
+ }
+
+ OpenDialog( dialogData )
+}
+
+bool function IsDialog( var menu )
+{
+ if ( menu == null )
+ return false
+
+ return uiGlobal.menuData[ menu ].isDialog
+}
+
+bool function IsDialogActive( DialogData dialogData )
+{
+ if ( !IsDialog( uiGlobal.activeMenu ) )
+ return false
+
+ return uiGlobal.menuData[ uiGlobal.activeMenu ].dialogData == dialogData
+}
+
+bool function IsDialogOnlyActiveMenu()
+{
+ if ( !IsDialog( uiGlobal.activeMenu ) )
+ return false
+
+ int stackLen = uiGlobal.menuStack.len()
+ if ( stackLen < 1 )
+ return false
+
+ if ( uiGlobal.menuStack[stackLen - 1] != uiGlobal.activeMenu )
+ return false
+
+ if ( stackLen == 1 )
+ return true
+
+ if ( uiGlobal.menuStack[stackLen - 2] == null )
+ return true
+
+ return false
+}
+
+void function SetNavUpDown( array<var> buttons, var wrap = true )
+{
+ Assert( buttons.len() > 0 )
+
+ var first = buttons[0]
+ var last = buttons[buttons.len() - 1]
+ var prev
+ var next
+ var button
+
+ for ( int i = 0; i < buttons.len(); i++ )
+ {
+ button = buttons[i]
+
+ if ( button == first )
+ prev = last
+ else
+ prev = buttons[i - 1]
+
+ if ( button == last )
+ next = first
+ else
+ next = buttons[i + 1]
+
+ button.SetNavUp( prev )
+ button.SetNavDown( next )
+
+ //printt( "SetNavUP for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( prev ) )
+ //printt( "SetNavDown for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( next ) )
+ }
+}
+
+void function SetNavLeftRight( array<var> buttons, var wrap = true )
+{
+ Assert( buttons.len() > 0 )
+
+ var first = buttons[0]
+ var last = buttons[buttons.len() - 1]
+ var prev
+ var next
+ var button
+
+ for ( int i = 0; i < buttons.len(); i++ )
+ {
+ button = buttons[i]
+
+ if ( button == first )
+ prev = last
+ else
+ prev = buttons[i - 1]
+
+ if ( button == last )
+ next = first
+ else
+ next = buttons[i + 1]
+
+ button.SetNavLeft( prev )
+ button.SetNavRight( next )
+
+ //printt( "SetNavUP for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( prev ) )
+ //printt( "SetNavDown for:", Hud_GetHudName( button ), "to:", Hud_GetHudName( next ) )
+ }
+}
+
+void function UICodeCallback_EntitlementsChanged()
+{
+ if ( uiGlobal.activeMenu == null )
+ return
+
+ if ( uiGlobal.menuData[ uiGlobal.activeMenu ].entitlementsChangedFunc != null )
+ thread uiGlobal.menuData[ uiGlobal.activeMenu ].entitlementsChangedFunc()
+}
+
+#if PC_PROG
+void function QuitGame()
+{
+ ClientCommand( "quit" )
+}
+#endif
+
+void function UICodeCallback_StoreTransactionCompleted()
+{
+ // this callback is only supported and needed on PS4 currently
+#if PS4_PROG
+ if ( InStoreMenu() )
+ OnOpenDLCStore()
+#endif
+}
+
+void function UICodeCallback_GamePurchased()
+{
+ // this callback is only supported and needed on PC currently
+#if PC_PROG
+ DialogData dialogData
+ dialogData.header = "#PURCHASE_GAME_COMPLETE"
+ dialogData.message = "#PURCHASE_GAME_RESTART"
+ AddDialogButton( dialogData, "#QUIT", QuitGame )
+
+ OpenDialog( dialogData )
+#endif
+}
+
+bool function IsTrialPeriodActive()
+{
+ return GetConVarBool( "trialPeriodIsActive" )
+}
+
+void function LaunchGamePurchaseOrDLCStore( array<string> menuNames = [ "StoreMenu" ] )
+{
+ if ( Script_IsRunningTrialVersion() )
+ {
+ LaunchGamePurchase()
+ }
+ else
+ {
+ void functionref() preOpenFunc = null
+
+ foreach ( menuName in menuNames )
+ {
+ // Special case because this menu needs a few properties set before opening
+ if ( menuName == "StoreMenu_WeaponSkins" )
+ {
+ preOpenFunc = DefaultToDLC11WeaponWarpaintBundle
+ break
+ }
+ }
+
+ OpenStoreMenu( menuNames, preOpenFunc )
+ }
+}
+
+void function UICodeCallback_PartyUpdated()
+{
+ if ( AmIPartyLeader() )
+ {
+ string activeSearchingPlaylist = GetActiveSearchingPlaylist()
+ if ( activeSearchingPlaylist != "" && !CanPlaylistFitMyParty( activeSearchingPlaylist ) )
+ {
+ CancelMatchSearch()
+
+ DialogData dialogData
+ dialogData.header = "#MATCHMAKING_CANCELED"
+ dialogData.message = "#MATCHMAKING_CANCELED_REASON_PARTY_SIZE"
+ AddDialogButton( dialogData, "#OK" )
+
+ OpenDialog( dialogData )
+ }
+ }
+}
+
+
+void function HACK_DelayedSetFocus_BecauseWhy( var item )
+{
+ wait 0.1
+ if ( IsValid( item ) )
+ Hud_SetFocused( item )
+}
+
+void function ClassicMusic_OnChange( var button )
+{
+ bool isEnabled = GetConVarBool( "sound_classic_music" )
+
+ if ( IsFullyConnected() && IsMultiplayer() && GetUIPlayer() )
+ {
+ if ( IsItemLocked( GetUIPlayer(), "classic_music" ) )
+ SetConVarBool( "sound_classic_music", false )
+
+ if ( IsLobby() )
+ thread RunClientScript( "OnSoundClassicMusicChanged" )
+ }
+}
+
+bool function IsClassicMusicAvailable()
+{
+ bool classicMusicAvailable = false
+ if ( IsFullyConnected() && IsMultiplayer() && GetUIPlayer() )
+ classicMusicAvailable = !IsItemLocked( GetUIPlayer(), "classic_music" )
+
+ return classicMusicAvailable
+}
+
+void function UICodeCallback_KeyBindOverwritten( string key, string oldbinding, string newbinding )
+{
+ DialogData dialogData
+ dialogData.header = Localize( "#MENU_KEYBIND_WAS_BEING_USED", key )
+ dialogData.message = Localize( "#MENU_KEYBIND_WAS_BEING_USED_SUB", key, Localize( oldbinding ) )
+
+ AddDialogButton( dialogData, "#OK" )
+
+ OpenDialog( dialogData )
+}
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut
new file mode 100644
index 00000000..03bd8959
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ingame.nut
@@ -0,0 +1,693 @@
+//global function InitLobbyStartMenu
+global function InitInGameMPMenu
+global function InitInGameSPMenu
+global function ServerCallback_UI_ObjectiveUpdated
+global function ServerCallback_UI_UpdateMissionLog
+global function SP_ResetObjectiveStringIndex
+global function SCB_SetDoubleXPStatus
+
+global function SCB_SetCompleteMeritState
+global function SCB_SetEvacMeritState
+global function SCB_SetMeritCount
+global function SCB_SetScoreMeritState
+global function SCB_SetWinMeritState
+global function SCB_SetWeaponMeritCount
+global function SCB_SetTitanMeritCount
+
+const DATA_TABLE = $"datatable/sp_difficulty.rpak"
+
+struct
+{
+ var menuMP
+ var menuSP
+ var BtnTrackedChallengeBackground
+ var BtnTrackedChallengeTitle
+ array trackedChallengeButtons
+ var BtnLastCheckpoint
+ int objectiveStringIndex
+ bool SP_displayObjectiveOnClose
+ var settingsHeader
+ var faqButton
+ int titanHeaderIndex
+ var titanHeader
+ var titanSelectButton
+ var titanEditButton
+
+ ComboStruct &comboStruct
+
+ array<var> loadoutButtons
+ array<var> loadoutHeaders
+} file
+
+void function InitInGameMPMenu()
+{
+ var menu = GetMenu( "InGameMPMenu" )
+ file.menuMP = menu
+
+ SP_ResetObjectiveStringIndex()
+ file.SP_displayObjectiveOnClose = true
+
+ AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnInGameMPMenu_Open )
+ AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnInGameMPMenu_Close )
+
+ AddUICallback_OnLevelInit( OnInGameLevelInit )
+
+ ComboStruct comboStruct = ComboButtons_Create( menu )
+
+ int headerIndex = 0
+ int buttonIndex = 0
+ var pilotHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_PILOT" )
+ file.loadoutHeaders.append( pilotHeader )
+ var pilotSelectButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#SELECT" )
+ Hud_AddEventHandler( pilotSelectButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "PilotLoadoutsMenu" ) ) )
+ file.loadoutButtons.append( pilotSelectButton )
+ var pilotEditButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#EDIT" )
+ Hud_AddEventHandler( pilotEditButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditPilotLoadoutsMenu" ) ) )
+ file.loadoutButtons.append( pilotEditButton )
+
+ headerIndex++
+ buttonIndex = 0
+ var titanHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_TITAN" )
+ file.titanHeader = titanHeader
+ file.titanHeaderIndex = headerIndex
+ file.loadoutHeaders.append( titanHeader )
+ var titanSelectButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#SELECT" )
+ file.titanSelectButton = titanSelectButton
+ file.loadoutButtons.append( titanSelectButton )
+ Hud_AddEventHandler( titanSelectButton, UIE_CLICK, TitanSelectButtonHandler )
+ var titanEditButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#EDIT" )
+ Hud_AddEventHandler( titanEditButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditTitanLoadoutsMenu" ) ) )
+ file.titanEditButton = titanEditButton
+ file.loadoutButtons.append( titanEditButton )
+
+ headerIndex++
+ buttonIndex = 0
+ var gameHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_GAME" )
+ var leaveButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#LEAVE_MATCH" )
+ Hud_AddEventHandler( leaveButton, UIE_CLICK, OnLeaveButton_Activate )
+ #if DEV
+ var devButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "Dev" )
+ Hud_AddEventHandler( devButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "DevMenu" ) ) )
+ #endif
+
+ headerIndex++
+ buttonIndex = 0
+ var dummyHeader = AddComboButtonHeader( comboStruct, headerIndex, "" )
+ var dummyButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "" )
+ Hud_SetVisible( dummyHeader, false )
+ Hud_SetVisible( dummyButton, false )
+
+ headerIndex++
+ buttonIndex = 0
+ file.settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" )
+ var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CONTROLS" )
+ Hud_AddEventHandler( controlsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ControlsMenu" ) ) )
+ #if CONSOLE_PROG
+ var avButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO_VIDEO" )
+ Hud_AddEventHandler( avButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioVideoMenu" ) ) )
+ #elseif PC_PROG
+ var videoButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO" )
+ Hud_AddEventHandler( videoButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioMenu" ) ) )
+ var soundButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" )
+ Hud_AddEventHandler( soundButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) )
+ #endif
+
+ file.faqButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#KNB_MENU_HEADER" )
+ Hud_AddEventHandler( file.faqButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "KnowledgeBaseMenu" ) ) )
+
+ //var dataCenterButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#DATA_CENTER" )
+ //Hud_AddEventHandler( dataCenterButton, UIE_CLICK, OpenDataCenterDialog )
+
+ ComboButtons_Finalize( comboStruct )
+
+ file.comboStruct = comboStruct
+
+ AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
+ AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_CLOSE", "#CLOSE" )
+}
+
+void function OnInGameMPMenu_Open()
+{
+ Lobby_SetFDMode( GetCurrentPlaylistVarInt( "ingame_menu_fd_mode", 0 ) == 1 )
+ UI_SetPresentationType( ePresentationType.DEFAULT )
+
+ bool faqIsNew = !GetConVarBool( "menu_faq_viewed" ) || HaveNewPatchNotes() || HaveNewCommunityNotes()
+ RuiSetBool( Hud_GetRui( file.settingsHeader ), "isNew", faqIsNew )
+ ComboButton_SetNew( file.faqButton, faqIsNew )
+
+ UpdateLoadoutButtons()
+ RefreshCreditsAvailable()
+ thread UpdateCachedNewItems()
+}
+
+void function OnInGameMPMenu_Close()
+{
+ UI_SetPresentationType( ePresentationType.INACTIVE )
+
+ if ( IsConnected() && !IsLobby() && IsLevelMultiplayer( GetActiveLevel() ) )
+ {
+ //printt( "OnInGameMPMenu_Close() uiGlobal.updatePilotSpawnLoadout is:", uiGlobal.updatePilotSpawnLoadout )
+ //printt( "OnInGameMPMenu_Close() uiGlobal.updateTitanSpawnLoadout is:", uiGlobal.updateTitanSpawnLoadout )
+
+ string updatePilotSpawnLoadout = uiGlobal.updatePilotSpawnLoadout ? "1" : "0"
+ string updateTitanSpawnLoadout = uiGlobal.updateTitanSpawnLoadout ? "1" : "0"
+
+ ClientCommand( "InGameMPMenuClosed " + updatePilotSpawnLoadout + " " + updateTitanSpawnLoadout )
+
+ uiGlobal.updatePilotSpawnLoadout = false
+ uiGlobal.updateTitanSpawnLoadout = false
+
+ RunClientScript( "RefreshIntroLoadoutDisplay", GetLocalClientPlayer(), uiGlobal.pilotSpawnLoadoutIndex, uiGlobal.titanSpawnLoadoutIndex )
+ }
+}
+
+void function UpdateLoadoutButtons()
+{
+ bool loadoutSelectionEnabled = (GetCurrentPlaylistVarInt( "loadout_selection_enabled", 1 ) == 1)
+
+ SetTitanSelectButtonVisibleState( true )
+
+ foreach ( button in file.loadoutButtons )
+ {
+ Hud_SetEnabled( button, loadoutSelectionEnabled )
+ }
+
+ foreach ( header in file.loadoutHeaders )
+ {
+ if ( loadoutSelectionEnabled )
+ Hud_Show( header )
+ else
+ Hud_Hide( header )
+ }
+
+ entity player = GetUIPlayer()
+
+ if ( GetAvailableTitanRefs( player ).len() > 1 )
+ {
+ SetComboButtonHeaderTitle( file.menuMP, file.titanHeaderIndex, "#MENU_HEADER_TITAN" )
+ ComboButton_SetText( file.titanSelectButton, "#SELECT" )
+ Hud_Show( file.titanEditButton )
+ }
+ else if ( GetAvailableTitanRefs( player ).len() == 1 )
+ {
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.titanSpawnLoadoutIndex )
+
+ SetComboButtonHeaderTitle( file.menuMP, file.titanHeaderIndex, GetTitanLoadoutName( loadout ) )
+ ComboButton_SetText( file.titanSelectButton, "#EDIT" )
+
+ Hud_Hide( file.titanEditButton )
+ ComboButtons_ResetColumnFocus( file.comboStruct )
+ }
+ else
+ {
+ SetTitanSelectButtonVisibleState( true )
+ }
+}
+
+//////////
+
+//////////
+
+void function InitInGameSPMenu()
+{
+ var menu = GetMenu( "InGameSPMenu" )
+ file.menuSP = menu
+
+ AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenInGameSPMenu )
+ AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnCloseInGameSPMenu )
+
+ ComboStruct comboStruct = ComboButtons_Create( menu )
+
+ int headerIndex = 0
+ int buttonIndex = 0
+
+ // MISSION Menu
+ var missionHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_MISSION" )
+ var resumeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#RESUME_GAME_SHORT" )
+ Hud_AddEventHandler( resumeButton, UIE_CLICK, OnResumeGame_Activate )
+ var lastCheckpointButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#LAST_CHECKPOINT" )
+ Hud_AddEventHandler( lastCheckpointButton, UIE_CLICK, OnReloadCheckpoint_Activate )
+ file.BtnLastCheckpoint = lastCheckpointButton
+ var restartButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#RESTART_LEVEL_SHORT" )
+ Hud_AddEventHandler( restartButton, UIE_CLICK, OnRestartLevel_Activate )
+
+ // GAME Menu
+ // headerIndex++
+ // buttonIndex = 0
+ // var gameHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_GAME" )
+ // var difficultyButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CHANGE_DIFFICULTY" )
+ // Hud_AddEventHandler( difficultyButton, UIE_CLICK, OnChangeDifficulty_Activate )
+ // var leaveButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#QUIT" )
+ // Hud_AddEventHandler( leaveButton, UIE_CLICK, OnLeaveButton_Activate )
+
+ // SETTINGS Menu
+ headerIndex++
+ buttonIndex = 0
+ var settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" )
+ var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CONTROLS" )
+ Hud_AddEventHandler( controlsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ControlsMenu" ) ) )
+ #if CONSOLE_PROG
+ var avButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO_VIDEO" )
+ Hud_AddEventHandler( avButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioVideoMenu" ) ) )
+ #elseif PC_PROG
+ var audioButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO" )
+ Hud_AddEventHandler( audioButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "AudioMenu" ) ) )
+ var videoButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#VIDEO" )
+ Hud_AddEventHandler( videoButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "VideoMenu" ) ) )
+ #endif
+
+ array<var> orderedButtons
+
+ var changeDifficultyBtn = Hud_GetChild( menu, "BtnChangeDifficulty" )
+
+ AddButtonEventHandler( changeDifficultyBtn, UIE_CLICK, OnChangeDifficulty_Activate )
+ Hud_Show( changeDifficultyBtn )
+ orderedButtons.append( changeDifficultyBtn )
+
+ var quitBtn = Hud_GetChild( menu, "BtnQuit" )
+ SetButtonRuiText( quitBtn, "#QUIT" )
+ AddButtonEventHandler( quitBtn, UIE_CLICK, OnLeaveButton_Activate )
+ Hud_Show( quitBtn )
+ orderedButtons.append( quitBtn )
+
+ // DEV button
+ var devButton = Hud_GetChild( menu, "BtnDev" )
+ #if DEV
+ SetButtonRuiText( devButton, "--- Dev" )
+ AddButtonEventHandler( devButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "DevMenu" ) ) )
+ Hud_Show( devButton )
+ orderedButtons.append( devButton )
+ comboStruct.navUpButton = devButton
+ #else
+ Hud_Hide( devButton )
+ comboStruct.navUpButton = quitBtn
+ #endif // DEV
+
+ SetNavUpDown( orderedButtons )
+ comboStruct.navDownButton = changeDifficultyBtn
+
+ ComboButtons_Finalize( comboStruct )
+
+ AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
+ AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_CLOSE", "#CLOSE" )
+}
+
+
+void function OnOpenInGameSPMenu()
+{
+ var collectiblesFoundDesc = Hud_GetChild( file.menuSP, "CollectiblesFoundDesc" )
+ var missionLogDesc = Hud_GetChild( file.menuSP, "MissionLogDesc" )
+ var changeDifficultyBtn = Hud_GetChild( file.menuSP, "BtnChangeDifficulty" )
+
+ Hud_SetEnabled( file.BtnLastCheckpoint, HasValidSaveGame() )
+
+ int currentDifficulty = GetConVarInt( "sp_difficulty" )
+ string newDifficultyString
+
+ switch ( currentDifficulty )
+ {
+ case 0:
+ newDifficultyString = "#CHANGE_DIFFICULTY_EASY"
+ break
+
+ case 1:
+ newDifficultyString = "#CHANGE_DIFFICULTY_REGULAR"
+ break
+
+ case 2:
+ newDifficultyString = "#CHANGE_DIFFICULTY_HARD"
+ break
+
+ case 3:
+ newDifficultyString = "#CHANGE_DIFFICULTY_MASTER"
+ break
+
+ default:
+ Assert( 0, "Unknown difficulty " + currentDifficulty )
+ break
+ }
+ SetButtonRuiText( changeDifficultyBtn, newDifficultyString )
+
+ string activeLevelName = GetActiveLevel()
+ if ( activeLevelName != "" )
+ {
+ var dataTable = GetDataTable( $"datatable/sp_levels_data.rpak" )
+
+ // Make sure this level actually has data to display.
+ bool levelHasData = false
+ int numRows = GetDatatableRowCount( dataTable )
+ for ( int i = 0; i < numRows; i++ )
+ {
+ string levelName = GetDataTableString( dataTable, i, GetDataTableColumnByName( dataTable, "level" ) )
+ if ( activeLevelName == levelName )
+ {
+ levelHasData = true
+ break
+ }
+ }
+
+ if ( levelHasData )
+ {
+ // Mission Log
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "level" ), activeLevelName )
+ string missionLog = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "missionLog" ) )
+
+ if ( uiGlobal.sp_showAlternateMissionLog )
+ {
+ string alternateMissionLog = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "alternateMissionLog" ) )
+ missionLog = alternateMissionLog
+ }
+
+ Hud_SetText( missionLogDesc, missionLog )
+
+ // Collectibles
+ int foundLions = GetCollectiblesFoundForLevel( activeLevelName )
+ int maxLions = GetMaxLionsInLevel( activeLevelName )
+ Hud_SetText( collectiblesFoundDesc, "#MENU_SP_COLLECTIBLE_DESC", foundLions, maxLions )
+ }
+ else
+ {
+ Hud_SetText( missionLogDesc, "#MENU_SP_OBJECTIVES_NO_ENTRY" )
+ Hud_SetText( collectiblesFoundDesc, "#MENU_SP_COLLECTIBLE_DESC", 0, 0 )
+ }
+
+ // Make sure trial mode doesn't reveal any spoilers!
+ if ( Script_IsRunningTrialVersion() )
+ Hud_SetText( missionLogDesc, "#MENU_SP_OBJECTIVES_NO_ENTRY" )
+ }
+
+ SPMenu_UpdateReloadCheckpointButton()
+}
+
+
+void function OnCloseInGameSPMenu()
+{
+ if ( file.SP_displayObjectiveOnClose )
+ ClientCommand( "ShowObjective closedSPMenu" )
+}
+
+void function SPMenu_UpdateReloadCheckpointButton()
+{
+ if ( level.ui.playerRunningGauntlet )
+ ComboButton_SetText( file.BtnLastCheckpoint, "#GAUNTLET_RESTART" )
+ else
+ ComboButton_SetText( file.BtnLastCheckpoint, "#LAST_CHECKPOINT" )
+}
+
+void function MobilityDifficultyButton_Activate( var button )
+{
+ OpenMobilityDifficultyMenu()
+}
+
+void function OnLeaveButton_Activate( var button )
+{
+ file.SP_displayObjectiveOnClose = false
+ LeaveDialog()
+}
+
+void function OnRestartLevel_Activate( var button )
+{
+ ShowAreYouSureDialog( "#MENU_RESTART_MISSION_CONFIRM", RestartMission, "#WARNING_LOSE_PROGRESS" )
+}
+
+void function OnChangeDifficulty_Activate( var button )
+{
+ SPDifficultyButton_Click( button )
+}
+
+void function OnResumeGame_Activate( var button )
+{
+ CloseActiveMenu()
+}
+
+void function OnReloadCheckpoint_Activate( var button )
+{
+ if ( level.ui.playerRunningGauntlet )
+ {
+ CloseActiveMenu()
+ ClientCommand( "Gauntlet_PlayerRestartedFromMenu" )
+ }
+ else
+ {
+ ShowAreYouSureDialog( "#MENU_RESTART_CHECKPOINT_CONFIRM", ReloadLastCheckpoint, "#EMPTY_STRING" )
+ }
+}
+
+void function ShowAreYouSureDialog( string header, void functionref() func, string details )
+{
+ DialogData dialogData
+ dialogData.header = header
+ dialogData.message = details
+
+ AddDialogButton( dialogData, "#NO" )
+ AddDialogButton( dialogData, "#YES", func )
+
+ AddDialogFooter( dialogData, "#A_BUTTON_SELECT" )
+ AddDialogFooter( dialogData, "#B_BUTTON_BACK" )
+
+ OpenDialog( dialogData )
+}
+
+void function RestartMission()
+{
+ file.SP_displayObjectiveOnClose = false
+ ClientCommand( "RestartMission" )
+}
+
+void function ReloadLastCheckpoint()
+{
+ file.SP_displayObjectiveOnClose = false
+
+ printt( "SAVEGAME: Trying to load saveName" )
+ if ( HasValidSaveGame() )
+ {
+ printt( "SAVEGAME: Trying to load checkpoint from menu_ingame" )
+ SaveGame_LoadWithStartPointFallback()
+ return
+ }
+
+ ClientCommand( "RestartFromLevelTransition" )
+}
+
+void function SP_ResetObjectiveStringIndex()
+{
+ file.objectiveStringIndex = -1
+}
+
+void function ServerCallback_UI_ObjectiveUpdated( int stringIndex )
+{
+ file.objectiveStringIndex = stringIndex
+}
+
+void function ServerCallback_UI_UpdateMissionLog( bool showAltLog )
+{
+ uiGlobal.sp_showAlternateMissionLog = showAltLog
+}
+
+void function SPDifficultyButton_Click( var button )
+{
+ DialogData dialogData
+ dialogData.header = "#SP_DIFFICULTY_MISSION_SELECT_TITLE"
+
+ int currentDifficulty = GetConVarInt( "sp_difficulty" )
+ dialogData.coloredButton[ currentDifficulty ] <- true
+
+ if ( currentDifficulty == DIFFICULTY_EASY )
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_EASY_TITLE", SPPickEasy, "#SP_DIFFICULTY_EASY_DESCRIPTION", true )
+ else
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_EASY_TITLE", SPPickEasy, "#SP_DIFFICULTY_EASY_DESCRIPTION", false )
+
+
+ if ( currentDifficulty == DIFFICULTY_NORMAL )
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_NORMAL_TITLE", SPPickNormal, "#SP_DIFFICULTY_NORMAL_DESCRIPTION", true )
+ else
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_NORMAL_TITLE", SPPickNormal, "#SP_DIFFICULTY_NORMAL_DESCRIPTION", false )
+
+
+ if ( currentDifficulty == DIFFICULTY_HARD )
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_HARD_TITLE", SPPickHard, "#SP_DIFFICULTY_HARD_DESCRIPTION", true )
+ else
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_HARD_TITLE", SPPickHard, "#SP_DIFFICULTY_HARD_DESCRIPTION", false )
+
+
+ if ( currentDifficulty == DIFFICULTY_MASTER )
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_MASTER_TITLE", SPPickMaster, "#SP_DIFFICULTY_MASTER_DESCRIPTION", true )
+ else
+ AddDialogButton( dialogData, "#SP_DIFFICULTY_MASTER_TITLE", SPPickMaster, "#SP_DIFFICULTY_MASTER_DESCRIPTION", false )
+
+
+ AddDialogFooter( dialogData, "#A_BUTTON_SELECT" )
+ AddDialogFooter( dialogData, "#B_BUTTON_BACK" )
+ AddDialogPCBackButton( dialogData )
+
+ OpenDialog( dialogData )
+}
+
+void function SPPickEasy()
+{
+ RequestSPDifficultyChange( DIFFICULTY_EASY )
+ CloseAllMenus()
+}
+
+void function SPPickNormal()
+{
+ RequestSPDifficultyChange( DIFFICULTY_NORMAL )
+ CloseAllMenus()
+}
+
+void function SPPickHard()
+{
+ RequestSPDifficultyChange( DIFFICULTY_HARD )
+ CloseAllMenus()
+}
+
+void function SPPickMaster()
+{
+ RequestSPDifficultyChange( DIFFICULTY_MASTER )
+ CloseAllMenus()
+}
+
+void function RequestSPDifficultyChange( int selectedDifficulty )
+{
+ var dataTable = GetDataTable( DATA_TABLE )
+ int difficulty = GetDataTableInt( dataTable, selectedDifficulty, GetDataTableColumnByName( dataTable, "index" ) )
+
+ ClientCommand( "ClientCommand_RequestSPDifficultyChange " + difficulty )
+}
+
+void function SCB_SetDoubleXPStatus( int status )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ RuiSetInt( Hud_GetRui( doubleXPWidget ), "doubleXPStatus", status )
+
+ // update this menu too
+ TTSUpdateDoubleXPStatus( status )
+}
+
+void function OnInGameLevelInit()
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+ RuiSetInt( rui, "doubleXPStatus", 0 )
+ RuiSetBool( rui, "isVisible", false )
+
+ string gameModeScoreHint = expect string( GetCurrentPlaylistVar( "gamemode_score_hint" ) )
+ if ( gameModeScoreHint != "" )
+ {
+ RuiSetString( rui, "scoreMeritText", Localize( gameModeScoreHint ) )
+ RuiSetInt( rui, "matchScoreMerit", MERIT_STATE_AVAILABLE )
+ }
+ else
+ {
+ RuiSetString( rui, "scoreMeritText", "" )
+ RuiSetInt( rui, "matchScoreMerit", MERIT_STATE_HIDDEN )
+ }
+
+ Hud_SetVisible( doubleXPWidget, !IsPrivateMatch() )
+}
+/*
+int matchScoreMerit = MERIT_STATE_AVAILABLE
+int matchCompleteMerit = MERIT_STATE_AVAILABLE
+int matchWinMerit = MERIT_STATE_AVAILABLE
+int matchEvacMerit = MERIT_STATE_HIDDEN
+int happyHourMerits = MERIT_STATE_HIDDEN
+
+int meritCount = 0
+*/
+
+void function SCB_SetScoreMeritState( int meritState )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "matchScoreMerit", meritState )
+}
+
+void function SCB_SetCompleteMeritState( int meritState )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "matchCompleteMerit", meritState )
+}
+
+void function SCB_SetWinMeritState( int meritState )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "matchWinMerit", meritState )
+}
+
+void function SCB_SetEvacMeritState( int meritState )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "matchEvacMerit", meritState )
+}
+
+void function SCB_SetMeritCount( int meritCount )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "meritCount", meritCount )
+}
+
+void function SCB_SetWeaponMeritCount( int meritCount )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "weaponMeritCount", meritCount )
+}
+
+void function SCB_SetTitanMeritCount( int meritCount )
+{
+ var doubleXPWidget = Hud_GetChild( file.menuMP, "DoubleXP" )
+ var rui = Hud_GetRui( doubleXPWidget )
+
+ RuiSetInt( rui, "titanMeritCount", meritCount )
+}
+
+void function TitanSelectButtonHandler( var button )
+{
+ if ( !IsFullyConnected() )
+ return
+
+ entity player = GetUIPlayer()
+ if ( GetAvailableTitanRefs( player ).len() > 1 )
+ {
+ AdvanceMenu( GetMenu( "TitanLoadoutsMenu" ) )
+ }
+ else if ( GetAvailableTitanRefs( player ).len() == 1 )
+ {
+ uiGlobal.updateTitanSpawnLoadout = false
+ SetEditLoadout( "titan", uiGlobal.titanSpawnLoadoutIndex )
+
+ RunMenuClientFunction( "SetEditingTitanLoadoutIndex", uiGlobal.titanSpawnLoadoutIndex )
+ AdvanceMenu( GetMenu( "EditTitanLoadoutMenu" ) )
+ }
+ else
+ {
+ // HIDE
+ }
+}
+
+void function SetTitanSelectButtonVisibleState( bool state )
+{
+ if ( state )
+ {
+ Hud_Show( file.titanHeader )
+ Hud_Show( file.titanEditButton )
+ Hud_Show( file.titanSelectButton )
+ }
+ else
+ {
+ ComboButtons_ResetColumnFocus( file.comboStruct )
+ Hud_Hide( file.titanHeader )
+ Hud_Hide( file.titanEditButton )
+ Hud_Hide( file.titanSelectButton )
+ }
+}
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut
index 938e0d3f..3c868aab 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut
@@ -372,8 +372,6 @@ void function StartPrivateMatch( var button )
return
ClientCommand( "StartPrivateMatchSearch" )
- NSSetLoading(true)
- NSUpdateListenServer()
}
void function DoRoomInviteIfAllowed( var button )
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut
index 4a2cf64a..b757d089 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut
@@ -52,7 +52,8 @@ void function UpdateVisibleModes()
Hud_SetEnabled( buttons[ i ], true )
Hud_SetVisible( buttons[ i ], true )
- if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" )
+ // This check is refactored in the new mode menu so we can just ignore this atrocity
+ if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" || modesArray[ modeIndex ] == "at" )
Hud_SetLocked( buttons[ i ], false )
else if( IsFDMode( modesArray[ i ] ) )
Hud_SetLocked( buttons[ i ], false )
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut
index b5a2e9b6..1e10aa45 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut
@@ -54,5 +54,8 @@ void function OnConnectWithPasswordMenuOpened()
void function ConnectWithPassword( var button )
{
if ( GetTopNonDialogMenu() == file.menu )
+ {
+ TriggerConnectToServerCallbacks()
thread ThreadedAuthAndConnectToServer( Hud_GetUTF8Text( Hud_GetChild( file.menu, "EnterPasswordBox" ) ) )
+ }
} \ No newline at end of file
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
index 03028255..7ea8134a 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
@@ -4,6 +4,9 @@ untyped
global function AddNorthstarServerBrowserMenu
global function ThreadedAuthAndConnectToServer
+global function AddConnectToServerCallback
+global function RemoveConnectToServerCallback
+global function TriggerConnectToServerCallbacks
// Stop peeking
@@ -67,7 +70,6 @@ struct serverStruct {
struct {
// UI state vars
var menu
- int lastSelectedServer = 999
int focusedServerIndex = 0
int scrollOffset = 0
bool serverListRequestFailed = false
@@ -79,6 +81,10 @@ struct {
// filtered array of servers
array<serverStruct> serversArrayFiltered
+
+ array<ServerInfo> filteredServers
+ ServerInfo& focusedServer
+ ServerInfo& lastSelectedServer
// UI references
array<var> serverButtons
@@ -88,6 +94,8 @@ struct {
array<var> serversMap
array<var> serversGamemode
array<var> serversRegion
+
+ array< void functionref( ServerInfo ) > connectCallbacks
} file
@@ -253,7 +261,7 @@ void function FlushMouseDeltaBuffer()
void function SliderBarUpdate()
{
- if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE )
+ if ( file.filteredServers.len() <= BUTTONS_PER_PAGE )
{
FlushMouseDeltaBuffer()
return
@@ -270,7 +278,7 @@ void function SliderBarUpdate()
float maxYPos = minYPos - ( maxHeight - Hud_GetHeight( sliderPanel ) )
float useableSpace = ( maxHeight - Hud_GetHeight( sliderPanel ) )
- float jump = minYPos - ( useableSpace / ( float( file.serversArrayFiltered.len() ) ) )
+ float jump = minYPos - ( useableSpace / ( float( file.filteredServers.len() ) ) )
// got local from official respaw scripts, without untyped throws an error
local pos = Hud_GetPos( sliderButton )[1]
@@ -284,7 +292,7 @@ void function SliderBarUpdate()
Hud_SetPos( sliderPanel , 2, newPos )
Hud_SetPos( movementCapture , 2, newPos )
- file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.serversArrayFiltered.len() - BUTTONS_PER_PAGE ) )
+ file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.filteredServers.len() - BUTTONS_PER_PAGE ) )
UpdateShownPage()
}
@@ -328,13 +336,13 @@ void function UpdateListSliderPosition( int servers )
void function OnScrollDown( var button )
{
- if (file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE) return
+ if (file.filteredServers.len() <= BUTTONS_PER_PAGE) return
file.scrollOffset += 5
- if (file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len()) {
- file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE
+ if (file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len()) {
+ file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE
}
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
}
void function OnScrollUp( var button )
@@ -344,7 +352,7 @@ void function OnScrollUp( var button )
file.scrollOffset = 0
}
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
}
////////////////////////////
@@ -484,7 +492,7 @@ void function OnHitDummyTop( var button )
{
// only update if list position changed
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
DisplayFocusedServerInfo( file.serverButtonFocusedID )
Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer1" ) )
}
@@ -493,10 +501,10 @@ void function OnHitDummyTop( var button )
void function OnHitDummyBottom( var button )
{
file.scrollOffset += 1
- if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() )
+ if ( file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len() )
{
// was at bottom already
- file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE
+ file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE
Hud_SetFocused( Hud_GetChild( file.menu, "BtnServerSearch" ) )
HideServerInfo()
}
@@ -504,7 +512,7 @@ void function OnHitDummyBottom( var button )
{
// only update if list position changed
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
DisplayFocusedServerInfo( file.serverButtonFocusedID )
Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer15" ) )
}
@@ -518,15 +526,15 @@ void function OnHitDummyAfterFilterClear( var button )
void function OnDownArrowSelected( var button )
{
- if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE ) return
+ if ( file.filteredServers.len() <= BUTTONS_PER_PAGE ) return
file.scrollOffset += 1
- if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() )
+ if ( file.scrollOffset + BUTTONS_PER_PAGE > file.filteredServers.len() )
{
- file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE
+ file.scrollOffset = file.filteredServers.len() - BUTTONS_PER_PAGE
}
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
}
@@ -539,7 +547,7 @@ void function OnUpArrowSelected( var button )
}
UpdateShownPage()
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
}
////////////////////////
@@ -642,7 +650,7 @@ void function FilterAndUpdateList( var n )
filterArguments.hideProtected = GetConVarBool( "filter_hide_protected" )
file.scrollOffset = 0
- UpdateListSliderPosition( file.serversArrayFiltered.len() )
+ UpdateListSliderPosition( file.filteredServers.len() )
HideServerInfo()
FilterServerList()
@@ -741,51 +749,42 @@ void function WaitForServerListRequest()
void function FilterServerList()
{
- file.serversArrayFiltered.clear()
+ file.filteredServers.clear()
int totalPlayers = 0
- for ( int i = 0; i < NSGetServerCount(); i++ )
- {
- serverStruct tempServer
- tempServer.serverIndex = i
- tempServer.serverProtected = NSServerRequiresPassword( i )
- tempServer.serverName = NSGetServerName( i )
- tempServer.serverPlayers = NSGetServerPlayerCount( i )
- tempServer.serverPlayersMax = NSGetServerMaxPlayerCount( i )
- tempServer.serverMap = NSGetServerMap( i )
- tempServer.serverGamemode = GetGameModeDisplayName( NSGetServerPlaylist ( i ) )
- tempServer.serverRegion = NSGetServerRegion( i )
-
- totalPlayers += tempServer.serverPlayers
+ array<ServerInfo> servers = NSGetGameServers()
+ foreach ( ServerInfo server in servers )
+ {
+ totalPlayers += server.playerCount
// Filters
- if ( filterArguments.hideEmpty && tempServer.serverPlayers == 0 )
+ if ( filterArguments.hideEmpty && server.playerCount == 0 )
continue;
- if ( filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax )
+ if ( filterArguments.hideFull && server.playerCount == server.maxPlayerCount )
continue;
- if ( filterArguments.hideProtected && tempServer.serverProtected )
+ if ( filterArguments.hideProtected && server.requiresPassword )
continue;
- if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap != tempServer.serverMap )
+ if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap != server.map )
continue;
- if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode != tempServer.serverGamemode )
+ if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode != GetGameModeDisplayName(server.playlist) )
continue;
-
+
// Search
if ( filterArguments.useSearch )
{
array<string> sName
- sName.append( tempServer.serverName.tolower() )
- sName.append( Localize( GetMapDisplayName( tempServer.serverMap ) ).tolower() )
- sName.append( tempServer.serverMap.tolower() )
- sName.append( tempServer.serverGamemode.tolower() )
- sName.append( Localize( tempServer.serverGamemode ).tolower() )
- sName.append( NSGetServerDescription( i ).tolower() )
- sName.append( NSGetServerRegion( i ).tolower() )
+ sName.append( server.name.tolower() )
+ sName.append( Localize( GetMapDisplayName( server.map ) ).tolower() )
+ sName.append( server.map.tolower() )
+ sName.append( server.playlist.tolower() )
+ sName.append( Localize( server.playlist ).tolower() )
+ sName.append( server.description.tolower() )
+ sName.append( server.region.tolower() )
string sTerm = filterArguments.searchTerm.tolower()
@@ -799,9 +798,8 @@ void function FilterServerList()
if ( !found )
continue;
}
-
- // Server fits our requirements, add it to the list
- file.serversArrayFiltered.append( tempServer )
+
+ file.filteredServers.append( server )
}
// Update player and server count
@@ -824,23 +822,22 @@ void function UpdateShownPage()
Hud_SetText( file.serversRegion[ i ], "" )
}
- int j = file.serversArrayFiltered.len() > BUTTONS_PER_PAGE ? BUTTONS_PER_PAGE : file.serversArrayFiltered.len()
+ int j = file.filteredServers.len() > BUTTONS_PER_PAGE ? BUTTONS_PER_PAGE : file.filteredServers.len()
for ( int i = 0; i < j; i++ )
{
-
int buttonIndex = file.scrollOffset + i
- int serverIndex = file.serversArrayFiltered[ buttonIndex ].serverIndex
+ ServerInfo server = file.filteredServers[ buttonIndex ]
Hud_SetEnabled( file.serverButtons[ i ], true )
Hud_SetVisible( file.serverButtons[ i ], true )
- Hud_SetVisible( file.serversProtected[ i ], file.serversArrayFiltered[ buttonIndex ].serverProtected )
- Hud_SetText( file.serversName[ i ], file.serversArrayFiltered[ buttonIndex ].serverName )
- Hud_SetText( file.playerCountLabels[ i ], format( "%i/%i", file.serversArrayFiltered[ buttonIndex ].serverPlayers, file.serversArrayFiltered[ buttonIndex ].serverPlayersMax ) )
- Hud_SetText( file.serversMap[ i ], GetMapDisplayName( file.serversArrayFiltered[ buttonIndex ].serverMap ) )
- Hud_SetText( file.serversGamemode[ i ], file.serversArrayFiltered[ buttonIndex ].serverGamemode )
- Hud_SetText( file.serversRegion[ i ], file.serversArrayFiltered[ buttonIndex ].serverRegion )
+ Hud_SetVisible( file.serversProtected[ i ], server.requiresPassword )
+ Hud_SetText( file.serversName[ i ], server.name )
+ Hud_SetText( file.playerCountLabels[ i ], format( "%i/%i", server.playerCount, server.maxPlayerCount ) )
+ Hud_SetText( file.serversMap[ i ], GetMapDisplayName( server.map ) )
+ Hud_SetText( file.serversGamemode[ i ], GetGameModeDisplayName( server.playlist ) )
+ Hud_SetText( file.serversRegion[ i ], server.region )
}
@@ -850,7 +847,7 @@ void function UpdateShownPage()
Hud_SetVisible( file.serverButtons[ 0 ], true )
Hud_SetText( file.serversName[ 0 ], "#NS_SERVERBROWSER_NOSERVERS" )
}
- UpdateListSliderHeight( float( file.serversArrayFiltered.len() ) )
+ UpdateListSliderHeight( float( file.filteredServers.len() ) )
}
void function OnServerButtonFocused( var button )
@@ -860,8 +857,9 @@ void function OnServerButtonFocused( var button )
int scriptID = int ( Hud_GetScriptID( button ) )
file.serverButtonFocusedID = scriptID
- if ( file.serversArrayFiltered.len() > 0 )
- file.focusedServerIndex = file.serversArrayFiltered[ file.scrollOffset + scriptID ].serverIndex
+ if ( file.filteredServers.len() > 0 )
+ // file.focusedServerIndex = file.filteredServers[ file.scrollOffset + scriptID ].serverIndex
+ file.focusedServer = file.filteredServers[ file.scrollOffset + scriptID ]
DisplayFocusedServerInfo( scriptID )
}
@@ -882,13 +880,12 @@ void function CheckDoubleClick( int scriptID, bool wasClickNav )
int serverIndex = file.scrollOffset + scriptID
bool sameServer = false
- if ( file.lastSelectedServer == serverIndex ) sameServer = true
-
+ if ( file.lastSelectedServer == file.filteredServers[ serverIndex ] ) sameServer = true
file.serverSelectedTimeLast = file.serverSelectedTime
file.serverSelectedTime = Time()
- file.lastSelectedServer = serverIndex
+ file.lastSelectedServer = file.filteredServers[ serverIndex ]
if ( wasClickNav && ( file.serverSelectedTime - file.serverSelectedTimeLast < DOUBLE_CLICK_TIME_MS ) && sameServer )
{
@@ -900,7 +897,7 @@ void function DisplayFocusedServerInfo( int scriptID )
{
if ( scriptID == 999 || scriptID == -1 || scriptID == 16 ) return
- if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.serversArrayFiltered.len() == 0 )
+ if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.filteredServers.len() == 0 )
return
var menu = GetMenu( "ServerBrowserMenu" )
@@ -908,6 +905,7 @@ void function DisplayFocusedServerInfo( int scriptID )
int serverIndex = file.scrollOffset + scriptID
if ( serverIndex < 0 ) serverIndex = 0
+ ServerInfo server = file.filteredServers[ serverIndex ]
Hud_SetVisible( Hud_GetChild( menu, "BtnServerDescription" ), true )
Hud_SetVisible( Hud_GetChild( menu, "BtnServerMods" ), true )
@@ -915,39 +913,39 @@ void function DisplayFocusedServerInfo( int scriptID )
// text panels
Hud_SetVisible( Hud_GetChild( menu, "LabelDescription" ), true )
Hud_SetVisible( Hud_GetChild( menu, "LabelMods" ), false )
- Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), NSGetServerDescription( file.serversArrayFiltered[ serverIndex ].serverIndex ) + "\n\nRequired Mods:\n" + FillInServerModsLabel( file.serversArrayFiltered[ serverIndex ].serverIndex ) )
+ Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), server.description + "\n\nRequired Mods:\n" + FillInServerModsLabel( server.requiredMods ) )
// map name/image/server name
- string map = file.serversArrayFiltered[ serverIndex ].serverMap
+ string map = server.map
Hud_SetVisible( Hud_GetChild( menu, "NextMapImage" ), true )
Hud_SetVisible( Hud_GetChild( menu, "NextMapBack" ), true )
RuiSetImage( Hud_GetRui( Hud_GetChild( menu, "NextMapImage" ) ), "basicImage", GetMapImageForMapName( map ) )
Hud_SetVisible( Hud_GetChild( menu, "NextMapName" ), true )
Hud_SetText( Hud_GetChild( menu, "NextMapName" ), GetMapDisplayName( map ) )
Hud_SetVisible( Hud_GetChild( menu, "ServerName" ), true )
- Hud_SetText( Hud_GetChild( menu, "ServerName" ), NSGetServerName( file.serversArrayFiltered[ serverIndex ].serverIndex ) )
+ Hud_SetText( Hud_GetChild( menu, "ServerName" ), server.name )
// mode name/image
- string mode = file.serversArrayFiltered[ serverIndex ].serverGamemode
+ string mode = server.playlist
Hud_SetVisible( Hud_GetChild( menu, "NextModeIcon" ), true )
RuiSetImage( Hud_GetRui( Hud_GetChild( menu, "NextModeIcon" ) ), "basicImage", GetPlaylistThumbnailImage( mode ) )
Hud_SetVisible( Hud_GetChild( menu, "NextGameModeName" ), true )
if ( mode.len() != 0 )
- Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), mode )
+ Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), GetGameModeDisplayName( mode ) )
else
Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), "#NS_SERVERBROWSER_UNKNOWNMODE" )
}
-string function FillInServerModsLabel( int server )
+string function FillInServerModsLabel( array<RequiredModInfo> mods )
{
string ret
- for ( int i = 0; i < NSGetServerRequiredModsCount( server ); i++ )
+ foreach ( RequiredModInfo mod in mods )
{
- ret += " "
- ret += NSGetServerRequiredModName( server, i ) + " v" + NSGetServerRequiredModVersion( server, i ) + "\n"
+ ret += format( " %s v%s\n", mod.name, mod.version )
}
+
return ret
}
@@ -957,18 +955,17 @@ void function OnServerSelected( var button )
if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed )
return
- int serverIndex = file.focusedServerIndex
+ ServerInfo server = file.focusedServer
- file.lastSelectedServer = serverIndex
+ file.lastSelectedServer = server
- // check mods
- for ( int i = 0; i < NSGetServerRequiredModsCount( serverIndex ); i++ )
+ foreach ( RequiredModInfo mod in server.requiredMods )
{
- if ( !NSGetModNames().contains( NSGetServerRequiredModName( serverIndex, i ) ) )
+ if ( !NSGetModNames().contains( mod.name ) )
{
DialogData dialogData
dialogData.header = "#ERROR"
- dialogData.message = "Missing mod \"" + NSGetServerRequiredModName( serverIndex, i ) + "\" v" + NSGetServerRequiredModVersion( serverIndex, i )
+ dialogData.message = format( "Missing mod \"%s\" v%s", mod.name, mod.version )
dialogData.image = $"ui/menu/common/dialog_error"
#if PC_PROG
@@ -985,8 +982,8 @@ void function OnServerSelected( var button )
else
{
// this uses semver https://semver.org
- array<string> serverModVersion = split( NSGetServerRequiredModVersion( serverIndex, i ), "." )
- array<string> clientModVersion = split( NSGetModVersionByModName( NSGetServerRequiredModName( serverIndex, i ) ), "." )
+ array<string> serverModVersion = split( mod.name, "." )
+ array<string> clientModVersion = split( NSGetModVersionByModName( mod.name ), "." )
bool semverFail = false
// if server has invalid semver don't bother checking
@@ -1004,7 +1001,7 @@ void function OnServerSelected( var button )
{
DialogData dialogData
dialogData.header = "#ERROR"
- dialogData.message = "Server has mod \"" + NSGetServerRequiredModName( serverIndex, i ) + "\" v" + NSGetServerRequiredModVersion( serverIndex, i ) + " while we have v" + NSGetModVersionByModName( NSGetServerRequiredModName( serverIndex, i ) )
+ dialogData.message = format( "Server has mod \"%s\" v%s while we have v%s", mod.name, mod.version, NSGetModVersionByModName( mod.name ) )
dialogData.image = $"ui/menu/common/dialog_error"
#if PC_PROG
@@ -1021,13 +1018,16 @@ void function OnServerSelected( var button )
}
}
- if ( NSServerRequiresPassword( serverIndex ) )
+ if ( server.requiresPassword )
{
OnCloseServerBrowserMenu()
AdvanceMenu( GetMenu( "ConnectWithPasswordMenu" ) )
}
else
+ {
+ TriggerConnectToServerCallbacks()
thread ThreadedAuthAndConnectToServer()
+ }
}
@@ -1036,9 +1036,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" )
if ( NSIsAuthenticatingWithServer() )
return
- print( "trying to authenticate with server " + NSGetServerName( file.lastSelectedServer ) + " with password " + password )
-
- NSTryAuthWithServer( file.lastSelectedServer, password )
+ NSTryAuthWithServer( file.lastSelectedServer.index, password )
ToggleConnectingHUD( true )
@@ -1058,34 +1056,18 @@ void function ThreadedAuthAndConnectToServer( string password = "" )
}
file.cancelConnection = false
- NSSetLoading( true )
- NSUpdateServerInfo(
- NSGetServerID( file.lastSelectedServer ),
- NSGetServerName( file.lastSelectedServer ),
- password,
- NSGetServerPlayerCount( file.lastSelectedServer ),
- NSGetServerMaxPlayerCount( file.lastSelectedServer ),
- NSGetServerMap( file.lastSelectedServer ),
- Localize( GetMapDisplayName( NSGetServerMap( file.lastSelectedServer ) ) ),
- NSGetServerPlaylist( file.lastSelectedServer ),
- Localize( GetPlaylistDisplayName( NSGetServerPlaylist( file.lastSelectedServer ) ) )
- )
if ( NSWasAuthSuccessful() )
{
bool modsChanged
- array<string> requiredMods
- for ( int i = 0; i < NSGetServerRequiredModsCount( file.lastSelectedServer ); i++ )
- requiredMods.append( NSGetServerRequiredModName( file.lastSelectedServer, i ) )
-
// unload mods we don't need, load necessary ones and reload mods before connecting
- foreach ( string mod in NSGetModNames() )
+ foreach ( RequiredModInfo mod in file.lastSelectedServer.requiredMods )
{
- if ( NSIsModRequiredOnClient( mod ) )
+ if ( NSIsModRequiredOnClient( mod.name ) )
{
- modsChanged = modsChanged || NSIsModEnabled( mod ) != requiredMods.contains( mod )
- NSSetModEnabled( mod, requiredMods.contains( mod ) )
+ modsChanged = modsChanged || NSIsModEnabled( mod.name ) != file.lastSelectedServer.requiredMods.contains( mod )
+ NSSetModEnabled( mod.name, file.lastSelectedServer.requiredMods.contains( mod ) )
}
}
@@ -1097,9 +1079,11 @@ void function ThreadedAuthAndConnectToServer( string password = "" )
}
else
{
+ string reason = NSGetAuthFailReason()
+
DialogData dialogData
dialogData.header = "#ERROR"
- dialogData.message = "Authentication Failed"
+ dialogData.message = reason
dialogData.image = $"ui/menu/common/dialog_error"
#if PC_PROG
@@ -1116,7 +1100,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" )
//////////////////////////////////////
// Shadow realm
//////////////////////////////////////
-int function ServerSortLogic ( serverStruct a, serverStruct b )
+int function ServerSortLogic ( ServerInfo a, ServerInfo b )
{
var aTemp
var bTemp
@@ -1127,44 +1111,44 @@ int function ServerSortLogic ( serverStruct a, serverStruct b )
switch ( filterDirection.sortingBy )
{
case sortingBy.DEFAULT:
- aTemp = a.serverPlayers
- bTemp = b.serverPlayers
+ aTemp = a.playerCount
+ bTemp = b.playerCount
// `1000` is assumed to always be higher than `serverPlayersMax`
- if (aTemp + 1 < a.serverPlayersMax)
+ if (aTemp + 1 < a.maxPlayerCount)
aTemp = aTemp+2000
- if (bTemp + 1 < b.serverPlayersMax)
+ if (bTemp + 1 < b.maxPlayerCount)
bTemp = bTemp+2000
- if (aTemp + 1 == a.serverPlayersMax)
+ if (aTemp + 1 == a.maxPlayerCount)
aTemp = aTemp+1000
- if (bTemp + 1 == b.serverPlayersMax)
+ if (bTemp + 1 == b.maxPlayerCount)
bTemp = bTemp+1000
direction = filterDirection.serverName
break;
case sortingBy.NAME:
- aTemp = a.serverName.tolower()
- bTemp = b.serverName.tolower()
+ aTemp = a.name.tolower()
+ bTemp = b.name.tolower()
direction = filterDirection.serverName
break;
case sortingBy.PLAYERS:
- aTemp = a.serverPlayers
- bTemp = b.serverPlayers
+ aTemp = a.playerCount
+ bTemp = b.playerCount
direction = filterDirection.serverPlayers
break;
case sortingBy.MAP:
- aTemp = Localize( a.serverMap ).tolower()
- bTemp = Localize( b.serverMap ).tolower()
+ aTemp = Localize( a.map ).tolower()
+ bTemp = Localize( b.map ).tolower()
direction = filterDirection.serverMap
break;
case sortingBy.GAMEMODE:
- aTemp = Localize( a.serverGamemode ).tolower()
- bTemp = Localize( b.serverGamemode ).tolower()
+ aTemp = Localize( a.playlist ).tolower()
+ bTemp = Localize( b.playlist ).tolower()
direction = filterDirection.serverGamemode
break;
case sortingBy.REGION:
- aTemp = a.serverRegion
- bTemp = b.serverRegion
+ aTemp = a.region
+ bTemp = b.region
direction = filterDirection.serverRegion
break;
default:
@@ -1186,7 +1170,7 @@ void function SortServerListByDefault_Activate ( var button )
{
filterDirection.sortingBy = sortingBy.DEFAULT
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverName = !filterDirection.serverName
@@ -1198,7 +1182,7 @@ void function SortServerListByName_Activate ( var button )
{
filterDirection.sortingBy = sortingBy.NAME
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverName = !filterDirection.serverName
@@ -1210,7 +1194,7 @@ void function SortServerListByPlayers_Activate( var button )
{
filterDirection.sortingBy = sortingBy.PLAYERS
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverPlayers = !filterDirection.serverPlayers
@@ -1221,7 +1205,7 @@ void function SortServerListByMap_Activate( var button )
{
filterDirection.sortingBy = sortingBy.MAP
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverMap = !filterDirection.serverMap
@@ -1232,7 +1216,7 @@ void function SortServerListByGamemode_Activate( var button )
{
filterDirection.sortingBy = sortingBy.GAMEMODE
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverGamemode = !filterDirection.serverGamemode
@@ -1243,9 +1227,33 @@ void function SortServerListByRegion_Activate( var button )
{
filterDirection.sortingBy = sortingBy.REGION
- file.serversArrayFiltered.sort( ServerSortLogic )
+ file.filteredServers.sort( ServerSortLogic )
filterDirection.serverRegion = !filterDirection.serverRegion
UpdateShownPage()
}
+
+//////////////////////////////////////
+// Callbacks
+//////////////////////////////////////
+
+void function AddConnectToServerCallback( void functionref( ServerInfo ) callback )
+{
+ if ( file.connectCallbacks.find( callback ) >= 0 )
+ throw "ConnectToServerCallback has been registered twice. Duplicate callbacks are not allowed."
+ file.connectCallbacks.append( callback )
+}
+
+void function RemoveConnectToServerCallback( void functionref( ServerInfo ) callback )
+{
+ file.connectCallbacks.fastremovebyvalue( callback )
+}
+
+void function TriggerConnectToServerCallbacks()
+{
+ foreach( callback in file.connectCallbacks )
+ {
+ callback( file.lastSelectedServer )
+ }
+}
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
index 95b7bdae..53d85387 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
@@ -571,12 +571,12 @@ void function TryAuthWithLocalServer()
{
CloseAllDialogs()
- var reason = NSGetAuthFailReason()
+ string reason = NSGetAuthFailReason()
DialogData dialogData
dialogData.image = $"ui/menu/common/dialog_error"
dialogData.header = "#ERROR"
- dialogData.message = Localize("#NS_SERVERBROWSER_CONNECTIONFAILED") + "\nERROR: " + reason + "\n" + Localize("#" + reason)
+ dialogData.message = reason
AddDialogButton( dialogData, "#OK", null )
OpenDialog( dialogData )