diff options
Diffstat (limited to 'Northstar.Client/mod/scripts/vscripts/ui')
12 files changed, 5224 insertions, 0 deletions
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut new file mode 100644 index 00000000..3c868aab --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut @@ -0,0 +1,1628 @@ +untyped + + +global function MenuLobby_Init + +global function InitLobbyMenu +global function UICodeCallback_SetupPlayerListGenElements +global function UpdateAnnouncementDialog +global function EnableButton +global function DisableButton + +global function UICodeCallback_CommunityUpdated +global function UICodeCallback_FactionUpdated +global function Lobby_UpdateInboxButtons + +global function GetTimeToRestartMatchMaking + +global function RefreshCreditsAvailable + +global function InviteFriendsIfAllowed +global function SetPutPlayerInMatchmakingAfterDelay + +global function DLCStoreShouldBeMarkedAsNew + +global function SetNextAutoMatchmakingPlaylist +global function GetNextAutoMatchmakingPlaylist + +global function OnDpadCommsButton_Activate + +global function GetActiveSearchingPlaylist + +global function Lobby_SetFDModeBasedOnSearching +global function Lobby_IsFDMode +global function Lobby_SetAutoFDOpen +global function Lobby_SetFDMode +global function Lobby_ToggleFDMode +global function Lobby_CallsignButton3EventHandler +global function Lobby_RefreshButtons + +global function OnStoreButton_Activate +global function OnStoreBundlesButton_Activate +global function OnStoreNewReleasesButton_Activate + +const string MATCHMAKING_AUDIO_CONNECTING = "menu_campaignsummary_titanunlocked" + +struct +{ + struct { + string playlistName = "" + int mapIdx = -1 + int modeIdx = -1 + } preCacheInfo + + array searchIconElems + array searchTextElems + array matchStartCountdownElems + array matchStatusRuis + + array creditsAvailableElems + + var chatroomMenu + var chatroomMenu_chatroomWidget + + var findGameButton + var inviteRoomButton + var inviteFriendsButton + var inviteFriendsToNetworkButton + var toggleMenuModeButton + + var networksMoreButton + + int inboxHeaderIndex + var inboxButton + + int customizeHeaderIndex + var pilotButton + var titanButton + var boostsButton + var storeButton + var storeNewReleasesButton + var storeBundlesButton + var factionButton + var bannerButton + var patchButton + var statsButton + var networksHeader + var settingsHeader + var storeHeader + var browseNetworkButton + var faqButton + var dpadCommsButton + + var genUpButton + + array<var> lobbyButtons + var playHeader + var customizeHeader + var callsignHeader + + float timeToRestartMatchMaking = 0 + + string nextAutoMatchmakingPlaylist + + var callsignCard + + bool putPlayerInMatchmakingAfterDelay = false + float matchmakingStartTime = 0.0 + int etaTime = 0 + int etaMaxMinutes = 15 + string lastMixtapeMatchmakingStatus + + ComboStruct &lobbyComboStruct + + bool isFDMode = false + bool shouldAutoOpenFDMenu = false +} file + +void function MenuLobby_Init() +{ + PrecacheHUDMaterial( $"ui/menu/lobby/player_hover" ) + PrecacheHUDMaterial( $"ui/menu/lobby/chatroom_player" ) + PrecacheHUDMaterial( $"ui/menu/lobby/chatroom_hover" ) + PrecacheHUDMaterial( $"ui/menu/main_menu/motd_background" ) + PrecacheHUDMaterial( $"ui/menu/main_menu/motd_background_happyhour" ) + + AddUICallback_OnLevelInit( OnLobbyLevelInit ) +} + + +bool function ChatroomIsVisibleAndFocused() +{ + return Hud_IsVisible( file.chatroomMenu ) && Hud_IsFocused( file.chatroomMenu_chatroomWidget ); +} + +bool function ChatroomIsVisibleAndNotFocused() +{ + return Hud_IsVisible( file.chatroomMenu ) && !Hud_IsFocused( file.chatroomMenu_chatroomWidget ); +} + +void function Lobby_UpdateInboxButtons() +{ + var menu = GetMenu( "LobbyMenu" ) + if ( GetUIPlayer() == null || !IsPersistenceAvailable() ) + return + + bool hasNewMail = (Inbox_HasUnreadMessages() && Inbox_GetTotalMessageCount() > 0) || PlayerRandomUnlock_GetTotal( GetUIPlayer() ) > 0 + if ( hasNewMail ) + { + int messageCount = Inbox_GetTotalMessageCount() + int lootCount = PlayerRandomUnlock_GetTotal( GetUIPlayer() ) + int totalCount = messageCount + lootCount + + string countString + if ( totalCount >= MAX_MAIL_COUNT ) + countString = MAX_MAIL_COUNT + "+" + else + countString = string( totalCount ) + + SetComboButtonHeaderTitle( menu, file.inboxHeaderIndex, Localize( "#MENU_HEADER_NETWORKS_NEW_MSGS", countString ) ) + ComboButton_SetText( file.inboxButton, Localize( "#MENU_TITLE_INBOX_NEW_MSGS", countString ) ) + } + else + { + SetComboButtonHeaderTitle( menu, file.inboxHeaderIndex, Localize( "#MENU_HEADER_NETWORKS" ) ) + ComboButton_SetText( file.inboxButton, Localize( "#MENU_TITLE_READ" ) ) + } + + ComboButton_SetNewMail( file.inboxButton, hasNewMail ) +} + +void function InitLobbyMenu() +{ + var menu = GetMenu( "LobbyMenu" ) + + InitOpenInvitesMenu() + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT", "", null, ChatroomIsVisibleAndNotFocused ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + AddMenuFooterOption( menu, BUTTON_BACK, "#BACK_BUTTON_POSTGAME_REPORT", "#POSTGAME_REPORT", OpenPostGameMenu, IsPostGameMenuValid ) + AddMenuFooterOption( menu, BUTTON_TRIGGER_RIGHT, "#R_TRIGGER_CHAT", "", null, IsVoiceChatPushToTalk ) + + InitChatroom( menu ) + + file.chatroomMenu = Hud_GetChild( menu, "ChatRoomPanel" ) + file.chatroomMenu_chatroomWidget = Hud_GetChild( file.chatroomMenu, "ChatRoom" ) + file.genUpButton = Hud_GetChild( menu, "GenUpButton" ) + + SetupComboButtonTest( menu ) + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnLobbyMenu_Open ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnLobbyMenu_Close ) + AddMenuEventHandler( menu, eUIEvent.MENU_NAVIGATE_BACK, OnLobbyMenu_NavigateBack ) + + RegisterUIVarChangeCallback( "gameStartTime", GameStartTime_Changed ) + + RegisterUIVarChangeCallback( "showGameSummary", ShowGameSummary_Changed ) + + file.searchIconElems = GetElementsByClassnameForMenus( "SearchIconClass", uiGlobal.allMenus ) + file.searchTextElems = GetElementsByClassnameForMenus( "SearchTextClass", uiGlobal.allMenus ) + file.matchStartCountdownElems = GetElementsByClassnameForMenus( "MatchStartCountdownClass", uiGlobal.allMenus ) + file.matchStatusRuis = GetElementsByClassnameForMenus( "MatchmakingStatusRui", uiGlobal.allMenus ) + file.creditsAvailableElems = GetElementsByClassnameForMenus( "CreditsAvailableClass", uiGlobal.allMenus ) + + file.callsignCard = Hud_GetChild( menu, "CallsignCard" ) + + AddEventHandlerToButton( menu, "GenUpButton", UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "Generation_Respawn" ) ) ) + + AddMenuVarChangeHandler( "focus", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isFullyConnected", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isPartyLeader", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isPrivateMatch", UpdateFooterOptions ) + #if DURANGO_PROG + AddMenuVarChangeHandler( "DURANGO_canInviteFriends", UpdateFooterOptions ) + AddMenuVarChangeHandler( "DURANGO_isJoinable", UpdateFooterOptions ) + AddMenuVarChangeHandler( "DURANGO_isGameFullyInstalled", UpdateFooterOptions ) + #elseif PS4_PROG + AddMenuVarChangeHandler( "PS4_canInviteFriends", UpdateFooterOptions ) + #elseif PC_PROG + AddMenuVarChangeHandler( "ORIGIN_isEnabled", UpdateFooterOptions ) + AddMenuVarChangeHandler( "ORIGIN_isJoinable", UpdateFooterOptions ) + #endif + + RegisterSignal( "BypassWaitBeforeRestartingMatchmaking" ) + RegisterSignal( "PutPlayerInMatchmakingAfterDelay" ) + RegisterSignal( "CancelRestartingMatchmaking" ) + RegisterSignal( "LeaveParty" ) +} + +void function SetupComboButtonTest( var menu ) +{ + ComboStruct comboStruct = ComboButtons_Create( menu ) + file.lobbyComboStruct = comboStruct + + int headerIndex = 0 + int buttonIndex = 0 + file.playHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_PLAY" ) + + bool isModded = IsNorthstarServer() + + + // this will be the server browser + if ( isModded ) + { + file.findGameButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_SERVER_BROWSER" ) + file.lobbyButtons.append( file.findGameButton ) + Hud_SetLocked( file.findGameButton, true ) + Hud_AddEventHandler( file.findGameButton, UIE_CLICK, OpenServerBrowser ) + } + else + { + file.findGameButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_FIND_GAME" ) + file.lobbyButtons.append( file.findGameButton ) + Hud_AddEventHandler( file.findGameButton, UIE_CLICK, BigPlayButton1_Activate ) + } + + // this is used for launching private matches now + if ( isModded ) + { + file.inviteRoomButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#PRIVATE_MATCH" ) + Hud_AddEventHandler( file.inviteRoomButton, UIE_CLICK, StartPrivateMatch ) + } + else + { + file.inviteRoomButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_ROOM" ) + Hud_AddEventHandler( file.inviteRoomButton, UIE_CLICK, DoRoomInviteIfAllowed ) + } + + file.inviteFriendsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_FRIENDS" ) + Hud_AddEventHandler( file.inviteFriendsButton, UIE_CLICK, InviteFriendsIfAllowed ) + + if ( isModded ) + { + Hud_SetEnabled( file.inviteFriendsButton, false ) + Hud_SetVisible( file.inviteFriendsButton, false ) + } + + // file.toggleMenuModeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LOBBY_SWITCH_FD" ) + // Hud_AddEventHandler( file.toggleMenuModeButton, UIE_CLICK, ToggleLobbyMode ) + + headerIndex++ + buttonIndex = 0 + file.customizeHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_LOADOUTS" ) + file.customizeHeaderIndex = headerIndex + var pilotButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_PILOT" ) + file.pilotButton = pilotButton + file.lobbyButtons.append( pilotButton ) + Hud_AddEventHandler( pilotButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditPilotLoadoutsMenu" ) ) ) + var titanButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_TITAN" ) + file.titanButton = titanButton + Hud_AddEventHandler( titanButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditTitanLoadoutsMenu" ) ) ) + file.boostsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_BOOSTS" ) + Hud_AddEventHandler( file.boostsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "BurnCardMenu" ) ) ) + + headerIndex++ + buttonIndex = 0 + file.callsignHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_CALLSIGN" ) + file.bannerButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_BANNER" ) + file.lobbyButtons.append( file.bannerButton ) + Hud_AddEventHandler( file.bannerButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "CallsignCardSelectMenu" ) ) ) + file.patchButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_PATCH" ) + Hud_AddEventHandler( file.patchButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "CallsignIconSelectMenu" ) ) ) + file.factionButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_FACTION" ) + Hud_AddEventHandler( file.factionButton, UIE_CLICK, Lobby_CallsignButton3EventHandler ) + file.statsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STATS" ) + Hud_AddEventHandler( file.statsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStatsMenu" ) ) ) + + file.callsignCard = Hud_GetChild( menu, "CallsignCard" ) + + headerIndex++ + buttonIndex = 0 + file.networksHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_NETWORKS" ) + file.inboxHeaderIndex = headerIndex + var networksInbox = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INBOX" ) + file.inboxButton = networksInbox + file.lobbyButtons.append( networksInbox ) + Hud_AddEventHandler( networksInbox, UIE_CLICK, OnInboxButton_Activate ) + var switchButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#COMMUNITY_SWITCHCOMMUNITY" ) + Hud_AddEventHandler( switchButton, UIE_CLICK, OnSwitchButton_Activate ) + var browseButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#COMMUNITY_BROWSE_NETWORKS" ) + file.lobbyButtons.append( browseButton ) + Hud_AddEventHandler( browseButton, UIE_CLICK, OnBrowseNetworksButton_Activate ) + file.browseNetworkButton = browseButton + #if NETWORK_INVITE + file.inviteFriendsToNetworkButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#INVITE_FRIENDS" ) + file.lobbyButtons.append( file.inviteFriendsToNetworkButton ) + Hud_AddEventHandler( file.inviteFriendsToNetworkButton, UIE_CLICK, OnInviteFriendsToNetworkButton_Activate ) + #endif + + headerIndex++ + buttonIndex = 0 + file.storeHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_STORE" ) + SetComboButtonHeaderTint( GetMenu( "LobbyMenu" ), headerIndex, true ) + file.storeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_BROWSE" ) + Hud_AddEventHandler( file.storeButton, UIE_CLICK, OnStoreButton_Activate ) + file.storeNewReleasesButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_NEW_RELEASES" ) + Hud_AddEventHandler( file.storeNewReleasesButton, UIE_CLICK, OnStoreNewReleasesButton_Activate ) + file.storeBundlesButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_BUNDLES" ) + Hud_AddEventHandler( file.storeBundlesButton, UIE_CLICK, OnStoreBundlesButton_Activate ) + + headerIndex++ + buttonIndex = 0 + file.settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" ) + var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_CONTROLS" ) + Hud_AddEventHandler( controlsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ControlsMenu" ) ) ) + file.lobbyButtons.append( controlsButton ) + #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" ) ) ) + + comboStruct.navUpButtonDisabled = true + comboStruct.navDownButton = file.genUpButton + + ComboButtons_Finalize( comboStruct ) +} + +bool function MatchResultsExist() +{ + return true // TODO +} + +void function StartPrivateMatch( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + ClientCommand( "StartPrivateMatchSearch" ) +} + +void function DoRoomInviteIfAllowed( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + if ( !DoesCurrentCommunitySupportInvites() ) + { + OnBrowseNetworksButton_Activate( button ) + return + } + + entity player = GetUIPlayer() + + if ( IsValid( player ) && Player_NextAvailableMatchmakingTime( player ) > 0 ) + { + DisplayMatchmakingPenaltyDialog( player ) + return + } + + SendOpenInvite( true ) + OpenSelectedPlaylistMenu() +} + +void function DisplayMatchmakingPenaltyDialog( entity player ) +{ + int minutesRemaining = int( ceil( Player_GetRemainingMatchmakingDelay( player ) / 60) ) + if ( minutesRemaining <= 1 ) + ServerCallback_GenericDialog( 30, 31, true ) + else if ( minutesRemaining == 2 ) + ServerCallback_GenericDialog( 30, 32, true ) + else if ( minutesRemaining == 3 ) + ServerCallback_GenericDialog( 30, 33, true ) + else if ( minutesRemaining == 4 ) + ServerCallback_GenericDialog( 30, 34, true ) + else if ( minutesRemaining == 5 ) + ServerCallback_GenericDialog( 30, 35, true ) + else + ServerCallback_GenericDialog( 30, 36, true ) +} + +void function CreatePartyAndInviteFriends() +{ + if ( CanInvite() ) + { + while ( !PartyHasMembers() && !AmIPartyLeader() ) + { + ClientCommand( "createparty" ) + WaitFrameOrUntilLevelLoaded() + } + InviteFriends( file.inviteFriendsButton ) + } + else + { + printt( "Not inviting friends - CanInvite() returned false" ); + } +} + +void function ToggleLobbyMode( var button ) +{ + Lobby_ToggleFDMode() +} + +void function Lobby_ToggleFDMode() +{ + Hud_SetFocused( file.findGameButton ) + ComboButtons_ResetColumnFocus( file.lobbyComboStruct ) + file.isFDMode = !file.isFDMode + Lobby_RefreshButtons() +} + +void function Lobby_CallsignButton3EventHandler( var button ) +{ + if ( Lobby_IsFDMode() ) + { + AdvanceMenu( GetMenu( "ViewStatsMenu" ) ) + } + else + { + AdvanceMenu( GetMenu( "FactionChoiceMenu" ) ) + } +} + +void function InviteFriendsIfAllowed( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + entity player = GetUIPlayer() + if ( IsValid( player ) && Player_NextAvailableMatchmakingTime( player ) > 0 ) + { + DisplayMatchmakingPenaltyDialog( player ) + return + } + + #if PC_PROG + if ( !Origin_IsOverlayAvailable() ) + { + PopUpOriginOverlayDisabledDialog() + return + } + #endif + + thread CreatePartyAndInviteFriends() +} + +bool function CanInvite() +{ + if ( Player_NextAvailableMatchmakingTime( GetUIPlayer() ) > 0 ) + return false + +#if DURANGO_PROG + return ( GetMenuVarBool( "isFullyConnected" ) && GetMenuVarBool( "DURANGO_canInviteFriends" ) && GetMenuVarBool( "DURANGO_isJoinable" ) && GetMenuVarBool( "DURANGO_isGameFullyInstalled" ) ) + #elseif PS4_PROG + return GetMenuVarBool( "PS4_canInviteFriends" ) + #elseif PC_PROG + return ( GetMenuVarBool( "isFullyConnected" ) && GetMenuVarBool( "ORIGIN_isEnabled" ) && GetMenuVarBool( "ORIGIN_isJoinable" ) && Origin_IsOverlayAvailable() ) + #endif +} + +void function Lobby_RefreshButtons() +{ + bool fdMode = Lobby_IsFDMode() + var menu = GetMenu( "LobbyMenu" ) + + if ( GetTopNonDialogMenu() == GetMenu( "LobbyMenu" ) ) + { + if ( fdMode ) + UI_SetPresentationType( ePresentationType.FD_MAIN ) + else + UI_SetPresentationType( ePresentationType.DEFAULT ) + } + + string buttonString = fdMode ? "#MENU_LOBBY_SWITCH_DEFAULT" : "#MENU_LOBBY_SWITCH_FD" + // ComboButton_SetText( file.toggleMenuModeButton, buttonString ) + + buttonString = fdMode ? "" : "#MENU_TITLE_BOOSTS" + Hud_SetEnabled( file.boostsButton, !fdMode ) + ComboButton_SetText( file.boostsButton, buttonString ) + + buttonString = fdMode ? "#MENU_TITLE_STATS" : "#MENU_TITLE_FACTION" + ComboButton_SetText( file.factionButton, buttonString ) + + buttonString = fdMode ? "" : "#MENU_TITLE_STATS" + Hud_SetEnabled( file.statsButton, !fdMode ) + ComboButton_SetText( file.statsButton, buttonString ) + + buttonString = fdMode ? "#MENU_HEADER_PLAY_FD" : "#MENU_HEADER_PLAY" + SetComboButtonHeaderTitle( menu, 0, buttonString ) + + if ( fdMode ) + Hud_Hide( Hud_GetChild( menu, "ImgTopBar" ) ) + else + Hud_Show( Hud_GetChild( menu, "ImgTopBar" ) ) + + ComboButtons_ResetColumnFocus( file.lobbyComboStruct ) + + if ( fdMode ) + { + Hud_SetText( Hud_GetChild( menu, "MenuTitle" ), "" ) + } + else + { + Hud_SetText( Hud_GetChild( menu, "MenuTitle" ), "#MULTIPLAYER" ) + } +} + +void function OnLobbyMenu_Open() +{ + Assert( IsConnected() ) + + // code will start loading DLC info from first party unless already done + InitDLCStore() + + thread UpdateCachedNewItems() + if ( file.putPlayerInMatchmakingAfterDelay ) + { + entity player = GetUIPlayer() + if (IsValid( player )) + { + string playlistToSearch = expect string( player.GetPersistentVar( "lastPlaylist" ) ) + string nextAutoPlaylist = GetNextAutoMatchmakingPlaylist() + if ( nextAutoPlaylist.len() > 0 ) + playlistToSearch = nextAutoPlaylist + + Lobby_SetFDModeBasedOnSearching( playlistToSearch ) + } + AdvanceMenu( GetMenu( "SearchMenu" ) ) + thread PutPlayerInMatchmakingAfterDelay() + file.putPlayerInMatchmakingAfterDelay = false + } + else if ( uiGlobal.activeMenu == GetMenu( "LobbyMenu" ) ) + Lobby_SetFDMode( false ) + + thread UpdateLobbyUI() + thread LobbyMenuUpdate( GetMenu( "LobbyMenu" ) ) + + Hud_Show( file.chatroomMenu ) + + Lobby_RefreshButtons() + + if ( IsFullyConnected() ) + { + entity player = GetUIPlayer() + if ( !IsValid( player ) ) + return + + while ( IsPersistenceAvailable() && (player.GetPersistentVarAsInt( "initializedVersion" ) < PERSISTENCE_INIT_VERSION) ) + { + WaitFrame() + } + if ( !IsPersistenceAvailable() ) + return + + // Clear hidden boosts + array<ItemData> boosts = GetAllItemsOfType( eItemTypes.BURN_METER_REWARD ) + foreach ( boost in boosts ) + { + if ( boost.hidden ) + { + ClearNewStatus( null, boost.ref ) + } + } + + UpdateCallsignElement( file.callsignCard ) + RefreshCreditsAvailable() + + bool emotesAreEnabled = EmotesEnabled() + // "Customize" + { + bool anyNewPilotItems = HasAnyNewPilotItems( player ) + bool anyNewTitanItems = HasAnyNewTitanItems( player ) + bool anyNewBoosts = HasAnyNewBoosts( player ) + bool anyNewCommsIcons = emotesAreEnabled ? HasAnyNewDpadCommsIcons( player ) : false + bool anyNewCustomizeHeader = (anyNewPilotItems || anyNewTitanItems || anyNewBoosts || anyNewCommsIcons) + + RuiSetBool( Hud_GetRui( file.customizeHeader ), "isNew", anyNewCustomizeHeader ) + ComboButton_SetNew( file.pilotButton, anyNewPilotItems ) + ComboButton_SetNew( file.titanButton, anyNewTitanItems ) + ComboButton_SetNew( file.boostsButton, anyNewBoosts ) + } + + // "Store" + { + bool storeIsNew = DLCStoreShouldBeMarkedAsNew() + RuiSetBool( Hud_GetRui( file.storeHeader ), "isNew", storeIsNew ) + ComboButton_SetNew( file.storeButton, storeIsNew ) + } + + // "Callsign" + { + bool anyNewBanners = HasAnyNewCallsignBanners( player ) + bool anyNewPatches = HasAnyNewCallsignPatches( player ) + bool anyNewFactions = HasAnyNewFactions( player ) && Lobby_IsFDMode() + bool anyNewCallsignHeader = (anyNewBanners || anyNewPatches || anyNewFactions) + + RuiSetBool( Hud_GetRui( file.callsignHeader ), "isNew", anyNewCallsignHeader ) + ComboButton_SetNew( file.bannerButton, anyNewBanners ) + ComboButton_SetNew( file.patchButton, anyNewPatches ) + ComboButton_SetNew( file.factionButton, anyNewFactions ) + } + + bool faqIsNew = !GetConVarBool( "menu_faq_viewed" ) || HaveNewPatchNotes() || HaveNewCommunityNotes() + RuiSetBool( Hud_GetRui( file.settingsHeader ), "isNew", faqIsNew ) + ComboButton_SetNew( file.faqButton, faqIsNew ) + + TryUnlockSRSCallsign() + + Lobby_UpdateInboxButtons() + + if ( file.shouldAutoOpenFDMenu ) + { + file.shouldAutoOpenFDMenu = false + AdvanceMenu( GetMenu( GetPlaylistMenuName() ) ) + AdvanceMenu( GetMenu( "FDMenu" ) ) + } + } +} + +bool function DLCStoreShouldBeMarkedAsNew() +{ + if ( !IsFullyConnected() ) + return false + + if ( !IsPersistenceAvailable() ) + return false + + bool hasSeenStore = expect bool( GetPersistentVar( "hasSeenStore" ) ) + bool result = (!hasSeenStore) + return result +} + +void function LobbyMenuUpdate( var menu ) +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + while ( GetTopNonDialogMenu() == menu ) + { + bool inPendingOpenInvite = InPendingOpenInvite() + Hud_SetLocked( file.findGameButton, !IsPartyLeader() || inPendingOpenInvite ) + Hud_SetLocked( file.inviteRoomButton, IsOpenInviteVisible() || GetPartySize() > 1 || inPendingOpenInvite ) + Hud_SetLocked( file.inviteFriendsButton, inPendingOpenInvite ) + + bool canGenUp = false + if ( GetUIPlayer() ) + canGenUp = GetPersistentVarAsInt( "xp" ) == GetMaxPlayerXP() && GetGen() < MAX_GEN + + Hud_SetVisible( file.genUpButton, canGenUp ) + Hud_SetEnabled( file.genUpButton, canGenUp ) + + WaitFrame() + } +} + +void function SetNextAutoMatchmakingPlaylist( string playlistName ) +{ + file.nextAutoMatchmakingPlaylist = playlistName +} + +string function GetNextAutoMatchmakingPlaylist() +{ + return file.nextAutoMatchmakingPlaylist +} + +void function PutPlayerInMatchmakingAfterDelay() +{ + Signal( uiGlobal.signalDummy, "PutPlayerInMatchmakingAfterDelay" ) + EndSignal( uiGlobal.signalDummy, "PutPlayerInMatchmakingAfterDelay" ) + EndSignal( uiGlobal.signalDummy, "CancelRestartingMatchmaking" ) + EndSignal( uiGlobal.signalDummy, "LeaveParty" ) + EndSignal( uiGlobal.signalDummy, "OnCloseLobbyMenu" ) + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + if ( AreWeMatchmaking() ) //Party member, party leader is already searching + return + + entity player = GetUIPlayer() + if ( !player ) + return + + string lastPlaylist = expect string( player.GetPersistentVar( "lastPlaylist" ) ) + + //Bump player out of match making if they were playing coliseum and are out of tickets. + if ( ("coliseum" == lastPlaylist) && Player_GetColiseumTicketCount( GetLocalClientPlayer() ) <= 0 ) + { + SetNextAutoMatchmakingPlaylist( "" ) + return + } + + // Need to know if you were a party member before the countdown starts in case you leave + bool wasAPartyMemberThatIsNotLeader = AmIPartyMember() + waitthread WaitBeforeRestartingMatchmaking() + // Only the leader should proceed to start matchmaking + if ( wasAPartyMemberThatIsNotLeader ) + return + + if ( !Console_HasPermissionToPlayMultiplayer() ) + { + ClientCommand( "disconnect" ) + return + } + + string playlistToSearch = lastPlaylist + string nextAutoPlaylist = GetNextAutoMatchmakingPlaylist() + if ( nextAutoPlaylist.len() > 0 ) + playlistToSearch = nextAutoPlaylist + + StartMatchmakingPlaylists( playlistToSearch ) +} + +void function WaitBeforeRestartingMatchmaking() +{ + Signal( uiGlobal.signalDummy, "BypassWaitBeforeRestartingMatchmaking" ) + EndSignal( uiGlobal.signalDummy, "BypassWaitBeforeRestartingMatchmaking" ) + + float timeToWait + + bool isPartyMemberThatIsNotLeader = AmIPartyMember() + SetPutPlayerInMatchmakingAfterDelay( !isPartyMemberThatIsNotLeader ) + + if ( isPartyMemberThatIsNotLeader ) + timeToWait = 99999 //HACK, JFS + else + timeToWait = GetCurrentPlaylistVarFloat( "wait_before_restarting_matchmaking_time", 30.0 ) + + float timeToEnd = Time() + timeToWait + + UpdateTimeToRestartMatchmaking( timeToEnd ) + + OnThreadEnd( + function() : ( ) + { + UpdateTimeToRestartMatchmaking( 0.0 ) + UpdateFooterOptions() + } + ) + + if ( isPartyMemberThatIsNotLeader ) + { + while( Time() < timeToEnd ) //Hack hack, JFS. No appropriate signals for StartMatchmaking() being called. Replace when code gives us notifications about it + { + if ( isPartyMemberThatIsNotLeader != ( AmIPartyMember() ) ) //Party Status changed. Party leader probably left? + break + + if ( AreWeMatchmaking() ) //Need to break out if Party Leader brings us into matchmaking + break + + WaitFrame() + } + + } + else + { + wait timeToWait + } +} + +void function OnLobbyMenu_Close() +{ + Signal( uiGlobal.signalDummy, "OnCloseLobbyMenu" ) +} + +void function OnLobbyMenu_NavigateBack() +{ + if ( ChatroomIsVisibleAndFocused() ) + { + foreach ( button in file.lobbyButtons ) + { + if ( Hud_IsVisible( button ) && Hud_IsEnabled( button ) && !Hud_IsLocked( button ) ) + { + Hud_SetFocused( button ) + return + } + } + } + + if ( InPendingOpenInvite() ) + LeaveOpenInvite() + else + LeaveDialog() +} + +function GameStartTime_Changed() +{ + UpdateGameStartTimeCounter() +} + +function ShowGameSummary_Changed() +{ + if ( level.ui.showGameSummary ) + uiGlobal.EOGOpenInLobby = true +} + +function UpdateGameStartTimeCounter() +{ + if ( level.ui.gameStartTime == null ) + return + + MatchmakingSetSearchText( "#STARTING_IN_LOBBY" ) + MatchmakingSetCountdownTimer( expect float( level.ui.gameStartTime + 0.0 ), true ) + + HideMatchmakingStatusIcons() +} + +bool function MatchmakingStatusShouldShowAsActiveSearch( string matchmakingStatus ) +{ + if ( matchmakingStatus == "#MATCHMAKING_QUEUED" ) + return true + if ( matchmakingStatus == "#MATCHMAKING_ALLOCATING_SERVER" ) + return true + if ( matchmakingStatus == "#MATCHMAKING_MATCH_CONNECTING" ) + return true + + return false +} + +string function GetActiveSearchingPlaylist() +{ + if ( !IsConnected() ) + return "" + if ( !AreWeMatchmaking() ) + return "" + + string matchmakingStatus = GetMyMatchmakingStatus() + if ( !MatchmakingStatusShouldShowAsActiveSearch( matchmakingStatus ) ) + return "" + + string param1 = GetMyMatchmakingStatusParam( 1 ) + return param1 +} + +float function CalcMatchmakingWaitTime() +{ + float result = ((file.matchmakingStartTime > 0.01) ? (Time() - file.matchmakingStartTime) : 0.0) + return result +} + +float function GetMixtapeWaitTimeForPlaylist( string playlistName ) +{ + float maxWaitTime = float( GetPlaylistVarOrUseValue( playlistName, "mixtape_timeout", "0" ) ) + return maxWaitTime +} + +void function UpdateRestartMatchmakingStatus( float time ) +{ + if ( AmIPartyMember() ) + { + MatchmakingSetSearchText( "#MATCHMAKING_WAIT_ON_PARTY_LEADER_RESTARTING_MATCHMAKING" ) + } + else + { + string statusText = "#MATCHMAKING_WAIT_BEFORE_RESTARTING_MATCHMAKING" + string matchmakeNowText = "" + if ( uiGlobal.activeMenu == GetMenu( "SearchMenu" ) ) + matchmakeNowText = Localize( "#MATCHMAKING_WAIT_MATCHMAKE_NOW" ) + MatchmakingSetSearchText( statusText, matchmakeNowText ) + MatchmakingSetCountdownTimer( time, false ) + } +} + +void function UpdateMatchmakingStatus() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + OnThreadEnd( + function() : () + { + printt( "Hiding all matchmaking elems due to UpdateMatchmakingStatus thread ending" ) + + HideMatchmakingStatusIcons() + + MatchmakingSetSearchText( "" ) + MatchmakingSetCountdownTimer( 0.0, true ) + + MatchmakingSetSearchVisible( false ) + MatchmakingSetCountdownVisible( false ) + } + ) + + MatchmakingSetSearchVisible( true ) + MatchmakingSetCountdownVisible( true ) + + var lobbyMenu = GetMenu( "LobbyMenu" ) + var searchMenu = GetMenu( "SearchMenu" ) + var postGameMenu = GetMenu( "PostGameMenu" ) + + string lastActiveSearchingPlaylist + file.matchmakingStartTime = 0.0 + file.etaTime = 0 + file.etaMaxMinutes = int( GetCurrentPlaylistVarOrUseValue( "etaMaxMinutes", file.etaMaxMinutes ) ) + file.lastMixtapeMatchmakingStatus = "" + + while ( true ) + { + int lobbyType = GetLobbyTypeScript() + string matchmakingStatus = GetMyMatchmakingStatus() + bool isConnectingToMatch = matchmakingStatus == "#MATCHMAKING_MATCH_CONNECTING" + + { + string activeSearchingPlaylist = GetActiveSearchingPlaylist() + if ( lastActiveSearchingPlaylist != activeSearchingPlaylist ) + { + if ( activeSearchingPlaylist.len() > 0 ) + { + lastActiveSearchingPlaylist = activeSearchingPlaylist + file.matchmakingStartTime = Time() + } + else + { + lastActiveSearchingPlaylist = "" + file.matchmakingStartTime = 0.0 + } + } + + if ( isConnectingToMatch && (matchmakingStatus != file.lastMixtapeMatchmakingStatus) ) + { + EmitUISound( MATCHMAKING_AUDIO_CONNECTING ) + + int mixtape_version = GetMixtapeMatchmakingVersion() + if ( IsMixtapeVersionNew() ) + LogMixtapeHasNew( mixtape_version ) + } + + file.lastMixtapeMatchmakingStatus = matchmakingStatus + } + + if ( level.ui.gameStartTime != null || lobbyType == eLobbyType.PRIVATE_MATCH ) + { + if ( level.ui.gameStartTimerComplete ) + { + MatchmakingSetSearchText( matchmakingStatus, GetMyMatchmakingStatusParam( 1 ), GetMyMatchmakingStatusParam( 2 ), GetMyMatchmakingStatusParam( 3 ), GetMyMatchmakingStatusParam( 4 ) ) + } + + if ( uiGlobal.activeMenu == searchMenu ) + CloseActiveMenu() + } + else if ( GetTimeToRestartMatchMaking() > 0 ) + { + UpdateRestartMatchmakingStatus( GetTimeToRestartMatchMaking() ) + } + else if ( level.ui.gameStartTime == null ) + { + MatchmakingSetCountdownTimer( 0.0, true ) + MatchmakingSetSearchText( "" ) + HideMatchmakingStatusIcons() + + if ( !IsConnected() || !AreWeMatchmaking() ) + { + if ( uiGlobal.activeMenu == searchMenu ) + CloseActiveMenu() + } + else + { + ShowMatchmakingStatusIcons() + + if ( GetActiveMenu() == lobbyMenu && !IsMenuInMenuStack( searchMenu ) ) + { + CloseAllDialogs() + AdvanceMenu( searchMenu ) + } + + var statusEl = Hud_GetChild( searchMenu, "MatchmakingStatusBig" ) + if ( matchmakingStatus == "#MATCH_NOTHING" ) + { + Hud_Hide( statusEl ) + } + else if ( MatchmakingStatusShouldShowAsActiveSearch( matchmakingStatus ) ) + { + string playlistName = GetMyMatchmakingStatusParam( 1 ) + int etaSeconds = int( GetMyMatchmakingStatusParam( 2 ) ) + int mapIdx = int( GetMyMatchmakingStatusParam( 3 ) ) + int modeIdx = int( GetMyMatchmakingStatusParam( 4 ) ) + string playlistList = GetMyMatchmakingStatusParam( 5 ) + + { + string statusText = Localize( "#MATCHMAKING_PLAYLISTS" ) + RuiSetString( Hud_GetRui( statusEl ), "statusText", statusText ) + for ( int idx = 1; idx <= 5; ++idx ) + RuiSetString( Hud_GetRui( statusEl ), ("bulletPointText" + idx), "" ) + + const int MAX_SHOWN_PLAYLISTS = 9 + array< string > searchingPlaylists = split( playlistList, "," ) + int searchingCount = minint( searchingPlaylists.len(), MAX_SHOWN_PLAYLISTS ) + RuiSetInt( Hud_GetRui( statusEl ), "playlistCount", searchingCount ) + for( int idx = 0; idx < searchingCount; ++idx ) + { + asset playlistThumbnail = GetPlaylistThumbnailImage( searchingPlaylists[idx] ) + RuiSetImage( Hud_GetRui( statusEl ), format( "playlistIcon%d", idx ), playlistThumbnail ) + } + } + + Hud_Show( statusEl ) + + if ( mapIdx > -1 && modeIdx > -1 ) + { + if ( file.preCacheInfo.playlistName != playlistName || file.preCacheInfo.mapIdx != mapIdx || file.preCacheInfo.modeIdx != modeIdx ) + { + file.preCacheInfo.playlistName = playlistName + file.preCacheInfo.mapIdx = mapIdx + file.preCacheInfo.modeIdx = modeIdx + } + } + + string etaStr = "" + if ( !etaSeconds && !isConnectingToMatch ) + { + matchmakingStatus = "#MATCHMAKING_SEARCHING_FOR_MATCH" + } + else + { + int now = int( Time() ) + int etaTime = now + etaSeconds + if ( !file.etaTime || etaTime < file.etaTime ) + file.etaTime = etaTime + + int etaSeconds = file.etaTime - now + if ( etaSeconds <= 0 ) + file.etaTime = etaTime + + etaSeconds = file.etaTime - now + if ( etaSeconds <= 90 ) + { + etaStr = Localize( "#MATCHMAKING_ETA_SECONDS", etaSeconds ) + } + else + { + int etaMinutes = int( ceil( etaSeconds / 60.0 ) ) + if ( etaMinutes < file.etaMaxMinutes ) + etaStr = Localize( "#MATCHMAKING_ETA_MINUTES", etaMinutes ) + else + etaStr = Localize( "#MATCHMAKING_ETA_UNKNOWN", etaMinutes ) + } + } + + MatchmakingSetSearchText( matchmakingStatus, etaStr ) + } + else + { + Hud_Show( statusEl ) + RuiSetString( Hud_GetRui( statusEl ), "statusText", "" ) + RuiSetInt( Hud_GetRui( statusEl ), "playlistCount", 0 ) + } + } + } + + WaitFrameOrUntilLevelLoaded() + } +} + +void function UpdateAnnouncementDialog() +{ + while ( IsLobby() && IsFullyConnected() ) + { + // Only safe on these menus. Not safe if these variables are true because they indicate the search menu or postgame menu are going to be opened. + if ( ( uiGlobal.activeMenu == GetMenu( "LobbyMenu" ) || uiGlobal.activeMenu == GetMenu( "PrivateLobbyMenu" ) ) && !file.putPlayerInMatchmakingAfterDelay && !uiGlobal.EOGOpenInLobby ) + { + entity player = GetUIPlayer() + + // Only initialize here, CloseAnnouncementDialog() handles setting it when closing + if ( uiGlobal.announcementVersionSeen == -1 ) + uiGlobal.announcementVersionSeen = player.GetPersistentVarAsInt( "announcementVersionSeen" ) + + int announcementVersion = GetConVarInt( "announcementVersion" ) + if ( announcementVersion > uiGlobal.announcementVersionSeen ) + { + OpenAnnouncementDialog() + } + else if ( uiGlobal.activeMenu != "AnnouncementDialog" && ShouldShowEmotesAnnouncement( player ) ) + { + OpenCommsIntroDialog() + } + } + + WaitFrame() + } +} + +bool function CurrentMenuIsPVEMenu() +{ + var topMenu = GetTopNonDialogMenu() + if ( topMenu == null ) + return false + + return (uiGlobal.menuData[topMenu].isPVEMenu) +} + +void function RefreshCreditsAvailable( int creditsOverride = -1 ) +{ + entity player = GetUIPlayer() + if ( !IsValid( player ) ) + return + if ( !IsPersistenceAvailable() ) + return + + int credits = creditsOverride >= 0 ? creditsOverride : GetAvailableCredits( GetLocalClientPlayer() ) + string pveTitle = "" + int pveCredits = 0 + bool isPVE = CurrentMenuIsPVEMenu() + if ( isPVE ) + { + TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.editingLoadoutIndex ) + pveCredits = GetAvailableFDUnlockPoints( player, loadout.titanClass ) + pveTitle = GetTitanLoadoutName( loadout ) + } + + foreach ( elem in file.creditsAvailableElems ) + { + SetUIPlayerCreditsInfo( elem, credits, GetLocalClientPlayer().GetXP(), GetGen(), GetLevel(), GetNextLevel( GetLocalClientPlayer() ), isPVE, pveCredits, pveTitle ) + } +} + +void function SetUIPlayerCreditsInfo( var infoElement, int credits, int xp, int gen, int level, int nextLevel, bool isPVE, int pveCredits, string pveTitle ) +{ + var rui = Hud_GetRui( infoElement ) + RuiSetInt( rui, "credits", credits ) + RuiSetString( rui, "nameText", GetPlayerName() ) + + RuiSetBool( rui, "isPVE", isPVE ) + if ( isPVE ) + { + RuiSetInt( rui, "pveCredits", pveCredits ) + RuiSetString( rui, "pveTitle", pveTitle ) + } + + if ( xp == GetMaxPlayerXP() && gen < MAX_GEN ) + { + RuiSetString( rui, "levelText", PlayerXPDisplayGenAndLevel( gen, level ) ) + RuiSetString( rui, "nextLevelText", Localize( "#REGEN_AVAILABLE" ) ) + RuiSetInt( rui, "numLevelPips", GetXPPipsForLevel( level - 1 ) ) + RuiSetInt( rui, "filledLevelPips", GetXPPipsForLevel( level - 1 ) ) + } + else if ( xp == GetMaxPlayerXP() && gen == MAX_GEN ) + { + RuiSetString( rui, "levelText", PlayerXPDisplayGenAndLevel( gen, level ) ) + RuiSetString( rui, "nextLevelText", Localize( "#MAX_GEN" ) ) + RuiSetInt( rui, "numLevelPips", GetXPPipsForLevel( level - 1 ) ) + RuiSetInt( rui, "filledLevelPips", GetXPPipsForLevel( level - 1 ) ) + } + else + { + RuiSetString( rui, "levelText", PlayerXPDisplayGenAndLevel( gen, level ) ) + RuiSetString( rui, "nextLevelText", PlayerXPDisplayGenAndLevel( gen, nextLevel ) ) + RuiSetInt( rui, "numLevelPips", GetXPPipsForLevel( level ) ) + RuiSetInt( rui, "filledLevelPips", GetXPFilledPipsForXP( xp ) ) + } + + CallsignIcon callsignIcon = PlayerCallsignIcon_GetActive( GetLocalClientPlayer() ) + + RuiSetImage( rui, "callsignIcon", callsignIcon.image ) +} + +void function OpenServerBrowser( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + // nothing here yet lol + // look at OpenSelectedPlaylistMenu for advancing to server browser menu probably + AdvanceMenu( GetMenu( "ServerBrowserMenu" ) ) +} + +void function BigPlayButton1_Activate( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + SendOpenInvite( false ) + OpenSelectedPlaylistMenu() +} + +function EnableButton( button ) +{ + Hud_SetEnabled( button, true ) + Hud_Show( button ) +} + +function DisableButton( button ) +{ + Hud_SetEnabled( button, false ) + Hud_Hide( button ) +} + +void function OpenSelectedPlaylistMenu() +{ + if ( Lobby_IsFDMode() ) + { + AdvanceMenu( GetMenu( "FDMenu" ) ) + } + else + { + string playlistMenuName = GetPlaylistMenuName() + AdvanceMenu( GetMenu( playlistMenuName ) ) + } +} + +function UpdateLobbyUI() +{ + if ( uiGlobal.updatingLobbyUI ) + return + uiGlobal.updatingLobbyUI = true + + thread UpdateLobbyType() + thread UpdateMatchmakingStatus() + thread UpdateChatroomThread() + //thread UpdateInviteJoinButton() + thread UpdateInviteFriendsToNetworkButton() + thread UpdatePlayerInfo() + + if ( uiGlobal.menuToOpenFromPromoButton != null ) + { + // Special case because this menu needs a few properties set before opening + + if ( IsStoreMenu( uiGlobal.menuToOpenFromPromoButton ) ) + { + string menuName = expect string( uiGlobal.menuToOpenFromPromoButton._name ) + + void functionref() preOpenfunc = null + if ( uiGlobal.menuToOpenFromPromoButton == GetMenu( "StoreMenu_WeaponSkins" ) ) // Hardcoded special case for now + preOpenfunc = DefaultToDLC11WeaponWarpaintBundle + + OpenStoreMenu( [ menuName ], preOpenfunc ) + } + else + { + AdvanceMenu( uiGlobal.menuToOpenFromPromoButton ) + } + + uiGlobal.menuToOpenFromPromoButton = null + } + else if ( uiGlobal.EOGOpenInLobby ) + { + EOGOpen() + } + + WaitSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + uiGlobal.updatingLobbyUI = false +} + +void function UpdateInviteJoinButton() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + var menu = GetMenu( "LobbyMenu" ) + + while ( true ) + { + if ( DoesCurrentCommunitySupportInvites() ) + ComboButton_SetText( file.inviteRoomButton, Localize( "#MENU_TITLE_INVITE_ROOM" ) ) + else + ComboButton_SetText( file.inviteRoomButton, Localize( "#MENU_TITLE_JOIN_NETWORK" ) ) + + WaitFrame() + } +} + +void function UpdateInviteFriendsToNetworkButton() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + var menu = GetMenu( "LobbyMenu" ) + + while ( true ) + { + bool areInvitesToNetworkNotAllowed = !DoesCurrentCommunitySupportChat() + if ( areInvitesToNetworkNotAllowed || ( IsCurrentCommunityInviteOnly() && !AreWeAdminInCurrentCommunity() ) ) + DisableButton( file.inviteFriendsToNetworkButton ) + else + EnableButton( file.inviteFriendsToNetworkButton ) + + WaitFrame() + } +} + +function UpdateLobbyType() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + var menu = GetMenu( "LobbyMenu" ) + int lobbyType + local lastType + local partySize + local lastPartySize + local debugArray = [ "SOLO", "PARTY_LEADER", "PARTY_MEMBER", "MATCH", "PRIVATE_MATCH" ] // Must match enum + + WaitFrameOrUntilLevelLoaded() + + while ( true ) + { + lobbyType = GetLobbyTypeScript() + partySize = GetPartySize() + + if ( IsConnected() && ((lobbyType != lastType) || (partySize != lastPartySize)) ) + { + if ( lastType == null ) + printt( "Lobby lobbyType changing from:", lastType, "to:", debugArray[lobbyType] ) + else + printt( "Lobby lobbyType changing from:", debugArray[lastType], "to:", debugArray[lobbyType] ) + + local animation = null + + switch ( lobbyType ) + { + case eLobbyType.SOLO: + animation = "SoloLobby" + break + + case eLobbyType.PARTY_LEADER: + animation = "PartyLeaderLobby" + break + + case eLobbyType.PARTY_MEMBER: + animation = "PartyMemberLobby" + break + + case eLobbyType.MATCH: + animation = "MatchLobby" + break + + case eLobbyType.PRIVATE_MATCH: + animation = "PrivateMatchLobby" + break + } + + if ( animation != null ) + { + menu.RunAnimationScript( animation ) + } + + // Force the animation scripts (which have zero duration) to complete before anything can cancel them. + ForceUpdateHUDAnimations() + + lastType = lobbyType + lastPartySize = partySize + } + + WaitFrameOrUntilLevelLoaded() + } +} + +void function UICodeCallback_CommunityUpdated() +{ + Community_CommunityUpdated() + UpdateChatroomUI() +} + +void function UICodeCallback_FactionUpdated() +{ + printt( "Faction changed! to " + GetCurrentFaction() ); +} + +void function UICodeCallback_SetupPlayerListGenElements( table params, int gen, int rank, bool isPlayingRanked, int pilotClassIndex ) +{ + params.image = "" + params.label = "" + params.imageOverlay = "" +} + +float function GetTimeToRestartMatchMaking() +{ + return file.timeToRestartMatchMaking +} + +void function UpdateTimeToRestartMatchmaking( float time )//JFS: This uses UI time instead of server time, which leads to awkwardness in MatchmakingSetCountdownTimer() and the rui involved +{ + file.timeToRestartMatchMaking = time + + if ( time > 0 ) + { + UpdateRestartMatchmakingStatus( time ) + ShowMatchmakingStatusIcons() + } + else + { + MatchmakingSetSearchText( "" ) + MatchmakingSetCountdownTimer( 0.0, true ) + HideMatchmakingStatusIcons() + } +} + +void function HideMatchmakingStatusIcons() +{ + foreach ( element in file.searchIconElems ) + Hud_Hide( element ) + + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "iconVisible", false ) +} + +void function ShowMatchmakingStatusIcons() +{ + //foreach ( element in file.searchIconElems ) + // Hud_Show( element ) + + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "iconVisible", true ) +} + +void function MatchmakingSetSearchVisible( bool state ) +{ + foreach ( el in file.searchTextElems ) + { + //if ( state ) + // Hud_Show( el ) + //else + Hud_Hide( el ) + } + + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "statusVisible", state ) +} + +void function MatchmakingSetSearchText( string searchText, var param1 = "", var param2 = "", var param3 = "", var param4 = "" ) +{ + foreach ( el in file.searchTextElems ) + { + Hud_SetText( el, searchText, param1, param2, param3, param4 ) + } + + foreach ( element in file.matchStatusRuis ) + { + RuiSetBool( Hud_GetRui( element ), "statusHasText", searchText != "" ) + + RuiSetString( Hud_GetRui( element ), "statusText", Localize( searchText, param1, param2, param3, param4 ) ) + } +} + + +void function MatchmakingSetCountdownVisible( bool state ) +{ + foreach ( el in file.matchStartCountdownElems ) + { + //if ( state ) + // Hud_Show( el ) + //else + Hud_Hide( el ) + } + + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "timerVisible", state ) +} + +void function MatchmakingSetCountdownTimer( float time, bool useServerTime = true ) //JFS: useServerTime bool is awkward, comes from level.ui.gameStartTime using server time and UpdateTimeToRestartMatchmaking() uses UI time. +{ + foreach ( element in file.matchStatusRuis ) + { + RuiSetBool( Hud_GetRui( element ), "timerHasText", time != 0.0 ) + RuiSetGameTime( Hud_GetRui( element ), "startTime", Time() ) + RuiSetBool( Hud_GetRui( element ), "useServerTime", useServerTime ) + RuiSetGameTime( Hud_GetRui( element ), "timerEndTime", time ) + } +} + +void function OnLobbyLevelInit() +{ + UpdateCallsignElement( file.callsignCard ) + RefreshCreditsAvailable() +} + +function UpdatePlayerInfo() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + var menu = GetMenu( "LobbyMenu" ) + + WaitFrameOrUntilLevelLoaded() + + while ( true ) + { + RefreshCreditsAvailable() + WaitFrame() + } +} + +void function TryUnlockSRSCallsign() +{ + if ( Script_IsRunningTrialVersion() ) + return + + int numCallsignsToUnlock = 0 + + if ( GetTotalLionsCollected() >= GetTotalLionsInGame() ) + numCallsignsToUnlock = 3 + else if ( GetTotalLionsCollected() >= ACHIEVEMENT_COLLECTIBLES_2_COUNT ) + numCallsignsToUnlock = 2 + else if ( GetTotalLionsCollected() >= ACHIEVEMENT_COLLECTIBLES_1_COUNT ) + numCallsignsToUnlock = 1 + else + numCallsignsToUnlock = 0 + + if ( numCallsignsToUnlock > 0 ) + ClientCommand( "UnlockSRSCallsign " + numCallsignsToUnlock ) +} + +void function SetPutPlayerInMatchmakingAfterDelay( bool value ) +{ + file.putPlayerInMatchmakingAfterDelay = value +} + +void function OnStoreButton_Activate( var button ) +{ + LaunchGamePurchaseOrDLCStore() +} + +void function OnStoreNewReleasesButton_Activate( var button ) +{ + //LaunchGamePurchaseOrDLCStore( [ "StoreMenu", "StoreMenu_NewReleases" ] ) + LaunchGamePurchaseOrDLCStore( [ "StoreMenu", "StoreMenu_WeaponSkins" ] ) +} + +void function OnStoreBundlesButton_Activate( var button ) +{ + LaunchGamePurchaseOrDLCStore( [ "StoreMenu", "StoreMenu_Sales" ] ) +} + +void function OnDpadCommsButton_Activate( var button ) +{ + AdvanceMenu( GetMenu( "EditDpadCommsMenu" ) ) +} + +void function OpenCommsIntroDialog() +{ + DialogData dialogData + dialogData.menu = GetMenu( "AnnouncementDialog" ) + dialogData.header = "#DPAD_COMMS_ANNOUNCEMENT_HEADER" + dialogData.ruiMessage.message = "#DPAD_COMMS_ANNOUNCEMENT" + dialogData.image = $"ui/menu/common/dialog_announcement_1" + + AddDialogButton( dialogData, "#DPAD_COMMS_ANNOUNCEMENT_B1" , OpenDpadCommsMenu ) + AddDialogButton( dialogData, "#DPAD_COMMS_ANNOUNCEMENT_B2" ) + + AddDialogPCBackButton( dialogData ) + AddDialogFooter( dialogData, "#A_BUTTON_ACCEPT" ) + AddDialogFooter( dialogData, "#B_BUTTON_BACK" ) + + OpenDialog( dialogData ) + + ClientCommand( "SetCommsIntroSeen" ) +} + +void function OpenDpadCommsMenu() +{ + OnDpadCommsButton_Activate( null ) +} + +bool function ShouldShowEmotesAnnouncement( entity player ) +{ + if ( !EmotesEnabled() ) + return false + + if ( player.GetPersistentVarAsInt( "numTimesUsedComms" ) > 2 ) + return false + + if ( player.GetPersistentVar( "hasBeenIntroducedToComms" ) ) + return false + + #if !DEV + if ( PlayerGetRawLevel( player ) <= 2 ) + return false + #endif + + return true +} + +void function Lobby_SetFDMode( bool mode ) +{ + file.isFDMode = mode +} + +//Function returns whether lobby is currently in "Frontier Defense" lobby mode. +bool function Lobby_IsFDMode() +{ + return file.isFDMode +} + +void function Lobby_SetAutoFDOpen( bool autoFD ) +{ + Lobby_SetFDMode( autoFD ) + file.shouldAutoOpenFDMenu = autoFD +} + +void function Lobby_SetFDModeBasedOnSearching( string playlistToSearch ) +{ + array< string > searchingPlaylists = split( playlistToSearch, "," ) + + bool isFDMode = false + int searchingCount = searchingPlaylists.len() + for( int idx = 0; idx < searchingCount; ++idx ) + { + isFDMode = isFDMode || IsFDMode( searchingPlaylists[idx] ) + if ( isFDMode ) + break + } + + Lobby_SetFDMode( isFDMode ) +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut new file mode 100644 index 00000000..7ed0d177 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut @@ -0,0 +1,162 @@ +untyped + + +global function MenuMapSelect_Init + +global function InitMapsMenu + +struct { + int mapsPerPage = 21 + int currentMapPage +} file + +// note: this does have a scrolling system in vanilla, but it's honestly really weird and jank and i don't like it +// so for parity with menu_mode_select i'm removing it in favour of a page system + +function MenuMapSelect_Init() +{ + RegisterSignal( "OnCloseMapsMenu" ) +} + +void function InitMapsMenu() +{ + var menu = GetMenu( "MapsMenu" ) + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenMapsMenu ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnCloseMapsMenu ) + + AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_GET_FOCUS, MapButton_Focused ) + AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_LOSE_FOCUS, MapButton_LostFocus ) + AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_CLICK, MapButton_Activate ) + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack, IsNorthstarServer ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward, IsNorthstarServer ) +} + +void function OnOpenMapsMenu() +{ + if ( IsNorthstarServer() ) + file.mapsPerPage = 15 + else + file.mapsPerPage = 21 + + UpdateVisibleMaps() +} + +void function UpdateVisibleMaps() +{ + array<var> buttons = GetElementsByClassname( GetMenu( "MapsMenu" ), "MapButtonClass" ) + array<string> mapsArray = GetPrivateMatchMaps() + + foreach ( button in buttons ) + { + int buttonID = int( Hud_GetScriptID( button ) ) + int mapID = buttonID + ( file.currentMapPage * file.mapsPerPage ) + + if ( buttonID < file.mapsPerPage && mapID < GetPrivateMatchMaps().len() ) + { + string name = mapsArray[ mapID ] + SetButtonRuiText( button, GetMapDisplayName( name ) ) + Hud_SetEnabled( button, true ) + + if ( IsItemInEntitlementUnlock( name ) && IsValid( GetUIPlayer() ) ) + { + if ( IsItemLocked( GetUIPlayer(), name ) && GetCurrentPlaylistVarInt( name + "_available" , 0 ) == 0 ) + { + SetButtonRuiText( button, Localize( "#MAP_LOCKED", Localize( GetMapDisplayName( name ) ) ) ) + } + } + + bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( name, PrivateMatch_GetSelectedMode() ) + Hud_SetLocked( button, !mapSupportsMode ) + + if ( !mapSupportsMode ) + SetButtonRuiText( button, Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetMapDisplayName( name ) ) ) ) + } + else + { + SetButtonRuiText( button, "" ) + Hud_SetEnabled( button, false ) + } + + if ( mapID == level.ui.privatematch_map ) + { + printt( buttonID, mapsArray[buttonID] ) + Hud_SetFocused( button ) + } + } +} + +void function OnCloseMapsMenu() +{ + Signal( uiGlobal.signalDummy, "OnCloseMapsMenu" ) +} + +void function MapButton_Focused( var button ) +{ + int mapID = int( Hud_GetScriptID( button ) ) + ( file.currentMapPage * file.mapsPerPage ) + + var menu = GetMenu( "MapsMenu" ) + var nextMapImage = Hud_GetChild( menu, "NextMapImage" ) + var nextMapName = Hud_GetChild( menu, "NextMapName" ) + var nextMapDesc = Hud_GetChild( menu, "NextMapDesc" ) + + array<string> mapsArray = GetPrivateMatchMaps() + string mapName = mapsArray[ mapID ] + + asset mapImage = GetMapImageForMapName( mapName ) + RuiSetImage( Hud_GetRui( nextMapImage ), "basicImage", mapImage ) + Hud_SetText( nextMapName, GetMapDisplayName( mapName ) ) + + string modeName = PrivateMatch_GetSelectedMode() + bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( mapName, modeName ) + if ( !mapSupportsMode ) + Hud_SetText( nextMapDesc, Localize( "#PRIVATE_MATCH_MAP_NO_MODE_SUPPORT", Localize( GetMapDisplayName( mapName ) ), Localize( GetGameModeDisplayName( modeName ) ) ) ) + else + Hud_SetText( nextMapDesc, GetMapDisplayDesc( mapName ) ) + +} + +void function MapButton_LostFocus( var button ) +{ + HandleLockedCustomMenuItem( GetMenu( "MapsMenu" ), button, [], true ) +} + +void function MapButton_Activate( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + if ( !AmIPartyLeader() && GetPartySize() > 1 ) + return + + array<string> mapsArray = GetPrivateMatchMaps() + int mapID = int( Hud_GetScriptID( button ) ) + string mapName = mapsArray[ mapID + ( file.currentMapPage * file.mapsPerPage ) ] + + printt( mapName, mapID ) + + ClientCommand( "SetCustomMap " + mapName ) + CloseActiveMenu() +} + +void function CycleModesBack( var button ) +{ + if ( file.currentMapPage == 0 ) + return + + file.currentMapPage-- + UpdateVisibleMaps() +} + +void function CycleModesForward( var button ) +{ + if ( ( file.currentMapPage + 1 ) * file.mapsPerPage >= GetPrivateMatchMaps().len() ) + return + + file.currentMapPage++ + UpdateVisibleMaps() +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_match_settings.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_match_settings.nut new file mode 100644 index 00000000..fb6cde1a --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_match_settings.nut @@ -0,0 +1,468 @@ +untyped + +global function InitMatchSettingsMenu + +global function UpdateMatchSettingsForGamemode +global function MatchSettings_FormatPlaylistVarValue + +global const table< string, string > MatchSettings_PlaylistVarLabels = { + match_visibility = "#PM_MATCH_VISIBILITY", + roundscorelimit = "#PM_SCORE_LIMIT", + scorelimit = "#PM_SCORE_LIMIT", + roundtimelimit = "#PM_TIME_LIMIT", + timelimit = "#PM_TIME_LIMIT", + boosts_enabled = "#PM_PILOT_BOOSTS", + earn_meter_pilot_overdrive = "#PM_PILOT_OVERDRIVE", + earn_meter_pilot_multiplier = "#PM_PILOT_EARN", + pilot_health_multiplier = "#PM_PILOT_HEALTH", + respawn_delay = "#PM_PILOT_RESPAWN_DELAY", + riff_titan_availability = "#PM_TITAN_AVAILABILITY", + earn_meter_titan_multiplier = "#PM_TITAN_EARN", +} + +struct PlaylistVarValueFormat +{ + string localizeStr + string formatStr + table< int, string > enumStrs +} + +const string FORMAT_PERCENTAGE = "%d%%" + +struct { + var menu = null + var matchVisibilityButton = null + var scoreLimitButton = null + var scoreLimitLabel = null + var timeLimitButton = null + var timeLimitLabel = null + var pilotBoostsButton = null + var pilotOverdriveButton = null + var pilotEarnButton = null + var pilotEarnLabel = null + var pilotHealthButton = null + var pilotHealthLabel = null + var pilotRespawnDelayButton = null + var pilotRespawnDelayLabel = null + var titanAvailabilityButton = null + var titanEarnButton = null + var titanEarnLabel = null + var gameModeLabel = null + var matchSettingDescLabel = null + string modeSettingsName + bool isModeRoundBased + table< string, PlaylistVarValueFormat > playlistVarValueFormats +} file + +struct +{ + table< string, float > timelimit = { + min = 1.0, + max = 40.0, + step = 1.0, + } + + // pilot + table< string, float > pilot_health_multiplier = { + min = 0.25, + max = 5.0, + step = 0.25, + } + + table< string, float > respawn_delay = { + min = 0.0, + max = 40.0, + step = 0.5, + } + + table< string, float > earn_meter_pilot_multiplier = { + min = 0.25, + max = 5.0, + step = 0.25, + } + + // titan + table< string, float > earn_meter_titan_multiplier = { + min = 0.25, + max = 5.0, + step = 0.25, + } + + // gamemode + table< string, table< string, float > > scorelimit = { + at = { + min = 4000.0, + max = 6000.0, + step = 200.0, + } + ctf = { + min = 2.0, + max = 10.0, + step = 1.0, + }, + lts = { + min = 2.0, + max = 9.0, + step = 1.0, + }, + cp = { + min = 150.0, + max = 750.0, + step = 50.0, + }, + mfd = { + min = 1.0, + max = 25.0, + step = 2.0, + }, + } +} customMatchSettings + +void function InitMatchSettingsMenu() +{ + RegisterUIVarChangeCallback( "privatematch_starting", Privatematch_starting_Changed ) + + var menu = GetMenu( "MatchSettingsMenu" ) + file.menu = menu + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenMatchSettingsMenu ) + AddMenuEventHandler( menu, eUIEvent.MENU_NAVIGATE_BACK, OnMatchSettingsMenu_NavigateBack ) + + file.matchVisibilityButton = Hud_GetChild( menu, "BtnMatchVisibility" ) + SetButtonRuiText( file.matchVisibilityButton, MatchSettings_PlaylistVarLabels["match_visibility"] ) + PlaylistVarValueFormat matchVisibilityFormat = { + enumStrs = { + [MATCHVISIBILITY_PRIVATE] = "#MATCH_VISIBILITY_PRIVATE", + [MATCHVISIBILITY_LOCKED] = "#MATCH_VISIBILITY_LOCKED", + }, + ... + } + file.playlistVarValueFormats["match_visibility"] <- matchVisibilityFormat + foreach ( int enum_, string val in matchVisibilityFormat.enumStrs ) + Hud_DialogList_AddListItem( file.matchVisibilityButton, val, string( enum_ ) ) + + file.scoreLimitButton = Hud_GetChild( menu, "BtnScoreLimit" ) + Hud_AddEventHandler( file.scoreLimitButton, UIE_CHANGE, SetScoreLimitText ) + SetButtonRuiText( Hud_GetChild( file.scoreLimitButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["scorelimit"] ) + file.scoreLimitLabel = Hud_GetChild( menu, "LblScoreLimit" ) + PlaylistVarValueFormat roundScoreLimitFormat = { + localizeStr = "#N_ROUND_WINS", + ... + } + file.playlistVarValueFormats["roundscorelimit"] <- roundScoreLimitFormat + PlaylistVarValueFormat scoreLimitFormat = { + localizeStr = "#N_POINTS", + ... + } + file.playlistVarValueFormats["scorelimit"] <- scoreLimitFormat + + file.timeLimitButton = Hud_GetChild( menu, "BtnTimeLimit" ) + Hud_AddEventHandler( file.timeLimitButton, UIE_CHANGE, SetTimeLimitText ) + SetButtonRuiText( Hud_GetChild( file.timeLimitButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["timelimit"] ) + file.timeLimitLabel = Hud_GetChild( menu, "LblTimeLimit" ) + PlaylistVarValueFormat roundTimeLimitFormat = { + localizeStr = "#N_MINUTE_ROUNDS", + ... + } + file.playlistVarValueFormats["roundtimelimit"] <- roundTimeLimitFormat + PlaylistVarValueFormat timeLimitFormat = { + localizeStr = "#N_MINUTES", + ... + } + file.playlistVarValueFormats["timelimit"] <- timeLimitFormat + + // pilot + + file.pilotBoostsButton = Hud_GetChild( menu, "BtnPilotBoosts" ) + SetButtonRuiText( file.pilotBoostsButton, MatchSettings_PlaylistVarLabels["boosts_enabled"] ) + PlaylistVarValueFormat pilotBoostsFormat = { + enumStrs = { + [eBoostAvailability.Default] = "#PILOT_BOOSTS_DEFAULT", + [eBoostAvailability.Disabled] = "#PILOT_BOOSTS_DISABLED", + }, + ... + } + file.playlistVarValueFormats["boosts_enabled"] <- pilotBoostsFormat + foreach ( int enum_, string val in pilotBoostsFormat.enumStrs ) + Hud_DialogList_AddListItem( file.pilotBoostsButton, val, string( enum_ ) ) + + file.pilotOverdriveButton = Hud_GetChild( menu, "BtnPilotOverdrive" ) + SetButtonRuiText( file.pilotOverdriveButton, MatchSettings_PlaylistVarLabels["earn_meter_pilot_overdrive"] ) + PlaylistVarValueFormat pilotOverdriveFormat = { + enumStrs = { + [ePilotOverdrive.Enabled] = "#PILOT_OVERDRIVE_ON", + [ePilotOverdrive.Disabled] = "#PILOT_OVERDRIVE_OFF", + [ePilotOverdrive.Only] = "#PILOT_OVERDRIVE_ONLY", + }, + ... + } + file.playlistVarValueFormats["earn_meter_pilot_overdrive"] <- pilotOverdriveFormat + foreach ( int enum_, string val in pilotOverdriveFormat.enumStrs ) + Hud_DialogList_AddListItem( file.pilotOverdriveButton, val, string( enum_ ) ) + + file.pilotEarnButton = Hud_GetChild( menu, "BtnPilotEarn" ) + Hud_AddEventHandler( file.pilotEarnButton, UIE_CHANGE, SetPilotEarnText ) + SetButtonRuiText( Hud_GetChild( file.pilotEarnButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["earn_meter_pilot_multiplier"] ) + file.pilotEarnLabel = Hud_GetChild( menu, "LblPilotEarn" ) + PlaylistVarValueFormat pilotEarnFormat = { + formatStr = FORMAT_PERCENTAGE, + ... + } + file.playlistVarValueFormats["earn_meter_pilot_multiplier"] <- pilotEarnFormat + + file.pilotHealthButton = Hud_GetChild( menu, "BtnPilotHealth" ) + Hud_AddEventHandler( file.pilotHealthButton, UIE_CHANGE, SetPilotHealthText ) + SetButtonRuiText( Hud_GetChild( file.pilotHealthButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["pilot_health_multiplier"] ) + file.pilotHealthLabel = Hud_GetChild( menu, "LblPilotHealth" ) + PlaylistVarValueFormat pilotHealthFormat = { + formatStr = FORMAT_PERCENTAGE, + ... + } + file.playlistVarValueFormats["pilot_health_multiplier"] <- pilotHealthFormat + + file.pilotRespawnDelayButton = Hud_GetChild( menu, "BtnPilotRespawnDelay" ) + Hud_AddEventHandler( file.pilotRespawnDelayButton, UIE_CHANGE, SetPilotRespawnDelayText ) + SetButtonRuiText( Hud_GetChild( file.pilotRespawnDelayButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["respawn_delay"] ) + file.pilotRespawnDelayLabel = Hud_GetChild( menu, "LblPilotRespawnDelay" ) + PlaylistVarValueFormat pilotRespawnDelayFormat = { + localizeStr = "#N_SECONDS", + formatStr = "%2.1f", + ... + } + file.playlistVarValueFormats["respawn_delay"] <- pilotRespawnDelayFormat + + // titan + + file.titanAvailabilityButton = Hud_GetChild( menu, "BtnTitanAvailability" ) + SetButtonRuiText( file.titanAvailabilityButton, MatchSettings_PlaylistVarLabels["riff_titan_availability"] ) + PlaylistVarValueFormat titanAvailabilityFormat = { + enumStrs = { + [eTitanAvailability.Default] = "#TITAN_AVAILABILITY_DEFAULT", + [eTitanAvailability.Never] = "#TITAN_AVAILABILITY_NEVER", + }, + ... + } + file.playlistVarValueFormats["riff_titan_availability"] <- titanAvailabilityFormat + foreach ( int enum_, string val in titanAvailabilityFormat.enumStrs ) + Hud_DialogList_AddListItem( file.titanAvailabilityButton, val, string( enum_ ) ) + + file.titanEarnButton = Hud_GetChild( menu, "BtnTitanEarn" ) + Hud_AddEventHandler( file.titanEarnButton, UIE_CHANGE, SetTitanEarnText ) + SetButtonRuiText( Hud_GetChild( file.titanEarnButton, "BtnDropButton" ), MatchSettings_PlaylistVarLabels["earn_meter_titan_multiplier"] ) + file.titanEarnLabel = Hud_GetChild( menu, "LblTitanEarn" ) + PlaylistVarValueFormat titanEarnFormat = { + formatStr = FORMAT_PERCENTAGE, + ... + } + file.playlistVarValueFormats["earn_meter_titan_multiplier"] <- titanEarnFormat + + file.gameModeLabel = Hud_GetChild( menu, "LblModeSubheaderText" ) + + file.matchSettingDescLabel = Hud_GetChild( menu, "LblMenuItemDescription" ) + + AddDescFocusHandler( file.matchVisibilityButton, "#PM_DESC_MATCH_VISIBILITY" ) + AddDescFocusHandler( file.scoreLimitButton, "#PM_DESC_SCORE_LIMIT" ) + AddDescFocusHandler( file.timeLimitButton, "#PM_DESC_TIME_LIMIT" ) + AddDescFocusHandler( file.pilotBoostsButton, "#PM_DESC_PILOT_BOOSTS" ) + AddDescFocusHandler( file.pilotOverdriveButton, "#PM_DESC_PILOT_OVERDRIVE" ) + AddDescFocusHandler( file.pilotEarnButton, "#PM_DESC_PILOT_EARN" ) + AddDescFocusHandler( file.pilotHealthButton, "#PM_DESC_PILOT_HEALTH" ) + AddDescFocusHandler( file.pilotRespawnDelayButton, "#PM_DESC_PILOT_RESPAWN_DELAY" ) + AddDescFocusHandler( file.titanAvailabilityButton, "#PM_DESC_TITAN_AVAILABILITY" ) + AddDescFocusHandler( file.titanEarnButton, "#PM_DESC_TITAN_EARN" ) + + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + AddMenuFooterOption( menu, BUTTON_Y, "#Y_BUTTON_RESTORE_DEFAULTS", "#RESTORE_DEFAULTS", ResetMatchSettingsToDefaultDialog ) +} + +void function SetControlGamemodeAndPlaylistVar( var button, int gamemodeIdx, string playlistVar ) +{ + Hud_SetGamemodeIdx( button, gamemodeIdx ) + Hud_SetPlaylistVarName( button, playlistVar ) +} + +void function UpdateMatchSettingsForGamemode() +{ + file.modeSettingsName = PrivateMatch_GetSelectedMode() + Hud_SetText( file.gameModeLabel, GetGameModeDisplayName( file.modeSettingsName ) ) + + Hud_SetPlaylistVarName( file.matchVisibilityButton, "match_visibility" ) + SetGameModeSettings() + + int gamemodeIdx = expect int( level.ui.privatematch_mode ) + + // pilot + + SetControlGamemodeAndPlaylistVar( file.pilotBoostsButton, gamemodeIdx, "boosts_enabled" ) + SetControlGamemodeAndPlaylistVar( file.pilotOverdriveButton, gamemodeIdx, "earn_meter_pilot_overdrive" ) + SetSliderSettings( file.pilotHealthButton, customMatchSettings.pilot_health_multiplier, gamemodeIdx, "pilot_health_multiplier" ) + SetSliderSettings( file.pilotRespawnDelayButton, customMatchSettings.respawn_delay, gamemodeIdx, "respawn_delay" ) + SetSliderSettings( file.pilotEarnButton, customMatchSettings.earn_meter_pilot_multiplier, gamemodeIdx, "earn_meter_pilot_multiplier" ) + + // titan + + SetControlGamemodeAndPlaylistVar( file.titanAvailabilityButton, gamemodeIdx, "riff_titan_availability" ) + SetSliderSettings( file.titanEarnButton, customMatchSettings.earn_meter_titan_multiplier, gamemodeIdx, "earn_meter_titan_multiplier" ) +} + +void function OnOpenMatchSettingsMenu() +{ + UpdateMatchSettingsForGamemode() + Hud_SetFocused( file.matchVisibilityButton ) +} + +void function OnMatchSettingsMenu_NavigateBack() +{ + CloseActiveMenu() +} + +function Privatematch_starting_Changed() +{ + if ( GetActiveMenu() == file.menu ) + CloseActiveMenu() +} + +void function SetSliderSettings( var button, table< string, float > settings, int gamemodeIdx, string playlistVar ) +{ + Hud_SliderControl_SetStepSize( button, settings.step ) + Hud_SliderControl_SetMin( button, settings.min ) + Hud_SliderControl_SetMax( button, settings.max ) + Hud_SetGamemodeIdx( button, gamemodeIdx ) + Hud_SetPlaylistVarName( button, playlistVar ) + // TODO: the label should be part of the SliderControl, so there is a direct + // reference between the elements that make up the control. See the callbacks + // listening for this event and find that they have to specify their elements + // explicity as opposed to generically referencing releative child element(s). + // XXX: fire the change event to update a label with the current value + Hud_HandleEvent( button, UIE_CHANGE ) +} + +void function SetGameModeSettings() +{ + table< string, float > scoreSettings = { + min = -1.0, + max = -1.0, + step = -1.0, + } + if ( file.modeSettingsName in customMatchSettings.scorelimit ) + scoreSettings = customMatchSettings.scorelimit[file.modeSettingsName] + + int gamemodeIdx = expect int( level.ui.privatematch_mode ) + string scoreLimitVar = "roundscorelimit" + string scoreLimitStr = GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, scoreLimitVar, false ) + string timeLimitVar = "roundtimelimit" + if ( scoreLimitStr.len() ) + { + file.isModeRoundBased = true + } + else + { + file.isModeRoundBased = false + scoreLimitVar = "scorelimit" + scoreLimitStr = GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, scoreLimitVar, false ) + timeLimitVar = "timelimit" + } + + int scoreLimit = scoreLimitStr.len() ? int( scoreLimitStr ) : 100; + if ( scoreSettings.min <= 0 ) + { + scoreSettings.min = max( scoreLimit / 5.0, 1.0 ) + scoreSettings.max = max( scoreLimit + (scoreLimit - scoreSettings.min), 1.0 ) + scoreSettings.step = scoreSettings.min + } + + SetSliderSettings( file.scoreLimitButton, scoreSettings, gamemodeIdx, scoreLimitVar ) + + table< string, float > timeSettings = customMatchSettings.timelimit + SetSliderSettings( file.timeLimitButton, timeSettings, gamemodeIdx, timeLimitVar ) +} + +string function MatchSettings_FormatPlaylistVarValue( string playlistVar, float value ) +{ + if ( !(playlistVar in file.playlistVarValueFormats) ) + return "#" + playlistVar + " unknown" + + PlaylistVarValueFormat fmt = file.playlistVarValueFormats[playlistVar] + if ( fmt.formatStr.len() ) + { + if ( fmt.formatStr == FORMAT_PERCENTAGE ) + return format( fmt.formatStr, int( value * 100 ) ) + else + return Localize( fmt.localizeStr, format( fmt.formatStr, value ) ) + } + + if ( fmt.enumStrs.len() ) + return Localize( fmt.enumStrs[int( value )] ) + + return Localize( fmt.localizeStr, int( value ) ) +} + +void function SetScoreLimitText( var button ) +{ + string playlistVar = file.isModeRoundBased ? "roundscorelimit" : "scorelimit" + float scoreLimit = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( playlistVar, scoreLimit ) + Hud_SetText( file.scoreLimitLabel, labelText ) +} + +void function SetTimeLimitText( var button ) +{ + string playlistVar = file.isModeRoundBased ? "roundtimelimit" : "timelimit" + float timeLimit = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( playlistVar, timeLimit ) + Hud_SetText( file.timeLimitLabel, labelText ) +} + +void function SetPilotHealthText( var button ) +{ + float healthMultiplier = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( "pilot_health_multiplier", healthMultiplier ) + Hud_SetText( file.pilotHealthLabel, labelText ) +} + +void function SetPilotRespawnDelayText( var button ) +{ + float respawnDelay = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( "respawn_delay", respawnDelay ) + Hud_SetText( file.pilotRespawnDelayLabel, labelText ) +} + +void function SetPilotEarnText( var button ) +{ + float earnMultiplier = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( "earn_meter_pilot_multiplier", earnMultiplier ) + Hud_SetText( file.pilotEarnLabel, labelText ) +} + +void function SetTitanEarnText( var button ) +{ + float earnMultiplier = Hud_SliderControl_GetCurrentValue( button ) + string labelText = MatchSettings_FormatPlaylistVarValue( "earn_meter_titan_multiplier", earnMultiplier ) + Hud_SetText( file.titanEarnLabel, labelText ) +} + +void function AddDescFocusHandler( var button, string descText ) +{ + button.s.descText <- descText + Hud_AddEventHandler( button, UIE_GET_FOCUS, MatchSettingsFocusUpdate ) + if ( !Hud_HasChild( button, "BtnDropButton" ) ) + return + + var child = Hud_GetChild( button, "BtnDropButton" ) + child.s.descText <- descText + Hud_AddEventHandler( child, UIE_GET_FOCUS, MatchSettingsFocusUpdate ) + + child = Hud_GetChild( button, "PnlDefaultMark" ) + child.SetColor( [0,0,0,0] ) + Hud_Hide( child ) +} + +void function MatchSettingsFocusUpdate( var button ) +{ + RuiSetString( Hud_GetRui( file.matchSettingDescLabel ), "description", button.s.descText ) +} + +void function ResetMatchSettingsToDefaultDialog( var button ) +{ + ClientCommand( "ResetMatchSettingsToDefault" ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut new file mode 100644 index 00000000..a017fb42 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut @@ -0,0 +1,140 @@ +global function InitModesMenu + +struct { + int currentModePage +} file + +const int MODES_PER_PAGE = 15 + +void function InitModesMenu() +{ + var menu = GetMenu( "ModesMenu" ) + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenModesMenu ) + + AddEventHandlerToButtonClass( menu, "ModeButton", UIE_GET_FOCUS, ModeButton_GetFocus ) + AddEventHandlerToButtonClass( menu, "ModeButton", UIE_CLICK, ModeButton_Click ) + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack, IsNorthstarServer ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward, IsNorthstarServer ) +} + +void function OnOpenModesMenu() +{ + UpdateVisibleModes() + + if ( level.ui.privatematch_mode == 0 ) // set to the first mode if there's no mode focused + Hud_SetFocused( GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" )[ 0 ] ) +} + +void function UpdateVisibleModes() +{ + // ensures that we only ever show enough buttons for the number of modes we have + array<var> buttons = GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" ) + foreach ( var button in buttons ) + { + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } + + array<string> modesArray = GetPrivateMatchModes() + for ( int i = 0; i < MODES_PER_PAGE; i++ ) + { + if ( i + ( file.currentModePage * MODES_PER_PAGE ) >= modesArray.len() ) + break + + int modeIndex = i + ( file.currentModePage * MODES_PER_PAGE ) + SetButtonRuiText( buttons[ i ], GetGameModeDisplayName( modesArray[ modeIndex ] ) ) + + Hud_SetEnabled( buttons[ i ], true ) + Hud_SetVisible( buttons[ i ], true ) + + if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) ) + Hud_SetLocked( buttons[ i ], false ) + else + Hud_SetLocked( buttons[ i ], true ) + + if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeIndex ] ) && !IsNorthstarServer() ) + { + Hud_SetLocked( buttons[ i ], true ) + SetButtonRuiText( buttons[ i ], Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetGameModeDisplayName( modesArray[ modeIndex ] ) ) ) ) + } + } +} + +void function ModeButton_GetFocus( var button ) +{ + int modeId = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE ) + + var menu = GetMenu( "ModesMenu" ) + var nextModeImage = Hud_GetChild( menu, "NextModeImage" ) + var nextModeIcon = Hud_GetChild( menu, "ModeIconImage" ) + var nextModeName = Hud_GetChild( menu, "NextModeName" ) + var nextModeDesc = Hud_GetChild( menu, "NextModeDesc" ) + + array<string> modesArray = GetPrivateMatchModes() + + if ( modeId > modesArray.len() ) + return + + string modeName = modesArray[modeId] + + asset playlistImage = GetPlaylistImage( modeName ) + RuiSetImage( Hud_GetRui( nextModeImage ), "basicImage", playlistImage ) + RuiSetImage( Hud_GetRui( nextModeIcon ), "basicImage", GetPlaylistThumbnailImage( modeName ) ) + Hud_SetText( nextModeName, GetGameModeDisplayName( modeName ) ) + + string mapName = PrivateMatch_GetSelectedMap() + bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( mapName, modeName ) + if ( !mapSupportsMode && !IsNorthstarServer() ) + Hud_SetText( nextModeDesc, Localize( "#PRIVATE_MATCH_MODE_NO_MAP_SUPPORT", Localize( GetGameModeDisplayName( modeName ) ), Localize( GetMapDisplayName( mapName ) ) ) ) + else if ( IsFDMode( modeName ) ) // HACK! + Hud_SetText( nextModeDesc, Localize( "#FD_PLAYERS_DESC", Localize( GetGameModeDisplayHint( modeName ) ) ) ) + else + Hud_SetText( nextModeDesc, GetGameModeDisplayHint( modeName ) ) +} + +void function ModeButton_Click( var button ) +{ + // this never activates on custom servers, but keeping it for parity with official + if ( !AmIPartyLeader() && GetPartySize() > 1 ) + return + + if ( Hud_IsLocked( button ) ) + return + + int modeID = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE ) + + array<string> modesArray = GetPrivateMatchModes() + string modeName = modesArray[ modeID ] + + // on modded servers set us to the first map for that mode automatically + // need this for coliseum mainly which is literally impossible to select without this + if ( IsNorthstarServer() && !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeID ] ) ) + ClientCommand( "SetCustomMap " + GetPrivateMatchMapsForMode( modeName )[ 0 ] ) + + // set it + ClientCommand( "PrivateMatchSetMode " + modeName ) + CloseActiveMenu() +} + +void function CycleModesBack( var button ) +{ + if ( file.currentModePage == 0 ) + return + + file.currentModePage-- + UpdateVisibleModes() +} + +void function CycleModesForward( var button ) +{ + if ( ( file.currentModePage + 1 ) * MODES_PER_PAGE >= GetPrivateMatchModes().len() ) + return + + file.currentModePage++ + UpdateVisibleModes() +}
\ No newline at end of file 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 new file mode 100644 index 00000000..e1ed8991 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut @@ -0,0 +1,30 @@ +global function AddNorthstarConnectWithPasswordMenu + +void function AddNorthstarConnectWithPasswordMenu() +{ + AddMenu( "ConnectWithPasswordMenu", $"resource/ui/menus/connect_password.menu", InitConnectWithPasswordMenu, "#MENU_CONNECT" ) +} + +void function InitConnectWithPasswordMenu() +{ + AddMenuEventHandler( GetMenu( "ConnectWithPasswordMenu" ), eUIEvent.MENU_OPEN, OnConnectWithPasswordMenuOpened ) + AddMenuFooterOption( GetMenu( "ConnectWithPasswordMenu" ), BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + AddButtonEventHandler( Hud_GetChild( GetMenu( "ConnectWithPasswordMenu" ), "ConnectButton" ), UIE_CLICK, ConnectWithPassword ) + RegisterButtonPressedCallback( KEY_ENTER, ConnectWithPassword ) +} + +void function OnConnectWithPasswordMenuOpened() +{ + UI_SetPresentationType( ePresentationType.KNOWLEDGEBASE_SUB ) + + Hud_SetText( Hud_GetChild( GetMenu( "ConnectWithPasswordMenu" ), "Title" ), "#MENU_TITLE_CONNECT_PASSWORD" ) + Hud_SetText( Hud_GetChild( GetMenu( "ConnectWithPasswordMenu" ), "ConnectButton" ), "#MENU_CONNECT_MENU_CONNECT" ) + Hud_SetText( Hud_GetChild( GetMenu( "ConnectWithPasswordMenu" ), "EnterPasswordBox" ), "" ) +} + +void function ConnectWithPassword( var button ) +{ + if ( GetTopNonDialogMenu() == GetMenu( "ConnectWithPasswordMenu" ) ) + thread ThreadedAuthAndConnectToServer( Hud_GetUTF8Text( Hud_GetChild( GetMenu( "ConnectWithPasswordMenu" ), "EnterPasswordBox" ) ) ) +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings.nut new file mode 100644 index 00000000..d39b7774 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings.nut @@ -0,0 +1,140 @@ +global function AddNorthstarCustomMatchSettingsMenu +global function SetNextMatchSettingsCategory + +const string SETTING_ITEM_TEXT = " " // this is long enough to be the same size as the textentry field + +struct { + string currentCategory + + table< int, int > enumRealValues +} file + +void function AddNorthstarCustomMatchSettingsMenu() +{ + AddMenu( "CustomMatchSettingsMenu", $"resource/ui/menus/custom_match_settings.menu", InitNorthstarCustomMatchSettingsMenu, "#MENU_MATCH_SETTINGS" ) +} + +void function SetNextMatchSettingsCategory( string category ) +{ + file.currentCategory = category + print( "Category: " + category ) + + file.enumRealValues.clear() +} + +void function InitNorthstarCustomMatchSettingsMenu() +{ + AddMenuEventHandler( GetMenu( "CustomMatchSettingsMenu" ), eUIEvent.MENU_OPEN, OnNorthstarCustomMatchSettingsMenuOpened ) + AddMenuFooterOption( GetMenu( "CustomMatchSettingsMenu" ), BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + foreach ( var button in GetElementsByClassname( GetMenu( "CustomMatchSettingsMenu" ), "MatchSettingButton" ) ) + { + // it's not possible to clear dialoglists, so we have to hack together stuff that effectively recreates their functionality + Hud_DialogList_AddListItem( button, SETTING_ITEM_TEXT, "prev" ) + Hud_DialogList_AddListItem( button, SETTING_ITEM_TEXT, "main" ) + Hud_DialogList_AddListItem( button, SETTING_ITEM_TEXT, "next" ) + + AddButtonEventHandler( button, UIE_CHANGE, OnSettingButtonPressed ) + } + + foreach ( var textPanel in GetElementsByClassname( GetMenu( "CustomMatchSettingsMenu" ), "MatchSettingTextEntry" ) ) + Hud_AddEventHandler( textPanel, UIE_LOSE_FOCUS, SendTextPanelChanges ) +} + +void function OnNorthstarCustomMatchSettingsMenuOpened() +{ + array<var> buttons = GetElementsByClassname( GetMenu( "CustomMatchSettingsMenu" ), "MatchSettingButton" ) + array<var> textPanels = GetElementsByClassname( GetMenu( "CustomMatchSettingsMenu" ), "MatchSettingTextEntry" ) + + foreach ( var button in buttons ) + { + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } + + foreach ( var textPanel in textPanels ) + { + Hud_SetEnabled( textPanel, false ) + Hud_SetVisible( textPanel, false ) + } + + int i = 0; + foreach ( CustomMatchSettingContainer setting in GetPrivateMatchCustomSettingsForCategory( file.currentCategory ) ) + { + Hud_SetEnabled( buttons[ i ], true ) + Hud_SetVisible( buttons[ i ], true ) + Hud_SetText( buttons[ i ], setting.localizedName ) + Hud_SetDialogListSelectionValue( buttons[ i ], "main" ) + + Hud_SetEnabled( textPanels[ i ], true ) + Hud_SetVisible( textPanels[ i ], true ) + + // manually resolve default gamemode/playlist vars since game won't do it for us if we aren't using GetCurrentPlaylistVar + string gamemode = PrivateMatch_GetSelectedMode() + if ( gamemode != "speedball" ) // hack since lf is weird + gamemode = GetPlaylistGamemodeByIndex( gamemode, 0 ) + + string gamemodeVar = GetGamemodeVarOrUseValue( PrivateMatch_GetSelectedMode(), setting.playlistVar, setting.defaultValue ) + string playlistVar = GetPlaylistVarOrUseValue( PrivateMatch_GetSelectedMode(), setting.playlistVar, setting.defaultValue ) + + if ( playlistVar != gamemodeVar && playlistVar == setting.defaultValue ) + playlistVar = gamemodeVar + + if ( setting.isEnumSetting ) + { + // setup internal state for enums + int enumIndex = int ( max( 0, setting.enumValues.find( playlistVar ) ) ) + + file.enumRealValues[ int( Hud_GetScriptID( textPanels[ i ] ) ) ] <- enumIndex + Hud_SetText( textPanels[ i ], setting.enumNames[ enumIndex ] ) + } + else + Hud_SetText( textPanels[ i ], playlistVar ) + + i++ + } +} + +void function OnSettingButtonPressed( var button ) +{ + CustomMatchSettingContainer setting = GetPrivateMatchCustomSettingsForCategory( file.currentCategory )[ int( Hud_GetScriptID( button ) ) ] + var textPanel = GetElementsByClassname( GetMenu( "CustomMatchSettingsMenu" ), "MatchSettingTextEntry" )[ int( Hud_GetScriptID( button ) ) ] + + if ( setting.isEnumSetting ) + { + string selectionVal = Hud_GetDialogListSelectionValue( button ) + if ( selectionVal == "main" ) + return + + int enumVal = file.enumRealValues[ int( Hud_GetScriptID( button ) ) ] + if ( selectionVal == "next" ) // enum val += 1 + enumVal = ( enumVal + 1 ) % setting.enumValues.len() + else // enum val -= 1 + { + enumVal-- + if ( enumVal == -1 ) + enumVal = setting.enumValues.len() - 1 + } + + file.enumRealValues[ int( Hud_GetScriptID( button ) ) ] = enumVal + Hud_SetText( textPanel, setting.enumNames[ enumVal ] ) + + ClientCommand( "PrivateMatchSetPlaylistVarOverride " + setting.playlistVar + " " + setting.enumValues[ enumVal ] ) + } + else + { + // this doesn't work for some reason + Hud_SetFocused( textPanel ) + } + + Hud_SetDialogListSelectionValue( button, "main" ) +} + +void function SendTextPanelChanges( var textPanel ) +{ + CustomMatchSettingContainer setting = GetPrivateMatchCustomSettingsForCategory( file.currentCategory )[ int( Hud_GetScriptID( textPanel ) ) ] + + // enums don't need to do this + if ( !setting.isEnumSetting ) + ClientCommand( "PrivateMatchSetPlaylistVarOverride " + setting.playlistVar + " " + Hud_GetUTF8Text( textPanel ) ) +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut new file mode 100644 index 00000000..711cbbbc --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut @@ -0,0 +1,68 @@ +global function AddNorthstarCustomMatchSettingsCategoryMenu + +void function AddNorthstarCustomMatchSettingsCategoryMenu() +{ + AddMenu( "CustomMatchSettingsCategoryMenu", $"resource/ui/menus/custom_match_settings_categories.menu", InitNorthstarCustomMatchSettingsCategoryMenu, "#MENU_MATCH_SETTINGS" ) +} + +void function InitNorthstarCustomMatchSettingsCategoryMenu() +{ + AddMenuEventHandler( GetMenu( "CustomMatchSettingsCategoryMenu" ), eUIEvent.MENU_OPEN, OnNorthstarCustomMatchSettingsCategoryMenuOpened ) + AddMenuFooterOption( GetMenu( "CustomMatchSettingsCategoryMenu" ), BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + AddMenuFooterOption( GetMenu( "CustomMatchSettingsCategoryMenu" ), BUTTON_Y, "#Y_BUTTON_RESTORE_DEFAULTS", "#RESTORE_DEFAULTS", ResetMatchSettingsToDefault ) + + foreach ( var button in GetElementsByClassname( GetMenu( "CustomMatchSettingsCategoryMenu" ), "MatchSettingCategoryButton" ) ) + { + AddButtonEventHandler( button, UIE_CLICK, SelectPrivateMatchSettingsCategory ) + + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } +} + +void function OnNorthstarCustomMatchSettingsCategoryMenuOpened() +{ + array<string> categories = GetPrivateMatchSettingCategories() + array<var> buttons = GetElementsByClassname( GetMenu( "CustomMatchSettingsCategoryMenu" ), "MatchSettingCategoryButton" ) + + for ( int i = 0, j = 0; j < categories.len() && i < buttons.len(); i++, j++ ) + { + Hud_SetEnabled( buttons[ i ], false ) + Hud_SetVisible( buttons[ i ], false ) + + // skip gamemode/playlist categories for modes that aren't the current one + // todo this fucking breaks everything lmao + //bool gamemode = categories[ j ].find( "#GAMEMODE_" ) == 0 + //if ( gamemode || categories[ j ].find( "#PL_" ) == 0 ) + //{ + // if ( gamemode ) + // { + // if ( categories[ j ].slice( 10 ) != PrivateMatch_GetSelectedMode() ) + // { + // i-- + // continue + // } + // } + // else if ( categories[ j ].slice( 4 ) != PrivateMatch_GetSelectedMode() ) + // { + // i-- + // continue + // } + //} + + Hud_SetText( buttons[ i ], Localize( categories[ j ] ) + " ->" ) + Hud_SetEnabled( buttons[ i ], true ) + Hud_SetVisible( buttons[ i ], true ) + } +} + +void function SelectPrivateMatchSettingsCategory( var button ) +{ + SetNextMatchSettingsCategory( GetPrivateMatchSettingCategories()[ int( Hud_GetScriptID( button ) ) ] ) + AdvanceMenu( GetMenu( "CustomMatchSettingsMenu" ) ) +} + +void function ResetMatchSettingsToDefault( var button ) +{ + ClientCommand( "ResetMatchSettingsToDefault" ) +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut new file mode 100644 index 00000000..4a56891e --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut @@ -0,0 +1,108 @@ +global function AddNorthstarModMenu +global function AddNorthstarModMenu_MainMenuFooter + +void function AddNorthstarModMenu() +{ + AddMenu( "ModListMenu", $"resource/ui/menus/modlist.menu", InitModMenu ) +} + +void function AddNorthstarModMenu_MainMenuFooter() +{ + AddMenuFooterOption( GetMenu( "MainMenu" ), BUTTON_Y, "#Y_MENU_TITLE_MODS", "#MENU_TITLE_MODS", AdvanceToModListMenu ) +} + +void function AdvanceToModListMenu( var button ) +{ + AdvanceMenu( GetMenu( "ModListMenu" ) ) +} + +void function InitModMenu() +{ + var menu = GetMenu( "ModListMenu" ) + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnModMenuOpened ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + AddMenuFooterOption( menu, BUTTON_Y, "#Y_RELOAD_MODS", "#RELOAD_MODS", ReloadMods ) + + foreach ( var button in GetElementsByClassname( GetMenu( "ModListMenu" ), "ModButton" ) ) + AddButtonEventHandler( button, UIE_GET_FOCUS, OnModMenuButtonFocused ) +} + +void function OnModMenuOpened() +{ + Hud_SetText( Hud_GetChild( GetMenu( "ModListMenu" ), "Title" ), "#MENU_TITLE_MODS" ) + + array<var> buttons = GetElementsByClassname( GetMenu( "ModListMenu" ), "ModButton" ) + + // disable all buttons, we'll enable the ones we need later + foreach ( var button in buttons ) + { + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } + + array<string> modNames = NSGetModNames() + for ( int i = 0; i < modNames.len() && i < buttons.len(); i++ ) + { + Hud_SetEnabled( buttons[ i ], true ) + Hud_SetVisible( buttons[ i ], true ) + + SetButtonRuiText( buttons[ i ], modNames[ i ] + " v" + NSGetModVersionByModName( modNames[ i ] ) ) + } +} + +void function OnModMenuButtonFocused( var button ) +{ + string modName = NSGetModNames()[ int ( Hud_GetScriptID( button ) ) ] + + var rui = Hud_GetRui( Hud_GetChild( GetMenu( "ModListMenu" ), "LabelDetails" ) ) + + RuiSetGameTime( rui, "startTime", -99999.99 ) // make sure it skips the whole animation for showing this + RuiSetString( rui, "headerText", modName ) + RuiSetString( rui, "messageText", FormatModDescription( modName ) ) +} + +string function FormatModDescription( string modName ) +{ + string ret + // version + ret += format( "Version %s\n", NSGetModVersionByModName( modName ) ) + + // download link + string modLink = NSGetModDownloadLinkByModName( modName ) + if ( modLink.len() != 0 ) + ret += format( "Download link: \"%s\"\n", modLink ) + + // load priority + ret += format( "Load Priority: %i\n", NSGetModLoadPriority( modName ) ) + + // todo: add ClientRequired here + + // convars + array<string> modCvars = NSGetModConvarsByModName( modName ) + if ( modCvars.len() != 0 ) + { + ret += "ConVars: " + + for ( int i = 0; i < modCvars.len(); i++ ) + { + if ( i != modCvars.len() - 1 ) + ret += format( "\"%s\", ", modCvars[ i ] ) + else + ret += format( "\"%s\"", modCvars[ i ] ) + } + + ret += "\n" + } + + // description + ret += format( "\n%s\n", NSGetModDescriptionByModName( modName ) ) + + return ret +} + +void function ReloadMods( var button ) +{ + NSReloadMods() + OnModMenuOpened() // temp, until we start doing uiscript_reset here +}
\ 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 new file mode 100644 index 00000000..bbeb0d0b --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -0,0 +1,198 @@ +global function AddNorthstarServerBrowserMenu +global function ThreadedAuthAndConnectToServer + +const int BUTTONS_PER_PAGE = 15 + +struct { + int page = 0 + int lastSelectedServer = 0 +} file + +void function AddNorthstarServerBrowserMenu() +{ + AddMenu( "ServerBrowserMenu", $"resource/ui/menus/server_browser.menu", InitServerBrowserMenu, "#MENU_SERVER_BROWSER" ) +} + +void function InitServerBrowserMenu() +{ + AddMenuEventHandler( GetMenu( "ServerBrowserMenu" ), eUIEvent.MENU_OPEN, OnServerBrowserMenuOpened ) + AddMenuFooterOption( GetMenu( "ServerBrowserMenu" ), BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + AddMenuFooterOption( GetMenu( "ServerBrowserMenu" ), BUTTON_Y, "#Y_REFRESH_SERVERS", "#REFRESH_SERVERS", RefreshServers ) + + foreach ( var button in GetElementsByClassname( GetMenu( "ServerBrowserMenu" ), "ServerButton" ) ) + { + AddButtonEventHandler( button, UIE_GET_FOCUS, OnServerFocused ) + AddButtonEventHandler( button, UIE_CLICK, OnServerSelected ) + } +} + +void function OnServerBrowserMenuOpened() +{ + Hud_SetText( Hud_GetChild( GetMenu( "ServerBrowserMenu" ), "Title" ), "#MENU_TITLE_SERVER_BROWSER" ) + UI_SetPresentationType( ePresentationType.KNOWLEDGEBASE_MAIN ) + + file.page = 0 + // dont rerequest if we came from the connect menu + if ( !NSIsRequestingServerList() && uiGlobal.lastMenuNavDirection != MENU_NAV_BACK ) + { + NSClearRecievedServerList() + NSRequestServerList() + } + + thread WaitForServerListRequest() +} + +void function RefreshServers( var button ) +{ + if ( NSIsRequestingServerList() ) + return + + NSClearRecievedServerList() + NSRequestServerList() + + thread WaitForServerListRequest() +} + +void function WaitForServerListRequest() +{ + var menu = GetMenu( "ServerBrowserMenu" ) + array<var> serverButtons = GetElementsByClassname( menu, "ServerButton" ) + foreach ( var button in serverButtons ) + { + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } + + Hud_SetVisible( Hud_GetChild( menu, "LabelDetails" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextMapImage" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextMapName" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextModeIcon" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextGameModeName" ), false ) + + Hud_SetEnabled( serverButtons[ 0 ], true ) + Hud_SetVisible( serverButtons[ 0 ], true ) + + SetButtonRuiText( serverButtons[ 0 ], "#NS_SERVERBROWSER_WAITINGFORSERVERS" ) + + // wait for request to complete + while ( NSIsRequestingServerList() ) + WaitFrame() + + if ( !NSMasterServerConnectionSuccessful() ) + SetButtonRuiText( serverButtons[ 0 ], "#NS_SERVERBROWSER_CONNECTIONFAILED" ) + else + UpdateShownPage() +} + +void function UpdateShownPage() +{ + var menu = GetMenu( "ServerBrowserMenu" ) + + // hide old ui elements + array<var> serverButtons = GetElementsByClassname( menu, "ServerButton" ) + foreach ( var button in serverButtons ) + { + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } + + Hud_SetFocused( serverButtons[ serverButtons.len() - 1 ] ) + + Hud_SetVisible( Hud_GetChild( menu, "LabelDetails" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextMapImage" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextMapName" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextModeIcon" ), false ) + Hud_SetVisible( Hud_GetChild( menu, "NextGameModeName" ), false ) + + for ( int i = 0; i < NSGetServerCount() && i < serverButtons.len(); i++ ) + { + int serverIndex = file.page * BUTTONS_PER_PAGE + i + + Hud_SetEnabled( serverButtons[ i ], true ) + Hud_SetVisible( serverButtons[ i ], true ) + SetButtonRuiText( serverButtons[ i ], NSGetServerName( serverIndex ) ) + } + + if ( NSGetServerCount() == 0 ) + { + Hud_SetEnabled( serverButtons[ 0 ], true ) + Hud_SetVisible( serverButtons[ 0 ], true ) + SetButtonRuiText( serverButtons[ 0 ], "#NS_SERVERBROWSER_NOSERVERS" ) + } +} + +void function OnServerFocused( var button ) +{ + if ( NSIsRequestingServerList() || !NSMasterServerConnectionSuccessful() || NSGetServerCount() == 0 ) + return + + var menu = GetMenu( "ServerBrowserMenu" ) + int serverIndex = file.page * BUTTONS_PER_PAGE + int ( Hud_GetScriptID( button ) ) + + // text panel + Hud_SetVisible( Hud_GetChild( menu, "LabelDetails" ), true ) + var textRui = Hud_GetRui( Hud_GetChild( menu, "LabelDetails" ) ) + RuiSetGameTime( textRui, "startTime", -99999.99 ) // make sure it skips the whole animation for showing this + RuiSetString( textRui, "messageText", FormatServerDescription( serverIndex ) ) + + // map name/image + string map = NSGetServerMap( serverIndex ) + Hud_SetVisible( Hud_GetChild( menu, "NextMapImage" ), 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 ) ) + + // mode name/image + string mode = NSGetServerPlaylist( serverIndex ) + Hud_SetVisible( Hud_GetChild( menu, "NextModeIcon" ), true ) + RuiSetImage( Hud_GetRui( Hud_GetChild( menu, "NextModeIcon" ) ), "basicImage", GetPlaylistThumbnailImage( mode ) ) + Hud_SetVisible( Hud_GetChild( menu, "NextGameModeName" ), true ) + + string displayName = GetGameModeDisplayName( mode ) + if ( displayName.len() != 0 ) + Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), displayName ) + else + Hud_SetText( Hud_GetChild( menu, "NextGameModeName" ), "#NS_SERVERBROWSER_UNKNOWNMODE" ) +} + +string function FormatServerDescription( int server ) +{ + string ret = "\n\n\n\n" + + ret += NSGetServerName( server ) + "\n" + ret += format( "%i/%i players\n", NSGetServerPlayerCount( server ), NSGetServerMaxPlayerCount( server ) ) + ret += NSGetServerDescription( server ) + "\n" + + return ret +} + +void function OnServerSelected( var button ) +{ + if ( NSIsRequestingServerList() || !NSMasterServerConnectionSuccessful() ) + return + + var menu = GetMenu( "ServerBrowserMenu" ) + int serverIndex = file.page * BUTTONS_PER_PAGE + int ( Hud_GetScriptID( button ) ) + + file.lastSelectedServer = serverIndex + + if ( NSServerRequiresPassword( serverIndex ) ) + AdvanceMenu( GetMenu( "ConnectWithPasswordMenu" ) ) + else + thread ThreadedAuthAndConnectToServer() +} + +void function ThreadedAuthAndConnectToServer( string password = "" ) +{ + if ( NSIsAuthenticatingWithServer() ) + return + + print( "trying to authenticate with server " + NSGetServerName( file.lastSelectedServer ) + " with password " + password ) + NSTryAuthWithServer( file.lastSelectedServer, password ) + + while ( NSIsAuthenticatingWithServer() ) + WaitFrame() + + if ( NSWasAuthSuccessful() ) + NSConnectToAuthedServer() +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut new file mode 100644 index 00000000..b1da22ee --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut @@ -0,0 +1,804 @@ +untyped + +global function MenuPrivateMatch_Init + +global function InitPrivateMatchMenu + +global function HandleLockedCustomMenuItem +global function GetMapImageForMapName + +struct +{ + var menu + + array matchStatusRuis + + array MMDevStringElems + + array teamSlotBackgrounds + array teamSlotBackgroundsNeutral + + var enemyTeamBackgroundPanel + var friendlyTeamBackgroundPanel + var enemyTeamBackground + var friendlyTeamBackground + var enemyPlayersPanel + var friendlyPlayersPanel + + var listFriendlies + var listEnemies + + var nextMapNameLabel + var nextGameModeLabel + + var inviteRoomButton + var inviteFriendsButton + + int inboxHeaderIndex + + int customizeHeaderIndex + var pilotButton + var titanButton + var boostsButton + var storeButton + var factionButton + var bannerButton + var patchButton + var statsButton + var dpadCommsButton + + var playHeader + var customizeHeader + var callsignHeader + var storeHeader + + var startMatchButton + var selectMapButton + var selectModeButton + var matchSettingsButton + + var callsignCard + + var spectatorLabel + + var matchSettingsPanel + + ComboStruct &lobbyComboStruct +} file + +const table<asset> mapImages = +{ + mp_forwardbase_kodai = $"loadscreens/mp_forwardbase_kodai_lobby", + mp_grave = $"loadscreens/mp_grave_lobby", + mp_homestead = $"loadscreens/mp_homestead_lobby", + mp_thaw = $"loadscreens/mp_thaw_lobby", + mp_black_water_canal = $"loadscreens/mp_black_water_canal_lobby", + mp_eden = $"loadscreens/mp_eden_lobby", + mp_drydock = $"loadscreens/mp_drydock_lobby", + mp_crashsite3 = $"loadscreens/mp_crashsite3_lobby", + mp_complex3 = $"loadscreens/mp_complex3_lobby", + mp_angel_city = $"loadscreens/mp_angle_city_r2_lobby", + mp_colony02 = $"loadscreens/mp_colony02_lobby", + mp_glitch = $"loadscreens/mp_glitch_lobby", + mp_lf_stacks = $"loadscreens/mp_stacks_lobby", + mp_lf_meadow = $"loadscreens/mp_meadow_lobby", + mp_lf_deck = $"loadscreens/mp_lf_deck_lobby", + mp_lf_traffic = $"loadscreens/mp_lf_traffic_lobby", + mp_coliseum = $"loadscreens/mp_coliseum_lobby", + mp_coliseum_column = $"loadscreens/mp_coliseum_column_lobby", + mp_relic02 = $"loadscreens/mp_relic02_lobby", + mp_wargames = $"loadscreens/mp_wargames_lobby", + mp_rise = $"loadscreens/mp_rise_lobby", + mp_lf_township = $"loadscreens/mp_lf_township_lobby", + mp_lf_uma = $"loadscreens/mp_lf_uma_lobby", +} + +void function MenuPrivateMatch_Init() +{ + PrecacheHUDMaterial( $"ui/menu/common/menu_background_neutral" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_imc" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_militia" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_imc_blur" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_militia_blur" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_neutral_blur" ) + PrecacheHUDMaterial( $"ui/menu/common/menu_background_blackMarket" ) + PrecacheHUDMaterial( $"ui/menu/rank_menus/ranked_FE_background" ) + + PrecacheHUDMaterial( $"ui/menu/lobby/friendly_slot" ) + PrecacheHUDMaterial( $"ui/menu/lobby/friendly_player" ) + PrecacheHUDMaterial( $"ui/menu/lobby/enemy_slot" ) + PrecacheHUDMaterial( $"ui/menu/lobby/enemy_player" ) + PrecacheHUDMaterial( $"ui/menu/lobby/neutral_slot" ) + PrecacheHUDMaterial( $"ui/menu/lobby/neutral_player" ) + PrecacheHUDMaterial( $"ui/menu/lobby/player_hover" ) + PrecacheHUDMaterial( $"ui/menu/main_menu/motd_background" ) + PrecacheHUDMaterial( $"ui/menu/main_menu/motd_background_happyhour" ) + + AddUICallback_OnLevelInit( OnPrivateLobbyLevelInit ) +} + +asset function GetMapImageForMapName( string mapName ) +{ + if ( mapName in mapImages ) + return mapImages[mapName] + + // no way to convert string => asset for dynamic stuff so + // pain + return expect asset ( compilestring( "return $\"loadscreens/" + mapName + "_lobby\"" )() ) +} + + +void function InitPrivateMatchMenu() +{ + var menu = GetMenu( "PrivateLobbyMenu" ) + file.menu = menu + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnPrivateMatchMenu_Open ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnLobbyMenu_Close ) + AddMenuEventHandler( menu, eUIEvent.MENU_NAVIGATE_BACK, OnLobbyMenu_NavigateBack ) + + file.startMatchButton = Hud_GetChild( menu, "StartMatchButton" ) + Hud_AddEventHandler( file.startMatchButton, UIE_CLICK, OnStartMatchButton_Activate ) + + RegisterUIVarChangeCallback( "privatematch_map", Privatematch_map_Changed ) + RegisterUIVarChangeCallback( "privatematch_mode", Privatematch_mode_Changed ) + RegisterUIVarChangeCallback( "privatematch_starting", Privatematch_starting_Changed ) + RegisterUIVarChangeCallback( "gameStartTime", GameStartTime_Changed ) + + file.matchStatusRuis = GetElementsByClassnameForMenus( "MatchmakingStatusRui", uiGlobal.allMenus ) + file.MMDevStringElems = GetElementsByClassnameForMenus( "MMDevStringClass", uiGlobal.allMenus ) + + file.friendlyPlayersPanel = Hud_GetChild( menu, "MatchFriendliesPanel" ) + file.enemyPlayersPanel = Hud_GetChild( menu, "MatchEnemiesPanel" ) + + file.listFriendlies = Hud_GetChild( file.friendlyPlayersPanel, "ListFriendlies" ) + file.listEnemies = Hud_GetChild( file.enemyPlayersPanel, "ListEnemies" ) + + file.friendlyTeamBackgroundPanel = Hud_GetChild( file.friendlyPlayersPanel, "LobbyFriendlyTeamBackground" ) + file.enemyTeamBackgroundPanel = Hud_GetChild( file.enemyPlayersPanel, "LobbyEnemyTeamBackground" ) + +#if PC_PROG + var panelSize = Hud_GetSize( file.enemyPlayersPanel ) + Hud_SetSize( Hud_GetChild( menu, "LobbyChatBox" ), panelSize[0], panelSize[1] ) +#endif // #if PC_PROG + + file.friendlyTeamBackground = Hud_GetChild( file.friendlyTeamBackgroundPanel, "TeamBackground" ) + file.enemyTeamBackground = Hud_GetChild( file.enemyTeamBackgroundPanel, "TeamBackground" ) + + file.teamSlotBackgrounds = GetElementsByClassnameForMenus( "LobbyTeamSlotBackgroundClass", uiGlobal.allMenus ) + file.teamSlotBackgroundsNeutral = GetElementsByClassnameForMenus( "LobbyTeamSlotBackgroundNeutralClass", uiGlobal.allMenus ) + + file.nextMapNameLabel = Hud_GetChild( menu, "NextMapName" ) + file.nextGameModeLabel = Hud_GetChild( menu, "NextGameModeName" ) + + file.callsignCard = Hud_GetChild( menu, "CallsignCard" ) + + file.spectatorLabel = Hud_GetChild( menu, "SpectatorLabel" ) + + file.matchSettingsPanel = Hud_GetChild( menu, "MatchSettings" ) + + SetupComboButtons( menu, file.startMatchButton, file.listFriendlies ) + + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT", "" ) + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) + + AddMenuFooterOption( menu, BUTTON_Y, "#Y_BUTTON_SWITCH_TEAMS", "#SWITCH_TEAMS", PCSwitchTeamsButton_Activate, CanSwitchTeams ) + AddMenuFooterOption( menu, BUTTON_X, "#X_BUTTON_MUTE", "#MOUSE2_MUTE", null, CanMute ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#RB_TRIGGER_TOGGLE_SPECTATE", "#SPECTATE_TEAM", PCToggleSpectateButton_Activate, CanSwitchTeams ) + + AddMenuVarChangeHandler( "focus", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isFullyConnected", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isPartyLeader", UpdateFooterOptions ) + AddMenuVarChangeHandler( "isPrivateMatch", UpdateFooterOptions ) + #if DURANGO_PROG + AddMenuVarChangeHandler( "DURANGO_canInviteFriends", UpdateFooterOptions ) + AddMenuVarChangeHandler( "DURANGO_isJoinable", UpdateFooterOptions ) + AddMenuVarChangeHandler( "DURANGO_isGameFullyInstalled", UpdateFooterOptions ) + #elseif PS4_PROG + AddMenuVarChangeHandler( "PS4_canInviteFriends", UpdateFooterOptions ) + #elseif PC_PROG + AddMenuVarChangeHandler( "ORIGIN_isEnabled", UpdateFooterOptions ) + AddMenuVarChangeHandler( "ORIGIN_isJoinable", UpdateFooterOptions ) + #endif +} + + +void function OnSelectMapButton_Activate( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + AdvanceMenu( GetMenu( "MapsMenu" ) ) +} + +void function OnSelectModeButton_Activate( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + AdvanceMenu( GetMenu( "ModesMenu" ) ) +} + +void function OnSelectMatchSettings_Activate( var button ) +{ + if ( Hud_IsLocked( button ) ) + return + + if ( !IsNorthstarServer() ) + AdvanceMenu( GetMenu( "MatchSettingsMenu" ) ) + else + AdvanceMenu( GetMenu( "CustomMatchSettingsCategoryMenu" ) ) +} + +void function SetupComboButtons( var menu, var navUpButton, var navDownButton ) +{ + ComboStruct comboStruct = ComboButtons_Create( menu ) + file.lobbyComboStruct = comboStruct + + comboStruct.navUpButton = navUpButton + comboStruct.navDownButton = navDownButton + + int headerIndex = 0 + int buttonIndex = 0 + file.playHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_PRIVATE_MATCH" ) + var selectModeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_SELECT_MODE" ) + file.selectModeButton = selectModeButton + Hud_AddEventHandler( selectModeButton, UIE_CLICK, OnSelectModeButton_Activate ) + var selectMapButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_SELECT_MAP" ) + file.selectMapButton = selectMapButton + Hud_AddEventHandler( selectMapButton, UIE_CLICK, OnSelectMapButton_Activate ) + + file.matchSettingsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_MATCH_SETTINGS" ) + Hud_AddEventHandler( file.matchSettingsButton, UIE_CLICK, OnSelectMatchSettings_Activate ) + + var friendsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_INVITE_FRIENDS" ) + file.inviteFriendsButton = friendsButton + Hud_AddEventHandler( friendsButton, UIE_CLICK, InviteFriendsIfAllowed ) + + headerIndex++ + buttonIndex = 0 + file.customizeHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_LOADOUTS" ) + file.customizeHeaderIndex = headerIndex + var pilotButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_PILOT" ) + file.pilotButton = pilotButton + + Hud_AddEventHandler( pilotButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditPilotLoadoutsMenu" ) ) ) + var titanButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_TITAN" ) + file.titanButton = titanButton + Hud_AddEventHandler( titanButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "EditTitanLoadoutsMenu" ) ) ) + file.boostsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_BOOSTS" ) + Hud_AddEventHandler( file.boostsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "BurnCardMenu" ) ) ) + file.dpadCommsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_COMMS" ) + Hud_AddEventHandler( file.dpadCommsButton, UIE_CLICK, OnDpadCommsButton_Activate ) + + headerIndex++ + buttonIndex = 0 + file.callsignHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_CALLSIGN" ) + file.bannerButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_BANNER" ) + Hud_AddEventHandler( file.bannerButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "CallsignCardSelectMenu" ) ) ) + file.patchButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_PATCH" ) + Hud_AddEventHandler( file.patchButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "CallsignIconSelectMenu" ) ) ) + file.factionButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_FACTION" ) + Hud_AddEventHandler( file.factionButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "FactionChoiceMenu" ) ) ) + file.statsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STATS" ) + Hud_AddEventHandler( file.statsButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "ViewStatsMenu" ) ) ) + + file.callsignCard = Hud_GetChild( menu, "CallsignCard" ) + + headerIndex++ + buttonIndex = 0 + file.storeHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_STORE" ) + file.storeButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_BROWSE" ) + Hud_AddEventHandler( file.storeButton, UIE_CLICK, OnStoreButton_Activate ) + var storeNewReleasesButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_NEW_RELEASES" ) + Hud_AddEventHandler( storeNewReleasesButton, UIE_CLICK, OnStoreNewReleasesButton_Activate ) + var storeBundlesButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_STORE_BUNDLES" ) + Hud_AddEventHandler( storeBundlesButton, UIE_CLICK, OnStoreBundlesButton_Activate ) + + headerIndex++ + buttonIndex = 0 + var settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" ) + var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_TITLE_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 + var knbButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#KNB_MENU_HEADER" ) + Hud_AddEventHandler( knbButton, UIE_CLICK, AdvanceMenuEventHandler( GetMenu( "KnowledgeBaseMenu" ) ) ) + + ComboButtons_Finalize( comboStruct ) +} + + +bool function IsPlayerListFocused() +{ + var focusedItem = GetFocus() + + // The check for GetScriptID existing isn't ideal, but if the text chat text output element has focus it will script error otherwise + return ( (focusedItem != null) && ("GetScriptID" in focusedItem) && (Hud_GetScriptID( focusedItem ) == "PlayerListButton") ) +} + +bool function MatchResultsExist() +{ + return true // TODO +} + +bool function CanSwitchTeams() +{ + return ( GetMenuVarBool( "isPrivateMatch" ) && ( level.ui.privatematch_starting != ePrivateMatchStartState.STARTING ) ) +} + +bool function CanMute() +{ + return IsPlayerListFocused() +} + +void function OnLobbyMenu_Open() +{ + Assert( IsConnected() ) + + UpdatePrivateMatchButtons() + + thread UpdateLobbyUI() + thread LobbyMenuUpdate( GetMenu( "PrivateLobbyMenu" ) ) + + if ( uiGlobal.activeMenu == GetMenu( "PrivateLobbyMenu" ) ) + UI_SetPresentationType( ePresentationType.NO_MODELS ) + + if ( IsFullyConnected() ) + { + entity player = GetUIPlayer() + if ( !IsValid( player ) ) + return + + while ( player.GetPersistentVarAsInt( "initializedVersion" ) < PERSISTENCE_INIT_VERSION ) + { + WaitFrame() + } + + UpdateCallsignElement( file.callsignCard ) + RefreshCreditsAvailable() + + bool emotesAreEnabled = EmotesEnabled() + // "Customize" + { + bool anyNewPilotItems = HasAnyNewPilotItems( player ) + bool anyNewTitanItems = HasAnyNewTitanItems( player ) + bool anyNewBoosts = HasAnyNewBoosts( player ) + bool anyNewCommsIcons = false // emotesAreEnabled ? HasAnyNewDpadCommsIcons( player ) : false + bool anyNewCustomizeHeader = (anyNewPilotItems || anyNewTitanItems || anyNewBoosts || anyNewCommsIcons) + + RuiSetBool( Hud_GetRui( file.customizeHeader ), "isNew", anyNewCustomizeHeader ) + ComboButton_SetNew( file.pilotButton, anyNewPilotItems ) + ComboButton_SetNew( file.titanButton, anyNewTitanItems ) + ComboButton_SetNew( file.boostsButton, anyNewBoosts ) + ComboButton_SetNew( file.dpadCommsButton, anyNewCommsIcons ) + + if ( !emotesAreEnabled ) + { + Hud_Hide( file.dpadCommsButton ) + ComboButtons_ResetColumnFocus( file.lobbyComboStruct ) + } + else + { + Hud_Show( file.dpadCommsButton ) + } + } + + // "Store" + { + bool storeIsNew = DLCStoreShouldBeMarkedAsNew() + RuiSetBool( Hud_GetRui( file.storeHeader ), "isNew", storeIsNew ) + ComboButton_SetNew( file.storeButton, storeIsNew ) + } + + // "Callsign" + { + bool anyNewBanners = HasAnyNewCallsignBanners( player ) + bool anyNewPatches = HasAnyNewCallsignPatches( player ) + bool anyNewFactions = HasAnyNewFactions( player ) + bool anyNewCallsignHeader = (anyNewBanners || anyNewPatches || anyNewFactions) + + RuiSetBool( Hud_GetRui( file.callsignHeader ), "isNew", anyNewCallsignHeader ) + ComboButton_SetNew( file.bannerButton, anyNewBanners ) + ComboButton_SetNew( file.patchButton, anyNewPatches ) + ComboButton_SetNew( file.factionButton, anyNewFactions ) + } + } +} + +void function LobbyMenuUpdate( var menu ) +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + while ( GetTopNonDialogMenu() == menu ) + { + WaitFrame() + } +} + + + +void function OnLobbyMenu_Close() +{ + Signal( uiGlobal.signalDummy, "OnCloseLobbyMenu" ) +} + +void function OnLobbyMenu_NavigateBack() +{ + LeaveDialog() +} + +function GameStartTime_Changed() +{ + printt( "GameStartTime_Changed", level.ui.gameStartTime ) + UpdateGameStartTimeCounter() +} + +function UpdateGameStartTimeCounter() +{ + if ( level.ui.gameStartTime == null ) + { + MatchmakingSetSearchText( "" ) + MatchmakingSetCountdownTimer( 0.0 ) + HideMatchmakingStatusIcons() + return + } + + MatchmakingSetSearchText( "#STARTING_IN_LOBBY" ) + MatchmakingSetCountdownTimer( expect float( level.ui.gameStartTime + 0.0 ) ) + ShowMatchmakingStatusIcons() +} + +function UpdateDebugStatus() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + OnThreadEnd( + function() : () + { + foreach ( elem in file.MMDevStringElems ) + Hud_Hide( elem ) + } + ) + + foreach ( elem in file.MMDevStringElems ) + Hud_Show( elem ) + + while ( true ) + { + local strstr = GetLobbyDevString() + foreach ( elem in file.MMDevStringElems ) + Hud_SetText( elem, strstr ) + + WaitFrameOrUntilLevelLoaded() + } +} + +void function SetMapInfo( string mapName ) +{ + var nextMapImage = Hud_GetChild( file.menu, "NextMapImage" ) + + asset mapImage = GetMapImageForMapName( mapName ) + RuiSetImage( Hud_GetRui( nextMapImage ), "basicImage", mapImage ) + Hud_Show( nextMapImage ) + + Hud_SetText( file.nextMapNameLabel, GetMapDisplayName( mapName ) ) +} + +void function SetModeInfo( string modeName ) +{ + var nextModeIcon = Hud_GetChild( file.menu, "NextModeIcon" ) + RuiSetImage( Hud_GetRui( nextModeIcon ), "basicImage", GetPlaylistThumbnailImage( modeName ) ) + Hud_Show( nextModeIcon ) + + Hud_SetText( file.nextGameModeLabel, GetGameModeDisplayName( modeName ) ) +} + +function Privatematch_map_Changed() +{ + if ( !IsPrivateMatch() ) + return + if ( !IsLobby() ) + return + + string mapName = PrivateMatch_GetSelectedMap() + SetMapInfo( mapName ) +} + +function Privatematch_mode_Changed() +{ + if ( !IsPrivateMatch() ) + return + if ( !IsLobby() ) + return + + string modeName = PrivateMatch_GetSelectedMode() + SetModeInfo( modeName ) + + UpdatePrivateMatchButtons() + UpdateMatchSettingsForGamemode() +} + + +function Privatematch_starting_Changed() +{ + if ( !IsPrivateMatch() ) + return + if ( !IsLobby() ) + return + + UpdatePrivateMatchButtons() + UpdateFooterOptions() +} + + +function UpdatePrivateMatchButtons() +{ + var menu = file.menu + + if ( level.ui.privatematch_starting == ePrivateMatchStartState.STARTING ) + { + RHud_SetText( file.startMatchButton, "#STOP_MATCH" ) + Hud_SetLocked( file.selectMapButton, true ) + Hud_SetLocked( file.selectModeButton, true ) + Hud_SetLocked( file.matchSettingsButton, true ) + Hud_SetLocked( file.inviteFriendsButton, true ) + } + else + { + RHud_SetText( file.startMatchButton, "#START_MATCH" ) + Hud_SetLocked( file.selectMapButton, false ) + Hud_SetLocked( file.selectModeButton, false ) + Hud_SetLocked( file.inviteFriendsButton, false ) + + string modeName = PrivateMatch_GetSelectedMode() + bool settingsLocked = IsFDMode( modeName ) + + if ( settingsLocked && uiGlobal.activeMenu == GetMenu( "MatchSettingsMenu" ) ) + CloseActiveMenu() + + Hud_SetLocked( file.matchSettingsButton, settingsLocked ) + } +} + +function UpdateLobbyUI() +{ + if ( uiGlobal.updatingLobbyUI ) + return + uiGlobal.updatingLobbyUI = true + + thread UpdateLobby() + thread UpdateDebugStatus() + thread UpdatePlayerInfo() + + if ( uiGlobal.EOGOpenInLobby ) + EOGOpen() + + WaitSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + uiGlobal.updatingLobbyUI = false +} + +function UpdateLobby() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + var menu = file.menu + + WaitFrameOrUntilLevelLoaded() + + while ( true ) + { + if ( !IsConnected() ) + { + WaitFrameOrUntilLevelLoaded() + continue + } + + menu.RunAnimationScript( "PrivateMatchLobby" ) + // Force the animation scripts (which have zero duration) to complete before anything can cancel them. + ForceUpdateHUDAnimations() + + UpdatePrivateMatchButtons() + + int gamemodeIdx = expect int( level.ui.privatematch_mode ) + int numPlaylistOverrides = GetPlaylistVarOverridesCount() + string playlistOverridesDesc = "" + for ( int varIdx = 0; varIdx < numPlaylistOverrides; ++varIdx ) + { + // temp fix for playlistoverrides that aren't handled by private match + string varName = GetPlaylistVarOverrideNameByIndex( varIdx ) + + if ( varName in MatchSettings_PlaylistVarLabels ) + { + float varOrigVal = float( GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, varName, false ) ) + float varOverrideVal = float( GetCurrentPlaylistGamemodeByIndexVar( gamemodeIdx, varName, true ) ) + if ( varOrigVal == varOverrideVal && !IsNorthstarServer() ) // stuff seems to break outside of northstar servers since we dont always use private_match playlist + continue + + string label = Localize( MatchSettings_PlaylistVarLabels[varName] ) + ": " + string value = MatchSettings_FormatPlaylistVarValue( varName, varOverrideVal ) + playlistOverridesDesc = playlistOverridesDesc + label + "`2" + value + " `0\n" + } + else + { + foreach ( string category in GetPrivateMatchSettingCategories() ) + { + foreach ( CustomMatchSettingContainer setting in GetPrivateMatchCustomSettingsForCategory( category ) ) + { + if ( setting.playlistVar == varName ) + { + if ( setting.isEnumSetting ) + { + playlistOverridesDesc += Localize( setting.localizedName ) + ": `2" + setting.enumNames[ setting.enumValues.find( expect string ( GetCurrentPlaylistVar( varName ) ) ) ] + "`0\n" + } + else + playlistOverridesDesc += Localize( setting.localizedName ) + ": `2" + GetCurrentPlaylistVar( varName ) + "`0\n" + + break + } + } + } + + // sorta temp: ideally wanna localise playlist var names in the future + } + } + + if ( playlistOverridesDesc.len() ) + { + RuiSetString( Hud_GetRui( file.matchSettingsPanel ), "description", playlistOverridesDesc ) + Hud_Show( file.matchSettingsPanel ) + } + else + { + Hud_Hide( file.matchSettingsPanel ) + } + + if ( GetUIPlayer() && GetPersistentVar( "privateMatchState" ) == 1 ) + Hud_SetVisible( file.spectatorLabel, true ) + else + Hud_SetVisible( file.spectatorLabel, false ) + + WaitFrameOrUntilLevelLoaded() + } +} + +void function OnSettingsButton_Activate( var button ) +{ + if ( level.ui.privatematch_starting == ePrivateMatchStartState.STARTING ) + return + + AdvanceMenu( GetMenu( "MatchSettingsMenu" ) ) +} + + +void function OnPrivateMatchButton_Activate( var button ) +{ + ShowPrivateMatchConnectDialog() + ClientCommand( "match_playlist private_match" ) + ClientCommand( "StartPrivateMatchSearch" ) +} + +void function OnStartMatchButton_Activate( var button ) +{ + if ( AmIPartyLeader() || GetPartySize() == 1 ) + ClientCommand( "PrivateMatchLaunch" ) +} + +function HandleLockedCustomMenuItem( menu, button, tipInfo, hideTip = false ) +{ + array<var> elements = GetElementsByClassname( menu, "HideWhenLocked" ) + var buttonTooltip = Hud_GetChild( menu, "ButtonTooltip" ) + var toolTipLabel = Hud_GetChild( buttonTooltip, "Label" ) + + if ( Hud_IsLocked( button ) && !hideTip ) + { + foreach( elem in elements ) + Hud_Hide( elem ) + + local tipArray = clone tipInfo + tipInfo.resize( 6, null ) + + Hud_SetText( toolTipLabel, tipInfo[0], tipInfo[1], tipInfo[2], tipInfo[3], tipInfo[4], tipInfo[5] ) + + local buttonPos = button.GetAbsPos() + local buttonHeight = button.GetHeight() + local tooltipHeight = buttonTooltip.GetHeight() + local yOffset = ( tooltipHeight - buttonHeight ) / 2.0 + + buttonTooltip.SetPos( buttonPos[0] + button.GetWidth() * 0.9, buttonPos[1] - yOffset ) + Hud_Show( buttonTooltip ) + + return true + } + else + { + foreach( elem in elements ) + Hud_Show( elem ) + Hud_Hide( buttonTooltip ) + } + return false +} + +void function PrivateMatchSwitchTeams( button ) +{ + if ( !IsPrivateMatch() ) + return + + if ( !IsConnected() ) + return + + if ( uiGlobal.activeMenu != file.menu ) + return + + EmitUISound( "Menu_GameSummary_ScreenSlideIn" ) + + ClientCommand( "PrivateMatchSwitchTeams" ) +} + +void function HideMatchmakingStatusIcons() +{ + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "iconVisible", false ) +} + +void function ShowMatchmakingStatusIcons() +{ + foreach ( element in file.matchStatusRuis ) + RuiSetBool( Hud_GetRui( element ), "iconVisible", true ) +} + +void function MatchmakingSetSearchText( string searchText, var param1 = "", var param2 = "", var param3 = "", var param4 = "" ) +{ + foreach ( element in file.matchStatusRuis ) + { + RuiSetBool( Hud_GetRui( element ), "statusHasText", searchText != "" ) + + RuiSetString( Hud_GetRui( element ), "statusText", Localize( searchText, param1, param2, param3, param4 ) ) + } +} + + +void function MatchmakingSetCountdownTimer( float time ) +{ + foreach ( element in file.matchStatusRuis ) + { + RuiSetBool( Hud_GetRui( element ), "timerHasText", time != 0.0 ) + RuiSetGameTime( Hud_GetRui( element ), "timerEndTime", time ) + } +} + + +void function OnPrivateLobbyLevelInit() +{ + UpdateCallsignElement( file.callsignCard ) + RefreshCreditsAvailable() +} + + +function UpdatePlayerInfo() +{ + EndSignal( uiGlobal.signalDummy, "CleanupInGameMenus" ) + + var menu = file.menu + + WaitFrameOrUntilLevelLoaded() + + while ( true ) + { + RefreshCreditsAvailable() + WaitFrame() + } +} + +void function OnPrivateMatchMenu_Open() +{ + Lobby_SetFDMode( false ) + OnLobbyMenu_Open() +}
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut new file mode 100644 index 00000000..acd11237 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -0,0 +1,844 @@ +untyped + +global function InitMainMenuPanel +global function UpdatePromoData + +global function UICodeCallback_GetOnPartyServer +global function UICodeCallback_MainMenuPromosUpdated + +struct +{ + var menu + var panel + array<var> spButtons + array<void functionref()> spButtonFuncs + var mpButton + var fdButton + void functionref() mpButtonActivateFunc = null + var buttonData + array<var> menuButtons + var activeProfile + var serviceStatus + + MainMenuPromos& promoData + var whatsNew + var spotlightPanel + array<var> spotlightButtons + + bool installing = false +} file + +const DEBUG_PERMISSIONS = false + +void function InitMainMenuPanel() +{ + RegisterSignal( "EndShowMainMenuPanel" ) + + file.panel = GetPanel( "MainMenuPanel" ) + file.menu = GetParentMenu( file.panel ) + + AddPanelEventHandler( file.panel, eUIEvent.PANEL_SHOW, OnShowMainMenuPanel ) + AddPanelEventHandler( file.panel, eUIEvent.PANEL_HIDE, OnHideMainMenuPanel ) + + file.menuButtons = GetElementsByClassname( file.menu, "MainMenuButtonClass" ) + AddEventHandlerToButtonClass( file.menu, "MainMenuButtonClass", UIE_CLICK, MainMenuButton_Activate ) + + file.spotlightPanel = Hud_GetChild( file.panel, "SpotlightPanel" ) + file.spotlightButtons = GetElementsByClassname( file.menu, "SpotlightButtonClass" ) + foreach ( button in file.spotlightButtons ) + button.s.link <- "" + AddEventHandlerToButtonClass( file.menu, "SpotlightButtonClass", UIE_CLICK, SpotlightButton_Activate ) + + file.activeProfile = Hud_GetChild( file.panel, "ActiveProfile" ) + file.serviceStatus = Hud_GetRui( Hud_GetChild( file.panel, "ServiceStatus" ) ) + file.whatsNew = Hud_GetRui( Hud_GetChild( file.panel, "WhatsNew" ) ) + + ComboStruct comboStruct = ComboButtons_Create( file.panel ) + + int headerIndex = 0 + int buttonIndex = 0 + var campaignHeader = AddComboButtonHeader( comboStruct, headerIndex, "#GAMEMODE_SOLO" ) + file.spButtons.append( AddComboButton( comboStruct, headerIndex, buttonIndex, "" ) ) + file.spButtonFuncs.append( DoNothing() ) + Hud_AddEventHandler( file.spButtons[buttonIndex], UIE_CLICK, RunSPButton0 ) + buttonIndex++ + file.spButtons.append( AddComboButton( comboStruct, headerIndex, buttonIndex, "" ) ) + file.spButtonFuncs.append( DoNothing() ) + Hud_AddEventHandler( file.spButtons[buttonIndex], UIE_CLICK, RunSPButton1 ) + buttonIndex++ + file.spButtons.append( AddComboButton( comboStruct, headerIndex, buttonIndex, "" ) ) + file.spButtonFuncs.append( DoNothing() ) + Hud_AddEventHandler( file.spButtons[buttonIndex], UIE_CLICK, RunSPButton2 ) + buttonIndex++ + UpdateSPButtons() + + headerIndex++ + buttonIndex = 0 + var multiplayerHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MULTIPLAYER_ALLCAPS" ) + file.mpButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MULTIPLAYER_LAUNCH" ) + Hud_AddEventHandler( file.mpButton, UIE_CLICK, OnPlayMPButton_Activate ) + file.fdButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#GAMEMODE_COOP" ) + Hud_AddEventHandler( file.fdButton, UIE_CLICK, OnPlayFDButton_Activate ) + + headerIndex++ + buttonIndex = 0 + var settingsHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MENU_HEADER_SETTINGS" ) + var controlsButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#CONTROLS" ) + Hud_AddEventHandler( controlsButton, UIE_CLICK, ActivateControlsMenu ) + #if CONSOLE_PROG + var avButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#AUDIO_VIDEO" ) + Hud_AddEventHandler( avButton, UIE_CLICK, ActivateAudioVisualMenu ) + #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 + + var spotlightLargeButton = Hud_GetChild( file.spotlightPanel, "SpotlightLarge" ) + spotlightLargeButton.SetNavLeft( file.spButtons[0] ) + + var spotlightSmall0Button = Hud_GetChild( file.spotlightPanel, "SpotlightSmall0" ) + spotlightSmall0Button.SetNavLeft( file.spButtons[0] ) + + file.buttonData = [] + + #if PC_PROG + file.buttonData.append( { name = "#QUIT", activateFunc = OnQuitButton_Activate } ) + #endif // PC_PROG + + if ( file.buttonData.len() ) + { + comboStruct.navUpButton = file.menuButtons[ expect int( file.buttonData.len() ) - 1 ] + comboStruct.navDownButton = file.menuButtons[0] + + foreach ( button in file.menuButtons ) + button.SetNavRight( spotlightLargeButton ) + } + + comboStruct.navRightButton = spotlightLargeButton + + ComboButtons_Finalize( comboStruct ) + + //AddPanelFooterOption( file.panel, BUTTON_A, "#A_BUTTON_SELECT" ) + //AddPanelFooterOption( file.panel, BUTTON_B, "#B_BUTTON_CLOSE", "#CLOSE" ) + //AddPanelFooterOption( file.panel, BUTTON_BACK, "", "", ClosePostGameMenu ) + + thread TrackInstallProgress() +} + +void function OnShowMainMenuPanel() +{ + Signal( uiGlobal.signalDummy, "EndShowMainMenuPanel" ) + EndSignal( uiGlobal.signalDummy, "EndShowMainMenuPanel" ) + + foreach ( button in file.menuButtons ) + { + int buttonID = int( Hud_GetScriptID( button ) ) + + if ( buttonID < file.buttonData.len() ) + { + if ( "updateFunc" in file.buttonData[buttonID] ) + file.buttonData[buttonID].updateFunc.call( this, button ) + else + Hud_SetEnabled( button, true ) + + RuiSetString( Hud_GetRui( button ), "buttonText", file.buttonData[buttonID].name ) + Hud_Show( button ) + } + else + { + Hud_Hide( button ) + } + } + + #if PS4_PROG + thread EnableCheckPlus() + #endif // PS4_PROG + + UpdateSPButtons() + thread UpdatePlayButton( file.mpButton ) + thread MonitorTrialVersionChange() + + #if DURANGO_PROG + SetLabelRuiText( file.activeProfile, Durango_GetGameDisplayName() ) + Hud_Show( file.activeProfile ) + #endif // DURANGO_PROG + + ExecCurrentGamepadButtonConfig() + ExecCurrentGamepadStickConfig() + + + string defaultButtonRowFocus = "ButtonRow0x0" + bool shouldFocusMultiplayer = GetMenuWasMultiplayerPlayedLast() + if ( shouldFocusMultiplayer ) + defaultButtonRowFocus = "ButtonRow1x0" + + SetPanelDefaultFocus( file.panel, Hud_GetChild( file.panel, defaultButtonRowFocus ) ) + PanelFocusDefault( file.panel ) +} + +void function EnableCheckPlus() +{ + WaitFrame() // ???: doesn't work without a wait + if ( !Ps4_CheckPlus_Allowed() && !IsSingleplayer() ) + { + printt( "scheduling plus check" ) + Ps4_CheckPlus_Schedule() + } +} + +void function OnHideMainMenuPanel() +{ + Signal( uiGlobal.signalDummy, "EndShowMainMenuPanel" ) +} + +void function UpdatePlayButton( var button ) +{ + #if CONSOLE_PROG + bool isOnline + bool hasPermission + bool isFullyInstalled + #endif + + #if DURANGO_PROG + bool isGuest + #elseif PS4_PROG + bool isPSNConnected + bool isOverAge + bool hasPlus + bool hasLatestPatch + #elseif PC_PROG + bool isOriginConnected + bool hasLatestPatch + #endif + + bool isStryderAuthenticated + bool isMPAllowed + bool isLocked + string buttonText + string message + bool isMessageVisible + + while ( GetTopNonDialogMenu() == file.menu ) + { + bool isSpotlightReady = file.promoData.version != 0 ? true : false + Hud_SetVisible( file.spotlightPanel, isSpotlightReady ) + + if ( !Hud_IsFocused( button ) ) + { + RuiSetBool( file.serviceStatus, "isVisible", false ) + WaitFrame() + continue + } + + #if DURANGO_PROG + isFullyInstalled = IsGameFullyInstalled() + isOnline = Console_IsOnline() + isGuest = Durango_IsGuest() + hasPermission = Console_HasPermissionToPlayMultiplayer() + isStryderAuthenticated = IsStryderAuthenticated() + isMPAllowed = IsStryderAllowingMP() + + if ( DEBUG_PERMISSIONS ) + { + printt( "isFullyInstalled:", isFullyInstalled ) + printt( "isOnline:", isOnline ) + printt( "isGuest:", isGuest ) + printt( "hasPermission:", hasPermission ) + printt( "isStryderAuthenticated:", isStryderAuthenticated ) + printt( "isMPAllowedByStryder:", isMPAllowed ) + } + + buttonText = "#MULTIPLAYER_LAUNCH" + message = "" + + if ( !isOnline ) + { + message = "#INTERNET_NOT_FOUND" + file.mpButtonActivateFunc = null + } + else if ( isGuest ) + { + buttonText = "#SWITCH_PROFILE" + message = "#GUESTS_NOT_SUPPORTED" + file.mpButtonActivateFunc = XB1_SwitchAccount + } + else if ( !hasPermission || !isMPAllowed ) + { + message = "#MULTIPLAYER_NOT_AVAILABLE" + file.mpButtonActivateFunc = null + } + else if ( !isStryderAuthenticated ) + { + message = "#CONTACTING_RESPAWN_SERVERS" + file.mpButtonActivateFunc = null + } + else if ( !isFullyInstalled ) + { + //message = "#INSTALL_IN_PROGRESS" + file.mpButtonActivateFunc = LaunchMP + } + else + { + file.mpButtonActivateFunc = LaunchMP + } + + isLocked = file.mpButtonActivateFunc == null ? true : false + Hud_SetLocked( button, isLocked ) + + #elseif PS4_PROG + + isFullyInstalled = IsGameFullyInstalled() + hasLatestPatch = HasLatestPatch() + isOnline = Console_IsOnline() + isPSNConnected = Ps4_PSN_Is_Loggedin() + hasPermission = Console_HasPermissionToPlayMultiplayer() + isOverAge = !PS4_is_NetworkStatusAgeRestriction() + hasPlus = Ps4_CheckPlus_Allowed() + isStryderAuthenticated = IsStryderAuthenticated() + isMPAllowed = IsStryderAllowingMP() + + if ( DEBUG_PERMISSIONS ) + { + printt( "isFullyInstalled:", isFullyInstalled ) + printt( "hasLatestPatch:", hasLatestPatch ) + printt( "isOnline:", isOnline ) + printt( "isPSNConnected:", isPSNConnected ) + printt( "hasPermission:", hasPermission ) + printt( "isOverAge:", isOverAge ) + printt( "hasPlus:", hasPlus ) + printt( "isStryderAuthenticated:", isStryderAuthenticated ) + printt( "isMPAllowedByStryder:", isMPAllowed ) + } + + buttonText = "#MULTIPLAYER_LAUNCH" + message = "" + + if ( !isOnline ) + { + message = "#INTERNET_NOT_FOUND" + file.mpButtonActivateFunc = null + } + else if ( PS4_getUserNetworkingResolution() == PS4_NETWORK_STATUS_UNKNOWN ) + { + message = "#INTERNET_NOT_FOUND" + file.mpButtonActivateFunc = LaunchMP + } + else if ( !hasLatestPatch ) + { + message = "#UPDATE_AVAILABLE" + file.mpButtonActivateFunc = null + } + else if ( PS4_getUserNetworkingResolution() == PS4_NETWORK_STATUS_IN_ERROR ) + { + message = "#PSN_HAD_ERROR" + file.mpButtonActivateFunc = LaunchMP + } + else if ( !isPSNConnected ) + { + buttonText = "#PS4_SIGN_IN" + message = "#PS4_DISCONNECT_NOT_SIGNED_IN_TO_PSN" + file.mpButtonActivateFunc = PS4_PSNSignIn + } + else if ( !isFullyInstalled ) + { + //message = "#INSTALL_IN_PROGRESS" + file.mpButtonActivateFunc = null + } + else if ( !isOverAge ) + { + message = "#MULTIPLAYER_AGE_RESTRICTED" + file.mpButtonActivateFunc = null + } + else if ( !hasPermission || !isMPAllowed ) // A more general permission check. Can fail if not patched, underage profile logged in to another controller, network issue, etc. + { + message = "#MULTIPLAYER_NOT_AVAILABLE" + file.mpButtonActivateFunc = null + } + else if ( !hasPlus ) + { + //buttonText = "#PS4_GET_PLAYSTATION_PLUS" + //message = "#PSN_MUST_BE_PLUS_USER" + //file.mpButtonActivateFunc = PS4_PlusSignUp + // Their is a race on this. The function may not be completed. + + + // The LaunchMP handles this race and will retry/ issue an error dialog if needed. + file.mpButtonActivateFunc = LaunchMP + } + else if ( !isStryderAuthenticated ) + { + message = "#CONTACTING_RESPAWN_SERVERS" + file.mpButtonActivateFunc = null + } + else + { + file.mpButtonActivateFunc = LaunchMP + } + + isLocked = file.mpButtonActivateFunc == null ? true : false + Hud_SetLocked( button, isLocked ) + + #elseif PC_PROG + + hasLatestPatch = Origin_IsUpToDate() + isOriginConnected = Origin_IsEnabled() ? Origin_IsOnline() : true + isStryderAuthenticated = IsStryderAuthenticated() + isMPAllowed = IsStryderAllowingMP() + + if ( DEBUG_PERMISSIONS ) + { + printt( "isOriginConnected:", isOriginConnected ) + printt( "isStryderAuthenticated:", isStryderAuthenticated ) + } + + buttonText = "#MULTIPLAYER_LAUNCH" + message = "" + + if ( !isOriginConnected ) + { + message = "#ORIGIN_IS_OFFLINE" + file.mpButtonActivateFunc = null + } + else if ( !isStryderAuthenticated ) + { + message = "#CONTACTING_RESPAWN_SERVERS" + file.mpButtonActivateFunc = null + } + else if ( !isMPAllowed ) + { + message = "#MULTIPLAYER_NOT_AVAILABLE" + file.mpButtonActivateFunc = null + } + else if ( !hasLatestPatch ) + { + message = "#ORIGIN_UPDATE_AVAILABLE" + file.mpButtonActivateFunc = null + } + else + { + file.mpButtonActivateFunc = LaunchMP + } + + isLocked = file.mpButtonActivateFunc == null ? true : false + Hud_SetLocked( button, isLocked ) + #endif + + if ( Script_IsRunningTrialVersion() && !IsTrialPeriodActive() && file.mpButtonActivateFunc != LaunchGamePurchase ) + { + buttonText = "#MENU_GET_THE_FULL_GAME" + file.mpButtonActivateFunc = LaunchGamePurchase + Hud_SetLocked( button, false ) + message = "" + } + + ComboButton_SetText( file.mpButton, buttonText ) + + //if ( Hud_IsLocked( button ) || buttonText == "#MENU_GET_THE_FULL_GAME" ) + //{ + // ComboButton_SetText( file.fdButton, "" ) + // Hud_SetEnabled( file.fdButton, false ) + //} + //else + //{ + //ComboButton_SetText( file.fdButton, "#MULTIPLAYER_LAUNCH_FD" ) + ComboButton_SetText( file.fdButton, "Launch Northstar" ) // this needs to use localised text at some point when we have a modular way of doing that + Hud_SetEnabled( file.fdButton, true ) + //} + + if ( file.installing ) + message = "" + else if ( message == "" ) + message = GetConVarString( "rspn_motd" ) + + RuiSetString( file.serviceStatus, "messageText", message ) + + isMessageVisible = message != "" ? true : false + RuiSetBool( file.serviceStatus, "isVisible", isMessageVisible ) + + WaitFrame() + //wait 2 + } +} + +void function XB1_SwitchAccount() +{ + Durango_ShowAccountPicker() +} + +void function PS4_PSNSignIn() +{ + Ps4_LoginDialog_Schedule() +} + +void function PS4_PlusSignUp() +{ + if ( Ps4_ScreenPlusDialog_Schedule() ) + { + while ( Ps4_ScreenPlusDialog_Running() ) + WaitFrame() + + if ( Ps4_ScreenPlusDialog_Allowed() ) + Ps4_CheckPlus_Schedule() + } +} + +void function MainMenuButton_Activate( var button ) +{ + int buttonID = int( Hud_GetScriptID( button ) ) + + Assert( file.buttonData ) + + if ( file.buttonData[buttonID].activateFunc ) + file.buttonData[buttonID].activateFunc.call( this ) +} + +void function OnPlayFDButton_Activate( var button ) // repurposed for launching northstar lobby +{ + //if ( file.mpButtonActivateFunc == null ) + // printt( "file.mpButtonActivateFunc is null" ) + + if ( !Hud_IsLocked( button ) )// && file.mpButtonActivateFunc != null ) + { + //Lobby_SetAutoFDOpen( true ) + //// Lobby_SetFDMode( true ) + //thread file.mpButtonActivateFunc() + + //ClientCommand( "setplaylist tdm" ) + //ClientCommand( "map mp_lobby" ) + + NSTryAuthWithLocalServer() + thread TryAuthWithLocalServer() + } +} + +void function TryAuthWithLocalServer() +{ + while ( NSIsAuthenticatingWithServer() ) + WaitFrame() + + if ( NSWasAuthSuccessful() ) + NSCompleteAuthWithLocalServer() + + ClientCommand( "setplaylist tdm" ) + ClientCommand( "map mp_lobby" ) +} + +void function OnPlayMPButton_Activate( var button ) +{ + if ( file.mpButtonActivateFunc == null ) + printt( "file.mpButtonActivateFunc is null" ) + + if ( !Hud_IsLocked( button ) && file.mpButtonActivateFunc != null ) + { + Lobby_SetAutoFDOpen( false ) + // Lobby_SetFDMode( false ) + thread file.mpButtonActivateFunc() + } +} + +void function UICodeCallback_GetOnPartyServer() +{ + uiGlobal.launching = eLaunching.MULTIPLAYER_INVITE + Lobby_SetAutoFDOpen( false ) + // Lobby_SetFDMode( false ) + LaunchGame() +} + +#if PC_PROG +void function OnQuitButton_Activate() +{ + DialogData dialogData + dialogData.header = "#MENU_QUIT_GAME_CONFIRM" + + AddDialogButton( dialogData, "#CANCEL" ) + AddDialogButton( dialogData, "#QUIT", Quit ) + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_CANCEL" ) + + OpenDialog( dialogData ) +} + +void function Quit() +{ + ClientCommand( "quit" ) +} +#endif // #if PC_PROG + +void function MonitorTrialVersionChange() +{ + bool isTrialVersion + bool lastIsTrialVersion = Script_IsRunningTrialVersion() + + while ( GetTopNonDialogMenu() == file.menu ) + { + isTrialVersion = Script_IsRunningTrialVersion() + + if ( isTrialVersion != lastIsTrialVersion ) + UpdateSPButtons() + + lastIsTrialVersion = isTrialVersion + + WaitFrame() + } +} + +void function UpdateSPButtons() +{ + foreach( button in file.spButtons ) + { + ComboButton_SetText( button, "" ) + Hud_SetEnabled( button, false ) + } + + int buttonIndex = 0 + + if ( Script_IsRunningTrialVersion() ) + { + if ( HasStartedGameEver() ) + AddSPButton( buttonIndex, TrainingModeSelect, "#SP_TRIAL_MENU_TRAINING" ) + else + AddSPButton( buttonIndex, LaunchSPNew, "#SP_TRIAL_MENU_TRAINING" ) + buttonIndex++ + + if ( HasStartedGameEver() ) + { + AddSPButton( buttonIndex, TrialMissionSelect, "#SP_TRIAL_MENU_MISSION" ) + buttonIndex++ + } + + AddSPButton( buttonIndex, LaunchGamePurchase, "#MENU_GET_THE_FULL_GAME" ) + buttonIndex++ + } + else + { + if ( HasValidSaveGame() ) + { + AddSPButton( buttonIndex, LaunchSPContinue, "#MENU_CONTINUE_GAME" ) + buttonIndex++ + } + + if ( HasStartedGameEver() ) + { + AddSPButton( buttonIndex, LaunchSPMissionSelect, "#MENU_MISSION_SELECT" ) + buttonIndex++ + } + + AddSPButton( buttonIndex, LaunchSPNew, "#MENU_NEW_GAME" ) + } +} + +void function AddSPButton( int index, void functionref() func, string text ) +{ + var button = file.spButtons[ index ] + ComboButton_SetText( button, text ) + Hud_SetEnabled( button, true ) + file.spButtonFuncs[ index ] = func +} + +void function DoNothing() +{ +} + +void function RunSPButton0( var button ) +{ + void functionref() func = file.spButtonFuncs[ 0 ] + func() +} + +void function RunSPButton1( var button ) +{ + void functionref() func = file.spButtonFuncs[ 1 ] + func() +} + +void function RunSPButton2( var button ) +{ + void functionref() func = file.spButtonFuncs[ 2 ] + func() +} + +void function ActivateControlsMenu( var button ) +{ + #if CONSOLE_PROG + if ( GetEULAVersionAccepted() < 1 ) // Treat as binary for now, as discussed with Preston. + { + if ( uiGlobal.activeMenu == GetMenu( "EULADialog" ) ) + return + + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + uiGlobal.consoleSettingMenu = eConsoleSettingsMenu.CONTROLS_MENU + + EULA_Dialog() + return + } + else + { + AdvanceMenu( GetMenu( "ControlsMenu" ) ) + return + } + #endif + + #if PC_PROG + AdvanceMenu( GetMenu( "ControlsMenu" ) ) + #endif +} + +void function ActivateAudioVisualMenu( var button ) //This is only run on console +{ + if ( GetEULAVersionAccepted() < 1 ) // Treat as binary for now, as discussed with Preston. + { + if ( uiGlobal.activeMenu == GetMenu( "EULADialog" ) ) + return + + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + uiGlobal.consoleSettingMenu = eConsoleSettingsMenu.AUDIO_VISUAL_MENU + + EULA_Dialog() + return + } + else + { + AdvanceMenu( GetMenu( "AudioVideoMenu" ) ) + return + } +} + +void function TrackInstallProgress() +{ + var rui = Hud_GetRui( Hud_GetChild( file.panel, "InstallProgress" ) ) + + while ( GetGameFullyInstalledProgress() < 1.0 ) + { + file.installing = true + RuiSetFloat( rui, "installProgress", GetGameFullyInstalledProgress() ) + wait 0.5 + } + + file.installing = false + RuiSetFloat( rui, "installProgress", 1.0 ) +} + +bool function IsStryderAuthenticated() +{ + return GetConVarInt( "mp_allowed" ) != -1 +} + +bool function IsStryderAllowingMP() +{ + return GetConVarInt( "mp_allowed" ) == 1 +} + +#if PS4_PROG +bool function HasLatestPatch() +{ + int status = PS4_getUserNetworkingErrorStatus() + + if ( status == -2141913073 ) // SCE_NP_ERROR_LATEST_PATCH_PKG_EXIST + return false + + return true +} +#endif // PS4_PROG + +void function UpdatePromoData() +{ + file.promoData = GetMainMenuPromos() + + UpdateWhatsNewData() + UpdateSpotlightData() +} + +void function UICodeCallback_MainMenuPromosUpdated() +{ + printt( "MainMenuPromos updated" ) + + UpdatePromoData() +} + +void function UpdateWhatsNewData() +{ + // file.promoData.newInfo_ImageIndex + //RuiSetString( file.whatsNew, "line1Text", "`2%$rui/menu/main_menu/whats_new_bulletpoint%`0 Updated Live Fire Maps!\n`2%$rui/menu/main_menu/whats_new_bulletpoint%`0 Prime Titans`0 in the Store\n`2%$rui/menu/main_menu/whats_new_bulletpoint% DOUBLE XP`0 weekend!" )//file.promoData.newInfo_Title1 ) + RuiSetString( file.whatsNew, "line1Text", file.promoData.newInfo_Title1 ) + RuiSetString( file.whatsNew, "line2Text", file.promoData.newInfo_Title2 ) + RuiSetString( file.whatsNew, "line3Text", file.promoData.newInfo_Title3 ) + + bool isVisible = true + if ( file.promoData.newInfo_Title1 == "" && file.promoData.newInfo_Title2 == "" && file.promoData.newInfo_Title3 == "" ) + isVisible = false + + RuiSetBool( file.whatsNew, "isVisible", isVisible ) +} + +void function UpdateSpotlightData() +{ + SetSpotlightButtonData( file.spotlightButtons[0], file.promoData.largeButton_Url, file.promoData.largeButton_ImageIndex, file.promoData.largeButton_Title, file.promoData.largeButton_Text ) + SetSpotlightButtonData( file.spotlightButtons[1], file.promoData.smallButton1_Url, file.promoData.smallButton1_ImageIndex, file.promoData.smallButton1_Title ) + SetSpotlightButtonData( file.spotlightButtons[2], file.promoData.smallButton2_Url, file.promoData.smallButton2_ImageIndex, file.promoData.smallButton2_Title ) +} + +void function SetSpotlightButtonData( var button, string link, int imageIndex, string title, string details = "skip" ) +{ + var rui = Hud_GetRui( button ) + + var dataTable = GetDataTable( $"datatable/spotlight_images.rpak" ) + asset image = GetDataTableAsset( dataTable, imageIndex, GetDataTableColumnByName( dataTable, "image" ) ) + + RuiSetImage( rui, "buttonImage", image ) + RuiSetString( rui, "titleText", title ) + + if ( details != "skip" ) + RuiSetString( rui, "detailsText", details ) + + button.s.link = link +} + +void function SpotlightButton_Activate( var button ) +{ + string link = expect string( button.s.link ) + + if ( link == "" ) + return + + if ( link.find( "menu:" ) == 0 ) + { + var menu + + switch ( link ) + { + //case "menu:new": + // menu = GetMenu( "StoreMenu_NewReleases" ) + // break + + case "menu:new": + case "menu:weaponskins": + menu = GetMenu( "StoreMenu_WeaponSkins" ) + break + + //case "menu:limited": + // menu = GetMenu( "StoreMenu_Limited" ) + // break + + case "menu:sales": + menu = GetMenu( "StoreMenu_Sales" ) + break + } + + if ( menu != null ) + { + uiGlobal.menuToOpenFromPromoButton = menu + LaunchMP() + } + } + else + { + LaunchExternalWebBrowser( link, WEBBROWSER_FLAG_MUTEGAME ) + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/ui_utility.gnut b/Northstar.Client/mod/scripts/vscripts/ui/ui_utility.gnut new file mode 100644 index 00000000..02d77795 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/ui_utility.gnut @@ -0,0 +1,634 @@ +untyped + +globalize_all_functions + +global const NUM_EOG_CHALLENGE_BOXES = 6 + +global const WEBBROWSER_FLAG_NONE = 0 +global const WEBBROWSER_FLAG_MUTEGAME = 0x0001 + + +function UtilityUI_Init() +{ + level.getPersistentVarWrapper <- class + { + function GetPersistentVar( variable ) + { + // This looks up the code function GetPersistentVar + return GetPersistentVar( variable ) + } + + function GetPersistentVarAsInt( string variable ) + { + return GetPersistentVarAsInt( variable ) + } + } +} + +int[2] function GetScreenSize() +{ + var screenSize = Hud_GetSize( GetMenu( "MainMenu" ) ) + + int[2] returnSize + returnSize[0] = expect int( screenSize[0] ) + returnSize[1] = expect int( screenSize[1] ) + + return returnSize +} + +float[2] function GetContentScaleFactor( var menu ) +{ + local screenSize = menu.GetSize() + float screenSizeX = expect int( screenSize[0] ).tofloat() + float screenSizeY = expect int( screenSize[1] ).tofloat() + float aspectRatio = screenSizeX / screenSizeY + float[2] scaleFactor + scaleFactor[0] = screenSizeX / ( 1080.0 * aspectRatio ) + scaleFactor[1] = screenSizeY / 1080.0 + return scaleFactor +} + +float function ContentScaledX( int val ) +{ + return (val * GetContentScaleFactor( GetMenu( "MainMenu" ) )[0]) +} + +float function ContentScaledY( int val ) +{ + return (val * GetContentScaleFactor( GetMenu( "MainMenu" ) )[1]) +} + +int function ContentScaledXAsInt( int val ) +{ + float fVal = val * GetContentScaleFactor( GetMenu( "MainMenu" ) )[0] + return int( fVal + 0.5 ) +} + +int function ContentScaledYAsInt( int val ) +{ + float fVal = val * GetContentScaleFactor( GetMenu( "MainMenu" ) )[1] + return int( fVal + 0.5 ) +} + +// Returns string or null +function GetLobbyTeamImage( int team ) +{ + Assert( IsConnected() ) + + if ( !GetLobbyTeamsShowAsBalanced() ) + return null + + if ( GetLobbyTypeScript() == eLobbyType.MATCH || GetLobbyTypeScript() == eLobbyType.PRIVATE_MATCH ) + return GetTeamImage( team ) + + return null +} + +// Returns string or null +function GetLobbyTeamName( int team ) +{ + Assert( IsConnected() ) + + if ( !GetLobbyTeamsShowAsBalanced() ) + return null + + if ( GetLobbyTypeScript() == eLobbyType.MATCH || GetLobbyTypeScript() == eLobbyType.PRIVATE_MATCH ) + return GetTeamName( team ) + + return null +} + +asset function GetTeamImage( int team ) +{ + Assert( team == TEAM_IMC || team == TEAM_MILITIA ) + + if ( team == TEAM_IMC ) + return $"ui/scoreboard_imc_logo" + + return $"ui/scoreboard_mcorp_logo" +} + +function RefreshPersistentFunc( func ) +{ + for ( int i = 0; i < 5; i++ ) + { + // cause who knows when persistent data changes + delaythread( i * 0.1 ) RunFuncWithConnectedCheck( func ) + } +} + +function RunFuncWithConnectedCheck( func ) +{ + if ( !IsConnected() ) + return + func() +} + +string function GetActiveLevel() +{ + // The level load callbacks overlap with the level init/shutdown callbacks, so we track each one separately. + if ( uiGlobal.loadedLevel != "" ) + return uiGlobal.loadedLevel + return uiGlobal.loadingLevel +} + +function HandleLockedMenuItem( menu, button, hideTip = false ) +{ + /*array<var> elements = GetElementsByClassname( menu, "HideWhenLocked" ) + var buttonTooltip = Hud_GetChild( menu, "ButtonTooltip" ) + //var buttonTooltip = GetElementsByClassname( menu, "ButtonTooltip" )[0] + var toolTipLabel = Hud_GetChild( buttonTooltip, "Label" ) + + entity player = GetUIPlayer() + if ( player == null ) + return + + if ( "ref" in button.s && button.s.ref != null && IsItemLocked( player, expect string( button.s.ref ) ) && !hideTip ) + { + foreach( elem in elements ) + Hud_Hide( elem ) + + Hud_SetText( toolTipLabel, "#UNLOCKED_AT_LEVEL", g_unlocks[ expect string( button.s.ref ) ].unlockLevel, "" ) + + local buttonPos = Hud_GetAbsPos( button ) + local buttonHeight = Hud_GetHeight( button ) + local tooltipHeight = Hud_GetHeight( buttonTooltip ) + local yOffset = ( tooltipHeight - buttonHeight ) / 2.0 + + Hud_SetPos( buttonTooltip, buttonPos[0] + Hud_GetWidth( button ) * 0.9, buttonPos[1] - yOffset ) + Hud_Show( buttonTooltip ) + + return true + } + else + { + foreach( elem in elements ) + Hud_Show( elem ) + Hud_Hide( buttonTooltip ) + } + return false*/ +} + +// No way to test a named element exists so this is a workaround +var function GetSingleElementByClassname( var menu, string classname ) +{ + array<var> elems = GetElementsByClassname( menu, classname ) + + if ( elems.len() ) + { + Assert( elems.len() == 1 ) + return elems[0] + } + + return null +} + +array function GetElementsByClassnameForMenus( string classname, array menus ) +{ + array elements = [] + + foreach ( menu in menus ) + elements.extend( GetElementsByClassname( menu, classname ) ) + + return elements +} + +function WaitFrameOrUntilLevelLoaded() +{ + WaitFrame() + + while ( uiGlobal.loadedLevel == "" ) + WaitFrame() +} + +bool function IsPlayerAlone() +{ + int myTeam = GetTeam() + if ( GetTeamSize( myTeam ) <= 1 ) + return true + + return false +} + +bool function PartyHasMembers() +{ + if ( GetPartySize() > 1 ) + return true + + return false +} + +bool function AmIPartyMember() +{ + return ( PartyHasMembers() && !AmIPartyLeader() ) +} + +string function GetGameModeDisplayName( string mode ) +{ + string displayName = GetGamemodeVarOrUseValue( mode, "name", (mode in GAMETYPE_TEXT) ? GAMETYPE_TEXT[mode] : "" ) + + // modification to support playlists too + if ( displayName == "" ) + return GetPlaylistVarOrUseValue( mode, "name", "" ) + + return displayName +} + +string function GetGameModeDisplayDesc( string mode ) //TODO: Make this support attack/defend descriptions +{ + string displayDesc = GetGamemodeVarOrUseValue( mode, "description", (mode in GAMETYPE_DESC) ? GAMETYPE_DESC[mode] : "" ) + + // modification to support playlists too + if ( displayDesc == "" ) + { + displayDesc = Localize( GetPlaylistVarOrUseValue( mode, "description", "" ) ) + + if ( displayDesc.find( "^" ) != null ) + displayDesc = displayDesc.slice( 0, displayDesc.find( "^" ) ) + } + + return displayDesc +} + +string function GetGameModeDisplayHint( string mode ) //TODO: Make this support attack/defend descriptions +{ + string displayDesc = GetGamemodeVarOrUseValue( mode, "hint", GetGameModeDisplayDesc( mode ) ) + return displayDesc +} + +asset function GetGameModeDisplayImage( string mode ) +{ + return GAMETYPE_ICON[ mode ] +} + +array<int> function ColorStringToArray( string colorString ) +{ + array<string> tokens = split( colorString, " " ) + + Assert( tokens.len() >= 3 && tokens.len() <= 4 ) + + array<int> colorArray + foreach ( token in tokens ) + colorArray.append( int( token ) ) + + return colorArray +} + +array<int> function GetGameModeDisplayColor( string mode ) +{ + array<int> displayColor = ColorStringToArray( GetGamemodeVarOrUseValue( mode, "color", "" ) ) + if ( displayColor.len() == 0 ) + displayColor = GameMode_GetColor( mode ) + + return displayColor +} + +float function GetCurrentPlaylistVarFloat( val, useVal ) +{ + expect string( val ) + expect float( useVal ) + + local result = GetCurrentPlaylistVarOrUseValue( val, useVal ) + if ( result == null ) + return 0.0 + + return float( result ) +} + +// ???: player not used +bool function PlayerProgressionAllowed( player = null ) +{ + if ( IsPrivateMatch() ) + return false + + return true +} + +entity function GetUIPlayer() +{ + if ( !IsFullyConnected() ) + return null + + return GetLocalClientPlayer() +} + + +int function GetLobbyTypeScript() +{ + if ( GetLobbyType() == "game" ) + { + if ( IsPrivateMatch() ) + return eLobbyType.PRIVATE_MATCH + else + return eLobbyType.MATCH + } + else + { + if ( AmIPartyLeader() ) + { + if ( IsPlayerAlone() ) // TODO: This function was changed to only check your team size, not the true player count, so you'll probably now have access to some menus you shouldn't be able to. + return eLobbyType.SOLO + else + return eLobbyType.PARTY_LEADER + } + else + { + return eLobbyType.PARTY_MEMBER + } + } + + unreachable +} + +function AddMenu( blockName, asset resourceFile, void functionref() initFunc = null, string displayName = "" ) +{ + local menu = CreateMenu( "menu_" + blockName, resourceFile ) + uiGlobal.menus[blockName] <- menu + menu.SetHudName( blockName ) + + if ( displayName != "" ) + menu.SetDisplayName( displayName ) + else + menu.SetDisplayName( blockName ) + + uiGlobal.allMenus.append( menu ) + + MenuDef defaultMenuData + uiGlobal.menuData[ menu ] <- defaultMenuData + + if ( initFunc != null ) + uiGlobal.menuData[ menu ].initFunc = initFunc + + return menu +} + +function AddMenu_WithCreateFunc( blockName, asset resourceFile, void functionref() initFunc, createMenuFunc ) +{ + local menu = createMenuFunc( "menu_" + blockName, resourceFile ) + uiGlobal.menus[blockName] <- menu + menu.SetHudName( blockName ) + + uiGlobal.allMenus.append( menu ) + + MenuDef defaultMenuData + uiGlobal.menuData[ menu ] <- defaultMenuData + + if ( initFunc != null ) + uiGlobal.menuData[ menu ].initFunc = initFunc + + return menu +} + +function AddPanel( var menu, string panelName, void functionref() initFunc = null ) +{ + //printt( "AddPanel called, panelName:", panelName ) + + var panel = Hud_GetChild( menu, panelName ) + uiGlobal.panels[ panelName ] <- panel + uiGlobal.allPanels.append( panel ) + + PanelDef defaultPanelData + uiGlobal.panelData[ panel ] <- defaultPanelData + + if ( initFunc != null ) + uiGlobal.panelData[ panel ].initFunc = initFunc + + return panel +} + +function AddSubmenu( blockName, asset resourceFile, void functionref() initFunc = null ) +{ + local menu = CreateMenu( "menu_" + blockName, resourceFile ) + uiGlobal.menus[blockName] <- menu + menu.SetHudName( blockName ) + menu.SetType( "submenu" ) + + menu.s.newFocusRef <- null + + uiGlobal.allMenus.append( menu ) + + MenuDef defaultMenuData + uiGlobal.menuData[ menu ] <- defaultMenuData + + if ( initFunc != null ) + uiGlobal.menuData[ menu ].initFunc = initFunc + + return menu +} + +function ClearButton( button ) +{ + Hud_SetText( button, "" ) + Hud_SetEnabled( button, false ) + Hud_SetLocked( button, false ) + Hud_SetNew( button, false ) + Hud_SetSelected( button, false ) +} + +void function HudElem_SetText( var hudelem, string text ) +{ + hudelem.SetText( text ) +} + +void function SetButtonRuiText( var elem, string text ) +{ + var rui = Hud_GetRui( elem ) + RuiSetString( rui, "buttonText", text ) +} + +void function SetLabelRuiText( var elem, string text ) +{ + var rui = Hud_GetRui( elem ) + RuiSetString( rui, "labelText", text ) +} + +void function SetNamedRuiText( var elem, string name, string text ) +{ + var rui = Hud_GetRui( elem ) + RuiSetString( rui, name, text ) +} + +void function SetNamedRuiBool( var elem, string name, bool state ) +{ + var rui = Hud_GetRui( elem ) + RuiSetBool( rui, name, state ) +} + +void function SetNamedRuiImage( var elem, string name, asset assetName ) +{ + var rui = Hud_GetRui( elem ) + RuiSetImage( rui, name, assetName ) +} + +// Should be using Hud_GetChild() instead of this +var function GetMenuChild( var elem, string name ) +{ + return elem.GetChild( name ) +} + +bool function IsWeaponButton( var button ) +{ + array<var> weaponButtons = GetElementsByClassname( GetParentMenu( button ), "WeaponSelectClass" ) + + foreach ( weaponButton in weaponButtons ) + { + if ( button == weaponButton ) + return true + } + + return false +} + +void function SetPanelTabTitle( var panel, string title ) +{ + uiGlobal.panelData[ panel ].tabTitle = title +} + +string function GetPanelTabTitle( var panel ) +{ + return uiGlobal.panelData[ panel ].tabTitle +} + +void function ScriptCallback_UnlockAchievement( int achievementID ) +{ + Assert( achievementID > 0 && achievementID < achievements.MAX_ACHIVEMENTS, "Tried to unlock achievement with invalid enum value" ) + + #if DEV + string ref + foreach( string _ref, int val in achievements ) + { + if ( val != achievementID ) + continue + ref = _ref + break + } + printt( "#############################################" ) + printt( "UNLOCKED ACHIEVEMENT:", ref, "(" + achievementID + ")" ) + printt( "#############################################" ) + #endif //DEV + + if ( Script_IsRunningTrialVersion() ) + { + printt( "Achievements not awarded in trial version" ) + return + } + + + Plat_UnlockAchievementByID( achievementID ) +} + +void function TryUnlockCollectiblesAchievement() +{ + int totalLionsCollectedForGame = GetTotalLionsCollected() + + if ( totalLionsCollectedForGame >= GetTotalLionsInGame() ) + ScriptCallback_UnlockAchievement( achievements.COLLECTIBLES_3 ) + + if ( totalLionsCollectedForGame >= ACHIEVEMENT_COLLECTIBLES_2_COUNT ) + ScriptCallback_UnlockAchievement( achievements.COLLECTIBLES_2 ) + + if ( totalLionsCollectedForGame >= ACHIEVEMENT_COLLECTIBLES_1_COUNT ) + ScriptCallback_UnlockAchievement( achievements.COLLECTIBLES_1 ) +} + +void function TryUnlockCompletedGameAchievements() +{ + if ( Script_IsRunningTrialVersion() ) + return + + var dataTable = GetDataTable( $"datatable/sp_levels.rpak" ) + int numRows = GetDatatableRowCount( dataTable ) + + // Check Completed All Levels Achievement + int normalCompleted = 0 + int hardCompleted = 0 + int masterCompleted = 0 + for ( int i=0; i<numRows; i++ ) + { + int levelNum = GetDataTableInt( dataTable, i, GetDataTableColumnByName( dataTable, "levelNum" ) ) + + // always count training as master completed + if ( GetCompletedDifficultyForBSPNum( i, "sp_missionMasterCompletion" ) || levelNum == 0 ) + masterCompleted++ + if ( GetCompletedDifficultyForBSPNum( i, "sp_missionHardCompletion" ) || levelNum == 0 ) + hardCompleted++ + if ( GetCompletedDifficultyForBSPNum( i, "sp_missionNormalCompletion" ) || levelNum == 0 ) + normalCompleted++ + } + + if ( normalCompleted >= numRows ) + ScriptCallback_UnlockAchievement( achievements.COMPLETE_NORMAL ) + + if ( hardCompleted >= numRows ) + ScriptCallback_UnlockAchievement( achievements.COMPLETE_HARD ) + + if ( masterCompleted >= numRows ) + ScriptCallback_UnlockAchievement( achievements.COMPLETE_MASTER ) +} + +void function PopUpOriginOverlayDisabledDialog() +{ + DialogData dialogData + dialogData.header = "#ORIGIN_OVERLAY_DISABLED" + AddDialogButton( dialogData, "#OK" ) + OpenDialog( dialogData ) +} + +void function PrintPartyData() +{ + Party partyData = GetParty() + + printt( "PARTY DATA:" ) + + if ( partyData.numSlots == 0 ) + { + printt( " INVALID, numSlots: 0" ) + return + } + + printt( " partyType: ", partyData.partyType ) + printt( " playlistName: ", partyData.playlistName ) + printt( " originatorName: ", partyData.originatorName ) + printt( " originatorUID: ", partyData.originatorUID ) + printt( " numSlots: ", partyData.numSlots ) + printt( " numClaimedSlots:", partyData.numClaimedSlots ) + printt( " numFreeSlots: ", partyData.numFreeSlots ) + printt( " timeLeft: ", partyData.timeLeft ) + printt( " amIInThis: ", partyData.amIInThis ) + printt( " amILeader: ", partyData.amILeader ) + printt( " searching: ", partyData.searching ) + print( " members: " ) + + foreach ( index, member in partyData.members ) + { + if ( index != 0 ) + print( " " ) + + printt( member.name, "uid:", member.uid, "callsignIdx:", member.callsignIdx, "skillMu:", member.skillMu ) + } +} + +void function PlayVideoFullScreen( string video, bool showCaptions = false ) +{ + PlayVideo( video, 0, 0, 0, 0, showCaptions ) +} + +void function PlayVideoUsingPanelRect( string video, var panel ) +{ + int xPos = Hud_GetX( panel ) + int yPos = Hud_GetY( panel ) + int width = Hud_GetWidth( panel ) + int height = Hud_GetHeight( panel ) + + PlayVideo( video, xPos, yPos, width, height, false ) +} + +void function Hud_SetNavUp( var buttonFrom, var buttonTo ) +{ + buttonFrom.SetNavUp( buttonTo ) +} + +void function Hud_SetNavDown( var buttonFrom, var buttonTo ) +{ + buttonFrom.SetNavDown( buttonTo ) +}
\ No newline at end of file |