From 3e7186801d70e50a9135b897ef572076fe442cf4 Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Sun, 27 Mar 2022 00:45:23 +0100 Subject: Add mod code for updating state for discord RPC (#274) --- Northstar.Client/mod/scripts/vscripts/chat.gnut | 12 +- .../mod/scripts/vscripts/state_client.nut | 48 +++ Northstar.Client/mod/scripts/vscripts/state_ui.nut | 29 ++ .../mod/scripts/vscripts/ui/menu_lobby.nut | 2 + .../mod/scripts/vscripts/ui/menu_main.nut | 16 +- .../scripts/vscripts/ui/menu_ns_serverbrowser.nut | 14 + .../mod/scripts/vscripts/ui/panel_mainmenu.nut | 7 +- .../mod/scripts/vscripts/ui/ui_vscript.gnut | 352 +++++++++++++++++++++ 8 files changed, 466 insertions(+), 14 deletions(-) create mode 100644 Northstar.Client/mod/scripts/vscripts/state_client.nut create mode 100644 Northstar.Client/mod/scripts/vscripts/state_ui.nut create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/ui_vscript.gnut (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/chat.gnut b/Northstar.Client/mod/scripts/vscripts/chat.gnut index ce26434c..f5988bb7 100644 --- a/Northstar.Client/mod/scripts/vscripts/chat.gnut +++ b/Northstar.Client/mod/scripts/vscripts/chat.gnut @@ -1,18 +1,22 @@ untyped globalize_all_functions -void function Chat_NetworkWriteLine(string text) { +void function Chat_NetworkWriteLine(string text) +{ NSChatWriteLine(0, text) } -void function Chat_GameWriteLine(string text) { +void function Chat_GameWriteLine(string text) +{ NSChatWriteLine(1, text) } -void function Chat_NetworkWrite(string text) { +void function Chat_NetworkWrite(string text) +{ NSChatWrite(0, text) } -void function Chat_GameWrite(string text) { +void function Chat_GameWrite(string text) +{ NSChatWrite(1, text) } diff --git a/Northstar.Client/mod/scripts/vscripts/state_client.nut b/Northstar.Client/mod/scripts/vscripts/state_client.nut new file mode 100644 index 00000000..9ebcf006 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/state_client.nut @@ -0,0 +1,48 @@ +untyped + +int highestScore = 0 +int secondHighestScore = 0 +int ourScore = 0 + +globalize_all_functions + +void function OnPrematchStart() +{ + if (GetServerVar( "roundBased" )) + NSUpdateTimeInfo( level.nv.roundEndTime - Time() ) + else + NSUpdateTimeInfo( level.nv.gameEndTime - Time() ) +} + +void function NSUpdateGameStateClientStart() +{ + AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) + thread NSUpdateGameStateLoopClient() + OnPrematchStart() +} + +void function NSUpdateGameStateLoopClient() +{ + while ( true ) + { + foreach ( player in GetPlayerArray() ) + { + if ( GameRules_GetTeamScore( player.GetTeam() ) >= highestScore ) + { + highestScore = GameRules_GetTeamScore( player.GetTeam() ) + } + else if ( GameRules_GetTeamScore( player.GetTeam() ) > secondHighestScore ) + { + secondHighestScore = GameRules_GetTeamScore( player.GetTeam() ) + } + } + if ( GetLocalClientPlayer() != null ) + { + ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) + } + int limit = GetServerVar( "roundBased" ) ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) + NSUpdateGameStateClient( GetPlayerArray().len(), ourScore, secondHighestScore, highestScore, GetServerVar( "roundBased" ), limit ) + OnPrematchStart() + wait 1.0 + } +} \ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/state_ui.nut b/Northstar.Client/mod/scripts/vscripts/state_ui.nut new file mode 100644 index 00000000..907e38fa --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/state_ui.nut @@ -0,0 +1,29 @@ +untyped + +globalize_all_functions + +void function NSUpdateGameStateUIStart() +{ + thread NSUpdateGameStateLoopUI() +} + +void function NSUpdateGameStateLoopUI() +{ + while ( true ) + { + wait 1.0 + if ( uiGlobal.loadedLevel == "" ) + { + if ( uiGlobal.isLoading ) + NSSetLoading( true ) + else + { + NSSetLoading( false ) + NSUpdateGameStateUI( "", "", "", "", true, false ) + } + continue + } + NSSetLoading( false ) + NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString("mp_gamemode") ) ), IsFullyConnected(), false ) + } +} \ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut index 3c868aab..938e0d3f 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_lobby.nut @@ -372,6 +372,8 @@ void function StartPrivateMatch( var button ) return ClientCommand( "StartPrivateMatchSearch" ) + NSSetLoading(true) + NSUpdateListenServer() } void function DoRoomInviteIfAllowed( var button ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut index 87cba57e..b20699f9 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut @@ -72,7 +72,7 @@ void function OnMainMenu_Open() { Signal( uiGlobal.signalDummy, "EndOnMainMenu_Open" ) EndSignal( uiGlobal.signalDummy, "EndOnMainMenu_Open" ) - + SetConVarString( "communities_hostname", "" ) // disable communities due to crash exploits that are still possible through it UpdatePromoData() // On script restarts this gives us the last data until the new request is complete @@ -93,7 +93,7 @@ void function OnMainMenu_Open() ClientCommand( "map " + Dev_CommandLineParmValue( "+map" ) ) Dev_CommandLineRemoveParm( "+map" ) } - + // do agree to ns remote auth dialog if ( !GetConVarBool( "ns_has_agreed_to_send_token" ) ) NorthstarMasterServerAuthDialog() @@ -136,7 +136,7 @@ void function NorthstarMasterServerAuthDialog() { // todo: this should be in localisation DialogData dialogData - dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" + dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" dialogData.image = $"rui/menu/fd_menu/upgrade_northstar_chassis" dialogData.message = "#AUTHENTICATION_AGREEMENT_DIALOG_TEXT" AddDialogButton( dialogData, "#YES", NorthstarMasterServerAuthDialogAgree ) @@ -148,11 +148,11 @@ void function NorthstarMasterServerAuthDialogAgree() { int oldValue = GetConVarInt( "ns_has_agreed_to_send_token" ) SetConVarInt( "ns_has_agreed_to_send_token", NS_AGREED_TO_SEND_TOKEN ) - + if ( oldValue != 0 && oldValue != NS_AGREED_TO_SEND_TOKEN ) { DialogData dialogData - dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" + dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" dialogData.image = $"rui/menu/fd_menu/upgrade_northstar_chassis" dialogData.message = "#AUTHENTICATION_AGREEMENT_RESTART" AddDialogButton( dialogData, "#OK" ) @@ -164,11 +164,11 @@ void function NorthstarMasterServerAuthDialogDisagree() { int oldValue = GetConVarInt( "ns_has_agreed_to_send_token" ) SetConVarInt( "ns_has_agreed_to_send_token", NS_DISAGREED_TO_SEND_TOKEN ) - + if ( oldValue != 0 && oldValue != NS_DISAGREED_TO_SEND_TOKEN ) { DialogData dialogData - dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" + dialogData.header = "#DIALOG_TITLE_INSTALLED_NORTHSTAR" dialogData.image = $"rui/menu/fd_menu/upgrade_northstar_chassis" dialogData.message = "#AUTHENTICATION_AGREEMENT_RESTART" AddDialogButton( dialogData, "#OK" ) @@ -670,4 +670,4 @@ void function UpdateTrialLabel() void function OpenSinglePlayerDevMenu( var button ) { AdvanceMenu( GetMenu( "SinglePlayerDevMenu" ) ) -} +} \ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index b294f57c..bd263f2b 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -970,6 +970,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) return print( "trying to authenticate with server " + NSGetServerName( file.lastSelectedServer ) + " with password " + password ) + NSTryAuthWithServer( file.lastSelectedServer, password ) ToggleConnectingHUD( true ) @@ -988,6 +989,18 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) } file.cancelConnection = false + NSSetLoading(true) + NSUpdateServerInfo( + NSGetServerID(file.lastSelectedServer), + NSGetServerName(file.lastSelectedServer), + password, + NSGetServerPlayerCount(file.lastSelectedServer), + NSGetServerMaxPlayerCount(file.lastSelectedServer), + NSGetServerMap(file.lastSelectedServer), + Localize(GetMapDisplayName(NSGetServerMap(file.lastSelectedServer))), + NSGetServerPlaylist(file.lastSelectedServer), + Localize(GetPlaylistDisplayName(NSGetServerPlaylist(file.lastSelectedServer))) + ) if ( NSWasAuthSuccessful() ) { @@ -1010,6 +1023,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) // only actually reload if we need to since the uiscript reset on reload lags hard if ( modsChanged ) ReloadMods() + NSConnectToAuthedServer() } else diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index 65a8ca9b..fb4dfcd9 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -6,6 +6,8 @@ global function UpdatePromoData global function UICodeCallback_GetOnPartyServer global function UICodeCallback_MainMenuPromosUpdated +global bool isOnMainMenu = false + // defining this here because it's the only place it's used rn, custom const for a hook in launcher global const WEBBROWSER_FLAG_FORCEEXTERNAL = 1 << 1 // 2 @@ -526,6 +528,7 @@ void function OnPlayFDButton_Activate( var button ) // repurposed for launching if ( !Hud_IsLocked( button ) ) { SetConVarBool( "ns_is_modded_server", true ) + SetConVarString( "communities_hostname", "" ) // disable communities due to crash exploits that are still possible through it NSTryAuthWithLocalServer() thread TryAuthWithLocalServer() } @@ -552,12 +555,12 @@ void function TryAuthWithLocalServer() } WaitFrame() } - + if ( NSWasAuthSuccessful() ) { NSCompleteAuthWithLocalServer() } - + if ( GetConVarString( "mp_gamemode" ) == "solo" ) SetConVarString( "mp_gamemode", "tdm" ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/ui_vscript.gnut b/Northstar.Client/mod/scripts/vscripts/ui/ui_vscript.gnut new file mode 100644 index 00000000..63535bec --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/ui_vscript.gnut @@ -0,0 +1,352 @@ + +// Events for handlers +// UIE_CLICK +// UIE_GET_FOCUS +// UIE_LOSE_FOCUS + +global function UICodeCallback_UIInit +global function UICodeCallback_ControllerModeChanged +global function UICodeCallback_OnVideoOver +global function AddUICallback_OnLevelInit + +global struct TabDef +{ + var panel + string title +} + +global struct InputDef +{ + int input + string gamepadLabel + var vguiElem + string mouseLabel + bool functionref() conditionCheckFunc + bool lastConditionCheckResult + void functionref( var ) activateFunc + void functionref( InputDef ) updateFunc +} + +global struct DialogButtonData +{ + string label + void functionref() activateFunc + string focusMessage + bool startFocused +} + +global struct DialogFooterData +{ + string label + void functionref() activateFunc +} + +global struct DialogMessageRuiData +{ + string message = "" + vector style1Color = <1.0, 1.0, 1.0> + vector style2Color = <0.5, 0.5, 0.5> + vector style3Color = <0.5, 0.5, 0.5> + + float style1FontScale = 1.0 + float style2FontScale = 1.0 + float style3FontScale = 1.0 +} + +global struct DialogData +{ + var menu + string header + string message + DialogMessageRuiData &ruiMessage + array messageColor = [161, 161, 161, 255] + asset image + asset rightImage = $"" + bool forceChoice = false + bool noChoice = false + bool noChoiceWithNavigateBack = false + bool showSpinner = false + bool showPCBackButton = false + float inputDisableTime = 0 + table coloredButton + bool darkenBackground = false + bool useFullMessageHeight = false + + array buttonData + array footerData +} + +global struct MenuDef +{ + void functionref() initFunc + void functionref() openFunc + void functionref() closeFunc + void functionref() showFunc // TODO: Needs hooking up + void functionref() hideFunc // TODO: Needs hooking up + void functionref() thinkFunc + void functionref() navBackFunc + void functionref() tabChangedFunc + void functionref() inputModeChangedFunc + void functionref() entitlementsChangedFunc + + array footerData + table registeredInput + + bool hasTabs = false + array tabsData + int tabIndex = 0 + + bool isDialog = false + DialogData& dialogData + bool isDynamicHeight = false + + bool isPVEMenu = false + + var lastFocus // Only used for restoring submenu focus so far +} + +global struct PanelDef +{ + void functionref() initFunc + void functionref() showFunc + void functionref() hideFunc + + string tabTitle = "Default" + + array footerData + table registeredInput + + var defaultFocus +} + +global struct PieChartEntry +{ + string displayName + float numValue + array color = [127, 127, 127, 255] + float fracValue = 0.0 +} + +global struct PieChartData +{ + array entries + array labelColor = [46, 49, 51, 255] + bool timeBased = false + float sum = 0.0 +} + +global struct UIGlobals +{ + table menus = {} + array allMenus = [] + array menuStack + string loadingLevel = "" + string loadedLevel = "" + string previousLevel = "" + string previousPlaylist = "" + var activeMenu = null + bool lastMenuNavDirection = MENU_NAV_FORWARD + bool lobbyFromLoadingScreen = false + bool eventHandlersAdded = false + bool loadoutsInitialized = false + bool itemsInitialized = false + bool matchmaking = false + var dialogCloseCallback = null + table signalDummy = {} + float dialogInputEnableTime = 0.0 + bool lobbyMenusLeftOpen = false + bool playingMusic = false + var mainMenuFocus = null + int announcementVersionSeen = -1 + var lastCategoryFocus = null + + int pilotSpawnLoadoutIndex = -1 + int titanSpawnLoadoutIndex = -1 + + bool updatePilotSpawnLoadout = false + bool updateTitanSpawnLoadout = false + + string editingLoadoutType = "pilot" + string editingLoadoutProperty = "" + int editingLoadoutIndex = -1 + string editingItemRef = "" + int editingItemType = -1 + var editingSubitemRef = null + int editingSubitemType = -1 + var editingParentItemRef = null + int editingWeaponCategory = -1 + + int entitlementId = -1 + string testStoreWeaponRef // TODO: Remove when done testing + + bool EOGAutoAdvance = true + bool EOGOpenInLobby = false + string EOGChallengeFilter = "" + var eogCoopFocusedButton = null + var eogCoopSelectedButton = null + var eogScoreboardFocusedButton = null + bool eogNavigationButtonsRegistered = false + + table ui_ChallengeProgress = {} + + int decalScrollState = 0 + + bool isLobby + + var ConfirmMenuMessage + var ConfirmMenuErrorCode + array dialogButtonData + + bool updatingLobbyUI = false + + array buttonConfigs + array stickConfigs + + var playlistList + + table< string, array > eog_challengesToShow + table< string, array > eog_unlocks + + bool videoSettingsChanged = false + + bool playingVideo = false + bool playingCredits = false + + bool mapSupportsMenuModels = false + bool mapSupportsMenuModelsUpdated = false + bool interpolateCameraMoves = true + int activePresentationType = ePresentationType.INACTIVE + bool rotateCharacterInputRegistered = false + + table menuData + + table intVars + table boolVars + table varVars + table > varChangeFuncs + + array onLevelInitCallbacks + + bool tabButtonsRegistered = false + + table panels = {} + array allPanels + table panelData + + bool sp_showAlternateMissionLog = false + + int launching = eLaunching.FALSE + bool triedNucleusRegistration = false + int consoleSettingMenu = eConsoleSettingsMenu.FALSE + + bool updateCachedNewItems = true + + var menuToOpenFromPromoButton = null + + bool isLoading = false + +} + +global UIGlobals uiGlobal + +global const MAINMENU_MUSIC_DELAY = 4.0 + + +void function UICodeCallback_UIInit() +{ + ScriptCompilerTest() + + ShUtilityAll_Init() + LevelVarInit() + + VPKNotifyFile( "media/intro_captions.txt" ) + + UtilityUI_Init() + + Settings_Init() // UI script doesn't need everything in this, reorganize + GameModes_Init() + UIVars_Init() + + PassivesShared_Init() + ChallengesShared_Init() + ChallengesContent_Init() + XP_Init() + + MenuLobby_Init() + MenuPrivateMatch_Init() + + MenuGamepadLayout_Init() + MenuChallenges_Init() + MenuEOG_Init() + MenuUtility_Init() + MenuAdvocateLetter_Init() + MenuCredits_Init() + MenuMapSelect_Init() + + RegisterSignal( "LevelShutdown" ) + RegisterSignal( "CleanupInGameMenus" ) + RegisterSignal( "OnCloseLobbyMenu" ) + RegisterSignal( "OnCancelConnect" ) + RegisterSignal( "PlayVideoEnded" ) + RegisterSignal( "ActiveMenuChanged" ) + RegisterSignal( "LevelFinishedLoading") + RegisterSignal( "OpenErrorDialog" ) + RegisterSignal( "BoughtItem" ) + + thread UpdateClientMenuOpenState() + + InitGamepadConfigs() + Store_Init() + InitMenus() + + if ( !IsSingleplayer() ) + thread UpdateCachedLoadouts() // Needs to wait for persistent data to ready +} + +void function UICodeCallback_ControllerModeChanged( bool controllerModeEnabled ) +{ + //printt( "CONTROLLER! " + controllerModeEnabled + ", " + IsControllerModeActive() ) + + if ( uiGlobal.activeMenu == null ) + return + + if ( uiGlobal.menuData[ uiGlobal.activeMenu ].inputModeChangedFunc != null ) + thread uiGlobal.menuData[ uiGlobal.activeMenu ].inputModeChangedFunc() + + UpdateFooterOptions() + + if ( IsDialog( uiGlobal.activeMenu ) ) + UpdateDialogFooterVisibility( uiGlobal.activeMenu, controllerModeEnabled ) +} + +void function UICodeCallback_OnVideoOver() +{ + SetIntroViewed( true ) + + Signal( uiGlobal.signalDummy, "PlayVideoEnded" ) +} + +void function UpdateClientMenuOpenState() +{ + for ( ;; ) + { + WaitSignal( uiGlobal.signalDummy, "ActiveMenuChanged" ) + + if ( IsMultiplayer() && !IsLobby() ) + { + int newState = 0 + if ( IsDialogOnlyActiveMenu() ) + newState = 2 + else if ( uiGlobal.activeMenu != null) + newState = 1 + + RunMenuClientFunction( "SetMenuOpenState", newState ) + } + } +} + +void function AddUICallback_OnLevelInit( void functionref() callbackFunc ) +{ + Assert( !( uiGlobal.onLevelInitCallbacks.contains( callbackFunc ) ), "Already added " + string( callbackFunc ) + " with AddUICallback_OnLevelInit" ) + uiGlobal.onLevelInitCallbacks.append( callbackFunc ) +} -- cgit v1.2.3 From 52eb5c6fe396779d358a026586a4531306ca5bd6 Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Mon, 28 Mar 2022 23:51:53 +0200 Subject: Fix time left bug for Discord RPC (#277) * Fix a small bug with discord --- Northstar.Client/mod/scripts/vscripts/state_client.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/state_client.nut b/Northstar.Client/mod/scripts/vscripts/state_client.nut index 9ebcf006..3a0ed611 100644 --- a/Northstar.Client/mod/scripts/vscripts/state_client.nut +++ b/Northstar.Client/mod/scripts/vscripts/state_client.nut @@ -41,7 +41,7 @@ void function NSUpdateGameStateLoopClient() ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) } int limit = GetServerVar( "roundBased" ) ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) - NSUpdateGameStateClient( GetPlayerArray().len(), ourScore, secondHighestScore, highestScore, GetServerVar( "roundBased" ), limit ) + NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), ourScore, secondHighestScore, highestScore, GetServerVar( "roundBased" ), limit ) OnPrematchStart() wait 1.0 } -- cgit v1.2.3 From f7205efc36e971fa8704202f43ab30bd59c0dcbb Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Thu, 31 Mar 2022 23:26:19 +0200 Subject: Fix maps menu mode lock and slider (#283) --- .../mod/scripts/vscripts/ui/menu_map_select.nut | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut index 44a54e62..efe1d462 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut @@ -77,9 +77,6 @@ void function InitMapsMenu() AddButtonEventHandler( button, UIE_CLICK, MapButton_Activate ) AddButtonEventHandler( button, UIE_GET_FOCUS, MapButton_Focus ) } - - - FilterMapsArray() } @@ -133,8 +130,12 @@ void function OnHitDummyBottom( var button ) file.scrollOffset += 1 + int compensate = 0 + if ( file.mapsArrayFiltered.len() % 3 != 0 ) + compensate = 1 + if ((file.scrollOffset + BUTTONS_PER_PAGE) * 3 > file.mapsArrayFiltered.len()) - file.scrollOffset = (file.mapsArrayFiltered.len() - BUTTONS_PER_PAGE * 3) / 3 + 1 + file.scrollOffset = (file.mapsArrayFiltered.len() - BUTTONS_PER_PAGE * 3) / 3 + compensate UpdateMapsGrid() UpdateListSliderPosition() @@ -260,7 +261,6 @@ void function FilterMapsArray() string searchTerm = Hud_GetUTF8Text( Hud_GetChild( file.menu, "BtnMapsSearch" ) ) bool useSearch = searchTerm != "" - bool hideLocked = bool( GetConVarInt( "filter_map_hide_locked" ) ) foreach ( string map in GetPrivateMatchMaps() ) @@ -321,6 +321,10 @@ bool function IsLocked( string map ) } } + if ( !PrivateMatch_IsValidMapModeCombo( map, PrivateMatch_GetSelectedMode() ) ) + return true + + return false } @@ -375,7 +379,11 @@ void function SliderBarUpdate() Hud_SetPos( sliderPanel , 2, newPos ) Hud_SetPos( movementCapture , 2, newPos ) - file.scrollOffset = -int( ( (newPos - minYPos) / useableSpace ) * ( file.mapsArrayFiltered.len() / 3 + 1 - BUTTONS_PER_PAGE) ) + int compensate = 0 + if ( file.mapsArrayFiltered.len() % 3 != 0 ) + compensate = 1 + + file.scrollOffset = -int( ( (newPos - minYPos) / useableSpace ) * ( file.mapsArrayFiltered.len() / 3 + compensate - BUTTONS_PER_PAGE) ) UpdateMapsGrid() } @@ -410,7 +418,11 @@ void function UpdateListSliderPosition() var sliderPanel = Hud_GetChild( file.menu , "BtnMapGridSliderPanel" ) var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - float maps = float ( file.mapsArrayFiltered.len() / 3 + 1 ) + int compensate = 0 + if ( file.mapsArrayFiltered.len() % 3 != 0 ) + compensate = 1 + + float maps = float ( file.mapsArrayFiltered.len() / 3 + compensate ) float minYPos = -42.0 * (GetScreenSize()[1] / 1080.0) float useableSpace = (582.0 * (GetScreenSize()[1] / 1080.0) - Hud_GetHeight( sliderPanel )) @@ -429,7 +441,10 @@ void function UpdateListSliderPosition() void function OnDownArrowSelected( var button ) { if ( file.mapsArrayFiltered.len() <= BUTTONS_PER_PAGE || file.mapsArrayFiltered.len() <= 12 ) return + if ( file.scrollOffset + 5 > file.mapsArrayFiltered.len() / 3 && file.mapsArrayFiltered.len() % 3 == 0 ) return + file.scrollOffset += 1 + if ((file.scrollOffset + BUTTONS_PER_PAGE) * 3 > file.mapsArrayFiltered.len()) { file.scrollOffset = (file.mapsArrayFiltered.len() - BUTTONS_PER_PAGE * 3) / 3 + 1 } -- cgit v1.2.3 From d8cbd386a5e1b76625e7192a147d41fc1ae12e1d Mon Sep 17 00:00:00 2001 From: H0L0theBard <97146561+H0L0theBard@users.noreply.github.com> Date: Wed, 6 Apr 2022 23:56:11 +1000 Subject: Campaign RPC fix (#285) * Update state_ui.nut * Update state_client.nut * Update state_ui.nut * Fix accidental whitespace Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> --- Northstar.Client/mod/scripts/vscripts/state_client.nut | 13 ++++++++++++- Northstar.Client/mod/scripts/vscripts/state_ui.nut | 11 +++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/state_client.nut b/Northstar.Client/mod/scripts/vscripts/state_client.nut index 3a0ed611..2a380e35 100644 --- a/Northstar.Client/mod/scripts/vscripts/state_client.nut +++ b/Northstar.Client/mod/scripts/vscripts/state_client.nut @@ -16,7 +16,9 @@ void function OnPrematchStart() void function NSUpdateGameStateClientStart() { + #if MP AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) + #endif thread NSUpdateGameStateLoopClient() OnPrematchStart() } @@ -25,6 +27,14 @@ void function NSUpdateGameStateLoopClient() { while ( true ) { + if(GetConVarString( "mp_gamemode" ) == "solo") + { + + NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), 1, 1, 1, GetServerVar( "roundBased" ), 1 ) + wait 1.0 + } + else + { foreach ( player in GetPlayerArray() ) { if ( GameRules_GetTeamScore( player.GetTeam() ) >= highestScore ) @@ -45,4 +55,5 @@ void function NSUpdateGameStateLoopClient() OnPrematchStart() wait 1.0 } -} \ No newline at end of file + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/state_ui.nut b/Northstar.Client/mod/scripts/vscripts/state_ui.nut index 907e38fa..51e4856f 100644 --- a/Northstar.Client/mod/scripts/vscripts/state_ui.nut +++ b/Northstar.Client/mod/scripts/vscripts/state_ui.nut @@ -24,6 +24,13 @@ void function NSUpdateGameStateLoopUI() continue } NSSetLoading( false ) + if(GetConVarString( "mp_gamemode" ) == "solo") + { + NSUpdateGameStateUI( "northstar", Localize( GetMapDisplayName( GetActiveLevel()+"_CAMPAIGN_NAME" ) ) , "Campaign", "Campaign", IsFullyConnected(), false ) + + } + else{ NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString("mp_gamemode") ) ), IsFullyConnected(), false ) - } -} \ No newline at end of file + } +} +} -- cgit v1.2.3 From fa534ac10a4fdc134fc732b8920d78fca0395487 Mon Sep 17 00:00:00 2001 From: Kami Kaze Date: Mon, 11 Apr 2022 00:15:22 +0200 Subject: Server Browser: QOL and hide server info if no server focused (#295) * Serverbrowser QOL + Minor Fixes * Fix server info hidden on mouse hover * Retain focus on connect + cancel --- .../vscripts/ui/menu_ns_connect_password.nut | 2 + .../scripts/vscripts/ui/menu_ns_serverbrowser.nut | 50 +++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut index 56db0ccc..b5a2e9b6 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_connect_password.nut @@ -47,6 +47,8 @@ void function OnConnectWithPasswordMenuOpened() Hud_SetText( file.connectButton, "#MENU_CONNECT_MENU_CONNECT" ) Hud_SetText( file.enterPasswordBox, "" ) Hud_SetText( file.enterPasswordDummy, "" ) + Hud_SetFocused( file.enterPasswordBox ) + } void function ConnectWithPassword( var button ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index bd263f2b..6bffe8bb 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -399,6 +399,8 @@ void function OnCloseServerBrowserMenu() DeregisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) DeregisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) DeregisterButtonPressedCallback(KEY_TAB , OnKeyTabPressed) + DeregisterButtonPressedCallback(KEY_ENTER, OnEnterPressed) + DeregisterButtonPressedCallback(KEY_R, OnKeyRPressed) } catch ( ex ) {} } @@ -425,6 +427,8 @@ void function OnServerBrowserMenuOpened() RegisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) RegisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) RegisterButtonPressedCallback(KEY_TAB , OnKeyTabPressed) + RegisterButtonPressedCallback(KEY_ENTER, OnEnterPressed) + RegisterButtonPressedCallback(KEY_R, OnKeyRPressed) } //////////////////////////// @@ -448,11 +452,9 @@ void function OnKeyTabPressed(var button) { { // toggle focus between server list and filter panel if (IsFilterPanelElementFocused()) { - // print("Switching focus from filter panel to server list") Hud_SetFocused(Hud_GetChild(file.menu, "BtnServer1")) } else { - // print("Switching focus from server list to filter panel") Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerSearch")) HideServerInfo() } @@ -482,6 +484,7 @@ void function OnHitDummyBottom(var button) { // was at bottom already file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerSearch")) + HideServerInfo() } else { // only update if list position changed UpdateShownPage() @@ -518,6 +521,46 @@ void function OnUpArrowSelected( var button ) UpdateListSliderPosition( file.serversArrayFiltered.len() ) } +//////////////////////// +// Key Callbacks +//////////////////////// +void function OnEnterPressed(arg) +{ + // only trigger if a server is focused + if (IsServerButtonFocused()) + { + OnServerSelected(0) + } +} + +void function OnKeyRPressed(arg) +{ + if (!IsSearchBarFocused()) + { + RefreshServers(0); + } +} + +bool function IsServerButtonFocused() +{ + var focusedElement = GetFocus(); + var name = Hud_GetHudName(focusedElement); + + foreach (element in GetElementsByClassname( file.menu, "ServerButton")) + { + if ( element == focusedElement ) + return true + } + + + return false; +} + +bool function IsSearchBarFocused() +{ + return Hud_GetChild( file.menu, "BtnServerSearch") == GetFocus() +} + //////////////////////////// // Unused @@ -577,6 +620,7 @@ void function FilterAndUpdateList( var n ) file.scrollOffset = 0 UpdateListSliderPosition( file.serversArrayFiltered.len() ) + HideServerInfo() FilterServerList() @@ -985,6 +1029,8 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) if (file.cancelConnection) { file.cancelConnection = false + // re-focus server list + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer" + (file.serverButtonFocusedID + 1)) ) return } -- cgit v1.2.3 From dfcd5a901e038b7fad8db5d336399331bc87a848 Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Wed, 13 Apr 2022 23:42:40 +0200 Subject: Open wiki link in external browser (#297) --- Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index fb4dfcd9..171ee7dc 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -926,7 +926,7 @@ void function SpotlightButton_Activate( var button ) else { // discord links don't work in origin overlay - if ( link.find( "https://discord.gg" ) == 0 || link == "https://northstar.tf/discord" ) + if ( link.find( "https://discord.gg" ) == 0 || link == "https://northstar.tf/discord" || link == "https://northstar.tf/wiki" ) LaunchExternalWebBrowser( link, WEBBROWSER_FLAG_FORCEEXTERNAL ) else LaunchExternalWebBrowser( link, WEBBROWSER_FLAG_MUTEGAME ) -- cgit v1.2.3 From 0c61ea8d1b62415f25b1e54230195d455269b6aa Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Fri, 15 Apr 2022 16:08:16 +0100 Subject: cleanup file structure and code for presence and chat (#292) * refactor presence and chat * improve spacing in cl_chat --- Northstar.Client/mod.json | 6 +-- Northstar.Client/mod/scripts/vscripts/chat.gnut | 22 -------- .../mod/scripts/vscripts/client/cl_chat.gnut | 22 ++++++++ .../mod/scripts/vscripts/presence/cl_presence.nut | 60 ++++++++++++++++++++++ .../mod/scripts/vscripts/presence/ui_presence.nut | 38 ++++++++++++++ .../mod/scripts/vscripts/state_client.nut | 59 --------------------- Northstar.Client/mod/scripts/vscripts/state_ui.nut | 36 ------------- 7 files changed, 123 insertions(+), 120 deletions(-) delete mode 100644 Northstar.Client/mod/scripts/vscripts/chat.gnut create mode 100644 Northstar.Client/mod/scripts/vscripts/client/cl_chat.gnut create mode 100644 Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut create mode 100644 Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut delete mode 100644 Northstar.Client/mod/scripts/vscripts/state_client.nut delete mode 100644 Northstar.Client/mod/scripts/vscripts/state_ui.nut (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 4748d82e..5d5f66e4 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -42,7 +42,7 @@ } }, { - "Path": "chat.gnut", + "Path": "client/cl_chat.gnut", "RunOn": "CLIENT" }, { @@ -54,14 +54,14 @@ } }, { - "Path": "state_ui.nut", + "Path": "presence/ui_presence.nut", "RunOn": "UI", "UICallback": { "After": "NSUpdateGameStateUIStart" } }, { - "Path": "state_client.nut", + "Path": "presence/cl_presence.nut", "RunOn": "CLIENT", "ClientCallback": { "After": "NSUpdateGameStateClientStart" diff --git a/Northstar.Client/mod/scripts/vscripts/chat.gnut b/Northstar.Client/mod/scripts/vscripts/chat.gnut deleted file mode 100644 index f5988bb7..00000000 --- a/Northstar.Client/mod/scripts/vscripts/chat.gnut +++ /dev/null @@ -1,22 +0,0 @@ -untyped -globalize_all_functions - -void function Chat_NetworkWriteLine(string text) -{ - NSChatWriteLine(0, text) -} - -void function Chat_GameWriteLine(string text) -{ - NSChatWriteLine(1, text) -} - -void function Chat_NetworkWrite(string text) -{ - NSChatWrite(0, text) -} - -void function Chat_GameWrite(string text) -{ - NSChatWrite(1, text) -} diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_chat.gnut b/Northstar.Client/mod/scripts/vscripts/client/cl_chat.gnut new file mode 100644 index 00000000..3a43f312 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/client/cl_chat.gnut @@ -0,0 +1,22 @@ +untyped +globalize_all_functions + +void function Chat_NetworkWriteLine( string text ) +{ + NSChatWriteLine( 0, text) +} + +void function Chat_GameWriteLine( string text ) +{ + NSChatWriteLine( 1, text) +} + +void function Chat_NetworkWrite( string text ) +{ + NSChatWrite( 0, text) +} + +void function Chat_GameWrite( string text ) +{ + NSChatWrite( 1, text ) +} diff --git a/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut new file mode 100644 index 00000000..755396e3 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/presence/cl_presence.nut @@ -0,0 +1,60 @@ +untyped +globalize_all_functions + +struct { + int highestScore = 0 + int secondHighestScore = 0 +} file + +void function OnPrematchStart() +{ + if ( GetServerVar( "roundBased" ) ) + NSUpdateTimeInfo( level.nv.roundEndTime - Time() ) + else + NSUpdateTimeInfo( level.nv.gameEndTime - Time() ) +} + +void function NSUpdateGameStateClientStart() +{ + #if MP + AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) + #endif + + thread NSUpdateGameStateLoopClient() + OnPrematchStart() +} + +void function NSUpdateGameStateLoopClient() +{ + while ( true ) + { + if ( IsSingleplayer() ) + { + NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), 1, 1, 1, GetServerVar( "roundBased" ), 1 ) + wait 1.0 + } + else + { + foreach ( player in GetPlayerArray() ) + { + if ( GameRules_GetTeamScore( player.GetTeam() ) >= file.highestScore ) + { + file.highestScore = GameRules_GetTeamScore( player.GetTeam() ) + } + else if ( GameRules_GetTeamScore( player.GetTeam() ) > file.secondHighestScore ) + { + file.secondHighestScore = GameRules_GetTeamScore( player.GetTeam() ) + } + } + + int ourScore = 0 + if ( IsValid( GetLocalClientPlayer() ) ) + ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) + + int limit = IsRoundBased() ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) + NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), ourScore, file.secondHighestScore, file.highestScore, GetServerVar( "roundBased" ), limit ) + OnPrematchStart() + wait 1.0 + } + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut new file mode 100644 index 00000000..5f42cc7d --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut @@ -0,0 +1,38 @@ +untyped +globalize_all_functions + +void function NSUpdateGameStateUIStart() +{ + thread NSUpdateGameStateLoopUI() +} + +void function NSUpdateGameStateLoopUI() +{ + while ( true ) + { + wait 1.0 + + if ( uiGlobal.loadedLevel == "" ) + { + if ( uiGlobal.isLoading ) + NSSetLoading( true ) + else + { + NSSetLoading( false ) + NSUpdateGameStateUI( "", "", "", "", true, false ) + } + + continue + } + + NSSetLoading( false ) + if( GetConVarString( "mp_gamemode" ) == "solo" ) + { + NSUpdateGameStateUI( "northstar", Localize( GetMapDisplayName( GetActiveLevel() + "_CAMPAIGN_NAME" ) ), "Campaign", "Campaign", IsFullyConnected(), false ) + } + else + { + NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString( "mp_gamemode" ) ) ), IsFullyConnected(), false ) + } + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/state_client.nut b/Northstar.Client/mod/scripts/vscripts/state_client.nut deleted file mode 100644 index 2a380e35..00000000 --- a/Northstar.Client/mod/scripts/vscripts/state_client.nut +++ /dev/null @@ -1,59 +0,0 @@ -untyped - -int highestScore = 0 -int secondHighestScore = 0 -int ourScore = 0 - -globalize_all_functions - -void function OnPrematchStart() -{ - if (GetServerVar( "roundBased" )) - NSUpdateTimeInfo( level.nv.roundEndTime - Time() ) - else - NSUpdateTimeInfo( level.nv.gameEndTime - Time() ) -} - -void function NSUpdateGameStateClientStart() -{ - #if MP - AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) - #endif - thread NSUpdateGameStateLoopClient() - OnPrematchStart() -} - -void function NSUpdateGameStateLoopClient() -{ - while ( true ) - { - if(GetConVarString( "mp_gamemode" ) == "solo") - { - - NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), 1, 1, 1, GetServerVar( "roundBased" ), 1 ) - wait 1.0 - } - else - { - foreach ( player in GetPlayerArray() ) - { - if ( GameRules_GetTeamScore( player.GetTeam() ) >= highestScore ) - { - highestScore = GameRules_GetTeamScore( player.GetTeam() ) - } - else if ( GameRules_GetTeamScore( player.GetTeam() ) > secondHighestScore ) - { - secondHighestScore = GameRules_GetTeamScore( player.GetTeam() ) - } - } - if ( GetLocalClientPlayer() != null ) - { - ourScore = GameRules_GetTeamScore( GetLocalClientPlayer().GetTeam() ) - } - int limit = GetServerVar( "roundBased" ) ? GetCurrentPlaylistVarInt( "roundscorelimit", 0 ) : GetCurrentPlaylistVarInt( "scorelimit", 0 ) - NSUpdateGameStateClient( GetPlayerArray().len(), GetCurrentPlaylistVarInt( "max_players", 65535 ), ourScore, secondHighestScore, highestScore, GetServerVar( "roundBased" ), limit ) - OnPrematchStart() - wait 1.0 - } - } -} diff --git a/Northstar.Client/mod/scripts/vscripts/state_ui.nut b/Northstar.Client/mod/scripts/vscripts/state_ui.nut deleted file mode 100644 index 51e4856f..00000000 --- a/Northstar.Client/mod/scripts/vscripts/state_ui.nut +++ /dev/null @@ -1,36 +0,0 @@ -untyped - -globalize_all_functions - -void function NSUpdateGameStateUIStart() -{ - thread NSUpdateGameStateLoopUI() -} - -void function NSUpdateGameStateLoopUI() -{ - while ( true ) - { - wait 1.0 - if ( uiGlobal.loadedLevel == "" ) - { - if ( uiGlobal.isLoading ) - NSSetLoading( true ) - else - { - NSSetLoading( false ) - NSUpdateGameStateUI( "", "", "", "", true, false ) - } - continue - } - NSSetLoading( false ) - if(GetConVarString( "mp_gamemode" ) == "solo") - { - NSUpdateGameStateUI( "northstar", Localize( GetMapDisplayName( GetActiveLevel()+"_CAMPAIGN_NAME" ) ) , "Campaign", "Campaign", IsFullyConnected(), false ) - - } - else{ - NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() ) ), GetConVarString( "mp_gamemode" ), Localize( GetPlaylistDisplayName( GetConVarString("mp_gamemode") ) ), IsFullyConnected(), false ) - } -} -} -- cgit v1.2.3 From 2da71a5730b65d13049fbbd2635d1fac189f6662 Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Tue, 19 Apr 2022 22:33:45 +0200 Subject: Server browser fix + formatting (#315) * Fixes #314 * Updates formatting to project style --- .../scripts/vscripts/ui/menu_ns_serverbrowser.nut | 331 +++++++++++---------- 1 file changed, 174 insertions(+), 157 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index 6bffe8bb..c77000e9 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -7,15 +7,16 @@ global function ThreadedAuthAndConnectToServer // Stop peeking -const int BUTTONS_PER_PAGE = 15 -const float DOUBLE_CLICK_TIME_MS = 0.4 // unsure what the ideal value is - +const int BUTTONS_PER_PAGE = 15 // Number of servers we show +const float DOUBLE_CLICK_TIME_MS = 0.4 // Max time between clicks for double click registering +// Stores mouse delta used for scroll bar struct { int deltaX = 0 int deltaY = 0 } mouseDeltaBuffer +// Filters struct { bool hideFull = false bool hideEmpty = false @@ -39,6 +40,7 @@ enum sortingBy LATENCY } +// Column sort direction, only one of these can be aplied at once struct { // true = alphabeticaly false = reverse bool serverName = true @@ -62,6 +64,7 @@ struct serverStruct { } struct { + // UI state vars var menu int lastSelectedServer = 999 int focusedServerIndex = 0 @@ -72,9 +75,11 @@ struct { int serverButtonFocusedID = 0 bool shouldFocus = true bool cancelConnection = false - + + // filtered array of servers array serversArrayFiltered - + + // UI references array serverButtons array serversName array playerCountLabels @@ -86,9 +91,10 @@ struct { -bool function floatCompareInRange(float arg1, float arg2, float tolerance) +bool function FloatsEqual( float arg1, float arg2, float epsilon ) { - if ( arg1 > arg2 - tolerance && arg1 < arg2 + tolerance) return true + if ( fabs( arg1 - arg2 ) < epsilon ) return true + return false } @@ -159,7 +165,7 @@ void function InitServerBrowserMenu() AddMenuFooterOption( file.menu, BUTTON_Y, PrependControllerPrompts( BUTTON_Y, "#REFRESH_SERVERS" ), "#REFRESH_SERVERS", RefreshServers ) // Setup server buttons - var width = 1120.0 * (GetScreenSize()[1] / 1080.0) + var width = 1120.0 * ( GetScreenSize()[1] / 1080.0 ) foreach ( var button in GetElementsByClassname( file.menu, "ServerButton" ) ) { AddButtonEventHandler( button, UIE_CLICK, OnServerButtonClicked ) @@ -206,20 +212,20 @@ void function InitServerBrowserMenu() // Hidden cause no need, if server descriptions become too long use this - Hud_SetEnabled( Hud_GetChild( file.menu, "BtnServerDescription"), false) - Hud_SetEnabled( Hud_GetChild( file.menu, "BtnServerMods"), false) - Hud_SetText( Hud_GetChild( file.menu, "BtnServerDescription"), "") - Hud_SetText( Hud_GetChild( file.menu, "BtnServerMods"), "") + Hud_SetEnabled( Hud_GetChild( file.menu, "BtnServerDescription"), false ) + Hud_SetEnabled( Hud_GetChild( file.menu, "BtnServerMods"), false ) + Hud_SetText( Hud_GetChild( file.menu, "BtnServerDescription"), "" ) + Hud_SetText( Hud_GetChild( file.menu, "BtnServerMods"), "" ) // Unfinished features Hud_SetLocked( Hud_GetChild( file.menu, "BtnServerLatencyTab" ), true ) // Rui is a pain - RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideFull")), "buttonText", "") - RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideEmpty")), "buttonText", "") - RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideProtected")), "buttonText", "") - RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnSelectMap")), "buttonText", "") - RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnSelectGamemode")), "buttonText", "") + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideFull") ), "buttonText", "" ) + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideEmpty") ), "buttonText", "" ) + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnHideProtected") ), "buttonText", "" ) + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnSelectMap") ), "buttonText", "" ) + RuiSetString( Hud_GetRui( Hud_GetChild( file.menu, "SwtBtnSelectGamemode") ), "buttonText", "" ) ToggleConnectingHUD(false) @@ -231,7 +237,7 @@ void function InitServerBrowserMenu() //////////////////////////// // Slider //////////////////////////// -void function UpdateMouseDeltaBuffer(int x, int y) +void function UpdateMouseDeltaBuffer( int x, int y ) { mouseDeltaBuffer.deltaX += x mouseDeltaBuffer.deltaY += y @@ -248,7 +254,7 @@ void function FlushMouseDeltaBuffer() void function SliderBarUpdate() { - if ( file.serversArrayFiltered.len() <= 15 ) + if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE ) { FlushMouseDeltaBuffer() return @@ -258,17 +264,17 @@ void function SliderBarUpdate() var sliderPanel = Hud_GetChild( file.menu , "BtnServerListSliderPanel" ) var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - Hud_SetFocused(sliderButton) + Hud_SetFocused( sliderButton ) - float minYPos = -40.0 * (GetScreenSize()[1] / 1080.0) - float maxHeight = 562.0 * (GetScreenSize()[1] / 1080.0) - float maxYPos = minYPos - (maxHeight - Hud_GetHeight( sliderPanel )) - float useableSpace = (maxHeight - Hud_GetHeight( sliderPanel )) + float minYPos = -40.0 * ( GetScreenSize()[1] / 1080.0 ) + float maxHeight = 562.0 * ( GetScreenSize()[1] / 1080.0 ) + float maxYPos = minYPos - ( maxHeight - Hud_GetHeight( sliderPanel ) ) + float useableSpace = ( maxHeight - Hud_GetHeight( sliderPanel ) ) - float jump = minYPos - (useableSpace / ( float( file.serversArrayFiltered.len()))) + float jump = minYPos - ( useableSpace / ( float( file.serversArrayFiltered.len() ) ) ) // got local from official respaw scripts, without untyped throws an error - local pos = Hud_GetPos(sliderButton)[1] + local pos = Hud_GetPos( sliderButton )[1] local newPos = pos - mouseDeltaBuffer.deltaY FlushMouseDeltaBuffer() @@ -279,7 +285,7 @@ void function SliderBarUpdate() Hud_SetPos( sliderPanel , 2, newPos ) Hud_SetPos( movementCapture , 2, newPos ) - file.scrollOffset = -int( ( (newPos - minYPos) / useableSpace ) * (file.serversArrayFiltered.len() - 15) ) + file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.serversArrayFiltered.len() - BUTTONS_PER_PAGE ) ) UpdateShownPage() } @@ -289,10 +295,10 @@ void function UpdateListSliderHeight( float servers ) var sliderPanel = Hud_GetChild( file.menu , "BtnServerListSliderPanel" ) var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - float maxHeight = 562.0 * (GetScreenSize()[1] / 1080.0) - float minHeight = 80.0 * (GetScreenSize()[1] / 1080.0) + float maxHeight = 562.0 * ( GetScreenSize()[1] / 1080.0 ) + float minHeight = 80.0 * ( GetScreenSize()[1] / 1080.0 ) - float height = maxHeight * (15.0 / servers ) + float height = maxHeight * ( BUTTONS_PER_PAGE / servers ) if ( height > maxHeight ) height = maxHeight if ( height < minHeight ) height = minHeight @@ -309,12 +315,10 @@ void function UpdateListSliderPosition( int servers ) var sliderPanel = Hud_GetChild( file.menu , "BtnServerListSliderPanel" ) var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) - float minYPos = -40.0 * (GetScreenSize()[1] / 1080.0) - float useableSpace = (562.0 * (GetScreenSize()[1] / 1080.0) - Hud_GetHeight( sliderPanel )) + float minYPos = -40.0 * ( GetScreenSize()[1] / 1080.0 ) + float useableSpace = (562.0 * ( GetScreenSize()[1] / 1080.0 ) - Hud_GetHeight( sliderPanel ) ) - float jump = minYPos - (useableSpace / ( float( servers ) - 15.0 ) * file.scrollOffset) - - //jump = jump * (GetScreenSize()[1] / 1080.0) + float jump = minYPos - ( useableSpace / ( float( servers ) - BUTTONS_PER_PAGE ) * file.scrollOffset ) if ( jump > minYPos ) jump = minYPos @@ -325,7 +329,7 @@ void function UpdateListSliderPosition( int servers ) void function OnScrollDown( var button ) { - if (file.serversArrayFiltered.len() <= 15) return + if (file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE) return file.scrollOffset += 5 if (file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len()) { file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE @@ -337,7 +341,7 @@ void function OnScrollDown( var button ) void function OnScrollUp( var button ) { file.scrollOffset -= 5 - if (file.scrollOffset < 0) { + if ( file.scrollOffset < 0 ) { file.scrollOffset = 0 } UpdateShownPage() @@ -349,7 +353,7 @@ void function OnScrollUp( var button ) //////////////////////////// void function ToggleConnectingHUD( bool vis ) { - foreach (e in GetElementsByClassname(file.menu, "connectingHUD")) { + foreach (e in GetElementsByClassname( file.menu, "connectingHUD" ) ) { Hud_SetEnabled( e, vis ) Hud_SetVisible( e, vis ) } @@ -369,7 +373,7 @@ void function ConnectingButton_Activate( var button ) // This doesn't werk on some obscure resolutions, mostly really small 4:3 void function UpdateServerInfoBasedOnRes() { - if (floatCompareInRange(float(GetScreenSize()[0]) / float(GetScreenSize()[1]) , 1.6, 0.07)) // 16/10 + if ( FloatsEqual( float(GetScreenSize()[0] ) / float( GetScreenSize()[1] ) , 1.6, 0.07 ) ) // 16/10 { Hud_SetWidth( Hud_GetChild(file.menu, "ServerName"), 392) Hud_SetWidth( Hud_GetChild(file.menu, "NextMapImage"), 400) @@ -378,7 +382,7 @@ void function UpdateServerInfoBasedOnRes() Hud_SetWidth( Hud_GetChild(file.menu, "LabelDescription"), 360) Hud_SetWidth( Hud_GetChild(file.menu, "ServerDetailsPanel"), 400) } - if(floatCompareInRange(float(GetScreenSize()[0]) / float(GetScreenSize()[1]) , 1.3, 0.055)) // 4/3 + if( FloatsEqual( float( GetScreenSize()[0] ) / float( GetScreenSize()[1] ) , 1.3, 0.055 ) ) // 4/3 { Hud_SetWidth( Hud_GetChild(file.menu, "ServerName"), 292) Hud_SetWidth( Hud_GetChild(file.menu, "NextMapImage"), 300) @@ -396,19 +400,19 @@ void function OnCloseServerBrowserMenu() { try { - DeregisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) - DeregisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) - DeregisterButtonPressedCallback(KEY_TAB , OnKeyTabPressed) - DeregisterButtonPressedCallback(KEY_ENTER, OnEnterPressed) - DeregisterButtonPressedCallback(KEY_R, OnKeyRPressed) + DeregisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + DeregisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + DeregisterButtonPressedCallback( KEY_TAB , OnKeyTabPressed ) + DeregisterButtonPressedCallback( KEY_ENTER, OnEnterPressed ) + DeregisterButtonPressedCallback( KEY_R, OnKeyRPressed ) } catch ( ex ) {} } void function OnServerBrowserMenuOpened() { - Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize("#INGAME_PLAYERS", "0") ) - Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize("#TOTAL_SERVERS", "0") ) + Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize( "#INGAME_PLAYERS", "0" ) ) + Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize( "#TOTAL_SERVERS", "0" ) ) UpdatePrivateMatchModesAndMaps() Hud_SetText( Hud_GetChild( file.menu, "Title" ), "#MENU_TITLE_SERVER_BROWSER" ) UI_SetPresentationType( ePresentationType.KNOWLEDGEBASE_MAIN ) @@ -424,22 +428,23 @@ void function OnServerBrowserMenuOpened() thread WaitForServerListRequest() - RegisterButtonPressedCallback(MOUSE_WHEEL_UP , OnScrollUp) - RegisterButtonPressedCallback(MOUSE_WHEEL_DOWN , OnScrollDown) - RegisterButtonPressedCallback(KEY_TAB , OnKeyTabPressed) - RegisterButtonPressedCallback(KEY_ENTER, OnEnterPressed) - RegisterButtonPressedCallback(KEY_R, OnKeyRPressed) + RegisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + RegisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + RegisterButtonPressedCallback( KEY_TAB , OnKeyTabPressed ) + RegisterButtonPressedCallback( KEY_ENTER, OnEnterPressed ) + RegisterButtonPressedCallback( KEY_R, OnKeyRPressed ) } //////////////////////////// // Arrow navigation fuckery //////////////////////////// -bool function IsFilterPanelElementFocused() { +bool function IsFilterPanelElementFocused() +{ // get name of focused element - var focusedElement = GetFocus(); - var name = Hud_GetHudName(focusedElement); + var focusedElement = GetFocus() - foreach (element in GetElementsByClassname( file.menu, "FilterPanelChild")) { + foreach ( element in GetElementsByClassname( file.menu, "FilterPanelChild" ) ) + { if ( element == focusedElement ) return true } @@ -447,65 +452,78 @@ bool function IsFilterPanelElementFocused() { return false; } -void function OnKeyTabPressed(var button) { +void function OnKeyTabPressed( var button ) +{ try { // toggle focus between server list and filter panel - if (IsFilterPanelElementFocused()) { - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServer1")) + if ( IsFilterPanelElementFocused() ) + { + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer1" ) ) } - else { - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerSearch")) + else + { + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServerSearch" ) ) HideServerInfo() } } catch ( ex ) {} } -void function OnHitDummyTop(var button) { +void function OnHitDummyTop( var button ) +{ file.scrollOffset -= 1 - if (file.scrollOffset < 0) { + if ( file.scrollOffset < 0 ) + { // was at top already file.scrollOffset = 0 Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerNameTab")) - } else { + } + else + { // only update if list position changed UpdateShownPage() UpdateListSliderPosition( file.serversArrayFiltered.len() ) - DisplayFocusedServerInfo(file.serverButtonFocusedID) - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServer1")) + DisplayFocusedServerInfo( file.serverButtonFocusedID ) + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer1" ) ) } } -void function OnHitDummyBottom(var button) { +void function OnHitDummyBottom( var button ) +{ file.scrollOffset += 1 - if (file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len()) + if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() ) { // was at bottom already file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerSearch")) + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServerSearch" ) ) HideServerInfo() - } else { + } + else + { // only update if list position changed UpdateShownPage() UpdateListSliderPosition( file.serversArrayFiltered.len() ) - DisplayFocusedServerInfo(file.serverButtonFocusedID) - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServer15")) + DisplayFocusedServerInfo( file.serverButtonFocusedID ) + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer15" ) ) } } -void function OnHitDummyAfterFilterClear(var button) { - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServerNameTab")) +void function OnHitDummyAfterFilterClear( var button ) +{ + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServerNameTab" ) ) } void function OnDownArrowSelected( var button ) { - if (file.serversArrayFiltered.len() <= 15) return + if ( file.serversArrayFiltered.len() <= BUTTONS_PER_PAGE ) return file.scrollOffset += 1 - if (file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len()) { + if ( file.scrollOffset + BUTTONS_PER_PAGE > file.serversArrayFiltered.len() ) + { file.scrollOffset = file.serversArrayFiltered.len() - BUTTONS_PER_PAGE } + UpdateShownPage() UpdateListSliderPosition( file.serversArrayFiltered.len() ) } @@ -514,9 +532,11 @@ void function OnDownArrowSelected( var button ) void function OnUpArrowSelected( var button ) { file.scrollOffset -= 1 - if (file.scrollOffset < 0) { + if ( file.scrollOffset < 0 ) + { file.scrollOffset = 0 } + UpdateShownPage() UpdateListSliderPosition( file.serversArrayFiltered.len() ) } @@ -524,18 +544,18 @@ void function OnUpArrowSelected( var button ) //////////////////////// // Key Callbacks //////////////////////// -void function OnEnterPressed(arg) +void function OnEnterPressed( arg ) { // only trigger if a server is focused - if (IsServerButtonFocused()) + if ( IsServerButtonFocused() ) { OnServerSelected(0) } } -void function OnKeyRPressed(arg) +void function OnKeyRPressed( arg ) { - if (!IsSearchBarFocused()) + if ( !IsSearchBarFocused() ) { RefreshServers(0); } @@ -543,22 +563,24 @@ void function OnKeyRPressed(arg) bool function IsServerButtonFocused() { - var focusedElement = GetFocus(); - var name = Hud_GetHudName(focusedElement); + var focusedElement = GetFocus() + if ( focusedElement == null ) + return false + + var name = Hud_GetHudName( focusedElement ) - foreach (element in GetElementsByClassname( file.menu, "ServerButton")) + foreach ( element in GetElementsByClassname( file.menu, "ServerButton" ) ) { if ( element == focusedElement ) return true } - - return false; + return false } bool function IsSearchBarFocused() { - return Hud_GetChild( file.menu, "BtnServerSearch") == GetFocus() + return Hud_GetChild( file.menu, "BtnServerSearch" ) == GetFocus() } @@ -567,31 +589,32 @@ bool function IsSearchBarFocused() //////////////////////////// void function ShowServerDescription( var button ) { - Hud_SetVisible( Hud_GetChild( file.menu, "LabelDescription"), true) - Hud_SetVisible( Hud_GetChild( file.menu, "LabelMods"), false) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelDescription" ), true ) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelMods" ), false ) } void function ShowServerMods( var button ) { - Hud_SetVisible( Hud_GetChild( file.menu, "LabelDescription"), false) - Hud_SetVisible( Hud_GetChild( file.menu, "LabelMods"), true) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelDescription" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelMods" ), true ) } //////////////////////////// // Server list; filter,update,... //////////////////////////// -void function HideServerInfo() { - Hud_SetVisible(Hud_GetChild(file.menu, "BtnServerDescription"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "BtnServerMods"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "BtnServerJoin"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "LabelDescription"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "LabelMods"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "NextMapImage"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "NextMapBack"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "NextMapName"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "ServerName"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "NextModeIcon"), false) - Hud_SetVisible(Hud_GetChild(file.menu, "NextGameModeName"), false) +void function HideServerInfo() +{ + Hud_SetVisible( Hud_GetChild( file.menu, "BtnServerDescription" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "BtnServerMods" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "BtnServerJoin" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelDescription" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "LabelMods" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "NextMapImage" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "NextMapBack" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "NextMapName" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "ServerName" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "NextModeIcon" ), false ) + Hud_SetVisible( Hud_GetChild( file.menu, "NextGameModeName" ), false ) } void function OnBtnFiltersClear_Activate( var button ) @@ -677,8 +700,7 @@ void function RefreshServers( var button ) void function WaitForServerListRequest() { - - for ( int i = 0; i < 15; i++) + for ( int i = 0; i < BUTTONS_PER_PAGE; i++) { Hud_SetVisible( file.serversProtected[ i ], false ) Hud_SetVisible( file.serverButtons[ i ], false ) @@ -689,12 +711,9 @@ void function WaitForServerListRequest() Hud_SetText( file.serversLatency[ i ], "" ) } - HideServerInfo() - Hud_SetVisible( file.serversName[ 0 ], true ) - Hud_SetText( file.serversName[ 0 ], "#NS_SERVERBROWSER_WAITINGFORSERVERS" ) // wait for request to complete @@ -709,7 +728,7 @@ void function WaitForServerListRequest() else { FilterAndUpdateList(0) - Hud_SetFocused(Hud_GetChild(file.menu, "BtnServer1")) + Hud_SetFocused( Hud_GetChild(file.menu, "BtnServer1" ) ) } } @@ -735,21 +754,21 @@ void function FilterServerList() // Branchless programming ;) - if (!(filterArguments.hideEmpty && tempServer.serverPlayers == 0) && !(filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax) && !(filterArguments.hideProtected && tempServer.serverProtected)) + if ( !( filterArguments.hideEmpty && tempServer.serverPlayers == 0 ) && !( filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax ) && !( filterArguments.hideProtected && tempServer.serverProtected ) ) { if ( filterArguments.useSearch ) { - string sName = tempServer.serverName.tolower() + " " + Localize(GetMapDisplayName(tempServer.serverMap)).tolower() + " " + tempServer.serverMap.tolower() + " " + tempServer.serverGamemode.tolower() + " " + Localize(tempServer.serverGamemode).tolower() + string sName = tempServer.serverName.tolower() + " " + Localize( GetMapDisplayName( tempServer.serverMap ) ).tolower() + " " + tempServer.serverMap.tolower() + " " + tempServer.serverGamemode.tolower() + " " + Localize( tempServer.serverGamemode ).tolower() string sTerm = filterArguments.searchTerm.tolower() - if ( sName.find(sTerm) != null) + if ( sName.find( sTerm ) != null) { - if (filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap) + if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap ) { CheckGamemode( tempServer ) } - else if (filterArguments.filterMap == "SWITCH_ANY") + else if ( filterArguments.filterMap == "SWITCH_ANY" ) { CheckGamemode( tempServer ) } @@ -757,28 +776,28 @@ void function FilterServerList() } else { - if (filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap) + if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap ) { CheckGamemode( tempServer ) } - else if (filterArguments.filterMap == "SWITCH_ANY") + else if ( filterArguments.filterMap == "SWITCH_ANY" ) { CheckGamemode( tempServer ) } } } - Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize("#INGAME_PLAYERS", string(totalPlayers)) ) - Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize("#TOTAL_SERVERS", string( NSGetServerCount()) ) ) + Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize("#INGAME_PLAYERS", string( totalPlayers ) ) ) + Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize("#TOTAL_SERVERS", string( NSGetServerCount() ) ) ) } } void function CheckGamemode( serverStruct t ) { - if (filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode == t.serverGamemode) + if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode == t.serverGamemode ) { file.serversArrayFiltered.append( t ) } - else if (filterArguments.filterGamemode == "SWITCH_ANY") + else if ( filterArguments.filterGamemode == "SWITCH_ANY" ) { file.serversArrayFiltered.append( t ) } @@ -788,7 +807,7 @@ void function CheckGamemode( serverStruct t ) void function UpdateShownPage() { - for ( int i = 0; i < 15; i++) + for ( int i = 0; i < BUTTONS_PER_PAGE; i++ ) { Hud_SetVisible( file.serversProtected[ i ], false ) Hud_SetVisible( file.serverButtons[ i ], false ) @@ -799,7 +818,7 @@ void function UpdateShownPage() Hud_SetText( file.serversLatency[ i ], "" ) } - int j = file.serversArrayFiltered.len() > 15 ? 15 : file.serversArrayFiltered.len() + int j = file.serversArrayFiltered.len() > BUTTONS_PER_PAGE ? BUTTONS_PER_PAGE : file.serversArrayFiltered.len() for ( int i = 0; i < j; i++ ) { @@ -829,26 +848,26 @@ void function UpdateShownPage() void function OnServerButtonFocused( var button ) { - if (file.scrollOffset < 0) + if ( file.scrollOffset < 0 ) file.scrollOffset = 0 - int scriptID = int (Hud_GetScriptID(button)) + int scriptID = int ( Hud_GetScriptID( button ) ) file.serverButtonFocusedID = scriptID if ( file.serversArrayFiltered.len() > 0 ) file.focusedServerIndex = file.serversArrayFiltered[ file.scrollOffset + scriptID ].serverIndex - DisplayFocusedServerInfo(scriptID); + DisplayFocusedServerInfo( scriptID ) } void function OnServerButtonClicked(var button) { - int scriptID = int (Hud_GetScriptID(button)) + int scriptID = int ( Hud_GetScriptID( button ) ) - DisplayFocusedServerInfo(scriptID) - CheckDoubleClick(scriptID, true) + DisplayFocusedServerInfo( scriptID ) + CheckDoubleClick( scriptID, true ) } -void function CheckDoubleClick(int scriptID, bool wasClickNav) +void function CheckDoubleClick( int scriptID, bool wasClickNav ) { if ( NSGetServerCount() == 0 ) return @@ -856,34 +875,31 @@ void function CheckDoubleClick(int scriptID, bool wasClickNav) int serverIndex = file.scrollOffset + scriptID bool sameServer = false - if (file.lastSelectedServer == serverIndex) sameServer = true + if ( file.lastSelectedServer == serverIndex ) sameServer = true file.serverSelectedTimeLast = file.serverSelectedTime file.serverSelectedTime = Time() - printt(file.serverSelectedTime - file.serverSelectedTimeLast, file.lastSelectedServer, serverIndex) - file.lastSelectedServer = serverIndex - - if (wasClickNav && (file.serverSelectedTime - file.serverSelectedTimeLast < DOUBLE_CLICK_TIME_MS) && sameServer) + if ( wasClickNav && ( file.serverSelectedTime - file.serverSelectedTimeLast < DOUBLE_CLICK_TIME_MS ) && sameServer ) { OnServerSelected(0) } } -void function DisplayFocusedServerInfo( int scriptID) +void function DisplayFocusedServerInfo( int scriptID ) { - if (scriptID == 999 || scriptID == -1 || scriptID == 16) return + if ( scriptID == 999 || scriptID == -1 || scriptID == 16 ) return - if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.serversArrayFiltered.len() == 0) + if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed || file.serversArrayFiltered.len() == 0 ) return var menu = GetMenu( "ServerBrowserMenu" ) int serverIndex = file.scrollOffset + scriptID - if (serverIndex < 0) serverIndex = 0 + if ( serverIndex < 0 ) serverIndex = 0 Hud_SetVisible( Hud_GetChild( menu, "BtnServerDescription" ), true ) @@ -892,7 +908,7 @@ void function DisplayFocusedServerInfo( int scriptID) // text panels Hud_SetVisible( Hud_GetChild( menu, "LabelDescription" ), true ) Hud_SetVisible( Hud_GetChild( menu, "LabelMods" ), false ) - Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), NSGetServerDescription( file.serversArrayFiltered[ serverIndex ].serverIndex ) + "\n\nRequired Mods:\n" + FillInServerModsLabel( file.serversArrayFiltered[ serverIndex ].serverIndex )) + Hud_SetText( Hud_GetChild( menu, "LabelDescription" ), NSGetServerDescription( file.serversArrayFiltered[ serverIndex ].serverIndex ) + "\n\nRequired Mods:\n" + FillInServerModsLabel( file.serversArrayFiltered[ serverIndex ].serverIndex ) ) // map name/image/server name string map = file.serversArrayFiltered[ serverIndex ].serverMap @@ -1019,33 +1035,33 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) ToggleConnectingHUD( true ) - while ( NSIsAuthenticatingWithServer() && !file.cancelConnection) + while ( NSIsAuthenticatingWithServer() && !file.cancelConnection ) { WaitFrame() } ToggleConnectingHUD( false ) - if (file.cancelConnection) + if ( file.cancelConnection ) { file.cancelConnection = false // re-focus server list - Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer" + (file.serverButtonFocusedID + 1)) ) + Hud_SetFocused( Hud_GetChild( file.menu, "BtnServer" + ( file.serverButtonFocusedID + 1 ) ) ) return } file.cancelConnection = false - NSSetLoading(true) + NSSetLoading( true ) NSUpdateServerInfo( - NSGetServerID(file.lastSelectedServer), - NSGetServerName(file.lastSelectedServer), + NSGetServerID( file.lastSelectedServer ), + NSGetServerName( file.lastSelectedServer ), password, - NSGetServerPlayerCount(file.lastSelectedServer), - NSGetServerMaxPlayerCount(file.lastSelectedServer), - NSGetServerMap(file.lastSelectedServer), - Localize(GetMapDisplayName(NSGetServerMap(file.lastSelectedServer))), - NSGetServerPlaylist(file.lastSelectedServer), - Localize(GetPlaylistDisplayName(NSGetServerPlaylist(file.lastSelectedServer))) + NSGetServerPlayerCount( file.lastSelectedServer ), + NSGetServerMaxPlayerCount( file.lastSelectedServer ), + NSGetServerMap( file.lastSelectedServer ), + Localize( GetMapDisplayName( NSGetServerMap( file.lastSelectedServer ) ) ), + NSGetServerPlaylist( file.lastSelectedServer ), + Localize( GetPlaylistDisplayName( NSGetServerPlaylist( file.lastSelectedServer ) ) ) ) if ( NSWasAuthSuccessful() ) @@ -1093,7 +1109,7 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) ////////////////////////////////////// // Shadow realm ////////////////////////////////////// -int function ServerSortLogic ( serverStruct a, serverStruct b) +int function ServerSortLogic ( serverStruct a, serverStruct b ) { var aTemp var bTemp @@ -1101,7 +1117,8 @@ int function ServerSortLogic ( serverStruct a, serverStruct b) bool direction // We can hard code this cause adding entire columns isn't as easy - switch ( filterDirection.sortingBy ) { + switch ( filterDirection.sortingBy ) + { case sortingBy.NAME: aTemp = a.serverName.tolower() bTemp = b.serverName.tolower() @@ -1113,13 +1130,13 @@ int function ServerSortLogic ( serverStruct a, serverStruct b) direction = filterDirection.serverPlayers break; case sortingBy.MAP: - aTemp = Localize(a.serverMap).tolower() - bTemp = Localize(b.serverMap).tolower() + aTemp = Localize( a.serverMap ).tolower() + bTemp = Localize( b.serverMap ).tolower() direction = filterDirection.serverMap break; case sortingBy.GAMEMODE: - aTemp = Localize(a.serverGamemode).tolower() - bTemp = Localize(b.serverGamemode).tolower() + aTemp = Localize( a.serverGamemode ).tolower() + bTemp = Localize( b.serverGamemode ).tolower() direction = filterDirection.serverGamemode break; case sortingBy.LATENCY: -- cgit v1.2.3 From 31cba09fea290cfddde6cc77af836b1cd4756bdd Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Tue, 19 Apr 2022 23:27:54 +0200 Subject: Fix a freeze in stats menu (#307) --- .../mod/scripts/vscripts/ui/menu_stats_maps.nut | 322 ++++++++++++ .../mod/scripts/vscripts/ui/menu_stats_utility.nut | 560 +++++++++++++++++++++ 2 files changed, 882 insertions(+) create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/menu_stats_maps.nut create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/menu_stats_utility.nut (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_maps.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_maps.nut new file mode 100644 index 00000000..eb844af4 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_maps.nut @@ -0,0 +1,322 @@ +global function InitViewStatsMapsMenu +global function setit +struct +{ + var menu + GridMenuData gridData + bool isGridInitialized = false + array allMaps +} file + +// Why this file is included in Northstar: +// As it turns out, the Respawn developers in all their infinite wisdom decided to add a check to floats for NaN and Inf +// which does not exist in base Squirrel +// The code looks a bit like this: +// if ( strcpy_s(fos + 4, 0x16ui64, "1#QNAN") ) +// invoke_watson(0i64, 0i64, 0i64, 0, 0i64); +// goto LABEL_27; +// As if turns out, there is NO way to check if a float is one of these values in script +// This alone, however, wouldn't be that bad, as it would simply result in a 1#QNAN being output to the screen. +// Unfortunately, Respawns universe sized brains did not stop there. +// One day, a dev at Respawn had to write a function to convert an amount of hours into a timestring. +// Now, you and i dear reader would, being mortals, opt for the O(1) time solution of using the floor() and modulo functions +// You may think this would work perfectly, but you would be wrong. This is not the respawn Way! +// Instead, they opted to write the following piece of O(n) time algorithm: +// while ( minutes >= 60 ) +// { +// minutes -= 60 +// hours++ +// } +// Now you may ask: "Is this horribly inefficient and bug-prone?", but you must understand: This is the Respawn Way +// Passing in a NaN does not simply output a NaN to the screen, for that would be too simple. +// Nay, instead, it hangs the UI thread for all eternity, as it tries to subtract 60 from a NaN +// In fact, i think we should thank that developer for all the fun times we have had tracking and fixing this bug +// However, we mortals cannot possibly wield the greatness of Respawn's code, and we must settle for a lowly O(1) algorithm instead +// P.S: The other part of this fix is menu_stats_utility.nut + +void function InitViewStatsMapsMenu() +{ + var menu = GetMenu( "ViewStats_Maps_Menu" ) + file.menu = menu + + Hud_SetText( Hud_GetChild( file.menu, "MenuTitle" ), "#STATS_MAPS" ) + + file.gridData.rows = 5 + file.gridData.columns = 1 + //file.gridData.numElements // Set in OnViewStatsWeapons_Open after itemdata exists + file.gridData.pageType = eGridPageType.VERTICAL + file.gridData.tileWidth = 224 + file.gridData.tileHeight = 112 + file.gridData.paddingVert = 6 + file.gridData.paddingHorz = 6 + + Grid_AutoAspectSettings( menu, file.gridData ) + + file.gridData.initCallback = MapButton_Init + file.gridData.getFocusCallback = MapButton_GetFocus + file.gridData.clickCallback = MapButton_Activate + + AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnViewStatsWeapons_Open ) + + AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) +} + +void function OnViewStatsWeapons_Open() +{ + UI_SetPresentationType( ePresentationType.NO_MODELS ) + + file.allMaps = GetPrivateMatchMaps() + + file.gridData.numElements = file.allMaps.len() + + if ( !file.isGridInitialized ) + { + GridMenuInit( file.menu, file.gridData ) + file.isGridInitialized = true + } + + file.gridData.currentPage = 0 + + Grid_InitPage( file.menu, file.gridData ) + Hud_SetFocused( Grid_GetButtonForElementNumber( file.menu, 0 ) ) + UpdateStatsForMap( file.allMaps[ 0 ] ) +} + +bool function MapButton_Init( var button, int elemNum ) +{ + string mapName = file.allMaps[ elemNum ] + + asset mapImage = GetMapImageForMapName( mapName ) + + var rui = Hud_GetRui( button ) + RuiSetImage( rui, "buttonImage", mapImage ) + + Hud_SetEnabled( button, true ) + Hud_SetVisible( button, true ) + + return true +} + +void function MapButton_GetFocus( var button, int elemNum ) +{ + if ( IsControllerModeActive() ) + UpdateStatsForMap( file.allMaps[ elemNum ] ) +} + +void function MapButton_Activate( var button, int elemNum ) +{ + if ( !IsControllerModeActive() ) + UpdateStatsForMap( file.allMaps[ elemNum ] ) +} + +int function GetGameStatForMapInt( string gameStat, string mapName ) +{ + array privateMatchModes = GetPrivateMatchModes() + + int totalStat = 0 + int enumCount = PersistenceGetEnumCount( "gameModes" ) + for ( int modeId = 0; modeId < enumCount; modeId++ ) + { + string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId ) + + totalStat += GetGameStatForMapAndModeInt( gameStat, mapName, modeName ) + } + + return totalStat +} + +int function GetGameStatForMapAndModeInt( string gameStat, string mapName, string modeName, string difficulty = "1" ) +{ + string statString = GetStatVar( "game_stats", gameStat, "" ) + string persistentVar = Stats_GetFixedSaveVar( statString, mapName, modeName, difficulty ) + + return GetUIPlayer().GetPersistentVarAsInt( persistentVar ) +} + +float function GetGameStatForMapFloat( string gameStat, string mapName ) +{ + array privateMatchModes = GetPrivateMatchModes() + + float totalStat = 0 + int enumCount = PersistenceGetEnumCount( "gameModes" ) + for ( int modeId = 0; modeId < enumCount; modeId++ ) + { + string modeName = PersistenceGetEnumItemNameForIndex( "gameModes", modeId ) + + if ( (GetGameStatForMapAndModeFloat( gameStat, mapName, modeName ).tostring() ) != "1.#QNAN" ) + totalStat += GetGameStatForMapAndModeFloat( gameStat, mapName, modeName ) + else + print("Hey buddy, I just saved you from a game freeze. You're welcome :)") + } + + return totalStat +} + +float function GetGameStatForMapAndModeFloat( string gameStat, string mapName, string modeName ) +{ + string statString = GetStatVar( "game_stats", gameStat, "" ) + string persistentVar = Stats_GetFixedSaveVar( statString, mapName, modeName, "1" ) + + return expect float( GetUIPlayer().GetPersistentVar( persistentVar ) ) +} + + +void function UpdateStatsForMap( string mapName ) +{ + entity player = GetUIPlayer() + if ( player == null ) + return + + Hud_SetText( Hud_GetChild( file.menu, "WeaponName" ), GetMapDisplayName( mapName ) ) + + // Image + var imageElem = Hud_GetRui( Hud_GetChild( file.menu, "WeaponImageLarge" ) ) + RuiSetImage( imageElem, "basicImage", GetMapImageForMapName( mapName ) ) + var hoursplayed = GetGameStatForMapFloat( "hoursPlayed", mapName ) + string timePlayed = HoursToTimeString( GetGameStatForMapFloat( "hoursPlayed", mapName ) ) + string gamesPlayed = string( GetGameStatForMapInt( "game_completed", mapName ) ) + + SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat0" ), Localize( "#STATS_HEADER_TIME_PLAYED" ), timePlayed ) + SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat1" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed ) + //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat2" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed ) + //SetStatBoxDisplay( Hud_GetChild( file.menu, "Stat3" ), Localize( "#STATS_GAMES_PLAYED" ), gamesPlayed ) + + string winPercent = GetPercent( float( GetGameStatForMapInt( "game_won", mapName ) ), float( GetGameStatForMapInt( "game_completed", mapName ) ), 0 ) + + SetStatsLabelValue( file.menu, "KillsLabel0", "#STATS_GAMES_WIN_PERCENT" ) + SetStatsLabelValue( file.menu, "KillsValue0", ("" + winPercent + "%") ) + + SetStatsLabelValue( file.menu, "KillsLabel1", "#STATS_GAMES_WON" ) + SetStatsLabelValue( file.menu, "KillsValue1", GetGameStatForMapInt( "game_won", mapName ) ) + + SetStatsLabelValue( file.menu, "KillsLabel2", "#STATS_GAMES_MVP" ) + SetStatsLabelValue( file.menu, "KillsValue2", GetGameStatForMapInt( "mvp", mapName ) ) + + SetStatsLabelValue( file.menu, "KillsLabel3", "#STATS_GAMES_TOP3" ) + SetStatsLabelValue( file.menu, "KillsValue3", GetGameStatForMapInt( "top3OnTeam", mapName ) ) + + SetStatsLabelValue( file.menu, "KillsLabel4", "--" ) + SetStatsLabelValue( file.menu, "KillsValue4", "--" ) + + //var anchorElem = Hud_GetChild( file.menu, "WeaponStatsBackground" ) + //printt( Hud_GetX( anchorElem ) ) + //printt( Hud_GetX( anchorElem ) ) + //printt( Hud_GetX( anchorElem ) ) + //printt( Hud_GetX( anchorElem ) ) + //Hud_SetX( anchorElem, 0 ) + // + array gameModesArray = GetPersistenceEnumAsArray( "gameModes" ) + + array modes + foreach ( modeName in gameModesArray ) + { + float modePlayedTime = GetGameStatForMapAndModeFloat( "hoursPlayed", mapName, modeName ) + if ( modePlayedTime > 0 ) + AddPieChartEntry( modes, GameMode_GetName( modeName ), modePlayedTime, GetGameModeDisplayColor( modeName ) ) + } + + const MAX_MODE_ROWS = 8 + + if ( modes.len() > 0 ) + { + modes.sort( ComparePieChartEntryValues ) + + if ( modes.len() > MAX_MODE_ROWS ) + { + float otherValue + for ( int i = MAX_MODE_ROWS-1; i < modes.len() ; i++ ) + otherValue += modes[i].numValue + + modes.resize( MAX_MODE_ROWS-1 ) + AddPieChartEntry( modes, "#GAMEMODE_OTHER", otherValue, [127, 127, 127, 255] ) + } + } + + PieChartData modesPlayedData + modesPlayedData.entries = modes + modesPlayedData.labelColor = [ 255, 255, 255, 255 ] + SetPieChartData( file.menu, "ModesPieChart", "#GAME_MODES_PLAYED", modesPlayedData ) + + array fdMaps = GetPlaylistMaps( "fd" ) + + if ( fdMaps.contains( mapName ) ) + { + array pveElems = GetElementsByClassname( file.menu, "PvEGroup" ) + foreach ( elem in pveElems ) + { + Hud_Show( elem ) + } + + vector perfectColor = TEAM_COLOR_FRIENDLY / 219.0 + + var iconLegendRui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIconLegend" ) ) + RuiSetImage( iconLegendRui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" ) + RuiSetFloat3( iconLegendRui, "basicImageColor", perfectColor ) + + var icon0Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon0" ) ) + RuiSetImage( icon0Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_easy" ) + int easyWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "0" ) + SetStatsLabelValue( file.menu, "PvELabel0", "#FD_DIFFICULTY_EASY" ) + SetStatsLabelValue( file.menu, "PvEValueA0", easyWins ) + if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "0" ) ) + RuiSetFloat3( icon0Rui, "basicImageColor", perfectColor ) + else + RuiSetFloat3( icon0Rui, "basicImageColor", easyWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> ) + + var icon1Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon1" ) ) + RuiSetImage( icon1Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" ) + int normalWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "1" ) + SetStatsLabelValue( file.menu, "PvELabel1", "#FD_DIFFICULTY_NORMAL" ) + SetStatsLabelValue( file.menu, "PvEValueA1", normalWins ) + if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "1" ) ) + RuiSetFloat3( icon1Rui, "basicImageColor", perfectColor ) + else + RuiSetFloat3( icon1Rui, "basicImageColor", normalWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> ) + + var icon2Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon2" ) ) + RuiSetImage( icon2Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_hard" ) + int hardWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "2" ) + SetStatsLabelValue( file.menu, "PvELabel2", "#FD_DIFFICULTY_HARD" ) + SetStatsLabelValue( file.menu, "PvEValueA2", hardWins ) + if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "2" ) ) + RuiSetFloat3( icon2Rui, "basicImageColor", perfectColor ) + else + RuiSetFloat3( icon2Rui, "basicImageColor", hardWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> ) + + var icon3Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon3" ) ) + RuiSetImage( icon3Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_master" ) + int masterWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "3" ) + SetStatsLabelValue( file.menu, "PvELabel3", "#FD_DIFFICULTY_MASTER" ) + SetStatsLabelValue( file.menu, "PvEValueA3", masterWins ) + if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "3" ) ) + RuiSetFloat3( icon3Rui, "basicImageColor", perfectColor ) + else + RuiSetFloat3( icon3Rui, "basicImageColor", masterWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> ) + + var icon4Rui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIcon4" ) ) + RuiSetImage( icon4Rui, "basicImage", $"rui/menu/gametype_select/playlist_fd_insane" ) + int insaneWins = GetGameStatForMapAndModeInt( "games_completed_fd", mapName, "fd", "4" ) + SetStatsLabelValue( file.menu, "PvELabel4", "#FD_DIFFICULTY_INSANE" ) + SetStatsLabelValue( file.menu, "PvEValueA4", insaneWins ) + if ( GetGameStatForMapAndModeInt( "perfectMatches", mapName, "fd", "4" ) ) + RuiSetFloat3( icon4Rui, "basicImageColor", perfectColor ) + else + RuiSetFloat3( icon4Rui, "basicImageColor", insaneWins > 0 ? <1, 1, 1> : <0.15, 0.15, 0.15> ) + } + else + { + array pveElems = GetElementsByClassname( file.menu, "PvEGroup" ) + foreach ( elem in pveElems ) + { + Hud_Hide( elem ) + } + } +} + + +var function setit( vector color ) +{ + var iconLegendRui = Hud_GetRui( Hud_GetChild( file.menu, "PvEIconLegend" ) ) + RuiSetImage( iconLegendRui, "basicImage", $"rui/menu/gametype_select/playlist_fd_normal" ) + RuiSetFloat3( iconLegendRui, "basicImageColor", color ) +} \ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_utility.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_utility.nut new file mode 100644 index 00000000..e1d0a8f9 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_stats_utility.nut @@ -0,0 +1,560 @@ +untyped + + +global function SetPieChartData +global function SetStatsBarValues +global function SetStatsValueInfo +global function SetStatsLabelValue +global function GetPercent +//global function GetChallengeCompleteData +global function GetItemUnlockCountData +global function GetOverviewWeaponData +global function StatToTimeString +global function HoursToTimeString +global function StatToDistanceString +global function ComparePieChartEntryValues +global function SetStatBoxDisplay +global function SetMedalStatBoxDisplay + +void function SetPieChartData( var menu, string panelName, string titleString, PieChartData data ) +{ + Assert( data.entries.len() <= 8 ) + + // Get nested panel + var piePanel = GetElem( menu, panelName ) + + // Create background + var background = Hud_GetChild( piePanel, "BarBG" ) + Hud_SetBarProgress( background, 1.0 ) + Hud_SetColor( background, [190, 190, 190, 255] ) + + // Calculate total of all values combined + foreach ( entry in data.entries ) + data.sum += entry.numValue + + // Calculate bar fraction for each value + foreach ( entry in data.entries ) + { + if ( data.sum > 0 ) + entry.fracValue = entry.numValue / data.sum + else + entry.fracValue = 0.0 + } + + // Set slice sizes and text data + var titleLabel = Hud_GetChild( piePanel, "Title" ) + Hud_SetText( titleLabel, titleString ) + Hud_SetColor( titleLabel, data.labelColor ) + + var noDataLabel = Hud_GetChild( piePanel, "NoData" ) + + for ( int index = 0; index < 8; index++ ) + { + var barColorGuide = Hud_GetChild( piePanel, "BarColorGuide" + index ) + // Hud_SetColor( barColorGuide, entry.color ) + Hud_Hide( barColorGuide ) + + var barColorGuideFrame = Hud_GetChild( piePanel, "BarColorGuideFrame" + index ) + Hud_Hide( barColorGuideFrame ) + + var barName = Hud_GetChild( piePanel, "BarName" + index ) + Hud_SetColor( barName, data.labelColor ) + Hud_SetText( barName, "" ) + + var bar = Hud_GetChild( piePanel, "Bar" + index ) + //Hud_SetBarProgress( bar, combinedFrac ) + //Hud_SetColor( bar, entry.color ) + Hud_Hide( bar ) + } + + if ( data.entries.len() > 0 ) + { + Hud_Hide( noDataLabel ) + + float combinedFrac = 0.0 + int largestTextWidth = 0 + + foreach ( index, entry in data.entries ) + { + var barColorGuide = Hud_GetChild( piePanel, "BarColorGuide" + index ) + Hud_SetColor( barColorGuide, entry.color ) + Hud_Show( barColorGuide ) + + var barColorGuideFrame = Hud_GetChild( piePanel, "BarColorGuideFrame" + index ) + Hud_Show( barColorGuideFrame ) + + string percent = GetPercent( entry.fracValue, 1.0, 0, true ) + var barName = Hud_GetChild( piePanel, "BarName" + index ) + Hud_SetColor( barName, data.labelColor ) + + if ( data.timeBased ) + Hud_SetText( barName, PieChartHoursToTimeString( entry.numValue, entry.displayName, percent ) ) + else + Hud_SetText( barName, "#STATS_TEXT_AND_PERCENTAGE", entry.displayName, percent ) + + int currentTextWidth = Hud_GetTextWidth( barName ) + if ( currentTextWidth > largestTextWidth ) + largestTextWidth = currentTextWidth + + Hud_Show( barName ) + + combinedFrac += entry.fracValue + var bar = Hud_GetChild( piePanel, "Bar" + index ) + Hud_SetBarProgress( bar, combinedFrac ) + Hud_SetColor( bar, entry.color ) + Hud_Show( bar ) + } + + // Position the list + int xOffset = int( ( largestTextWidth / -2 ) + ContentScaledX( 18 ) ) + Hud_SetX( Hud_GetChild( piePanel, "BarName0" ), xOffset ) + } + else + { + Hud_Show( noDataLabel ) + for ( int index = 0; index < 8; index++ ) + { + var barColorGuide = Hud_GetChild( piePanel, "BarColorGuide" + index ) +// Hud_SetColor( barColorGuide, entry.color ) + Hud_Hide( barColorGuide ) + + var barColorGuideFrame = Hud_GetChild( piePanel, "BarColorGuideFrame" + index ) + Hud_Hide( barColorGuideFrame ) + + var barName = Hud_GetChild( piePanel, "BarName" + index ) + Hud_SetColor( barName, data.labelColor ) + Hud_SetText( barName, "" ) + + var bar = Hud_GetChild( piePanel, "Bar" + index ) + //Hud_SetBarProgress( bar, combinedFrac ) + //Hud_SetColor( bar, entry.color ) + Hud_Hide( bar ) + } + } +} + +function SetStatsBarValues( menu, panelName, titleString, startValue, endValue, currentValue ) +{ + Assert( endValue > startValue ) + Assert( currentValue >= startValue && currentValue <= endValue ) + + // Get nested panel + var panel = GetElem( menu, panelName ) + + // Update titel + var title = Hud_GetChild( panel, "Title" ) + Hud_SetText( title, titleString ) + + // Update progress text + var progressText = Hud_GetChild( panel, "ProgressText" ) + Hud_SetText( progressText, "#STATS_PROGRESS_BAR_VALUE", currentValue, endValue ) + + // Update bar progress + float frac = GraphCapped( currentValue, startValue, endValue, 0.0, 1.0 ) + + var barFill = Hud_GetChild( panel, "BarFill" ) + Hud_SetScaleX( barFill, frac ) + + var barFillShadow = Hud_GetChild( panel, "BarFillShadow" ) + Hud_SetScaleX( barFillShadow, frac ) +} + +void function SetStatsValueInfo( var menu, valueID, labelText, textString ) +{ + var elem = GetElem( menu, "Column0Label" + valueID ) + Assert( elem != null ) + Hud_SetText( elem, labelText ) + + elem = GetElem( menu, "Column0Value" + valueID ) + Assert( elem != null ) + SetStatsLabelValueOnLabel( elem, textString ) +} + +void function SetStatsLabelValue( var menu, labelName, textString ) +{ + var elem = GetElem( menu, labelName ) + Assert( elem != null) + SetStatsLabelValueOnLabel( elem, textString ) +} + +void function SetStatsLabelValueOnLabel( elem, textString ) +{ + if ( type( textString ) == "array" ) + { + if ( textString.len() == 6 ) + Hud_SetText( elem, string( textString[0] ), textString[1], textString[2], textString[3], textString[4], textString[5] ) + if ( textString.len() == 5 ) + Hud_SetText( elem, string( textString[0] ), textString[1], textString[2], textString[3], textString[4] ) + if ( textString.len() == 4 ) + Hud_SetText( elem, string( textString[0] ), textString[1], textString[2], textString[3] ) + if ( textString.len() == 3 ) + Hud_SetText( elem, string( textString[0] ), textString[1], textString[2] ) + if ( textString.len() == 2 ) + Hud_SetText( elem, string( textString[0] ), textString[1] ) + if ( textString.len() == 1 ) + Hud_SetText( elem, string( textString[0] ) ) + } + else + { + Hud_SetText( elem, string( textString ) ) + } +} + +string function GetPercent( float val, float total, float defaultPercent, bool doClamp = true ) +{ + float percent = defaultPercent + if ( total > 0 ) + { + percent = val / total + percent *= 100 + } + + if ( doClamp ) + percent = clamp( percent, 0, 100 ) + + string formattedPercent + if ( int( percent * 10 ) % 10 == 0 ) + formattedPercent = format( "%.0f", percent ) + else + formattedPercent = format( "%.1f", percent ) + + return formattedPercent +} + +//function GetChallengeCompleteData() +//{ +// local Table = {} +// Table.total <- 0 +// Table.complete <- 0 +// +// UI_GetAllChallengesProgress() +// var allChallenges = GetLocalChallengeTable() +// +// foreach( challengeRef, val in allChallenges ) +// { +// if ( IsDailyChallenge( challengeRef ) ) +// continue +// local tierCount = GetChallengeTierCount( challengeRef ) +// Table.total += tierCount +// for ( int i = 0; i < tierCount; i++ ) +// { +// if ( IsChallengeTierComplete( challengeRef, i ) ) +// Table.complete++ +// } +// } +// +// return Table +//} + +function GetItemUnlockCountData() +{ + entity player = GetUIPlayer() + if ( player == null ) + return {} + + local Table = {} + Table[ "weapons" ] <- {} + Table[ "weapons" ].total <- 0 + Table[ "weapons" ].unlocked <- 0 + Table[ "attachments" ] <- {} + Table[ "attachments" ].total <- 0 + Table[ "attachments" ].unlocked <- 0 + Table[ "mods" ] <- {} + Table[ "mods" ].total <- 0 + Table[ "mods" ].unlocked <- 0 + Table[ "abilities" ] <- {} + Table[ "abilities" ].total <- 0 + Table[ "abilities" ].unlocked <- 0 + Table[ "gear" ] <- {} + Table[ "gear" ].total <- 0 + Table[ "gear" ].unlocked <- 0 +/* + local tableMapping = {} + + tableMapping[ eItemTypes.PILOT_PRIMARY ] <- "weapons" + tableMapping[ eItemTypes.PILOT_SECONDARY ] <- "weapons" + tableMapping[ eItemTypes.PILOT_ORDNANCE ] <- "weapons" + tableMapping[ eItemTypes.TITAN_PRIMARY ] <- "weapons" + tableMapping[ eItemTypes.TITAN_ORDNANCE ] <- "weapons" + tableMapping[ eItemTypes.PILOT_PRIMARY_ATTACHMENT ] <- "attachments" + tableMapping[ eItemTypes.PILOT_PRIMARY_MOD ] <- "mods" + tableMapping[ eItemTypes.PILOT_SECONDARY_MOD ] <- "mods" + tableMapping[ eItemTypes.TITAN_PRIMARY_MOD ] <- "mods" + tableMapping[ eItemTypes.PILOT_SPECIAL_MOD ] <- "mods" + tableMapping[ eItemTypes.TITAN_SPECIAL_MOD ] <- "mods" + tableMapping[ eItemTypes.PILOT_SPECIAL ] <- "abilities" + tableMapping[ eItemTypes.TITAN_SPECIAL ] <- "abilities" + + local itemRefs = GetAllItemRefs() + foreach ( data in itemRefs ) + { + if ( !( data.Type in tableMapping ) ) + continue + Table[ tableMapping[ data.Type ] ].total++ + + if ( !IsItemLocked( player, expect string( data.childRef ), expect string( data.ref ) ) ) + Table[ tableMapping[ data.Type ] ].unlocked++ + } +*/ + return Table +} + +table function GetOverviewWeaponData() +{ + table Table = {} + Table[ "most_kills" ] <- {} + Table[ "most_kills" ].ref <- "" + Table[ "most_kills" ].printName <- "" + Table[ "most_kills" ].val <- 0 + Table[ "most_used" ] <- {} + Table[ "most_used" ].ref <- "" + Table[ "most_used" ].printName <- "" + Table[ "most_used" ].val <- 0 + Table[ "highest_kpm" ] <- {} + Table[ "highest_kpm" ].ref <- "" + Table[ "highest_kpm" ].printName <- "" + Table[ "highest_kpm" ].val <- 0 + + entity player = GetUIPlayer() + if ( player == null ) + return Table + + array allWeapons = [] + + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.PILOT_PRIMARY ) ) + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.PILOT_SECONDARY ) ) + //allWeapons.extend( GetVisibleItemsOfType( eItemTypes.PILOT_ORDNANCE ) ) // art looks bad + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.TITAN_PRIMARY ) ) + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.TITAN_ORDNANCE ) ) + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.TITAN_ANTIRODEO ) ) + allWeapons.extend( GetVisibleItemsOfType( eItemTypes.TITAN_SPECIAL ) ) + //allWeapons.extend( GetVisibleItemsOfType( eItemTypes.BURN_METER_REWARD ) ) // script errors + + foreach ( weapon in allWeapons ) + { + string weaponName = weapon.ref + string weaponDisplayName = expect string( GetWeaponInfoFileKeyField_Global( weaponName, "printname" ) ) + + if ( !PersistenceEnumValueIsValid( "loadoutWeaponsAndAbilities", weaponName ) ) + continue + + int val = GetPlayerStatInt( player, "weapon_kill_stats", "total", weaponName ) + if ( val > Table[ "most_kills" ].val ) + { + Table[ "most_kills" ].ref = weaponName + Table[ "most_kills" ].printName = weaponDisplayName + Table[ "most_kills" ].val = val + } + + float fVal = GetPlayerStatFloat( player, "weapon_stats", "hoursUsed", weaponName ) + if ( fVal > Table[ "most_used" ].val ) + { + Table[ "most_used" ].ref = weaponName + Table[ "most_used" ].printName = weaponDisplayName + Table[ "most_used" ].val = fVal + } + + local killsPerMinute = 0 + local hoursEquipped = GetPlayerStatFloat( player, "weapon_stats", "hoursEquipped", weaponName ) + local killCount = GetPlayerStatInt( player, "weapon_kill_stats", "total", weaponName ) + if ( hoursEquipped > 0 ) + killsPerMinute = format( "%.2f", ( killCount / ( hoursEquipped * 60.0 ) ).tofloat() ) + if ( killsPerMinute.tofloat() > Table[ "highest_kpm" ].val.tofloat() ) + { + Table[ "highest_kpm" ].ref = weaponName + Table[ "highest_kpm" ].printName = weaponDisplayName + Table[ "highest_kpm" ].val = killsPerMinute + } + } + + return Table +} + +string function StatToTimeString( string category, string alias, string weapon = "" ) +{ + entity player = GetUIPlayer() + if ( player == null ) + return "0" + + string statString = GetStatVar( category, alias, weapon ) + float savedHours = expect float( player.GetPersistentVar( statString ) ) + + return HoursToTimeString( savedHours ) +} + +string function HoursToTimeString( float savedHours ) +{ + string timeString + local minutes = floor( savedHours * 60.0 ) + + if ( minutes < 0 ) + minutes = 0 + + int days = 0 + int hours = 0 + + // For archiving code, i would like to keep this code here + // It is a testament to Respawn's hubris and determination to writing the absolutely worst fucking code ever + // These motherfuckers managed to run an O(1) operation in O(n) time. Genuinely impressive. + // while ( minutes >= 1440 ) + // { + // minutes -= 1440 + // days++ + // } + // + // while ( minutes >= 60 ) + // { + // minutes -= 60 + // hours++ + // } + + days = int(floor(minutes / 1440)) + minutes = minutes % 1440 + + hours = int(floor(minutes / 60)) + minutes = minutes % 60 + + if ( days > 0 && hours > 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_H_M", days, hours, minutes ) + } + else if ( days > 0 && hours == 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D", days ) + } + else if ( days == 0 && hours > 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_H", hours ) + } + else if ( days == 0 && hours == 0 && minutes >= 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_M", minutes ) + } + else if ( days > 0 && hours > 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_H", days, hours ) + } + else if ( days == 0 && hours > 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_H_M", hours, minutes ) + } + else if ( days > 0 && hours == 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_M", days, minutes ) + } + else + { + Assert( 0, "Unhandled time string creation case" ) + } + + return timeString +} + +string function PieChartHoursToTimeString( float savedHours, string pieChartHeader, string pieChartPercent ) +{ + string timeString + local minutes = floor( savedHours * 60.0 ) + + if ( minutes < 0 ) + minutes = 0 + + int days = 0 + int hours = 0 + + while ( minutes >= 1440 ) + { + minutes -= 1440 + days++ + } + + while ( minutes >= 60 ) + { + minutes -= 60 + hours++ + } + + if ( days > 0 && hours > 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_H_M_PIECHART", days, hours, minutes, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days > 0 && hours == 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_PIECHART", days, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days == 0 && hours > 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_H_PIECHART", hours, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days == 0 && hours == 0 && minutes >= 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_M_PIECHART", minutes, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days > 0 && hours > 0 && minutes == 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_H_PIECHART", days, hours, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days == 0 && hours > 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_H_M_PIECHART", hours, minutes, Localize( pieChartHeader ), pieChartPercent ) + } + else if ( days > 0 && hours == 0 && minutes > 0 ) + { + timeString = Localize( "#STATS_TIME_STRING_D_M_PIECHART", days, minutes, Localize( pieChartHeader ), pieChartPercent ) + } + else + { + Assert( 0, "Unhandled time string creation case" ) + } + + return timeString +} + +string function StatToDistanceString( string category, string alias, string weapon = "" ) +{ + entity player = GetUIPlayer() + if ( player == null ) + return "" + + string statString = GetStatVar( category, alias, weapon ) + float kilometers = expect float( player.GetPersistentVar( statString ) ) + + string formattedNum + if ( kilometers % 1 == 0 ) + formattedNum = format( "%.0f", kilometers ) + else + formattedNum = format( "%.2f", kilometers ) + + string distString = Localize( "#STATS_KILOMETERS_ABBREVIATION", formattedNum ) + + return distString +} + +int function ComparePieChartEntryValues( PieChartEntry a, PieChartEntry b ) +{ + float aVal = a.numValue + float bVal = b.numValue + + if ( aVal < bVal ) + return 1 + else if ( aVal > bVal ) + return -1 + + return 0 +} + +void function SetStatBoxDisplay( var vguiElem, string text, string value ) +{ + var rui = Hud_GetRui( vguiElem ) + + RuiSetString( rui, "statText", text ) + RuiSetString( rui, "statValue", value ) +} + +void function SetMedalStatBoxDisplay( var vguiElem, string text, asset image, int value ) +{ + var rui = Hud_GetRui( vguiElem ) + + RuiSetString( rui, "statText", text ) + RuiSetString( rui, "statValue", string( value ) ) + RuiSetImage( rui, "statImage", image ) +} \ No newline at end of file -- cgit v1.2.3 From 2cac435b9aa8108853481252bf1f2dc47bb96d3c Mon Sep 17 00:00:00 2001 From: Kami Kaze Date: Tue, 26 Apr 2022 00:48:26 +0200 Subject: Make mod button in main menu accessible when running with -dev (#320) --- Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut index b20699f9..d75bbb5d 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut @@ -57,7 +57,7 @@ void function InitMainMenu() #if DEV if ( DevStartPoints() ) - AddMenuFooterOption( menu, BUTTON_Y, "#Y_BUTTON_DEV_MENU", "#DEV_MENU", OpenSinglePlayerDevMenu ) + AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#Y_BUTTON_DEV_MENU", "#DEV_MENU", OpenSinglePlayerDevMenu ) #endif // DEV } -- cgit v1.2.3 From c1dc1a9e84f8375cab3fc7b66e44289be5fd6f80 Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Tue, 26 Apr 2022 21:45:08 +0200 Subject: Update ui_presence.nut (#326) works fine --- Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut index 5f42cc7d..1e381989 100644 --- a/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut +++ b/Northstar.Client/mod/scripts/vscripts/presence/ui_presence.nut @@ -28,7 +28,7 @@ void function NSUpdateGameStateLoopUI() NSSetLoading( false ) if( GetConVarString( "mp_gamemode" ) == "solo" ) { - NSUpdateGameStateUI( "northstar", Localize( GetMapDisplayName( GetActiveLevel() + "_CAMPAIGN_NAME" ) ), "Campaign", "Campaign", IsFullyConnected(), false ) + NSUpdateGameStateUI( GetActiveLevel(), Localize( GetMapDisplayName( GetActiveLevel() + "_CAMPAIGN_NAME" ) ), "Campaign", "Campaign", IsFullyConnected(), false ) } else { -- cgit v1.2.3 From d3945f4b65417d154492e28831b5fbd230416118 Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Fri, 29 Apr 2022 23:05:09 +0200 Subject: Add Attrition (#321) * Skyshow * Attrition score stuff * DropShip and DropPod spawn funcs * Attrition intro * Reaper spawn func * Attrition assault point logic * Cleanup * Match logic + basic spawn algo * Fix crash * Improve ai ? * Add AI weapon setter funcs * Bounty hunt score basics * code cleanup * add cleanup for bored ai * fix issue with failedChecks not being reset properly in cleanup * more cleanup * stop ai spawns on epilogue * don't run aitdm spawning code if we don't have ains/nms * Fix missing nodes crash * initial bounty hunt stuff * oops forgot to push this * me when i'm a competent developer * formatting and such * cap score + proper mp_rise spawns fix * Better squad handler * comment reaper out; needs to be checked out * Fix crash site crash * reapers * minor visual change is what Id call this * bh basic damage scoring * going to push this so there's a base to work with, still doesn't work * fix funny suicide bug :) * I hate crash site + score funnies * comlpex skill issue * final score fix, lets hope so * Hacked spectre fix * 1p npc executions fix * stalkers * Archer Grunts :) * minor fixing * Skyshow * Attrition score stuff * DropShip and DropPod spawn funcs * Attrition intro * Reaper spawn func * Attrition assault point logic * Cleanup * Match logic + basic spawn algo * Fix crash * Improve ai ? * Add AI weapon setter funcs * Bounty hunt score basics * code cleanup * add cleanup for bored ai * fix issue with failedChecks not being reset properly in cleanup * more cleanup * stop ai spawns on epilogue * don't run aitdm spawning code if we don't have ains/nms * Fix missing nodes crash * initial bounty hunt stuff * oops forgot to push this * me when i'm a competent developer * formatting and such * cap score + proper mp_rise spawns fix * Better squad handler * comment reaper out; needs to be checked out * Fix crash site crash * reapers * minor visual change is what Id call this * bh basic damage scoring * going to push this so there's a base to work with, still doesn't work * fix funny suicide bug :) * I hate crash site + score funnies * comlpex skill issue * final score fix, lets hope so * Hacked spectre fix * 1p npc executions fix * stalkers * Archer Grunts :) * minor fixing * Unlock attrition in mode select menu * move archer grunts settings Co-authored-by: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> --- .../northstar_client_localisation_english.txt | 4 +- .../mod/scripts/vscripts/ui/menu_mode_select.nut | 2 +- .../vscripts/sh_3psequence_to_1p_hacks.gnut | 22 +- .../scripts/vscripts/gamemodes/_ai_gamemodes.gnut | 164 +++++++ .../scripts/vscripts/gamemodes/_gamemode_aitdm.nut | 498 +++++++++++++++++++++ .../scripts/vscripts/gamemodes/_gamemode_at.nut | 366 ++++++++++++++- .../lobby/sh_private_lobby_modes_init.gnut | 3 +- .../mod/scripts/vscripts/mp/_gamestate_mp.nut | 2 +- 8 files changed, 1047 insertions(+), 14 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index fdda8bd8..50f2b51e 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -81,7 +81,9 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "cp_amped_capture_points" "Amped Hardpoints" "coliseum_loadouts_enabled" "Coliseum Loadouts" - + + "aitdm_archer_grunts" "Archer Grunts" + // northstar.custom localisation is just deciding not to work, so putting it here for now "PL_sbox" "Sandbox" "PL_sbox_lobby" "Sandbox Lobby" diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut index a017fb42..32a3c8f5 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut @@ -52,7 +52,7 @@ void function UpdateVisibleModes() Hud_SetEnabled( buttons[ i ], true ) Hud_SetVisible( buttons[ i ], true ) - if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) ) + if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" ) Hud_SetLocked( buttons[ i ], false ) else Hud_SetLocked( buttons[ i ], true ) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut index abfd269a..4d4d2744 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut @@ -123,19 +123,23 @@ Forced1PSequenceData function FirstPersonSequenceForce1P( FirstPersonSequenceStr thread FirstPersonSequence( sequence, thirdPersonProxy, other ) // create the viewpoint entity - entity camera = CreateEntity( "point_viewcontrol" ) - camera.SetParent( ownerProxy, attachment ) - camera.kv.spawnflags = 56 - DispatchSpawn( camera ) - player.SetViewEntity( camera, true ) - cleanupData.camera = camera - + if ( player.IsPlayer() ) // Check if the victim is an NPC + { + entity camera = CreateEntity( "point_viewcontrol" ) + camera.SetParent( ownerProxy, attachment ) + camera.kv.spawnflags = 56 + DispatchSpawn( camera ) + player.SetViewEntity( camera, true ) + cleanupData.camera = camera + } + // note for potential thing that could be done // entity e = CreatePropDynamic($"models/weapons/arms/pov_titan_light_cockpit.mdl"); e.SetParent(GetPlayerArray()[0].GetPetTitan(), "HATCH_HEAD"); e.SetOrigin(<0.75,0,-195>) // this is so we get a cockpit in these anims, issue with it is that the cockpit seems to break alot of rendering stuff // which really sucks since it'd be awesome to have a cockpit over these anims, really makes them better, even the client func to render through cockpits doesn't seem to work for it, just makes stuff rendering through the cockpit invisible rather than rendering in a broken way - Remote_CallFunction_NonReplay( player, "ServerCallback_HideHudForFPHackAnim" ) + if ( player.IsPlayer() ) // Check if the victim is an NPC + Remote_CallFunction_NonReplay( player, "ServerCallback_HideHudForFPHackAnim" ) // play this anim now, so we can cleanup after it's done thread CleanupForced1PSequenceAfterAnimDone( sequence, ownerProxy, other, cleanupData ) return cleanupData @@ -148,7 +152,7 @@ void function CleanupForced1PSequenceAfterAnimDone( FirstPersonSequenceStruct se OnThreadEnd( function() : ( cleanupData ) { - if ( IsValid( cleanupData.player ) ) + if ( IsValid( cleanupData.player ) && cleanupData.player.IsPlayer() ) CleanupForced1PSequence( cleanupData ) }) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_ai_gamemodes.gnut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_ai_gamemodes.gnut index cf7f7e15..d6d578bb 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_ai_gamemodes.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_ai_gamemodes.gnut @@ -1,6 +1,170 @@ global function AiGameModes_Init +global function AiGameModes_SetGruntWeapons +global function AiGameModes_SetSpectreWeapons + +global function AiGameModes_SpawnDropShip +global function AiGameModes_SpawnDropPod +global function AiGameModes_SpawnReaper +global function AiGameModes_SpawnTitan + +global function GetValidIntroDropShipSpawn + + +const INTRO_DROPSHIP_CUTOFF = 2000 + +struct +{ + array< string > gruntWeapons = [ "mp_weapon_rspn101" ] + array< string > spectreWeapons = [ "mp_weapon_hemlok_smg" ] +} file + void function AiGameModes_Init() { +} + +//------------------------------------------------------ + +void function AiGameModes_SetGruntWeapons( array< string > weapons ) +{ + file.gruntWeapons = weapons +} + +void function AiGameModes_SetSpectreWeapons( array< string > weapons ) +{ + file.spectreWeapons = weapons +} + +//------------------------------------------------------ + +void function AiGameModes_SpawnDropShip( vector pos, vector rot, int team, int count, void functionref( array guys ) squadHandler = null ) +{ + string squadName = MakeSquadName( team, UniqueString( "" ) ) + + CallinData drop + drop.origin = pos + drop.yaw = rot.y + drop.dist = 768 + drop.team = team + drop.squadname = squadName + SetDropTableSpawnFuncs( drop, CreateSoldier, count ) + SetCallinStyle( drop, eDropStyle.ZIPLINE_NPC ) + + thread RunDropshipDropoff( drop ) + + WaitSignal( drop, "OnDropoff" ) + + array< entity > guys = GetNPCArrayBySquad( squadName ) + + foreach ( guy in guys ) + { + ReplaceWeapon( guy, file.gruntWeapons[ RandomInt( file.gruntWeapons.len() ) ], [] ) + guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE ) + } + + if ( squadHandler != null ) + thread squadHandler( guys ) +} + + +void function AiGameModes_SpawnDropPod( vector pos, vector rot, int team, string content /*( ͡° ͜ʖ ͡°)*/, void functionref( array guys ) squadHandler = null ) +{ + string squadName = MakeSquadName( team, UniqueString( "" ) ) + array guys + + entity pod = CreateDropPod( pos, <0,0,0> ) + + InitFireteamDropPod( pod ) + + for ( int i = 0; i < 4 ;i++ ) + { + entity npc = CreateNPC( content, team, pos,<0,0,0> ) + DispatchSpawn( npc ) + SetSquad( npc, squadName ) + + switch ( content ) + { + case "npc_soldier": + ReplaceWeapon( npc, file.gruntWeapons[ RandomInt( file.gruntWeapons.len() ) ], [] ) + break + + case "npc_spectre": + ReplaceWeapon( npc, file.spectreWeapons[ RandomInt( file.spectreWeapons.len() ) ], [] ) + break + } + + npc.SetParent( pod, "ATTACH", true ) + + npc.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE ) + guys.append( npc ) + } + + // The order here is different so we can show on minimap while were still falling + if ( squadHandler != null ) + thread squadHandler( guys ) + + waitthread LaunchAnimDropPod( pod, "pod_testpath", pos, rot ) + + ActivateFireteamDropPod( pod, guys ) +} + +void function AiGameModes_SpawnReaper( vector pos, vector rot, int team, string aiSettings = "", void functionref( entity reaper ) reaperHandler = null ) +{ + entity reaper = CreateSuperSpectre( team, pos, rot ) + SetSpawnOption_Titanfall( reaper ) + SetSpawnOption_Warpfall( reaper ) + + if ( aiSettings != "" ) + SetSpawnOption_AISettings( reaper, aiSettings ) + + DispatchSpawn( reaper ) + + + if ( reaperHandler != null ) + thread reaperHandler( reaper ) +} + +// including aisettings stuff specifically for at bounty titans +void function AiGameModes_SpawnTitan( vector pos, vector rot, int team, string setFile, string aiSettings = "", void functionref( entity titan ) titanHandler = null ) +{ + entity titan = CreateNPCTitan( setFile, TEAM_BOTH, pos, rot ) + SetSpawnOption_Titanfall( titan ) + SetSpawnOption_Warpfall( titan ) + + if ( aiSettings != "" ) + SetSpawnOption_AISettings( titan, aiSettings ) + + DispatchSpawn( titan ) + + if ( titanHandler != null ) + thread titanHandler( titan ) +} + +// entity.ReplaceActiveWeapon gave grunts archers sometimes, this is my replacement for it +void function ReplaceWeapon( entity guy, string weapon, array mods ) +{ + guy.TakeActiveWeapon() + guy.GiveWeapon( weapon, mods ) + guy.SetActiveWeaponByName( weapon ) +} + +// Checks if we can spawn a dropship at a node, this should guarantee dropship ziplines +array function GetValidIntroDropShipSpawn( array introNodes ) +{ + array introShipSpawns + + if ( GetZiplineDropshipSpawns().len() == 0 ) + return [] + + foreach ( node in introNodes ) + { + entity closestNode = GetClosest( GetZiplineDropshipSpawns(), node.GetOrigin() ) + SetTeam( closestNode, node.GetTeam() ) + + if ( Distance( closestNode.GetOrigin(), node.GetOrigin() ) < INTRO_DROPSHIP_CUTOFF ) + introShipSpawns.append( closestNode ) + } + + return introShipSpawns } \ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_aitdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_aitdm.nut index a8089679..38c9cacd 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_aitdm.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_aitdm.nut @@ -1,6 +1,504 @@ +untyped global function GamemodeAITdm_Init +const SQUADS_PER_TEAM = 3 + +const REAPERS_PER_TEAM = 2 + +const LEVEL_SPECTRES = 125 +const LEVEL_STALKERS = 380 +const LEVEL_REAPERS = 500 + +struct +{ + // Due to team based escalation everything is an array + array< int > levels = [ LEVEL_SPECTRES, LEVEL_SPECTRES ] + array< array< string > > podEntities = [ [ "npc_soldier" ], [ "npc_soldier" ] ] + array< bool > reapers = [ false, false ] +} file + + void function GamemodeAITdm_Init() { + SetSpawnpointGamemodeOverride( ATTRITION ) // use bounty hunt spawns as vanilla game has no spawns explicitly defined for aitdm + + AddCallback_GameStateEnter( eGameState.Prematch, OnPrematchStart ) + AddCallback_GameStateEnter( eGameState.Playing, OnPlaying ) + + AddCallback_OnNPCKilled( HandleScoreEvent ) + AddCallback_OnPlayerKilled( HandleScoreEvent ) + + AddCallback_OnClientConnected( OnPlayerConnected ) + + AddCallback_NPCLeeched( OnSpectreLeeched ) + + if ( GetCurrentPlaylistVarInt( "aitdm_archer_grunts", 0 ) == 0 ) + { + AiGameModes_SetGruntWeapons( [ "mp_weapon_rspn101", "mp_weapon_dmr", "mp_weapon_r97", "mp_weapon_lmg" ] ) + AiGameModes_SetSpectreWeapons( [ "mp_weapon_hemlok_smg", "mp_weapon_doubletake", "mp_weapon_mastiff" ] ) + } + else + { + AiGameModes_SetGruntWeapons( [ "mp_weapon_rocket_launcher" ] ) + AiGameModes_SetSpectreWeapons( [ "mp_weapon_rocket_launcher" ] ) + } + + ScoreEvent_SetupEarnMeterValuesForMixedModes() +} + +// Starts skyshow, this also requiers AINs but doesn't crash if they're missing +void function OnPrematchStart() +{ + thread StratonHornetDogfightsIntense() +} + +void function OnPlaying() +{ + // don't run spawning code if ains and nms aren't up to date + if ( GetAINScriptVersion() == AIN_REV && GetNodeCount() != 0 ) + { + thread SpawnIntroBatch_Threaded( TEAM_MILITIA ) + thread SpawnIntroBatch_Threaded( TEAM_IMC ) + } +} + +// Sets up mode specific hud on client +void function OnPlayerConnected( entity player ) +{ + Remote_CallFunction_NonReplay( player, "ServerCallback_AITDM_OnPlayerConnected" ) +} + +// Used to handle both player and ai events +void function HandleScoreEvent( entity victim, entity attacker, var damageInfo ) +{ + // Basic checks + if ( victim == attacker || !( attacker.IsPlayer() || attacker.IsTitan() ) || GetGameState() != eGameState.Playing ) + return + + // Hacked spectre filter + if ( victim.GetOwner() == attacker ) + return + + // Split score so we can check if we are over the score max + // without showing the wrong value on client + int teamScore + int playerScore + string eventName + + // Handle AI, marvins aren't setup so we check for them to prevent crash + if ( victim.IsNPC() && victim.GetClassName() != "npc_marvin" ) + { + switch ( victim.GetClassName() ) + { + case "npc_soldier": + case "npc_spectre": + case "npc_stalker": + playerScore = 1 + break + case "npc_super_spectre": + playerScore = 3 + break + default: + playerScore = 0 + break + } + + // Titan kills get handled bellow this + if ( eventName != "KillNPCTitan" && eventName != "" ) + playerScore = ScoreEvent_GetPointValue( GetScoreEvent( eventName ) ) + } + + if ( victim.IsPlayer() ) + playerScore = 5 + + // Player ejecting triggers this without the extra check + if ( victim.IsTitan() && victim.GetBossPlayer() != attacker ) + playerScore += 10 + + + teamScore = playerScore + + // Check score so we dont go over max + if ( GameRules_GetTeamScore(attacker.GetTeam()) + teamScore > GetScoreLimit_FromPlaylist() ) + teamScore = GetScoreLimit_FromPlaylist() - GameRules_GetTeamScore(attacker.GetTeam()) + + // Add score + update network int to trigger the "Score +n" popup + AddTeamScore( attacker.GetTeam(), teamScore ) + attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, playerScore ) + attacker.SetPlayerNetInt("AT_bonusPoints", attacker.GetPlayerGameStat( PGS_ASSAULT_SCORE ) ) +} + +// When attrition starts both teams spawn ai on preset nodes, after that +// Spawner_Threaded is used to keep the match populated +void function SpawnIntroBatch_Threaded( int team ) +{ + array dropPodNodes = GetEntArrayByClass_Expensive( "info_spawnpoint_droppod_start" ) + array dropShipNodes = GetValidIntroDropShipSpawn( dropPodNodes ) + + array podNodes + + array shipNodes + + + // mp_rise has weird droppod_start nodes, this gets around it + // To be more specific the teams aren't setup and some nodes are scattered in narnia + if( GetMapName() == "mp_rise" ) + { + entity spawnPoint + + // Get a spawnpoint for team + foreach ( point in GetEntArrayByClass_Expensive( "info_spawnpoint_dropship_start" ) ) + { + if ( point.HasKey( "gamemode_tdm" ) ) + if ( point.kv[ "gamemode_tdm" ] == "0" ) + continue + + if ( point.GetTeam() == team ) + { + spawnPoint = point + break + } + } + + // Get nodes close enough to team spawnpoint + foreach ( node in dropPodNodes ) + { + if ( node.HasKey("teamnum") && Distance2D( node.GetOrigin(), spawnPoint.GetOrigin()) < 2000 ) + podNodes.append( node ) + } + } + else + { + // Sort per team + foreach ( node in dropPodNodes ) + { + if ( node.GetTeam() == team ) + podNodes.append( node ) + } + } + + shipNodes = GetValidIntroDropShipSpawn( podNodes ) + + + // Spawn logic + int startIndex = 0 + bool first = true + entity node + + int pods = RandomInt( podNodes.len() + 1 ) + + int ships = shipNodes.len() + + for ( int i = 0; i < SQUADS_PER_TEAM; i++ ) + { + if ( pods != 0 || ships == 0 ) + { + int index = i + + if ( index > podNodes.len() - 1 ) + index = RandomInt( podNodes.len() ) + + node = podNodes[ index ] + thread AiGameModes_SpawnDropPod( node.GetOrigin(), node.GetAngles(), team, "npc_soldier", SquadHandler ) + + pods-- + } + else + { + if ( startIndex == 0 ) + startIndex = i // save where we started + + node = shipNodes[ i - startIndex ] + thread AiGameModes_SpawnDropShip( node.GetOrigin(), node.GetAngles(), team, 4, SquadHandler ) + + ships-- + } + + // Vanilla has a delay after first spawn + if ( first ) + wait 2 + + first = false + } + + wait 15 + + thread Spawner_Threaded( team ) +} + +// Populates the match +void function Spawner_Threaded( int team ) +{ + svGlobal.levelEnt.EndSignal( "GameStateChanged" ) + + // used to index into escalation arrays + int index = team == TEAM_MILITIA ? 0 : 1 + + + while( true ) + { + Escalate( team ) + + // TODO: this should possibly not count scripted npc spawns, probably only the ones spawned by this script + array npcs = GetNPCArrayOfTeam( team ) + int count = npcs.len() + int reaperCount = GetNPCArrayEx( "npc_super_spectre", team, -1, <0,0,0>, -1 ).len() + + // REAPERS + if ( file.reapers[ index ] ) + { + array< entity > points = SpawnPoints_GetDropPod() + if ( reaperCount < REAPERS_PER_TEAM ) + { + entity node = points[ GetSpawnPointIndex( points, team ) ] + waitthread AiGameModes_SpawnReaper( node.GetOrigin(), node.GetAngles(), team, "npc_super_spectre_aitdm", ReaperHandler ) + } + } + + // NORMAL SPAWNS + if ( count < SQUADS_PER_TEAM * 4 - 2 ) + { + string ent = file.podEntities[ index ][ RandomInt( file.podEntities[ index ].len() ) ] + + array< entity > points = GetZiplineDropshipSpawns() + // Prefer dropship when spawning grunts + if ( ent == "npc_soldier" && points.len() != 0 ) + { + if ( RandomInt( points.len() ) ) + { + entity node = points[ GetSpawnPointIndex( points, team ) ] + waitthread AiGameModes_SpawnDropShip( node.GetOrigin(), node.GetAngles(), team, 4, SquadHandler ) + continue + } + } + + points = SpawnPoints_GetDropPod() + entity node = points[ GetSpawnPointIndex( points, team ) ] + waitthread AiGameModes_SpawnDropPod( node.GetOrigin(), node.GetAngles(), team, ent, SquadHandler ) + } + + WaitFrame() + } +} + +// Based on points tries to balance match +void function Escalate( int team ) +{ + int score = GameRules_GetTeamScore( team ) + int index = team == TEAM_MILITIA ? 1 : 0 + // This does the "Enemy x incoming" text + string defcon = team == TEAM_MILITIA ? "IMCdefcon" : "MILdefcon" + + // Return if the team is under score threshold to escalate + if ( score < file.levels[ index ] || file.reapers[ index ] ) + return + + // Based on score escalate a team + switch ( file.levels[ index ] ) + { + case LEVEL_SPECTRES: + file.levels[ index ] = LEVEL_STALKERS + file.podEntities[ index ].append( "npc_spectre" ) + SetGlobalNetInt( defcon, 2 ) + return + + case LEVEL_STALKERS: + file.levels[ index ] = LEVEL_REAPERS + file.podEntities[ index ].append( "npc_stalker" ) + SetGlobalNetInt( defcon, 3 ) + return + + case LEVEL_REAPERS: + file.reapers[ index ] = true + SetGlobalNetInt( defcon, 4 ) + return + } + + unreachable // hopefully +} + + +// Decides where to spawn ai +// Each team has their "zone" where they and their ai spawns +// These zones should swap based on which team is dominating where +int function GetSpawnPointIndex( array< entity > points, int team ) +{ + entity zone = DecideSpawnZone_Generic( points, team ) + + if ( IsValid( zone ) ) + { + // 20 Tries to get a random point close to the zone + for ( int i = 0; i < 20; i++ ) + { + int index = RandomInt( points.len() ) + + if ( Distance2D( points[ index ].GetOrigin(), zone.GetOrigin() ) < 6000 ) + return index + } + } + + return RandomInt( points.len() ) +} + +// tells infantry where to go +// In vanilla there seem to be preset paths ai follow to get to the other teams vone and capture it +// AI can also flee deeper into their zone suggesting someone spent way too much time on this +void function SquadHandler( array guys ) +{ + // Not all maps have assaultpoints / have weird assault points ( looking at you ac ) + // So we use enemies with a large radius + array< entity > points = GetNPCArrayOfEnemies( guys[0].GetTeam() ) + + if ( points.len() == 0 ) + return + + vector point + point = points[ RandomInt( points.len() ) ].GetOrigin() + + array players = GetPlayerArrayOfEnemies( guys[0].GetTeam() ) + + // Setup AI + foreach ( guy in guys ) + { + guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE ) + guy.AssaultPoint( point ) + guy.AssaultSetGoalRadius( 1600 ) // 1600 is minimum for npc_stalker, works fine for others + + // show on enemy radar + foreach ( player in players ) + guy.Minimap_AlwaysShow( 0, player ) + + + //thread AITdm_CleanupBoredNPCThread( guy ) + } + + // Every 5 - 15 secs change AssaultPoint + while ( true ) + { + foreach ( guy in guys ) + { + // Check if alive + if ( !IsAlive( guy ) ) + { + guys.removebyvalue( guy ) + continue + } + // Stop func if our squad has been killed off + if ( guys.len() == 0 ) + return + + // Get point and send guy to it + points = GetNPCArrayOfEnemies( guy.GetTeam() ) + if ( points.len() == 0 ) + continue + + point = points[ RandomInt( points.len() ) ].GetOrigin() + + guy.AssaultPoint( point ) + } + wait RandomFloatRange(5.0,15.0) + } +} + +// Award for hacking +void function OnSpectreLeeched( entity spectre, entity player ) +{ + // Set Owner so we can filter in HandleScore + spectre.SetOwner( player ) + // Add score + update network int to trigger the "Score +n" popup + AddTeamScore( player.GetTeam(), 1 ) + player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, 1 ) + player.SetPlayerNetInt("AT_bonusPoints", player.GetPlayerGameStat( PGS_ASSAULT_SCORE ) ) +} + +// Same as SquadHandler, just for reapers +void function ReaperHandler( entity reaper ) +{ + array players = GetPlayerArrayOfEnemies( reaper.GetTeam() ) + foreach ( player in players ) + reaper.Minimap_AlwaysShow( 0, player ) + + reaper.AssaultSetGoalRadius( 500 ) + + // Every 10 - 20 secs get a player and go to him + // Definetly not annoying or anything :) + while( IsAlive( reaper ) ) + { + players = GetPlayerArrayOfEnemies( reaper.GetTeam() ) + if ( players.len() != 0 ) + { + entity player = GetClosest2D( players, reaper.GetOrigin() ) + reaper.AssaultPoint( player.GetOrigin() ) + } + wait RandomFloatRange(10.0,20.0) + } + // thread AITdm_CleanupBoredNPCThread( reaper ) +} + +// Currently unused as this is handled by SquadHandler +// May need to use this if my implementation falls apart +void function AITdm_CleanupBoredNPCThread( entity guy ) +{ + // track all ai that we spawn, ensure that they're never "bored" (i.e. stuck by themselves doing fuckall with nobody to see them) for too long + // if they are, kill them so we can free up slots for more ai to spawn + // we shouldn't ever kill ai if players would notice them die + + // NOTE: this partially covers up for the fact that we script ai alot less than vanilla probably does + // vanilla probably messes more with making ai assaultpoint to fights when inactive and stuff like that, we don't do this so much + guy.EndSignal( "OnDestroy" ) + wait 15.0 // cover spawning time from dropship/pod + before we start cleaning up + + int cleanupFailures = 0 // when this hits 2, cleanup the npc + while ( cleanupFailures < 2 ) + { + wait 10.0 + + if ( guy.GetParent() != null ) + continue // never cleanup while spawning + + array otherGuys = GetPlayerArray() + otherGuys.extend( GetNPCArrayOfTeam( GetOtherTeam( guy.GetTeam() ) ) ) + + bool failedChecks = false + + foreach ( entity otherGuy in otherGuys ) + { + // skip dead people + if ( !IsAlive( otherGuy ) ) + continue + + failedChecks = false + + // don't kill if too close to anything + if ( Distance( otherGuy.GetOrigin(), guy.GetOrigin() ) < 2000.0 ) + break + + // don't kill if ai or players can see them + if ( otherGuy.IsPlayer() ) + { + if ( PlayerCanSee( otherGuy, guy, true, 135 ) ) + break + } + else + { + if ( otherGuy.CanSee( guy ) ) + break + } + + // don't kill if they can see any ai + if ( guy.CanSee( otherGuy ) ) + break + + failedChecks = true + } + + if ( failedChecks ) + cleanupFailures++ + else + cleanupFailures-- + } + + print( "cleaning up bored npc: " + guy + " from team " + guy.GetTeam() ) + guy.Destroy() } \ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_at.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_at.nut index 573ea72f..915e03e0 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_at.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_at.nut @@ -1,12 +1,376 @@ global function GamemodeAt_Init global function RateSpawnpoints_AT +const int BH_AI_TEAM = TEAM_BOTH +const int BOUNTY_TITAN_DAMAGE_POOL = 400 // Rewarded for damage +const int BOUNTY_TITAN_KILL_REWARD = 100 // Rewarded for kill +const float WAVE_STATE_TRANSITION_TIME = 5.0 + +const array VALID_BOUNTY_TITAN_SETTINGS = [ + "npc_titan_atlas_stickybomb_bounty", + "npc_titan_atlas_tracker_bounty", + "npc_titan_ogre_minigun_bounty", + "npc_titan_ogre_meteor_bounty", + "npc_titan_stryder_leadwall_bounty", + "npc_titan_stryder_sniper_bounty", + "npc_titan_atlas_vanguard_bounty" +] + + +// IMPLEMENTATION NOTES: +// bounty hunt is a mode that was clearly pretty heavily developed, and had alot of scrapped concepts (i.e. most wanted player bounties, turret bounties, collectable blackbox objectives) +// in the interest of time, this script isn't gonna support any of that atm +// alot of the remote functions also take parameters that aren't used, i'm not gonna populate these and just use default values for now instead +// however, if you do want to mess with this stuff, almost all the remote functions for this stuff are still present in cl_gamemode_at, and should work fine with minimal fuckery in my experience + +struct { + array campsToRegisterOnEntitiesDidLoad + + array banks + array camps + + table< int, table< string, int > > trackedCampNPCSpawns +} file + void function GamemodeAt_Init() { + AddCallback_GameStateEnter( eGameState.Playing, RunATGame ) + + AddCallback_OnClientConnected( InitialiseATPlayer ) + AddSpawnCallbackEditorClass( "info_target", "info_attrition_bank", CreateATBank ) + AddSpawnCallbackEditorClass( "info_target", "info_attrition_camp", CreateATCamp ) + AddCallback_EntitiesDidLoad( CreateATCamps_Delayed ) } void function RateSpawnpoints_AT( int checkclass, array spawnpoints, int team, entity player ) { RateSpawnpoints_Generic( checkclass, spawnpoints, team, player ) // temp -} \ No newline at end of file +} + +// world and player inits + +void function InitialiseATPlayer( entity player ) +{ + Remote_CallFunction_NonReplay( player, "ServerCallback_AT_OnPlayerConnected" ) +} + +void function CreateATBank( entity spawnpoint ) +{ + entity bank = CreatePropDynamic( spawnpoint.GetModelName(), spawnpoint.GetOrigin(), spawnpoint.GetAngles(), SOLID_VPHYSICS ) + bank.SetScriptName( "AT_Bank" ) + + // create tracker ent + // we don't need to store these at all, client just needs to get them + DispatchSpawn( GetAvailableBankTracker( bank ) ) + + thread PlayAnim( bank, "mh_inactive_idle" ) + + file.banks.append( bank ) +} + +void function CreateATCamp( entity spawnpoint ) +{ + // delay this so we don't do stuff before all spawns are initialised and that + file.campsToRegisterOnEntitiesDidLoad.append( spawnpoint ) +} + +void function CreateATCamps_Delayed() +{ + // we delay registering camps until EntitiesDidLoad since they rely on spawnpoints and stuff, which might not all be ready in the creation callback + // unsure if this would be an issue in practice, but protecting against it in case it would be + foreach ( entity camp in file.campsToRegisterOnEntitiesDidLoad ) + { + AT_WaveOrigin campStruct + campStruct.ent = camp + campStruct.origin = camp.GetOrigin() + campStruct.radius = expect string( camp.kv.radius ).tofloat() + campStruct.height = expect string( camp.kv.height ).tofloat() + + // assumes every info_attrition_camp will have all 9 phases, possibly not a good idea? + for ( int i = 0; i < 9; i++ ) + campStruct.phaseAllowed.append( expect string( camp.kv[ "phase_" + ( i + 1 ) ] ) == "1" ) + + // get droppod spawns + foreach ( entity spawnpoint in SpawnPoints_GetDropPod() ) + if ( Distance( camp.GetOrigin(), spawnpoint.GetOrigin() ) < 1500.0 ) + campStruct.dropPodSpawnPoints.append( spawnpoint ) + + foreach ( entity spawnpoint in SpawnPoints_GetTitan() ) + if ( Distance( camp.GetOrigin(), spawnpoint.GetOrigin() ) < 1500.0 ) + campStruct.titanSpawnPoints.append( spawnpoint ) + + // todo: turret spawns someday maybe + + file.camps.append( campStruct ) + } + + file.campsToRegisterOnEntitiesDidLoad.clear() +} + +// scoring funcs + +// don't use this where possible as it doesn't set score and stuff +void function AT_SetPlayerCash( entity player, int amount ) +{ + // split into stacks of 256 where necessary + int stacks = amount / 256 // automatically rounds down because int division + + player.SetPlayerNetInt( "AT_bonusPoints256", stacks ) + player.SetPlayerNetInt( "AT_bonusPoints", amount - stacks * 256 ) +} + +void function AT_AddPlayerCash( entity player, int amount ) +{ + // update score difference + AddTeamScore( player.GetTeam(), amount / 2 ) + AT_SetPlayerCash( player, player.GetPlayerNetInt( "AT_bonusPoints" ) + ( player.GetPlayerNetInt( "AT_bonusPoints256" ) * 256 ) + amount ) +} + +// run gamestate + +void function RunATGame() +{ + thread RunATGame_Threaded() +} + +void function RunATGame_Threaded() +{ + svGlobal.levelEnt.EndSignal( "GameStateChanged" ) + + OnThreadEnd( function() + { + SetGlobalNetBool( "banksOpen", false ) + }) + + wait WAVE_STATE_TRANSITION_TIME // initial wait before first wave + + for ( int waveCount = 1; ; waveCount++ ) + { + wait WAVE_STATE_TRANSITION_TIME + + // cap to number of real waves + int waveId = ( waveCount / 2 ) + // last wave is clearly unfinished so don't use, just cap to last actually used one + if ( waveId >= GetWaveDataSize() - 1 ) + { + waveId = GetWaveDataSize() - 2 + waveCount = waveId * 2 + } + + SetGlobalNetInt( "AT_currentWave", waveId ) + bool isBossWave = waveCount / float( 2 ) > waveId // odd number waveCount means boss wave + + // announce the wave + foreach ( entity player in GetPlayerArray() ) + { + if ( isBossWave ) + Remote_CallFunction_NonReplay( player, "ServerCallback_AT_AnnounceBoss" ) + else + Remote_CallFunction_NonReplay( player, "ServerCallback_AT_AnnouncePreParty", 0.0, waveId ) + } + + wait WAVE_STATE_TRANSITION_TIME + + // run the wave + + AT_WaveData wave = GetWaveData( waveId ) + array< array > campSpawnData + + if ( isBossWave ) + campSpawnData = wave.bossSpawnData + else + campSpawnData = wave.spawnDataArrays + + // initialise pending spawns + foreach ( array< AT_SpawnData > campData in campSpawnData ) + { + foreach ( AT_SpawnData spawnData in campData ) + spawnData.pendingSpawns = spawnData.totalToSpawn + } + + // clear tracked spawns + file.trackedCampNPCSpawns = {} + while ( true ) + { + // if this is ever 0 by the end of this loop, wave is complete + int numActiveCampSpawners = 0 + + // iterate over camp data for wave + for ( int campIdx = 0; campIdx < campSpawnData.len() && campIdx < file.camps.len(); campIdx++ ) + { + if ( !( campIdx in file.trackedCampNPCSpawns ) ) + file.trackedCampNPCSpawns[ campIdx ] <- {} + + // iterate over ai spawn data for camp + foreach ( AT_SpawnData spawnData in campSpawnData[ campIdx ] ) + { + if ( !( spawnData.aitype in file.trackedCampNPCSpawns[ campIdx ] ) ) + file.trackedCampNPCSpawns[ campIdx ][ spawnData.aitype ] <- 0 + + if ( spawnData.pendingSpawns > 0 || file.trackedCampNPCSpawns[ campIdx ][ spawnData.aitype ] > 0 ) + numActiveCampSpawners++ + + // try to spawn as many ai as we can, as long as the camp doesn't already have too many spawned + int spawnCount + for ( spawnCount = 0; spawnCount < spawnData.pendingSpawns && spawnCount < spawnData.totalAllowedOnField - file.trackedCampNPCSpawns[ campIdx ][ spawnData.aitype ]; ) + { + // not doing this in a generic way atm, but could be good for the future if we want to support more ai + switch ( spawnData.aitype ) + { + case "npc_soldier": + case "npc_spectre": + case "npc_stalker": + thread AT_SpawnDroppodSquad( campIdx, spawnData.aitype ) + spawnCount += 4 + break + + case "npc_super_spectre": + thread AT_SpawnReaper( campIdx ) + spawnCount += 1 + break + + case "npc_titan": + thread AT_SpawnBountyTitan( campIdx ) + spawnCount += 1 + break + + default: + print( "BOUNTY HUNT: Tried to spawn unsupported ai of type \"" + "\" at camp " + campIdx ) + } + } + + // track spawns + file.trackedCampNPCSpawns[ campIdx ][ spawnData.aitype ] += spawnCount + spawnData.pendingSpawns -= spawnCount + } + } + + if ( numActiveCampSpawners == 0 ) + break + + wait 0.5 + } + + wait WAVE_STATE_TRANSITION_TIME + + // banking phase + } +} + +// entity funcs + +void function AT_SpawnDroppodSquad( int camp, string aiType ) +{ + entity spawnpoint + if ( file.camps[ camp ].dropPodSpawnPoints.len() == 0 ) + spawnpoint = file.camps[ camp ].ent + else + spawnpoint = file.camps[ camp ].dropPodSpawnPoints.getrandom() + + // add variation to spawns + wait RandomFloat( 1.0 ) + + AiGameModes_SpawnDropPod( spawnpoint.GetOrigin(), spawnpoint.GetAngles(), BH_AI_TEAM, aiType, void function( array guys ) : ( camp, aiType ) + { + AT_HandleSquadSpawn( guys, camp, aiType ) + }) +} + +void function AT_HandleSquadSpawn( array guys, int camp, string aiType ) +{ + foreach ( entity guy in guys ) + { + guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE ) + + // untrack them on death + thread AT_WaitToUntrackNPC( guy, camp, aiType ) + } +} + +void function AT_SpawnReaper( int camp ) +{ + entity spawnpoint + if ( file.camps[ camp ].dropPodSpawnPoints.len() == 0 ) + spawnpoint = file.camps[ camp ].ent + else + spawnpoint = file.camps[ camp ].titanSpawnPoints.getrandom() + + // add variation to spawns + wait RandomFloat( 1.0 ) + + AiGameModes_SpawnReaper( spawnpoint.GetOrigin(), spawnpoint.GetAngles(), BH_AI_TEAM, "npc_super_spectre",void function( entity reaper ) : ( camp ) + { + thread AT_WaitToUntrackNPC( reaper, camp, "npc_super_spectre" ) + }) +} + +void function AT_SpawnBountyTitan( int camp ) +{ + entity spawnpoint + if ( file.camps[ camp ].dropPodSpawnPoints.len() == 0 ) + spawnpoint = file.camps[ camp ].ent + else + spawnpoint = file.camps[ camp ].titanSpawnPoints.getrandom() + + // add variation to spawns + wait RandomFloat( 1.0 ) + + // look up titan to use + int bountyID = 0 + try + { + bountyID = ReserveBossID( VALID_BOUNTY_TITAN_SETTINGS.getrandom() ) + } + catch ( ex ) {} // if we go above the expected wave count that vanilla supports, there's basically no way to ensure that this func won't error, so default 0 after that point + + string aisettings = GetTypeFromBossID( bountyID ) + string titanClass = expect string( Dev_GetAISettingByKeyField_Global( aisettings, "npc_titan_player_settings" ) ) + + + AiGameModes_SpawnTitan( spawnpoint.GetOrigin(), spawnpoint.GetAngles(), BH_AI_TEAM, titanClass, aisettings, void function( entity titan ) : ( camp, bountyID ) + { + // set up titan-specific death/damage callbacks + AddEntityCallback_OnDamaged( titan, OnBountyDamaged) + AddEntityCallback_OnKilled( titan, OnBountyKilled ) + + titan.GetTitanSoul().soul.skipDoomState = true + // i feel like this should be localised, but there's nothing for it in r1_english? + titan.SetTitle( GetNameFromBossID( bountyID ) ) + thread AT_WaitToUntrackNPC( titan, camp, "npc_titan" ) + } ) +} + +// Tracked entities will require their own "wallet" +// for titans it should be used for rounding error compenstation +// for infantry it sould be used to store money if the npc kills a player +void function OnBountyDamaged( entity titan, var damageInfo ) +{ + entity attacker = DamageInfo_GetAttacker( damageInfo ) + if ( !attacker.IsPlayer() ) + attacker = GetLatestAssistingPlayerInfo( titan ).player + + if ( IsValid( attacker ) && attacker.IsPlayer() ) + { + int reward = int ( BOUNTY_TITAN_DAMAGE_POOL * DamageInfo_GetDamage( damageInfo ) / titan.GetMaxHealth() ) + printt ( titan.GetMaxHealth(), DamageInfo_GetDamage( damageInfo ) ) + + AT_AddPlayerCash( attacker, reward ) + } +} + +void function OnBountyKilled( entity titan, var damageInfo ) +{ + entity attacker = DamageInfo_GetAttacker( damageInfo ) + if ( !attacker.IsPlayer() ) + attacker = GetLatestAssistingPlayerInfo( titan ).player + + if ( IsValid( attacker ) && attacker.IsPlayer() ) + AT_AddPlayerCash( attacker, BOUNTY_TITAN_KILL_REWARD ) +} + +void function AT_WaitToUntrackNPC( entity guy, int camp, string aiType ) +{ + guy.WaitSignal( "OnDeath", "OnDestroy" ) + file.trackedCampNPCSpawns[ camp ][ aiType ]-- +} diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut index 719ea336..ccccefaf 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut @@ -38,7 +38,8 @@ void function PrivateMatchModesInit() AddPrivateMatchModeSettingEnum( "#GAMEMODE_cp", "cp_amped_capture_points", [ "#SETTING_DISABLED", "#SETTING_ENABLED" ], "1" ) // would've been nice to use amped_capture_points, but this var is already used ingame and its value is default 0 AddPrivateMatchModeSettingEnum( "#GAMEMODE_coliseum", "coliseum_loadouts_#SETTING_ENABLED", [ "#SETTING_DISABLED", "#SETTING_ENABLED" ], "1" ) - + + AddPrivateMatchModeSettingEnum( "#PL_aitdm", "aitdm_archer_grunts", [ "Disabled", "Enabled" ], "0" ) // modes AddPrivateMatchMode( "ffa" ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut index 42aa4a62..bfcd23e0 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut @@ -682,7 +682,7 @@ void function CleanUpEntitiesForRoundEnd() foreach ( entity npc in GetNPCArray() ) { - if ( !IsValid( npc ) ) + if ( !IsValid( npc ) || !IsAlive( npc ) ) continue // kill rather than destroy, as destroying will cause issues with children which is an issue especially for dropships and titans npc.Die( svGlobal.worldspawn, svGlobal.worldspawn, { damageSourceId = eDamageSourceId.round_end } ) -- cgit v1.2.3 From 44894dfde583f7fb3a4491b4f17893a907336d1f Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Fri, 29 Apr 2022 23:28:41 +0200 Subject: Add default sort method for server browser (#303) * Add default sort method * Do gecko's change * Fixed it * Set default sort mode when opening browser * Update Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> * remove trailing space <3 gecko Co-authored-by: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> --- .../scripts/vscripts/ui/menu_ns_serverbrowser.nut | 39 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index c77000e9..5f6cda1a 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -33,6 +33,7 @@ struct { enum sortingBy { NONE, + DEFAULT, NAME, PLAYERS, MAP, @@ -48,8 +49,8 @@ struct { bool serverMap = true bool serverGamemode = true bool serverLatency = true - // 0 = none; 1 = name; 2 = players; 3 = map; 5 = gamemode; 6 = latency - int sortingBy = 0 + // 0 = none; 1 = default; 2 = name; 3 = players; 4 = map; 5 = gamemode; 6 = latency + int sortingBy = 1 } filterDirection struct serverStruct { @@ -425,6 +426,8 @@ void function OnServerBrowserMenuOpened() NSRequestServerList() } + filterDirection.sortingBy = sortingBy.DEFAULT + thread WaitForServerListRequest() @@ -652,6 +655,10 @@ void function FilterAndUpdateList( var n ) case sortingBy.NONE: UpdateShownPage() break + case sortingBy.DEFAULT: + filterDirection.serverName = !filterDirection.serverName + SortServerListByDefault_Activate(0) + break case sortingBy.NAME: filterDirection.serverName = !filterDirection.serverName SortServerListByName_Activate(0) @@ -1119,6 +1126,22 @@ int function ServerSortLogic ( serverStruct a, serverStruct b ) // We can hard code this cause adding entire columns isn't as easy switch ( filterDirection.sortingBy ) { + case sortingBy.DEFAULT: + aTemp = a.serverPlayers + bTemp = b.serverPlayers + + // `1000` is assumed to always be higher than `serverPlayersMax` + if (aTemp + 1 < a.serverPlayersMax) + aTemp = aTemp+2000 + if (bTemp + 1 < b.serverPlayersMax) + bTemp = bTemp+2000 + if (aTemp + 1 == a.serverPlayersMax) + aTemp = aTemp+1000 + if (bTemp + 1 == b.serverPlayersMax) + bTemp = bTemp+1000 + + direction = filterDirection.serverName + break; case sortingBy.NAME: aTemp = a.serverName.tolower() bTemp = b.serverName.tolower() @@ -1159,6 +1182,18 @@ int function ServerSortLogic ( serverStruct a, serverStruct b ) return 0 } +void function SortServerListByDefault_Activate ( var button ) +{ + filterDirection.sortingBy = sortingBy.DEFAULT + + file.serversArrayFiltered.sort( ServerSortLogic ) + + filterDirection.serverName = !filterDirection.serverName + + UpdateShownPage() +} + + void function SortServerListByName_Activate ( var button ) { filterDirection.sortingBy = sortingBy.NAME -- cgit v1.2.3 From c6b59dc449f4a39247b65d7800d04057f2f26be6 Mon Sep 17 00:00:00 2001 From: BotchedRPR <68894028+BotchedRPR@users.noreply.github.com> Date: Wed, 1 Jun 2022 14:17:24 +0200 Subject: Display Northstar version on title screen (#346) * Create main.menu for showing NS version on title screen * Display Northstar version on main menu. Pulling data from Northstar.Custom, now the version of Northstar is displayed on the main menu, above the Respawn logo. * Get version data from Northstar.Client instead of Northstar.Custom * formatted main.menu --- Northstar.Client/mod.json | 7 + Northstar.Client/mod/resource/ui/menus/main.menu | 176 +++++++++++++++++++++ .../vscripts/ui/menu_ns_setversionlabel.nut | 10 ++ 3 files changed, 193 insertions(+) create mode 100644 Northstar.Client/mod/resource/ui/menus/main.menu create mode 100644 Northstar.Client/mod/scripts/vscripts/ui/menu_ns_setversionlabel.nut (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 667c4aa2..100681d2 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -53,6 +53,13 @@ "After": "AddNorthstarModMenu_MainMenuFooter" } }, + { + "Path": "ui/menu_ns_setversionlabel.nut", + "RunOn": "UI", + "UICallback": { + "After": "NS_SetVersionLabel" + } + }, { "Path": "presence/ui_presence.nut", "RunOn": "UI", diff --git a/Northstar.Client/mod/resource/ui/menus/main.menu b/Northstar.Client/mod/resource/ui/menus/main.menu new file mode 100644 index 00000000..56198d94 --- /dev/null +++ b/Northstar.Client/mod/resource/ui/menus/main.menu @@ -0,0 +1,176 @@ +resource/ui/menus/main.menu +{ + menu + { + ControlName Frame + xpos 0 + ypos 0 + zpos 3 + wide f0 + tall f0 + autoResize 0 + pinCorner 0 + visible 1 + enabled 1 + tabPosition 0 + PaintBackgroundType 0 // 0 for normal(opaque), 1 for single texture from Texture1, and 2 for rounded box w/ four corner textures + infocus_bgcolor_override "0 0 0 0" + outoffocus_bgcolor_override "0 0 0 0" + + Screen + { + ControlName Label + wide %100 + tall %100 + labelText "" + visible 0 + } + + SafeArea + { + ControlName Label + wide %90 + tall %90 + labelText "" + visible 0 + + pin_to_sibling Screen + pin_corner_to_sibling CENTER + pin_to_sibling_corner CENTER + } + + TitleRui + { + ControlName RuiPanel + xpos -50 + ypos -160 + wide 1408 + tall 288 + rui "ui/basic_image_premul.rpak" + visible 1 + + pin_to_sibling Screen + pin_corner_to_sibling CENTER + pin_to_sibling_corner CENTER + } + + TrialLabel + { + ControlName Label + xpos -850 + ypos -190 + auto_wide_tocontents 1 + auto_tall_tocontents 1 + labelText "#TRIAL_MODE" + font DefaultBold_65 + visible 1 + fgcolor_override "254 184 0 255" + + pin_to_sibling TitleRui + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + VersionDisplay + { + ControlName Label + xpos -920 + ypos -198 + auto_wide_tocontents 1 + auto_tall_tocontents 1 + labelText "" + font Default_21 + visible 0 + fgcolor_override "120 120 140 0" + + pin_to_sibling TitleRui + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } + + CopyrightInfo + { + ControlName Label + ypos -4 + zpos 5 + wide 674 + auto_tall_tocontents 1 + labelText "#COPYRIGHT_TEXT" + font Default_16 + textAlignment east + allcaps 1 + visible 1 + fgcolor_override "255 255 255 127" + + pin_to_sibling SafeArea + pin_corner_to_sibling BOTTOM_RIGHT + pin_to_sibling_corner BOTTOM_RIGHT + } + + RespawnLogo + { + ControlName ImagePanel + xpos 24 + wide 284 + tall 56 + visible 1 + image "ui/menu/title_screen/title_respawn_logo" + scaleImage 1 + + pin_to_sibling CopyrightInfo + pin_corner_to_sibling BOTTOM_RIGHT + pin_to_sibling_corner TOP_RIGHT + } + + NSVersion + { + ControlName Label + classname "nsVersionClass" + xpos 0 + ypos 0 + auto_wide_tocontents 1 + auto_tall_tocontents 1 + labelText "" + font Default_21 + textAlignment east + allcaps 0 + visible 1 + fgcolor_override "101 109 208 255" + pin_to_sibling VersionDisplay + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + EstablishUserPanel + { + ControlName CNestedPanel + classname "MainMenuPanelClass" + wide 1920 + tall 1080 + visible 0 + controlSettingsFile "resource/ui/menus/panels/establish_user.res" + } + + MainMenuPanel + { + ControlName CNestedPanel + classname "MainMenuPanelClass" + //wide 1920 + //tall 1080 + wide %100 + tall %100 + visible 0 + tabPosition 1 + controlSettingsFile "resource/ui/menus/panels/mainmenu.res" + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + FooterButtons + { + ControlName CNestedPanel + InheritProperties FooterButtons + } + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_setversionlabel.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_setversionlabel.nut new file mode 100644 index 00000000..6dbafde9 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_setversionlabel.nut @@ -0,0 +1,10 @@ +untyped +global function NS_SetVersionLabel + +void function NS_SetVersionLabel() +{ + var mainMenu = GetMenu( "MainMenu" ) //Gets main menu element + var versionLabel = GetElementsByClassname( mainMenu, "nsVersionClass" )[0] //Gets the label from the mainMenu element. + Hud_SetText( versionLabel, "v" + NSGetModVersionByModName("Northstar.Client")) //Sets the label text (Getting Northstar version from Northstar.Client) +} + -- cgit v1.2.3 From b67a880c042d926352a6b3e7ed9148883b9b8bd8 Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Mon, 13 Jun 2022 22:13:34 +0200 Subject: Unlock SP when Coop is selected (#383) --- Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut index efe1d462..930e472b 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut @@ -309,7 +309,7 @@ void function LockMapButton( var element ) bool function IsLocked( string map ) { - bool sp = map.find( "sp_" ) == 0 + bool sp = map.find( "sp_" ) == 0 && PrivateMatch_GetSelectedMode() != "sp_coop" if ( sp ) return true -- cgit v1.2.3 From bdf8e684550ee4763e7eb93ae9e561ddc0dbde9a Mon Sep 17 00:00:00 2001 From: Emma Miler <27428383+emma-miler@users.noreply.github.com> Date: Thu, 16 Jun 2022 01:36:36 +0200 Subject: Localize masterserver errors (#333) * Dependent commit * Add english localization * Update northstar_client_localisation_mspanish.txt * Add more localizations * Update northstar_client_localisation_spanish.txt * Adhere to code style --- .../northstar_client_localisation_english.txt | 11 +++++++++++ .../northstar_client_localisation_french.txt | 11 +++++++++++ .../northstar_client_localisation_german.txt | 11 +++++++++++ .../northstar_client_localisation_italian.txt | 11 +++++++++++ .../northstar_client_localisation_mspanish.txt | 11 +++++++++++ .../northstar_client_localisation_russian.txt | 11 +++++++++++ .../northstar_client_localisation_spanish.txt | 11 +++++++++++ .../northstar_client_localisation_tchinese.txt | 11 +++++++++++ .../mod/scripts/vscripts/ui/panel_mainmenu.nut | 23 +++++++++++++++++----- 9 files changed, 106 insertions(+), 5 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index 50f2b51e..8c6cadcf 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -308,5 +308,16 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "Couldn't reach game server" + "BAD_GAMESERVER_RESPONSE" "Game server gave an invalid response" + "UNAUTHORIZED_GAMESERVER" "Game server is not authorized to make that request" + "UNAUTHORIZED_GAME" "Stryder couldn't confirm that this account owns Titanfall 2" + "UNAUTHORIZED_PWD" "Wrong password" + "STRYDER_RESPONSE" "Couldn't parse stryder response" + "PLAYER_NOT_FOUND" "Couldn't find player account" + "INVALID_MASTERSERVER_TOKEN" "Invalid or expired masterserver token" + "JSON_PARSE_ERROR" "Error parsing json response" + "UNSUPPORTED_VERSION" "The version you are using is no longer supported" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt index 8ad8b1c7..0d4786a0 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_french.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_french.txt @@ -306,5 +306,16 @@ Choisissez Oui si vous êtes d'accord. Ce choix peut être modifié à tout inst // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "Le serveur de jeu ne répond pas" + "BAD_GAMESERVER_RESPONSE" "Le serveur a renvoyé une réponse invalide" + "UNAUTHORIZED_GAMESERVER" "Le serveur de jeu n'est pas autorisé à réaliser cette requête" + "UNAUTHORIZED_GAME" "Stryder n'a pas pu confirmer que ce compte possède Titanfall 2" + "UNAUTHORIZED_PWD" "Mot de passe incorrect" + "STRYDER_RESPONSE" "Impossible d'analyser la réponse de Stryder" + "PLAYER_NOT_FOUND" "Impossible de trouver le compte du joueur" + "INVALID_MASTERSERVER_TOKEN" "Jeton du server maître invalide ou expiré" + "JSON_PARSE_ERROR" "Une erreur est survenue durant l'analyse JSON" + "UNSUPPORTED_VERSION" "La version que vous utilisez n'est plus supportée" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_german.txt b/Northstar.Client/mod/resource/northstar_client_localisation_german.txt index 2b5d2011..0eded5bc 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_german.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_german.txt @@ -269,5 +269,16 @@ Drücke Ja, um zuzustimmen. Du kannst diese Entscheidung jederzeit im Modmenü // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "Konnte den Server nicht erreichen" + "BAD_GAMESERVER_RESPONSE" "Ungültige Antwort vom Server erhalten" + "UNAUTHORIZED_GAMESERVER" "Der Server ist nicht autorisiert, diese Anfrage zu machen" + "UNAUTHORIZED_GAME" "Stryder konnte nicht bestätigen, dass dieser Account Titanfall 2 besitzt" + "UNAUTHORIZED_PWD" "Falsches Passwort" + "STRYDER_RESPONSE" "Stryder Antwort konnte nicht verarbeitet werden" + "PLAYER_NOT_FOUND" "Konnte das Spielerprofil nicht finden" + "INVALID_MASTERSERVER_TOKEN" "Ungültiger oder abgelaufener Token vom Masterserver" + "JSON_PARSE_ERROR" "Fehler beim Verarbeiten der JSON-Antwort" + "UNSUPPORTED_VERSION" "Die Version die du benutzt ist nicht länger unterstützt" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt index 897d2ba5..b8253ad9 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_italian.txt @@ -260,5 +260,16 @@ Premi Sì se sei d'accordo. Questa scelta può essere modificata in qualsiasi mo // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "Non è stato possibile raggiungere il server" + "BAD_GAMESERVER_RESPONSE" "Il server ha dato una risposta invalida" + "UNAUTHORIZED_GAMESERVER" "Il server non è autorizzato a fare quella richiesta" + "UNAUTHORIZED_GAME" "Stryder non è riuscito a confermare che questo account possiede Titanfall 2" + "UNAUTHORIZED_PWD" "Password errata" + "STRYDER_RESPONSE" "Non è stato possibile analizzare la risposta Stryder" + "PLAYER_NOT_FOUND" "Non è stato trovato l'account player" + "INVALID_MASTERSERVER_TOKEN" "Token Masterserver invalido o scaduto" + "JSON_PARSE_ERROR" "Errore nell'analisi di risposta json" + "UNSUPPORTED_VERSION" "La versione che stai usando non è più supportata" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt b/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt index 5d3a1bba..ea62415e 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_mspanish.txt @@ -306,5 +306,16 @@ Si estas de acuerdo con esto, presiona SI. Esta decision puede ser cambiada en e // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[SUSURRO]" "HUD_CHAT_SERVER_PREFIX" "[SERVIDOR]" + + "NO_GAMESERVER_RESPONSE" "No se pudo conectar al servidor" + "BAD_GAMESERVER_RESPONSE" "Servidor dio respuesta invalida" + "UNAUTHORIZED_GAMESERVER" "Servidor no esta autorizado" + "UNAUTHORIZED_GAME" "Stryder no pudo comprobar que esta cuenta posea Titanfall 2" + "UNAUTHORIZED_PWD" "Contraseña incorrecta" + "STRYDER_RESPONSE" "No se pudo procesar la respuesta del servidor" + "PLAYER_NOT_FOUND" "No se encontró la cuenta del jugador" + "INVALID_MASTERSERVER_TOKEN" "Token de jugador expirado o invalido" + "JSON_PARSE_ERROR" "Error procesando respuesta json" + "UNSUPPORTED_VERSION" "La versión que estas usando ya no esta soportada" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt index 28dd016f..af9eb0ff 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_russian.txt @@ -242,5 +242,16 @@ // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "Игровой сервер не отвечает" + "BAD_GAMESERVER_RESPONSE" "Игровой сервер не дал правильного ответа" + "UNAUTHORIZED_GAMESERVER" "Игровой сервер не авторизирован чтобы сделать данный запрос" + "UNAUTHORIZED_GAME" "Не удалось найти Titanfall 2 на этом аккаунте" + "UNAUTHORIZED_PWD" "Неправильный пароль" + "STRYDER_RESPONSE" "Не удалось разобрать ответ stryder" + "PLAYER_NOT_FOUND" "Не удалось найти аккаунт игрока" + "INVALID_MASTERSERVER_TOKEN" "Срок действия жетона главного сервера истек или не является правильным" + "JSON_PARSE_ERROR" "Ошибка разбора ответа json" + "UNSUPPORTED_VERSION" "Используемая вами версия больше не поддерживается" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt index ac896e7b..8d2df53b 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_spanish.txt @@ -306,5 +306,16 @@ Presiona Sí al estar de acuerdo. Esta opcion se puede cambiar en el menú de mo // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[SUSURRO]" "HUD_CHAT_SERVER_PREFIX" "[SERVIDOR]" + + "NO_GAMESERVER_RESPONSE" "No se pudo conectar al servidor" + "BAD_GAMESERVER_RESPONSE" "Servidor dio respuesta invalida" + "UNAUTHORIZED_GAMESERVER" "Servidor no esta autorizado" + "UNAUTHORIZED_GAME" "Stryder no pudo comprobar que esta cuenta posea Titanfall 2" + "UNAUTHORIZED_PWD" "Contraseña incorrecta" + "STRYDER_RESPONSE" "No se pudo procesar la respuesta del servidor" + "PLAYER_NOT_FOUND" "No se encontró la cuenta del jugador" + "INVALID_MASTERSERVER_TOKEN" "Token de jugador expirado o invalido" + "JSON_PARSE_ERROR" "Error procesando respuesta json" + "UNSUPPORTED_VERSION" "La versión que estas usando ya no esta soportada" } } diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt index 4981a0a8..5e6721a9 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_tchinese.txt @@ -310,5 +310,16 @@ // In-game chat "HUD_CHAT_WHISPER_PREFIX" "[WHISPER]" "HUD_CHAT_SERVER_PREFIX" "[SERVER]" + + "NO_GAMESERVER_RESPONSE" "無法連接到遊戲伺服器'" + "BAD_GAMESERVER_RESPONSE" "遊戲伺服器回應無效" + "UNAUTHORIZED_GAMESERVER" "遊戲伺服器無法完成請求,因為它未與主伺服器進行驗證" + "UNAUTHORIZED_GAME" "Stryder 無法確認當前賬戶擁有Titanfall 2" + "UNAUTHORIZED_PWD" "密碼錯誤" + "STRYDER_RESPONSE" "無法讀取Stryder回應" + "PLAYER_NOT_FOUND" "找不到玩家賬戶" + "INVALID_MASTERSERVER_TOKEN" "主伺服器token過期或無效" + "JSON_PARSE_ERROR" "讀取json回應時發生錯誤" + "UNSUPPORTED_VERSION" "您的遊戲版本過低" } } diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index 171ee7dc..95b7bdae 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -559,15 +559,28 @@ void function TryAuthWithLocalServer() if ( NSWasAuthSuccessful() ) { NSCompleteAuthWithLocalServer() + if ( GetConVarString( "mp_gamemode" ) == "solo" ) + SetConVarString( "mp_gamemode", "tdm" ) + + CloseAllDialogs() + + ClientCommand( "setplaylist tdm" ) + ClientCommand( "map mp_lobby" ) } + else + { + CloseAllDialogs() - if ( GetConVarString( "mp_gamemode" ) == "solo" ) - SetConVarString( "mp_gamemode", "tdm" ) + var reason = NSGetAuthFailReason() - CloseAllDialogs() + DialogData dialogData + dialogData.image = $"ui/menu/common/dialog_error" + dialogData.header = "#ERROR" + dialogData.message = Localize("#NS_SERVERBROWSER_CONNECTIONFAILED") + "\nERROR: " + reason + "\n" + Localize("#" + reason) - ClientCommand( "setplaylist tdm" ) - ClientCommand( "map mp_lobby" ) + AddDialogButton( dialogData, "#OK", null ) + OpenDialog( dialogData ) + } } void function CancelNSLocalAuth() -- cgit v1.2.3 From 9fb0e0732c09b1b7f84c657d877b87516619950a Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Thu, 16 Jun 2022 02:20:31 +0200 Subject: Include server description in search (#388) --- .../scripts/vscripts/ui/menu_ns_serverbrowser.nut | 87 +++++++++++----------- 1 file changed, 43 insertions(+), 44 deletions(-) (limited to 'Northstar.Client/mod/scripts/vscripts') diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut index 5f6cda1a..eb068374 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -760,54 +760,53 @@ void function FilterServerList() totalPlayers += tempServer.serverPlayers - // Branchless programming ;) - if ( !( filterArguments.hideEmpty && tempServer.serverPlayers == 0 ) && !( filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax ) && !( filterArguments.hideProtected && tempServer.serverProtected ) ) - { - if ( filterArguments.useSearch ) - { - string sName = tempServer.serverName.tolower() + " " + Localize( GetMapDisplayName( tempServer.serverMap ) ).tolower() + " " + tempServer.serverMap.tolower() + " " + tempServer.serverGamemode.tolower() + " " + Localize( tempServer.serverGamemode ).tolower() - - string sTerm = filterArguments.searchTerm.tolower() - - if ( sName.find( sTerm ) != null) - { - if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap ) - { - CheckGamemode( tempServer ) - } - else if ( filterArguments.filterMap == "SWITCH_ANY" ) - { - CheckGamemode( tempServer ) - } - } - } - else + // Filters + if ( filterArguments.hideEmpty && tempServer.serverPlayers == 0 ) + continue; + + if ( filterArguments.hideFull && tempServer.serverPlayers == tempServer.serverPlayersMax ) + continue; + + if ( filterArguments.hideProtected && tempServer.serverProtected ) + continue; + + if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap != tempServer.serverMap ) + continue; + + if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode != tempServer.serverGamemode ) + continue; + + // Search + if ( filterArguments.useSearch ) + { + array sName + sName.append( tempServer.serverName.tolower() ) + sName.append( Localize( GetMapDisplayName( tempServer.serverMap ) ).tolower() ) + sName.append( tempServer.serverMap.tolower() ) + sName.append( tempServer.serverGamemode.tolower() ) + sName.append( Localize( tempServer.serverGamemode ).tolower() ) + sName.append( NSGetServerDescription( i ).tolower() ) + + string sTerm = filterArguments.searchTerm.tolower() + + bool found = false + for( int j = 0; j < sName.len(); j++ ) { - if ( filterArguments.filterMap != "SWITCH_ANY" && filterArguments.filterMap == tempServer.serverMap ) - { - CheckGamemode( tempServer ) - } - else if ( filterArguments.filterMap == "SWITCH_ANY" ) - { - CheckGamemode( tempServer ) - } + if ( sName[j].find( sTerm ) != null ) + found = true } + + if ( !found ) + continue; } - Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize("#INGAME_PLAYERS", string( totalPlayers ) ) ) - Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize("#TOTAL_SERVERS", string( NSGetServerCount() ) ) ) - } -} - -void function CheckGamemode( serverStruct t ) -{ - if ( filterArguments.filterGamemode != "SWITCH_ANY" && filterArguments.filterGamemode == t.serverGamemode ) - { - file.serversArrayFiltered.append( t ) - } - else if ( filterArguments.filterGamemode == "SWITCH_ANY" ) - { - file.serversArrayFiltered.append( t ) + + // Server fits our requirements, add it to the list + file.serversArrayFiltered.append( tempServer ) } + + // Update player and server count + Hud_SetText( Hud_GetChild( file.menu, "InGamePlayerLabel" ), Localize("#INGAME_PLAYERS", string( totalPlayers ) ) ) + Hud_SetText( Hud_GetChild( file.menu, "TotalServerLabel" ), Localize("#TOTAL_SERVERS", string( NSGetServerCount() ) ) ) } -- cgit v1.2.3