diff options
author | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-10-14 21:01:40 +0100 |
---|---|---|
committer | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-10-14 21:01:40 +0100 |
commit | 9a2778eabc7ba968968e41dda9f03525d6c5383d (patch) | |
tree | 6d1c5dc64754d542d68a7f47742a701a4eec9308 | |
parent | c0a0c7e502f2bc99185d79a485b965f63de7a203 (diff) | |
download | NorthstarMods-9a2778eabc7ba968968e41dda9f03525d6c5383d.tar.gz NorthstarMods-9a2778eabc7ba968968e41dda9f03525d6c5383d.zip |
oh fuck i forgot to commit for a while
48 files changed, 1996 insertions, 1017 deletions
diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt Binary files differindex e6175e5b..ede68b36 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut new file mode 100644 index 00000000..9a40f788 --- /dev/null +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_main.nut @@ -0,0 +1,623 @@ +global function InitMainMenu +global function EULA_Dialog +global function UpdateDataCenterFooter +global function LaunchGamePurchase +global function SP_Trial_LaunchGamePurchase +global function LaunchSPNew +global function LaunchSPContinue +global function LaunchSPMissionSelect +global function LaunchMP +global function LaunchGame +global function LaunchSPTrialMission +global function GetUserSignInState + +struct +{ + var menu + var versionDisplay + var trialLabel +} file + + +void function InitMainMenu() +{ + RegisterSignal( "EndOnMainMenu_Open" ) + + var menu = GetMenu( "MainMenu" ) + file.menu = menu + + AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnMainMenu_Open ) + AddMenuEventHandler( menu, eUIEvent.MENU_NAVIGATE_BACK, OnMainMenu_NavigateBack ) + + var titleRui = Hud_GetRui( Hud_GetChild( file.menu, "TitleRui" ) ) + RuiSetImage( titleRui, "basicImage", $"rui/menu/main_menu/title") + + file.versionDisplay = Hud_GetChild( menu, "versionDisplay" ) + file.trialLabel = Hud_GetChild( menu, "TrialLabel" ) + + #if CONSOLE_PROG + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT", "", null, IsConsoleSignedIn ) + #if DURANGO_PROG + AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_SWITCH_PROFILE", "", null, IsConsoleSignedIn ) + #endif // DURANGO_PROG + + AddMenuVarChangeHandler( "CONSOLE_isSignedIn", UpdateFooterOptions ) + #endif // CONSOLE_PROG + + #if PC_PROG + AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT", "" ) + #endif // PC_PROG + + AddMenuFooterOption( menu, BUTTON_X, "#X_BUTTON_INBOX_ACCEPT", "#INBOX_ACCEPT", OpenDataCenterDialog, IsDataCenterFooterValid, UpdateDataCenterFooter ) + +#if DEV + if ( DevStartPoints() ) + AddMenuFooterOption( menu, BUTTON_Y, "#Y_BUTTON_DEV_MENU", "#DEV_MENU", OpenSinglePlayerDevMenu ) +#endif // DEV + + // do +map stuff + if ( Dev_CommandLineHasParm( "+map" ) ) + thread DelayedMapCommand() +} + +void function DelayedMapCommand() +{ + // if we do this too early, game won't run the map command, so we have to wait a bit + // 5.0 was determined exclusively by trial and error but seems to work pretty well + // might be possible to just do this in native instead, but idk effort + wait 5.0 + SetConVarBool( "ns_auth_allow_insecure", true ) // good for testing + ClientCommand( "map " + Dev_CommandLineParmValue( "+map" ) ) + Dev_CommandLineRemoveParm( "+map" ) +} + +#if CONSOLE_PROG + bool function IsConsoleSignedIn() + { + return ( GetMenuVarBool( "CONSOLE_isSignedIn" ) ) + } +#endif // CONSOLE_PROG + +void function OnMainMenu_Open() +{ + Signal( uiGlobal.signalDummy, "EndOnMainMenu_Open" ) + EndSignal( uiGlobal.signalDummy, "EndOnMainMenu_Open" ) + + UpdatePromoData() // On script restarts this gives us the last data until the new request is complete + RequestMainMenuPromos() // This will be ignored if there was a recent request. "infoblock_requestInterval" + + TryUnlockCollectiblesAchievement() + TryUnlockCompletedGameAchievements() + + Hud_SetText( file.versionDisplay, GetPublicGameVersion() ) + Hud_Show( file.versionDisplay ) + + thread UpdateTrialLabel() + +#if PC_PROG + ActivatePanel( GetPanel( "MainMenuPanel" ) ) + return +#endif // PC_PROG + + int state + int lastState = -1 + var panel + var lastPanel + + while ( GetTopNonDialogMenu() == file.menu ) + { + state = GetUserSignInState() + + if ( state != lastState ) + { + if ( state == userSignInState.SIGNED_IN ) + panel = GetPanel( "MainMenuPanel" ) + else + panel = GetPanel( "EstablishUserPanel" ) + + if ( panel != lastPanel ) + { + ActivatePanel( panel ) + lastPanel = panel + } + } + + lastState = state + + WaitFrame() + } +} + +void function ActivatePanel( var panel ) +{ + Assert( panel != null ) + + array<var> elems = GetElementsByClassname( file.menu, "MainMenuPanelClass" ) + foreach ( elem in elems ) + { + if ( elem != panel && Hud_IsVisible( elem ) ) + HidePanel( elem ) + } + + ShowPanel( panel ) +} + +void function OnMainMenu_NavigateBack() +{ +#if DURANGO_PROG + Durango_ShowAccountPicker() +#endif // DURANGO_PROG +} + +int function GetUserSignInState() +{ +#if DURANGO_PROG + if ( Durango_InErrorScreen() ) + { + return userSignInState.ERROR + } + else if ( Durango_IsSigningIn() ) + { + return userSignInState.SIGNING_IN + } + else if ( !Console_IsSignedIn() && !Console_SkippedSignIn() ) + { + //printt( "Console_IsSignedIn():", Console_IsSignedIn(), "Console_SkippedSignIn:", Console_SkippedSignIn() ) + return userSignInState.SIGNED_OUT + } + + Assert( Console_IsSignedIn() || Console_SkippedSignIn() ) +#endif + return userSignInState.SIGNED_IN +} + +void function UpdateDataCenterFooter( InputDef data ) +{ + EndSignal( uiGlobal.signalDummy, "EndFooterUpdateFuncs" ) + + int index = int( Hud_GetScriptID( data.vguiElem ) ) + int ping + string name + + while ( data.conditionCheckFunc() ) + { + ping = GetDatacenterPing() + name = GetDatacenterName() + + if ( ping > 0 ) + { + if ( IsControllerModeActive() ) + SetFooterText( file.menu, index, Localize( "#X_BUTTON_DATACENTER_INFO", name, ping ) ) + else + SetFooterText( file.menu, index, Localize( "#DATACENTER_INFO", name, ping ) ) + } + else + { + if ( IsControllerModeActive() ) + SetFooterText( file.menu, index, "#X_BUTTON_DATACENTER_CALCULATING" ) + else + SetFooterText( file.menu, index, "#DATACENTER_CALCULATING" ) + } + + WaitFrame() + } +} + +bool function IsDataCenterFooterValid() +{ + #if PC_PROG + return ( uiGlobal.activeMenu == file.menu ) + #else + return ( uiGlobal.activeMenu == file.menu ) && Console_IsOnline() && Console_IsSignedIn() + #endif +} + +void function SP_Trial_LaunchGamePurchase() +{ + Disconnect() + LaunchGamePurchase() +} + +void function LaunchGamePurchase() +{ + ShowGamePurchaseStore() +} + +void function LaunchSPNew() +{ + uiGlobal.launching = eLaunching.SINGLEPLAYER_NEW + LaunchGame() +} + +void function LaunchSPContinue() +{ + uiGlobal.launching = eLaunching.SINGLEPLAYER_CONTINUE + LaunchGame() +} + +void function LaunchSPMissionSelect() +{ + uiGlobal.launching = eLaunching.SINGLEPLAYER_MISSION_SELECT + LaunchGame() +} + +void function LaunchSPTrialMission() +{ + uiGlobal.launching = eLaunching.SINGLEPLAYER_MISSION_SELECT + SPTrialMission_Start() +} + +void function LaunchMP() +{ + uiGlobal.launching = eLaunching.MULTIPLAYER + LaunchGame() +} + +void function LaunchGame() +{ + Assert( uiGlobal.launching == eLaunching.SINGLEPLAYER_NEW || + uiGlobal.launching == eLaunching.SINGLEPLAYER_CONTINUE || + uiGlobal.launching == eLaunching.SINGLEPLAYER_MISSION_SELECT || + uiGlobal.launching == eLaunching.MULTIPLAYER || + uiGlobal.launching == eLaunching.MULTIPLAYER_INVITE ) + + if ( uiGlobal.activeMenu == GetMenu( "PlayVideoMenu" ) ) + { + SetVideoCompleteFunc( null ) + CloseActiveMenu() + } + + if ( !IsGamePartiallyInstalled() ) + { + DoGameNeedsToInstallDialog() + return + } + + // Because accepting an invite tries to launch the game we need this here + if ( !IsGameFullyInstalled() ) + { + printt( "Game is not fully installed." ) + + if ( uiGlobal.launching == eLaunching.SINGLEPLAYER_CONTINUE ) + { + string saveName = GetSaveName() + string mapName = SaveGame_GetMapName( saveName ) + int startPointIndex = SaveGame_GetStartPoint( saveName ) + + printt( mapName ) + printt( startPointIndex ) + + bool isInTraining = (mapName == "sp_training" && startPointIndex < 5) // "Titanfall" start point + + if ( !isInTraining ) + { + DoGameNeedsToInstallDialog() + return + } + + printt( "Allowing 'continue' option to load into training." ) + } + else if ( uiGlobal.launching != eLaunching.SINGLEPLAYER_NEW ) + { + DoGameNeedsToInstallDialog() + return + } + } + + #if CONSOLE_PROG + if ( !Console_IsSignedIn() ) + { + printt( "Not signed in." ) + return + } + + if ( GetEULAVersionAccepted() < 1 ) // Treat as binary for now, as discussed with Preston. + { + if ( uiGlobal.activeMenu == GetMenu( "EULADialog" ) ) + return + + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + EULA_Dialog() + return + } + + if ( Nucleus_GetState() == NUCLEUS_STATE_INACTIVE ) + Nucleus_Login() + + if ( !uiGlobal.triedNucleusRegistration && uiGlobal.launching == eLaunching.MULTIPLAYER && !Nucleus_GetSkipRegistration() ) + { + uiGlobal.triedNucleusRegistration = true + thread Nucleus_HandleLoginResponse() + return + } + + if ( !GetConVarBool( "gamma_adjusted" ) ) + { + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + AdvanceMenu( GetMenu( "GammaMenu" ) ) + return + } + #endif // CONSOLE_PROG + + if ( ( uiGlobal.launching == eLaunching.MULTIPLAYER || uiGlobal.launching == eLaunching.MULTIPLAYER_INVITE ) && !IsAdvocateGiftComplete() ) + { + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + + AdvanceMenu( GetMenu( "AdvocateGiftDialog" ) ) + return + } + + SetMenuWasMultiplayerPlayedLast( true ) + if ( uiGlobal.launching == eLaunching.SINGLEPLAYER_NEW ) + NewGameSelected() + else if ( uiGlobal.launching == eLaunching.SINGLEPLAYER_CONTINUE ) + LoadLastCheckpoint() + else if ( uiGlobal.launching == eLaunching.SINGLEPLAYER_MISSION_SELECT ) + AdvanceMenu( GetMenu( "SinglePlayerMenu" ) ) + else + thread StartSearchForPartyServer() + + uiGlobal.launching = eLaunching.FALSE +} + +void function StartSearchForPartyServer() +{ + printt( "StartSearchForPartyServer" ) + +#if DURANGO_PROG + // IMPORTANT: As a safety measure leave any party view we are in at this point. + // Otherwise, if you are unlucky enough to get stuck in a party view, you will + // trash its state by pointing it to your private lobby. + Durango_LeaveParty() + + // IMPORTANT: It's possible that you have permission to play multiplayer + // because your friend is signed in with his gold account on your machine, + // but once that guy signs out, you shouldn't be able to play like you have + // xboxlive gold anymore. To fix this, we need to check permissions periodically. + // One of the places where we do this periodic check is when you press "PLAY" + printt( "Durango - verifying MP permissions" ) + if ( !Console_HasPermissionToPlayMultiplayer() ) + Durango_VerifyMultiplayerPermissions() +#endif // DURANGO_PROG + + Signal( uiGlobal.signalDummy, "OnCancelConnect" ) + EndSignal( uiGlobal.signalDummy, "OnCancelConnect" ) + + if ( IsDialog( uiGlobal.activeMenu ) ) + CloseActiveMenu( true ) + OpenConnectingDialog() + + Hud_SetText( uiGlobal.ConfirmMenuMessage, "" ) + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, "" ) + + Hud_Show( uiGlobal.ConfirmMenuMessage ) + Hud_Show( uiGlobal.ConfirmMenuErrorCode ) + +#if DURANGO_PROG + if( !Console_IsOnline() ) + { + printt( "Durango - finding empty party server failed - not online" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#DURANGO_NOT_ONLINE" ) + return + } +#endif // DURANGO_PROG + +#if PS4_PROG + if( !Console_IsOnline() ) + { + printt( "PS4 - finding empty party server failed - not online" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#INTERNET_NOT_FOUND" ) + return + } + + if ( PS4_isNetworkingDown() ) + { + printt( "PS4 - finding empty party server failed - networking is down" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_CANNOT_CONNECT" ) + return + } + + if( !PS4_isUserNetworkingEnabled() ) + { + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_CHECKING_USABILITY" ) + PS4_ScheduleUserNetworkingEnabledTest() + WaitFrame() + + if( !PS4_isUserNetworkingResolved() ) + { + printt( "PS4 - finding empty party server stalled - networking isn't resolved yet" ) + // offer cancel ?? + while( !PS4_isUserNetworkingResolved()) + WaitFrame() + } + + if( PS4_getUserNetworkingResolution() == PS4_NETWORK_STATUS_NOT_LOGGED_IN ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, string(PS4_getUserNetworkingErrorStatus()) ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_LOGIN" ) + + Ps4_LoginDialog_Schedule() + while( Ps4_LoginDialog_Running() ) + WaitFrame() + + PS4_ScheduleUserNetworkingEnabledTest() + WaitFrame() + if( !PS4_isUserNetworkingResolved() ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, "" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_CHECKING_USABILITY" ) + while( !PS4_isUserNetworkingResolved()) + WaitFrame() + } + } + + if( PS4_getUserNetworkingResolution() == PS4_NETWORK_STATUS_AGE_RESTRICTION ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, string(PS4_getUserNetworkingErrorStatus()) ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#MULTIPLAYER_AGE_RESTRICTED" ) + return + } + + if( PS4_getUserNetworkingResolution() == PS4_NETWORK_STATUS_IN_ERROR ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, string(PS4_getUserNetworkingErrorStatus()) ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_HAD_ERROR" ) + return + } + + if( !PS4_isUserNetworkingEnabled() ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, string(PS4_getUserNetworkingErrorStatus()) ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_NOT_ALLOWED" ) + return + } + + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, "" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "" ) + } + + if ( !Ps4_PSN_Is_Loggedin() ) + { + Ps4_LoginDialog_Schedule() + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_LOGIN" ) + + while( Ps4_LoginDialog_Running() ) + WaitFrame() + + if ( !Ps4_PSN_Is_Loggedin() ) + return + } + + if( Ps4_CheckPlus_Schedule() ) + { + while( Ps4_CheckPlus_Running() ) + WaitFrame() + if( !Ps4_CheckPlus_Allowed() ) + { + if( Ps4_CheckPlus_GetLastRequestResults() != 0 ) + { + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, string( Ps4_CheckPlus_GetLastRequestResults()) ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_HAD_ERROR" ) + return + } + + if( Ps4_ScreenPlusDialog_Schedule() ) + { + while( Ps4_ScreenPlusDialog_Running() ) + WaitFrame() + if( !Ps4_ScreenPlusDialog_Allowed() ) + { + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#PSN_MUST_BE_PLUS_USER" ) + return + } + } + else + { + return + } + } + } + + Hud_SetText( uiGlobal.ConfirmMenuErrorCode, "" ) + Hud_SetText( uiGlobal.ConfirmMenuMessage, "" ) +#endif // #if PS4_PROG + + printt( "Checking if this user has permission to play MP\n" ) + if ( !Console_HasPermissionToPlayMultiplayer() ) + { + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#MULTIPLAYER_NOT_AVAILABLE" ) + return + } + + Plat_ShowUGCRestrictionNotice() + while ( Plat_IsSystemMessageDialogOpen() ) + WaitFrame() + + Plat_ShowChatRestrictionNotice() + while ( Plat_IsSystemMessageDialogOpen() ) + WaitFrame() + +#if PC_PROG + if ( Origin_IsEnabled() ) + { + Origin_RequestTicket() + Hud_SetText( uiGlobal.ConfirmMenuMessage, "#WAITING_FOR_ORIGIN" ) + + while ( !Origin_IsReady() ) + WaitFrame() + } +#endif // PC_PROG + + printt( "SearchForPartyServer" ) + SetMenuWasMultiplayerPlayedLast( true ) + SearchForPartyServer() + + Hud_SetAutoText( uiGlobal.ConfirmMenuMessage, "", HATT_MATCHMAKING_EMPTY_SERVER_SEARCH_STATE, 0 ) + Hud_SetAutoText( uiGlobal.ConfirmMenuErrorCode, "", HATT_MATCHMAKING_EMPTY_SERVER_SEARCH_ERROR, 0 ) +} + +void function EULA_Dialog() +{ + if ( GetUserSignInState() != userSignInState.SIGNED_IN ) + return + + if ( GetEULAVersionAccepted() >= 1 ) + return + + AdvanceMenu( GetMenu( "EULADialog" ) ) +} + +void function DoGameNeedsToInstallDialog() +{ + DialogData dialogData + dialogData.header = "#MENU_WAIT_FOR_INTALL" + + int installProgress = int( GetGameFullyInstalledProgress()*100 ) + + if ( uiGlobal.launching == eLaunching.MULTIPLAYER && IsGamePartiallyInstalled() && !Script_IsRunningTrialVersion() ) + { + dialogData.message = Localize("#MENU_WAIT_FOR_INTALL_HINT", installProgress ) + AddDialogButton( dialogData, "#YES", LaunchSPNew ) + AddDialogButton( dialogData, "#NO" ) + } + else + { + dialogData.message = Localize("#MENU_WAIT_FOR_INTALL_HINT_NOTRAINING", installProgress ) + AddDialogButton( dialogData, "#OK" ) + } + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + AddDialogFooter( dialogData, "#B_BUTTON_CANCEL" ) + + OpenDialog( dialogData ) +} + +void function UpdateTrialLabel() +{ + bool isTrialVersion + bool lastIsTrialVersion = Script_IsRunningTrialVersion() + + Hud_SetVisible( file.trialLabel, lastIsTrialVersion ) + + while ( GetTopNonDialogMenu() == file.menu ) + { + isTrialVersion = Script_IsRunningTrialVersion() + + if ( isTrialVersion != lastIsTrialVersion ) + Hud_SetVisible( file.trialLabel, isTrialVersion ) + + lastIsTrialVersion = isTrialVersion + + WaitFrame() + } +} + +void function OpenSinglePlayerDevMenu( var button ) +{ + AdvanceMenu( GetMenu( "SinglePlayerDevMenu" ) ) +} 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 7ed0d177..29daf0a8 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_map_select.nut @@ -59,7 +59,12 @@ void function UpdateVisibleMaps() if ( buttonID < file.mapsPerPage && mapID < GetPrivateMatchMaps().len() ) { string name = mapsArray[ mapID ] - SetButtonRuiText( button, GetMapDisplayName( name ) ) + + bool sp = name.find( "sp_" ) == 0 + if ( sp ) + SetButtonRuiText( button, Localize( "#PRIVATE_MATCH_SINGLEPLAYER_LEVEL", Localize( GetMapDisplayName( name ) ) ) ) + else + SetButtonRuiText( button, GetMapDisplayName( name ) ) Hud_SetEnabled( button, true ) if ( IsItemInEntitlementUnlock( name ) && IsValid( GetUIPlayer() ) ) @@ -73,7 +78,7 @@ void function UpdateVisibleMaps() bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( name, PrivateMatch_GetSelectedMode() ) Hud_SetLocked( button, !mapSupportsMode ) - if ( !mapSupportsMode ) + if ( !mapSupportsMode && !sp ) SetButtonRuiText( button, Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetMapDisplayName( name ) ) ) ) } else diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut index 711cbbbc..be2a1048 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_custom_match_settings_categories.nut @@ -25,31 +25,14 @@ void function OnNorthstarCustomMatchSettingsCategoryMenuOpened() array<string> categories = GetPrivateMatchSettingCategories() array<var> buttons = GetElementsByClassname( GetMenu( "CustomMatchSettingsCategoryMenu" ), "MatchSettingCategoryButton" ) - for ( int i = 0, j = 0; j < categories.len() && i < buttons.len(); i++, j++ ) + foreach ( var button in buttons ) { - Hud_SetEnabled( buttons[ i ], false ) - Hud_SetVisible( buttons[ i ], false ) + Hud_SetEnabled( button, false ) + Hud_SetVisible( button, false ) + } - // skip gamemode/playlist categories for modes that aren't the current one - // todo this fucking breaks everything lmao - //bool gamemode = categories[ j ].find( "#GAMEMODE_" ) == 0 - //if ( gamemode || categories[ j ].find( "#PL_" ) == 0 ) - //{ - // if ( gamemode ) - // { - // if ( categories[ j ].slice( 10 ) != PrivateMatch_GetSelectedMode() ) - // { - // i-- - // continue - // } - // } - // else if ( categories[ j ].slice( 4 ) != PrivateMatch_GetSelectedMode() ) - // { - // i-- - // continue - // } - //} - + for ( int i = 0, j = 0; j < categories.len() && i < buttons.len(); i++, j++ ) + { Hud_SetText( buttons[ i ], Localize( categories[ j ] ) + " ->" ) Hud_SetEnabled( buttons[ i ], true ) Hud_SetVisible( buttons[ i ], true ) diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut index 4a56891e..588fe705 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_modmenu.nut @@ -1,6 +1,10 @@ global function AddNorthstarModMenu global function AddNorthstarModMenu_MainMenuFooter +struct { + bool shouldReloadModsOnEnd +} file + void function AddNorthstarModMenu() { AddMenu( "ModListMenu", $"resource/ui/menus/modlist.menu", InitModMenu ) @@ -21,15 +25,21 @@ void function InitModMenu() var menu = GetMenu( "ModListMenu" ) AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnModMenuOpened ) + AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnModMenuClosed ) AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) - AddMenuFooterOption( menu, BUTTON_Y, "#Y_RELOAD_MODS", "#RELOAD_MODS", ReloadMods ) + AddMenuFooterOption( menu, BUTTON_Y, "#Y_RELOAD_MODS", "#RELOAD_MODS", OnReloadModsButtonPressed ) foreach ( var button in GetElementsByClassname( GetMenu( "ModListMenu" ), "ModButton" ) ) + { AddButtonEventHandler( button, UIE_GET_FOCUS, OnModMenuButtonFocused ) + AddButtonEventHandler( button, UIE_CLICK, OnModMenuButtonPressed ) + } } void function OnModMenuOpened() { + file.shouldReloadModsOnEnd = false + Hud_SetText( Hud_GetChild( GetMenu( "ModListMenu" ), "Title" ), "#MENU_TITLE_MODS" ) array<var> buttons = GetElementsByClassname( GetMenu( "ModListMenu" ), "ModButton" ) @@ -47,10 +57,36 @@ void function OnModMenuOpened() Hud_SetEnabled( buttons[ i ], true ) Hud_SetVisible( buttons[ i ], true ) - SetButtonRuiText( buttons[ i ], modNames[ i ] + " v" + NSGetModVersionByModName( modNames[ i ] ) ) + SetModMenuNameText( buttons[ i ] ) } } +void function OnModMenuClosed() +{ + if ( file.shouldReloadModsOnEnd ) + ReloadMods() +} + +void function SetModMenuNameText( var button ) +{ + string modName = NSGetModNames()[ int ( Hud_GetScriptID( button ) ) ] + + // should be localisation at some point + if ( NSIsModEnabled( modName ) ) + SetButtonRuiText( button, modName + " v" + NSGetModVersionByModName( modName ) ) + else + SetButtonRuiText( button, modName + " (DISABLED)" ) +} + +void function OnModMenuButtonPressed( var button ) +{ + string modName = NSGetModNames()[ int ( Hud_GetScriptID( button ) ) ] + NSSetModEnabled( modName, !NSIsModEnabled( modName ) ) + SetModMenuNameText( button ) + + file.shouldReloadModsOnEnd = true +} + void function OnModMenuButtonFocused( var button ) { string modName = NSGetModNames()[ int ( Hud_GetScriptID( button ) ) ] @@ -101,8 +137,17 @@ string function FormatModDescription( string modName ) return ret } -void function ReloadMods( var button ) +void function OnReloadModsButtonPressed( var button ) +{ + ReloadMods() +} + +void function ReloadMods() { NSReloadMods() - OnModMenuOpened() // temp, until we start doing uiscript_reset here + ClientCommand( "reload_localization" ) + ClientCommand( "loadPlaylists" ) + // ClientCommand( "weapon_reparse" ) // this doesn't work, weapon_reparse only works if a server is running and sv_cheats is 1, gotta figure this out eventually + // note: the logic for this seems really odd, unsure why it doesn't seem to update, since the same code seems to get run irregardless of whether we've read weapon data before + ClientCommand( "uiscript_reset" ) }
\ 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 bbeb0d0b..121de614 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut @@ -195,4 +195,22 @@ void function ThreadedAuthAndConnectToServer( string password = "" ) if ( NSWasAuthSuccessful() ) NSConnectToAuthedServer() + else + { + print( "fuck" ) + + DialogData dialogData + dialogData.header = "#ERROR" + dialogData.message = "Authentication Failed" + dialogData.image = $"ui/menu/common/dialog_error" + + #if PC_PROG + AddDialogButton( dialogData, "#DISMISS" ) + + AddDialogFooter( dialogData, "#A_BUTTON_SELECT" ) + #endif // PC_PROG + AddDialogFooter( dialogData, "#B_BUTTON_DISMISS_RUI" ) + + OpenDialog( dialogData ) + } }
\ No newline at end of file diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut index d203a673..41721455 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_private_match.nut @@ -91,6 +91,19 @@ const table<asset> mapImages = mp_rise = $"loadscreens/mp_rise_lobby", mp_lf_township = $"loadscreens/mp_lf_township_lobby", mp_lf_uma = $"loadscreens/mp_lf_uma_lobby", + + // not really sure if this should be here, whatever + // might be good to make this modular in the future? + sp_training = $"rui/menu/level_select/level_image1", + sp_crashsite = $"rui/menu/level_select/level_image2", + sp_sewers1 = $"rui/menu/level_select/level_image3", + sp_boomtown_start = $"rui/menu/level_select/level_image4", + sp_hub_timeshift = $"rui/menu/level_select/level_image5", + sp_beacon = $"rui/menu/level_select/level_image6", + sp_tday = $"rui/menu/level_select/level_image7", + sp_s2s = $"rui/menu/level_select/level_image8", + sp_skyway_v1 = $"rui/menu/level_select/level_image9", + } void function MenuPrivateMatch_Init() @@ -630,7 +643,7 @@ function UpdateLobby() { bool shouldBreak = false - foreach ( string category in GetPrivateMatchSettingCategories() ) + foreach ( string category in GetPrivateMatchSettingCategories( true ) ) { foreach ( CustomMatchSettingContainer setting in GetPrivateMatchCustomSettingsForCategory( category ) ) { diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut index acd11237..d42a2331 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut @@ -32,6 +32,11 @@ const DEBUG_PERMISSIONS = false void function InitMainMenuPanel() { + // disable communities because of the cool openinvite exploit (not required anymore but keeping here anyway + SetConVarBool( "communities_enabled", false ) + SetConVarString( "communities_hostname", "localhost" ) + + RegisterSignal( "EndShowMainMenuPanel" ) file.panel = GetPanel( "MainMenuPanel" ) @@ -77,7 +82,7 @@ void function InitMainMenuPanel() var multiplayerHeader = AddComboButtonHeader( comboStruct, headerIndex, "#MULTIPLAYER_ALLCAPS" ) file.mpButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MULTIPLAYER_LAUNCH" ) Hud_AddEventHandler( file.mpButton, UIE_CLICK, OnPlayMPButton_Activate ) - file.fdButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#GAMEMODE_COOP" ) + file.fdButton = AddComboButton( comboStruct, headerIndex, buttonIndex++, "#MENU_LAUNCH_NORTHSTAR" ) Hud_AddEventHandler( file.fdButton, UIE_CLICK, OnPlayFDButton_Activate ) headerIndex++ @@ -443,7 +448,7 @@ void function UpdatePlayButton( var button ) //else //{ //ComboButton_SetText( file.fdButton, "#MULTIPLAYER_LAUNCH_FD" ) - ComboButton_SetText( file.fdButton, "Launch Northstar" ) // this needs to use localised text at some point when we have a modular way of doing that + ComboButton_SetText( file.fdButton, "#MENU_LAUNCH_NORTHSTAR" ) // this needs to use localised text at some point when we have a modular way of doing that Hud_SetEnabled( file.fdButton, true ) //} @@ -521,6 +526,9 @@ void function TryAuthWithLocalServer() if ( NSWasAuthSuccessful() ) NSCompleteAuthWithLocalServer() + if ( GetConVarString( "mp_gamemode" ) == "solo" ) + SetConVarString( "mp_gamemode", "tdm" ) + ClientCommand( "setplaylist tdm" ) ClientCommand( "map mp_lobby" ) } diff --git a/Northstar.Coop/keyvalues/playlists_v2.txt b/Northstar.Coop/keyvalues/playlists_v2.txt new file mode 100644 index 00000000..e3a241b7 --- /dev/null +++ b/Northstar.Coop/keyvalues/playlists_v2.txt @@ -0,0 +1,59 @@ +playlists +{ + Playlists + { + sp_coop + { + inherit defaults + vars + { + name #PL_sp_coop + lobbytitle #PL_sp_coop_lobby + description #PL_sp_coop_desc + hint #PL_sp_coop_hint + abbreviation #PL_sp_coop_abbr + image ffa + + // taken from solo gamemode + always_enable_autotitans 1 + burn_meter_enabled 0 + cinematic_mode 1 + classic_mp 0 + hud_score_enabled 0 + max_players 16 + max_teams 1 + ranking_supported 0 + riff_allow_npcs 1 + riff_minimap_state 1 + riff_titan_availability 3 + riff_titan_exit_enabled 3 + rodeo_battery_disembark_to_pickup 0 + titan_build_time 300 + titan_health_bar_display default + titan_mode_change_allowed 0 + titan_rebuild_time 195 + titan_segmented_health 0 + titan_shield_regen 1 + } + + gamemodes + { + solo + { + maps + { + sp_training 1 + sp_crashsite 1 + sp_sewers1 1 + sp_boomtown_start 1 + sp_hub_timeshift 1 + sp_beacon 1 + sp_tday 1 + sp_s2s 1 + sp_skyway_v1 1 + } + } + } + } + } +}
\ No newline at end of file diff --git a/Northstar.Coop/mod.json b/Northstar.Coop/mod.json new file mode 100644 index 00000000..b4dfaeb2 --- /dev/null +++ b/Northstar.Coop/mod.json @@ -0,0 +1,25 @@ +{ + "Name" : "Northstar.Coop", + "Description" : "Allows the singleplayer campaign to be played in multiplayer", + + "LoadPriority": 0, + + "Scripts": [ + { + "Path": "sh_sp_coop.gnut", + "RunOn": "SP" + }, + + { + "Path": "sh_sp_coop_lobby.gnut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "After": "SingleplayerCoopLobby_Init" + }, + + "ServerCallback": { + "After": "SingleplayerCoopLobby_Init" + } + }, + ], +}
\ No newline at end of file diff --git a/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop.gnut b/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop.gnut new file mode 100644 index 00000000..09293a70 --- /dev/null +++ b/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop.gnut @@ -0,0 +1,6 @@ +global function IsSPCoopMode + +bool function IsSPCoopMode() +{ + return GAMETYPE == "solo" && GetCurrentPlaylistName() == "sp_coop" +}
\ No newline at end of file diff --git a/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop_lobby.gnut b/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop_lobby.gnut new file mode 100644 index 00000000..59a31ee8 --- /dev/null +++ b/Northstar.Coop/mod/scripts/vscripts/sh_sp_coop_lobby.gnut @@ -0,0 +1,19 @@ +global function SingleplayerCoopLobby_Init + +void function SingleplayerCoopLobby_Init() +{ + if ( !IsLobby() ) + return + + AddPrivateMatchMode( "sp_coop" ) + + AddPrivateMatchMap( "sp_training" ) + AddPrivateMatchMap( "sp_crashsite" ) + AddPrivateMatchMap( "sp_sewers1" ) + AddPrivateMatchMap( "sp_boomtown_start" ) + AddPrivateMatchMap( "sp_hub_timeshift" ) + AddPrivateMatchMap( "sp_beacon" ) + AddPrivateMatchMap( "sp_tday" ) + AddPrivateMatchMap( "sp_s2s" ) + AddPrivateMatchMap( "sp_skyway_v1" ) +}
\ No newline at end of file diff --git a/Northstar.Custom/keyvalues/playlists_v2.txt b/Northstar.Custom/keyvalues/playlists_v2.txt index 30ea6980..813accb6 100644 --- a/Northstar.Custom/keyvalues/playlists_v2.txt +++ b/Northstar.Custom/keyvalues/playlists_v2.txt @@ -185,6 +185,23 @@ playlists gamemode_bullet_005 #GAMEMODE_BULLET_CTF_005 } } + hs + { + inherit defaults + vars + { + name #GAMEMODE_hs + lobbytitle #PL_hs_lobby + description #PL_hs_desc + hint #PL_hs_hint + abbreviation #PL_hs_abbr + image tdm + timelimit 10 + max_players 16 + + gamemode_score_hint #GAMEMODE_SCORE_HINT_TDM + } + } } Playlists { @@ -242,6 +259,7 @@ playlists lobbytitle #PL_tt_lobby description #PL_tt_desc hint #PL_tt_hint + image lts abbreviation #PL_tt_abbr visible 0 } @@ -279,6 +297,7 @@ playlists lobbytitle #PL_inf_lobby description #PL_inf_desc hint #PL_inf_hint + image ps abbreviation #PL_inf_abbr visible 0 } @@ -376,7 +395,7 @@ playlists description #PL_kr_desc hint #PL_kr_hint abbreviation #PL_kr_abbr - + image ctf max_players 16 max_teams 16 classic_mp 1 @@ -424,7 +443,7 @@ playlists description #PL_fastball_desc hint #PL_fastball_hint abbreviation #PL_fastball_abbr - + image ffa max_players 16 max_teams 2 classic_mp 1 @@ -469,6 +488,7 @@ playlists description #PL_fw_desc hint #PL_fw_hint abbreviation #PL_fw_abbr + image fw max_players 16 max_teams 2 @@ -568,5 +588,57 @@ playlists } } } + hs + { + inherit defaults + vars + { + name #GAMEMODE_hs + lobbytitle #PL_hs_lobby + description #PL_hs_desc + hint #PL_hs_hint + abbreviation #PL_hs_abbr + image tdm + timelimit 10 + max_players 16 + + gamemode_score_hint #GAMEMODE_SCORE_HINT_TDM + } + gamemodes + { + hs + { + mp_complex3 1 + mp_drydock 1 + mp_glitch 1 + mp_homestead 2 + mp_eden 1 + mp_forwardbase_kodai 1 + mp_black_water_canal 1 + mp_glitch 1 + mp_angel_city 1 + mp_colony02 1 + mp_relic02 1 + mp_grave 1 + mp_homestead 1 + mp_drydock 1 + mp_glitch 1 + mp_thaw 1 + mp_eden 2 + mp_black_water_canal 1 + mp_glitch 1 + mp_relic02 1 + mp_wargames 1 + mp_rise 1 + mp_crashsite3 1 + mp_lf_stacks 1 + mp_lf_deck 1 + mp_lf_meadow 1 + mp_lf_traffic 1 + mp_lf_township 1 + mp_lf_uma 1 + } + } + } } }
\ No newline at end of file diff --git a/Northstar.Custom/keyvalues/scripts/weapons/mp_titanweapon_particle_accelerator.txt b/Northstar.Custom/keyvalues/scripts/weapons/mp_titanweapon_particle_accelerator.txt deleted file mode 100644 index a30ed8f8..00000000 --- a/Northstar.Custom/keyvalues/scripts/weapons/mp_titanweapon_particle_accelerator.txt +++ /dev/null @@ -1,4 +0,0 @@ -WeaponData -{ - "playermodel" "models/SPOILER_w_titan_particle_accelerator.mdl" -} diff --git a/Northstar.Custom/mod.json b/Northstar.Custom/mod.json index d1ebeec3..8a09c756 100644 --- a/Northstar.Custom/mod.json +++ b/Northstar.Custom/mod.json @@ -249,6 +249,27 @@ "RunOn": "CLIENT && MP" }, + // hide and seek + { + "Path": "gamemodes/sh_gamemode_hs.gnut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "Before": "Sh_GamemodeHideAndSeek_Init" + }, + + "ServerCallback": { + "Before": "Sh_GamemodeHideAndSeek_Init" + } + }, + { + "Path": "gamemodes/_gamemode_hs.gnut", + "RunOn": "SERVER && MP" + }, + { + "Path": "gamemodes/cl_gamemode_hs.gnut", + "RunOn": "CLIENT && MP" + }, + // ctf comp { "Path": "gamemodes/sh_gamemode_ctf_comp.gnut", @@ -267,10 +288,12 @@ "RunOn": "( CLIENT || SERVER ) && MP", "ClientCallback": { "Before": "FirstPersonEmbark_Init", + "After": "FirstPersonEmbark_InitPlaylistVars" }, "ServerCallback": { - "Before": "FirstPersonEmbark_Init" + "Before": "FirstPersonEmbark_Init", + "After": "FirstPersonEmbark_InitPlaylistVars" } }, @@ -285,7 +308,7 @@ { "Path": "_custom_air_accel.gnut", - "RunOn": "MP", + "RunOn": "CLIENT || SERVER", "ClientCallback": { "After": "CustomAirAccelVars_Init" }, @@ -306,6 +329,32 @@ "After": "Promode_Init" } }, + + { + "Path": "_bleedout_damage.gnut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "Before": "BleedoutDamage_PreInit", + "After": "BleedoutDamage_Init" + }, + + "ServerCallback": { + "Before": "BleedoutDamage_PreInit", + "After": "BleedoutDamage_Init" + } + }, + + { + "Path": "_custom_oob_timer.gnut", + "RunOn": "( CLIENT || SERVER ) && MP", + "ClientCallback": { + "After": "CustomOOBTimer_Init" + }, + + "ServerCallback": { + "After": "CustomOOBTimer_Init" + } + } ], "Localisation": [ diff --git a/Northstar.Custom/mod/scripts/levels/mp_bob.rson b/Northstar.Custom/mod/scripts/levels/mp_bob.rson new file mode 100644 index 00000000..58c8a1ca --- /dev/null +++ b/Northstar.Custom/mod/scripts/levels/mp_bob.rson @@ -0,0 +1,9 @@ +//C:\depot\r2dev\game autofastfunction.pl + +IsTestMap: false +When: "SERVER" +Scripts: +[ + mp/levels/mp_bob_temp_props.nut + mp/levels/mp_bob.nut +]
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/levels/mp_box.rson b/Northstar.Custom/mod/scripts/levels/mp_box.rson index 1a8d1ee7..3056c505 100644 --- a/Northstar.Custom/mod/scripts/levels/mp_box.rson +++ b/Northstar.Custom/mod/scripts/levels/mp_box.rson @@ -1,6 +1,6 @@ //C:\depot\r2dev\game autofastfunction.pl -IsTestMap: false +IsTestMap: true When: "SERVER" Scripts: [ diff --git a/Northstar.Custom/mod/scripts/vscripts/_bleedout_damage.gnut b/Northstar.Custom/mod/scripts/vscripts/_bleedout_damage.gnut new file mode 100644 index 00000000..8b21184a --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/_bleedout_damage.gnut @@ -0,0 +1,137 @@ +// note: this is technically vanilla content, since bleedout was shipped with retail, but it needs custom remote functions which would break vanilla compatiblity, so it's not in Northstar.CustomServers +// idk why bleedout was even shipped in retail lmao +global function BleedoutDamage_PreInit +global function BleedoutDamage_Init +global function SetShouldPlayerStartBleedoutFunc + +struct { + array<entity> bleedingPlayers // this is in _bleedout already, but it doesn't expose a way to track it, so we have to track it ourselves + bool functionref( entity, var ) shouldPlayerStartBleedoutFunc = null +} file + +void function BleedoutDamage_PreInit() +{ + AddCallback_OnRegisteringCustomNetworkVars( Bleedout_RegisterRemoteFunctions ) +} + +void function Bleedout_RegisterRemoteFunctions() +{ + Remote_RegisterFunction( "ServerCallback_BLEEDOUT_StartFirstAidProgressBar" ) + Remote_RegisterFunction( "ServerCallback_BLEEDOUT_StopFirstAidProgressBar" ) + Remote_RegisterFunction( "ServerCallback_BLEEDOUT_ShowWoundedMarker" ) + Remote_RegisterFunction( "ServerCallback_BLEEDOUT_HideWoundedMarker" ) +} + +// copied from sh_bleedout +const float DEFAULT_BLEEDOUT_TIME = 30.0 +const float DEFAULT_FIRSTAID_TIME = 3.0 +const float DEFAULT_FIRSTAID_TIME_SELF = -1.0 +const float DEFAULT_FIRSTAID_HEAL_PERCENT = 1.0 +const float DEFAULT_AI_BLEEDING_PLAYER_MISS_CHANCE = 0.0 +const bool DEFAULT_FORCE_WEAPON_HOLSTER = false +const bool DEFAULT_DEATH_ON_TEAM_BLEEDOUT = false + +void function BleedoutDamage_Init() +{ + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_BLEEDOUT", "riff_player_bleedout", [ "Default", "Disabled", "Enabled" ], "0" ) + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_forceHolster", [ "Disabled", "Enabled" ], DEFAULT_FORCE_WEAPON_HOLSTER.tostring() ) + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_forceDeathOnTeamBleedout", [ "Disabled", "Enabled" ], DEFAULT_DEATH_ON_TEAM_BLEEDOUT.tostring() ) + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_bleedoutTime", DEFAULT_BLEEDOUT_TIME.tostring() ) + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_firstAidTime", DEFAULT_FIRSTAID_TIME.tostring() ) + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_firstAidTimeSelf", DEFAULT_FIRSTAID_TIME_SELF.tostring() ) + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_firstAidHealPercent", DEFAULT_FIRSTAID_HEAL_PERCENT.tostring() ) + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_aiBleedingPlayerMissChance", DEFAULT_AI_BLEEDING_PLAYER_MISS_CHANCE.tostring() ) + + #if CLIENT + // because playlist var overrides fucking suck, they aren't actually updated by this point + // client bleedout can be inited late enough that we can just init it on local player spawn + AddCallback_LocalClientPlayerSpawned( InitClientBleedoutForLocalPlayer ) + #elseif SERVER + // sh_riff_settings should set this correctly on server + if ( !Riff_PlayerBleedout() ) + return + + AddDamageCallback( "player", HandleDamageForBleedout ) // do this irregardless of whether scripts inited, given it should always be used for bleedout + Bleedout_SetCallback_OnPlayerStartBleedout( OnPlayerBleedoutBegin ) // kinda sucks we have to use this callback since game scripts could be using it + + // dont init if scripts already inited it manually + if ( !Bleedout_IsBleedoutLogicActive() ) + { + InitSharedBleedoutWithPlaylistVars() + Bleedout_Init() + } + #endif +} + +void function SetShouldPlayerStartBleedoutFunc( bool functionref( entity, var ) func ) +{ + file.shouldPlayerStartBleedoutFunc = func +} + +void function InitSharedBleedoutWithPlaylistVars() +{ + BleedoutShared_Init( + GetCurrentPlaylistVarFloat( "player_bleedout_bleedoutTime", DEFAULT_BLEEDOUT_TIME ), + GetCurrentPlaylistVarFloat( "player_bleedout_firstAidTime", DEFAULT_FIRSTAID_TIME ), + GetCurrentPlaylistVarFloat( "player_bleedout_firstAidTimeSelf", DEFAULT_FIRSTAID_TIME_SELF ), + GetCurrentPlaylistVarFloat( "player_bleedout_firstAidHealPercent", DEFAULT_FIRSTAID_HEAL_PERCENT ), + GetCurrentPlaylistVarFloat( "player_bleedout_aiBleedingPlayerMissChance", DEFAULT_AI_BLEEDING_PLAYER_MISS_CHANCE ), + GetCurrentPlaylistVarInt( "player_bleedout_forceHolster", int( DEFAULT_FORCE_WEAPON_HOLSTER ) ) == 1, + GetCurrentPlaylistVarInt( "player_bleedout_forceDeathOnTeamBleedout", int( DEFAULT_DEATH_ON_TEAM_BLEEDOUT ) ) == 1 + ) +} + +#if CLIENT +void function InitClientBleedoutForLocalPlayer( entity player ) +{ + // dont init if bleedout is disabled or scripts already inited it + if ( !Riff_PlayerBleedout() || Bleedout_IsBleedoutLogicActive() ) + return + + InitSharedBleedoutWithPlaylistVars() + BleedoutClient_Init() +} +#endif + +#if SERVER +void function HandleDamageForBleedout( entity player, var damageInfo ) +{ + if ( IsInstantDeath( damageInfo ) || DamageInfo_GetForceKill( damageInfo ) || player.IsTitan() || file.bleedingPlayers.contains( player ) ) + return + + if ( file.shouldPlayerStartBleedoutFunc != null ) + if ( !file.shouldPlayerStartBleedoutFunc( player, damageInfo ) ) + return + + // check if damage would kill player + if ( player.GetHealth() - DamageInfo_GetDamage( damageInfo ) <= 0 ) + { + Bleedout_StartPlayerBleedout( player, DamageInfo_GetAttacker( damageInfo ) ) + DamageInfo_SetDamage( damageInfo, 1 ) // prevent player from dying, but if we set it to 0, player won't receive any knockback from damage source + } +} + +void function OnPlayerBleedoutBegin( entity player ) +{ + file.bleedingPlayers.append( player ) + + // would prefer to use Bleedout_SetCallback_OnPlayerGiveFirstAid for this, but it doesn't expose the player that's receiving first aid for some reason + thread TrackPlayerBleedout( player ) +} + +void function TrackPlayerBleedout( entity player ) +{ + player.EndSignal( "OnDeath" ) + player.EndSignal( "OnDestroy" ) + + OnThreadEnd( function() : ( player ) + { + file.bleedingPlayers.remove( file.bleedingPlayers.find( player ) ) + }) + + WaitFrame() // wait a frame, since this gets called before this status effect is added + + while ( StatusEffect_Get( player, eStatusEffect.bleedoutDOF ) != 0 ) + WaitFrame() +} +#endif
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/_custom_air_accel.gnut b/Northstar.Custom/mod/scripts/vscripts/_custom_air_accel.gnut index 8ebef034..faa92480 100644 --- a/Northstar.Custom/mod/scripts/vscripts/_custom_air_accel.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/_custom_air_accel.gnut @@ -1,8 +1,10 @@ global function CustomAirAccelVars_Init void function CustomAirAccelVars_Init() -{ - AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_PILOT", "custom_air_accel_pilot", "500" ) // 500 is the default airaccel +{ + #if MP + AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_PILOT", "custom_air_accel_pilot", "500" ) // 500 is the default airaccel + #endif #if SERVER AddCallback_OnPlayerRespawned( ApplyCustomPlayerAirAccel ) diff --git a/Northstar.Custom/mod/scripts/vscripts/_custom_oob_timer.gnut b/Northstar.Custom/mod/scripts/vscripts/_custom_oob_timer.gnut new file mode 100644 index 00000000..9689302c --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/_custom_oob_timer.gnut @@ -0,0 +1,7 @@ +global function CustomOOBTimer_Init + +void function CustomOOBTimer_Init() +{ + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_MATCH", "oob_timer_enabled", [ "Disabled", "Enabled" ], "1" ) + level.disableOutOfBounds <- GetCurrentPlaylistVarInt( "oob_timer_enabled", 1 ) == 0 +}
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut index b59cd2dd..00c19310 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball.gnut @@ -27,7 +27,6 @@ void function GamemodeFastball_Init() SetTimeoutWinnerDecisionFunc( FastballDecideWinner ) AddCallback_OnClientConnected( FastballInitPlayer ) - AddCallback_OnPlayerKilled( FastballOnPlayerKilled ) // move this to a system in _gamestate soon!! // setup spawns // first is a, second is b, third is c @@ -164,15 +163,6 @@ function FastballOnPanelHacked( panel, player, success ) } } -void function FastballOnPlayerKilled( entity victim, entity attacker, var damageInfo ) -{ - if ( !victim.IsPlayer() || GetGameState() != eGameState.Playing ) - return - - if ( GetPlayerArrayOfTeam_Alive( victim.GetTeam() ).len() == 0 ) - SetWinner( GetOtherTeam( victim.GetTeam() ) ) -} - int function FastballDecideWinner() { int militiaPanels diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut index b9ee40f1..e0178034 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_gg.gnut @@ -5,7 +5,7 @@ void function GamemodeGG_Init() SetSpawnpointGamemodeOverride( FFA ) SetShouldUseRoundWinningKillReplay( true ) - Evac_SetEnabled( false ) + ClassicMP_ForceDisableEpilogue( true ) SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period SetWeaponDropsEnabled( false ) Riff_ForceTitanAvailability( eTitanAvailability.Never ) diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut new file mode 100644 index 00000000..bc65e0b6 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut @@ -0,0 +1,191 @@ +global function GamemodeHideAndSeek_Init + +struct { + entity intermissionCam + array<entity> droppodSpawns + + float hidingTime + bool autobalance + + float hidingStartTime +} file + +void function GamemodeHideAndSeek_Init() +{ + SetSpawnpointGamemodeOverride( FFA ) + Riff_ForceTitanAvailability( eTitanAvailability.Never ) + Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + SetRespawnsEnabled( false ) + Riff_ForceSetEliminationMode( eEliminationMode.Pilots ) + + SetTimeoutWinnerDecisionFunc( HideAndSeekDecideWinner ) + ClassicMP_SetCustomIntro( GamemodeHideAndSeekIntroSetup, 0.0 ) + + AddCallback_OnPlayerRespawned( SetupHideAndSeekPlayer ) + AddCallback_OnPlayerKilled( TryNotifyLastPlayerAlive ) + AddSpawnCallback( "info_intermission", SetIntermissionCam ) + AddSpawnCallback( "info_spawnpoint_droppod_start", AddDroppodSpawn ) + + file.hidingTime = GetCurrentPlaylistVarFloat( "hideandseek_hiding_time", 60.0 ) + file.autobalance = GetCurrentPlaylistVarInt( "hideandseek_balance_teams", 1 ) == 1 +} + +void function GamemodeHideAndSeekIntroSetup() +{ + AddCallback_GameStateEnter( eGameState.Prematch, HideAndSeekIntroPrematch ) + AddCallback_OnClientConnected( AddPlayerToHideAndSeekIntro ) +} + +void function SetIntermissionCam( entity cam ) +{ + file.intermissionCam = cam +} + +void function AddDroppodSpawn( entity spawn ) +{ + file.droppodSpawns.append( spawn ) +} + +void function AddPlayerToHideAndSeekIntro( entity player ) +{ + if ( GetGameState() < eGameState.Prematch || Time() - file.hidingStartTime > file.hidingTime ) + return + + // seeker/hider autobalance + // try to have 1/6 of players be seekers + if ( file.autobalance ) + { + int wantedSeekers = int( max( 1, GetPlayerArray().len() / 6 ) ) + + if ( GetPlayerArrayOfTeam( HIDEANDSEEK_TEAM_SEEKER ).len() < wantedSeekers ) + SetTeam( player, HIDEANDSEEK_TEAM_SEEKER ) + } + + ScreenFadeFromBlack( player, 1.0, 0.75 ) + Remote_CallFunction_NonReplay( player, "ServerCallback_ShowHideAndSeekCountdown", file.hidingStartTime + file.hidingTime ) + + if ( player.GetTeam() == HIDEANDSEEK_TEAM_HIDER ) + { + player.kv.visibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY + Highlight_ClearEnemyHighlight( player ) + + thread HiderIntroThread( player ) + } + else + thread SeekerIntroThread( player ) + + thread DelayedRoleAnnounce( player ) +} + +void function HideAndSeekIntroPrematch() +{ + ClassicMP_OnIntroStarted() + + file.hidingStartTime = Time() + + foreach ( entity player in GetPlayerArray() ) + AddPlayerToHideAndSeekIntro( player ) + + // this intro is mostly done in playing, so just finish the intro up now and we can do fully custom logic from here + WaitFrame() + ClassicMP_OnIntroFinished() + + thread GlobalSeekerIntroThread() +} + +void function HiderIntroThread( entity player ) +{ + RespawnAsPilot( player ) + + wait ( file.hidingStartTime + file.hidingTime ) - Time() + + player.kv.visibilityFlags = ENTITY_VISIBLE_TO_EVERYONE // make sure everyone can see us again +} + +void function SeekerIntroThread( entity player ) +{ + MuteHalfTime( player ) + + player.SetObserverModeStaticPosition( file.intermissionCam.GetOrigin() ) + player.SetObserverModeStaticAngles( file.intermissionCam.GetAngles() ) + player.StartObserverMode( OBS_MODE_STATIC_LOCKED ) + + wait ( file.hidingStartTime + file.hidingTime ) - Time() + UnMuteAll( player ) +} + +void function DelayedRoleAnnounce( entity player ) +{ + wait 1.75 + Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceHideAndSeekRole" ) +} + +void function GlobalSeekerIntroThread() +{ + wait file.hidingTime + + + PlayMusicToAll( eMusicPieceID.GAMEMODE_1 ) + foreach ( entity hider in GetPlayerArrayOfTeam( HIDEANDSEEK_TEAM_HIDER ) ) + Remote_CallFunction_NonReplay( hider, "ServerCallback_SeekersIncoming" ) + + array<entity> seekers = GetPlayerArrayOfTeam( HIDEANDSEEK_TEAM_SEEKER ) + entity podSpawn = file.droppodSpawns.getrandom() + SpawnPlayersInDropPod( seekers, podSpawn.GetOrigin(), podSpawn.GetAngles() ) + + foreach ( entity seeker in seekers ) + if ( IsValid( seeker ) ) + Highlight_SetEnemyHighlight( seeker, "enemy_sonar" ) +} + +void function SetupHideAndSeekPlayer( entity player ) +{ + foreach ( entity weapon in player.GetMainWeapons() ) + player.TakeWeapon( weapon.GetWeaponClassName() ) + + player.TakeWeapon( player.GetOffhandWeapon( OFFHAND_ORDNANCE ).GetWeaponClassName() ) + + player.GiveWeapon( "mp_weapon_rocket_launcher" ) + player.SetActiveWeaponByName( "mp_weapon_rocket_launcher" ) + + Highlight_SetFriendlyHighlight( player, "sp_friendly_pilot" ) + + if ( player.GetTeam() == HIDEANDSEEK_TEAM_HIDER ) + { + player.TakeWeapon( player.GetMeleeWeapon().GetWeaponClassName() ) + + // set visibility flags if we're hiding, so seekers can't see us on intermission cam + if ( Time() - file.hidingStartTime < file.hidingTime ) + player.kv.visiblityFlags = ENTITY_VISIBLE_TO_FRIENDLY + + // remove red outline, ideally should work tm + Highlight_ClearEnemyHighlight( player ) + } + else + player.TakeWeapon( "mp_weapon_grenade_sonar" ) // seekers should not have pulse blade +} + +void function TryNotifyLastPlayerAlive( entity victim, entity attacker, var damageInfo ) +{ + if ( victim.GetTeam() == HIDEANDSEEK_TEAM_HIDER ) + { + array<entity> hiders = GetPlayerArrayOfTeam( HIDEANDSEEK_TEAM_HIDER ) + if ( hiders.len() == 1 ) + { + PlayMusicToAll( eMusicPieceID.GAMEMODE_2 ) + + // let them know they're the last hider + Remote_CallFunction_NonReplay( hiders[ 0 ], "ServerCallback_LastHiderAlive" ) + StimPlayer( hiders[ 0 ], 9999.9 ) // can't do endless since we don't get the visual effect in endless + + // tell seekers + foreach ( entity player in GetPlayerArrayOfTeam( HIDEANDSEEK_TEAM_SEEKER ) ) + Remote_CallFunction_NonReplay( player, "ServerCallback_LastHiderAlive" ) + } + } +} + +int function HideAndSeekDecideWinner() +{ + return HIDEANDSEEK_TEAM_HIDER // on timeout, hiders always win +}
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut index 8706d53b..b2e76aaf 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_inf.gnut @@ -13,6 +13,7 @@ void function GamemodeInfection_Init() Riff_ForceTitanAvailability( eTitanAvailability.Never ) Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) + SetShouldPlayerStartBleedoutFunc( InfectionShouldPlayerStartBleedout ) AddCallback_OnClientConnected( InfectionInitPlayer ) AddCallback_OnPlayerKilled( InfectionOnPlayerKilled ) AddCallback_OnPlayerRespawned( RespawnInfected ) @@ -176,4 +177,9 @@ int function TimeoutCheckSurvivors() return INFECTION_TEAM_SURVIVOR return INFECTION_TEAM_INFECTED +} + +bool function InfectionShouldPlayerStartBleedout( entity player, var damageInfo ) +{ + return player.GetTeam() != INFECTION_TEAM_INFECTED }
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut index cf9d6bc5..7a226e21 100644 --- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_kr.gnut @@ -13,7 +13,7 @@ void function GamemodeKR_Init() SetSpawnpointGamemodeOverride( FFA ) - Evac_SetEnabled( false ) + ClassicMP_ForceDisableEpilogue( true ) Riff_ForceTitanAvailability( eTitanAvailability.Never ) Riff_ForceBoostAvailability( eBoostAvailability.Disabled ) diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_hs.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_hs.gnut new file mode 100644 index 00000000..8bfbb10e --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/cl_gamemode_hs.gnut @@ -0,0 +1,91 @@ +global function ClGamemodeHideAndSeek_Init +global function ServerCallback_ShowHideAndSeekCountdown +global function ServerCallback_AnnounceHideAndSeekRole +global function ServerCallback_SeekersIncoming +global function ServerCallback_LastHiderAlive + +struct { + var countdownRui +} file + +void function ClGamemodeHideAndSeek_Init() +{ + ClGameState_RegisterGameStateAsset( $"ui/gamestate_info_lts.rpak" ) + + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_mp_fd_midwave", HIDEANDSEEK_TEAM_SEEKER ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_1, "music_skyway_01_intro", HIDEANDSEEK_TEAM_HIDER ) + + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_2, "music_skyway_04_smartpistolrun", TEAM_IMC ) + RegisterLevelMusicForTeam( eMusicPieceID.GAMEMODE_2, "music_skyway_04_smartpistolrun", TEAM_MILITIA ) +} + +void function ServerCallback_ShowHideAndSeekCountdown( float endTime ) +{ + file.countdownRui = CreateCockpitRui( $"ui/dropship_intro_countdown.rpak", 0 ) + RuiSetResolutionToScreenSize( file.countdownRui ) + RuiSetGameTime( file.countdownRui, "gameStartTime", endTime ) +} + +void function ServerCallback_AnnounceHideAndSeekRole() +{ + if ( GetLocalViewPlayer().GetTeam() == HIDEANDSEEK_TEAM_SEEKER ) + { + AnnouncementData announcement = Announcement_Create( "#HIDEANDSEEK_YOU_ARE_SEEKER" ) + Announcement_SetSubText( announcement, Localize( "#HIDEANDSEEK_SEEKER_DESC", GetCurrentPlaylistVarFloat( "hideandseek_hiding_time", 60.0 ).tostring() ) ) + Announcement_SetTitleColor( announcement, <0,0,1> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + } + else + { + AnnouncementData announcement = Announcement_Create( "#HIDEANDSEEK_YOU_ARE_HIDER" ) + Announcement_SetSubText( announcement, "#HIDEANDSEEK_HIDER_DESC" ) + Announcement_SetTitleColor( announcement, <0,0,1> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + } +} + +void function ServerCallback_SeekersIncoming() +{ + AnnouncementData announcement = Announcement_Create( "#HIDEANDSEEK_SEEKERS_INCOMING" ) + Announcement_SetSubText( announcement, "#HIDEANDSEEK_DONT_GET_FOUND" ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) +} + +void function ServerCallback_LastHiderAlive() +{ + if ( GetLocalViewPlayer().GetTeam() == HIDEANDSEEK_TEAM_SEEKER ) + { + AnnouncementData announcement = Announcement_Create( Localize( "#HIDEANDSEEK_GET_LAST_HIDER", GetPlayerArrayOfTeam_Alive( HIDEANDSEEK_TEAM_HIDER )[ 0 ].GetPlayerName() ) ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + } + else + { + AnnouncementData announcement = Announcement_Create( "#HIDEANDSEEK_YOU_ARE_LAST_HIDER" ) + Announcement_SetSubText( announcement, "#HIDEANDSEEK_GOT_STIM" ) + Announcement_SetTitleColor( announcement, <1,0,0> ) + Announcement_SetPurge( announcement, true ) + Announcement_SetPriority( announcement, 200 ) //Be higher priority than Titanfall ready indicator etc + Announcement_SetSoundAlias( announcement, SFX_HUD_ANNOUNCE_QUICK ) + Announcement_SetStyle( announcement, ANNOUNCEMENT_STYLE_QUICK ) + AnnouncementFromClass( GetLocalViewPlayer(), announcement ) + } +} + diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_hs.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_hs.gnut new file mode 100644 index 00000000..f4269ac4 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/sh_gamemode_hs.gnut @@ -0,0 +1,47 @@ +global function Sh_GamemodeHideAndSeek_Init + +global const string GAMEMODE_HIDEANDSEEK = "hs" +global const int HIDEANDSEEK_TEAM_SEEKER = TEAM_IMC +global const int HIDEANDSEEK_TEAM_HIDER = TEAM_MILITIA + +void function Sh_GamemodeHideAndSeek_Init() +{ + // create custom gamemode + AddCallback_OnCustomGamemodesInit( CreateGamemodeHideAndSeek ) + AddCallback_OnRegisteringCustomNetworkVars( HideAndSeekRegisterNetworkVars ) +} + +void function CreateGamemodeHideAndSeek() +{ + GameMode_Create( GAMEMODE_HIDEANDSEEK ) + GameMode_SetName( GAMEMODE_HIDEANDSEEK, "#GAMEMODE_hs" ) + GameMode_SetDesc( GAMEMODE_HIDEANDSEEK, "#PL_hs_desc" ) + GameMode_SetGameModeAnnouncement( GAMEMODE_HIDEANDSEEK, "ffa_modeDesc" ) + GameMode_SetColor( GAMEMODE_HIDEANDSEEK, [147, 204, 57, 255] ) + + AddPrivateMatchMode( GAMEMODE_HIDEANDSEEK ) // add to private lobby modes + AddPrivateMatchModeSettingEnum( "#GAMEMODE_hs", "hideandseek_balance_teams", [ "Disabled", "Enabled" ], "1" ) + AddPrivateMatchModeSettingArbitrary( "#GAMEMODE_hs", "hideandseek_hiding_time", "60" ) + + #if SERVER + GameMode_AddServerInit( GAMEMODE_HIDEANDSEEK, GamemodeHideAndSeek_Init ) + GameMode_SetPilotSpawnpointsRatingFunc( GAMEMODE_HIDEANDSEEK, RateSpawnpoints_Generic ) + GameMode_SetTitanSpawnpointsRatingFunc( GAMEMODE_HIDEANDSEEK, RateSpawnpoints_Generic ) + #elseif CLIENT + GameMode_AddClientInit( GAMEMODE_HIDEANDSEEK, ClGamemodeHideAndSeek_Init ) + #endif + #if !UI + GameMode_SetScoreCompareFunc( GAMEMODE_HIDEANDSEEK, CompareAssaultScore ) + #endif +} + +void function HideAndSeekRegisterNetworkVars() +{ + if ( GAMETYPE != GAMEMODE_HIDEANDSEEK ) + return + + Remote_RegisterFunction( "ServerCallback_ShowHideAndSeekCountdown" ) + Remote_RegisterFunction( "ServerCallback_SeekersIncoming" ) + Remote_RegisterFunction( "ServerCallback_LastHiderAlive" ) + Remote_RegisterFunction( "ServerCallback_AnnounceHideAndSeekRole" ) +}
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob.nut b/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob.nut new file mode 100644 index 00000000..afd4fc37 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob.nut @@ -0,0 +1,38 @@ +untyped +global function CodeCallback_MapInit + +const float PLATFORM_TRAVEL_TIME = 20.0 + +struct { + array<entity> platformMoverNodes + entity platformMover +} file + +void function CodeCallback_MapInit() +{ + AddCallback_EntitiesDidLoad( BobMap_EntitiesDidLoad ) +} + +void function BobMap_EntitiesDidLoad() +{ + BobMap_InitTempProps() + + file.platformMoverNodes = GetEntityLinkChain( GetEntByScriptName( "mp_bob_movingplatform_node_0" ) ) + file.platformMover = GetEntByScriptName( "mp_bob_movingplatform" ) + file.platformMover.SetOrigin( file.platformMoverNodes[ 0 ].GetOrigin() ) + + entity platformProp = CreatePropDynamic( file.platformMover.GetValueForModelKey(), file.platformMover.GetOrigin(), file.platformMover.GetAngles() ) + platformProp.SetParent( file.platformMover ) + + thread MovingPlatformThink() +} + +void function MovingPlatformThink() +{ + int currentNodeIdx = 0 + while ( true ) + { + file.platformMover.SetOrigin( file.platformMoverNodes[ currentNodeIdx % file.platformMoverNodes.len() ].GetOrigin() ) + file.platformMover.MoveTo( file.platformMoverNodes[ ++currentNodeIdx % file.platformMoverNodes.len() ].GetOrigin(), PLATFORM_TRAVEL_TIME, 0, 0 ) + } +}
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob_temp_props.nut b/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob_temp_props.nut new file mode 100644 index 00000000..84ffe3e9 --- /dev/null +++ b/Northstar.Custom/mod/scripts/vscripts/mp/levels/mp_bob_temp_props.nut @@ -0,0 +1,7 @@ +global function BobMap_InitTempProps + +void function BobMap_InitTempProps() +{ + PrecacheModel( $"models/vistas/planet_blue_sun.mdl" ) + CreatePropDynamic( $"models/vistas/planet_blue_sun.mdl", GetEnt( "skybox_cam_level" ).GetOrigin(), GetEnt( "skybox_cam_level" ).GetAngles() ) +}
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/vscripts/titan/sh_first_person_embark.gnut b/Northstar.Custom/mod/scripts/vscripts/titan/sh_first_person_embark.gnut index 0c95ae4c..0c47c014 100644 --- a/Northstar.Custom/mod/scripts/vscripts/titan/sh_first_person_embark.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/titan/sh_first_person_embark.gnut @@ -1,4 +1,5 @@ global function FirstPersonEmbark_Init +global function FirstPersonEmbark_InitPlaylistVars #if CLIENT global function ServerCallback_HideHudForFPEmbark @@ -24,6 +25,11 @@ void function FirstPersonEmbark_RegisterCustomNetworkFunctions() Remote_RegisterFunction( "ServerCallback_HideHudForFPEmbark" ) } +void function FirstPersonEmbark_InitPlaylistVars() +{ + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_TITAN", "fp_embark_enabled", [ "Disabled", "Enabled" ], "0" ) +} + #if CLIENT void function ServerCallback_HideHudForFPEmbark() { diff --git a/Northstar.Custom/mod/scripts/weapons/mp_weapon_peacekraber.txt b/Northstar.Custom/mod/scripts/weapons/mp_weapon_peacekraber.txt index c5e61f93..59219cab 100644 --- a/Northstar.Custom/mod/scripts/weapons/mp_weapon_peacekraber.txt +++ b/Northstar.Custom/mod/scripts/weapons/mp_weapon_peacekraber.txt @@ -335,13 +335,9 @@ WeaponData crosshairMovementY weapon_is_reloading } - Crosshair_2 + Crosshair_2 { "ui" "ui/crosshair_lstar" "base_spread" "4" - Args - { - - } } }
\ No newline at end of file diff --git a/Northstar.Custom/mod/scripts/weapons/mp_weapon_sniper.txt b/Northstar.Custom/mod/scripts/weapons/mp_weapon_sniper.txt deleted file mode 100644 index ede43d7d..00000000 --- a/Northstar.Custom/mod/scripts/weapons/mp_weapon_sniper.txt +++ /dev/null @@ -1,651 +0,0 @@ -WeaponData -{ - // General - "printname" "#WPN_SNIPER" - "shortprintname" "#WPN_SNIPER_SHORT" - "description" "#WPN_SNIPER_DESC" - "longdesc" "#WPN_SNIPER_LONGDESC" - - "menu_icon" "r2_ui/menus/loadout_icons/primary_weapon/primary_kraber" - "hud_icon" "r2_ui/menus/loadout_icons/primary_weapon/primary_kraber" - - "weaponClass" "human" - "weaponSubClass" "sniper" - "body_type" "heavy" - "fire_mode" "semi-auto" - "pickup_hold_prompt" "Hold [USE] [WEAPONNAME]" - "pickup_press_prompt" "[USE] [WEAPONNAME]" - "minimap_reveal_distance" "32000" - "leveled_pickup" "1" - - "OnWeaponActivate" "OnWeaponActivate_weapon_sniper" - "OnClientAnimEvent" "OnClientAnimEvent_weapon_sniper" - "OnWeaponPrimaryAttack" "OnWeaponPrimaryAttack_weapon_sniper" - "OnWeaponNpcPrimaryAttack" "OnWeaponNpcPrimaryAttack_weapon_sniper" - "OnProjectileCollision" "OnProjectileCollision_weapon_sniper" - - "viewmodel_offset_ads" "0 0 0" - - // Menu - "menu_category" "sniper" - "menu_anim_class" "large" - "stat_damage" "100" - "stat_range" "100" - "stat_accuracy" "60" - "stat_rof" "15" - - "ads_dof_disable" "1" - - // Models - "viewmodel" "models/weapons/at_rifle/ptpov_at_rifle.mdl" - "playermodel" "models/weapons/at_rifle/w_at_rifle.mdl" - "projectilemodel" "models/weapons/bullets/projectile_20mm.mdl" - - // Effects - "impact_effect_table" "titan_bullet" - "projectile_trail_effect_0" "weapon_kraber_projectile" - "projectile_do_predict_impact_effects" "1"//0" - "vortex_absorb_effect" "wpn_vortex_projectile_20mm_FP" - "vortex_absorb_effect_third_person" "wpn_vortex_projectile_20mm" - "vortex_absorb_sound" "Vortex_Shield_AbsorbBulletLarge" - "vortex_absorb_sound_1p_vs_3p" "Vortex_Shield_AbsorbBulletLarge_1P_VS_3P" - "projectile_adjust_to_gun_barrel" "1" - - // Sounds - "sound_dryfire" "rifle_dryfire" - "sound_pickup" "wpn_pickup_Rifle_1P" - "sound_zoom_in" "Weapon_Rangemaster_Kraber_ADS_In" - "sound_zoom_out" "Weapon_Rangemaster_Kraber_ADS_Out" - "fire_sound_1_player_1p" "large_shell_drop" - "fire_sound_1_player_3p" "large_shell_drop" - "fire_sound_1_npc" "large_shell_drop" - "fire_sound_2_player_1p" "Weapon_Kraber_Fire_1P" - "fire_sound_2_player_3p" "Weapon_Kraber_Fire_3P" - "fire_sound_2_npc" "Weapon_Kraber_Fire_npc" - - "low_ammo_sound_name_1" "Kraber_LowAmmo_Shot1" - "low_ammo_sound_name_2" "Kraber_LowAmmo_Shot2" - "low_ammo_sound_name_3" "Kraber_LowAmmo_Shot3" - - "fx_shell_eject_view" "wpn_shelleject_rifle_large_FP" - "fx_shell_eject_world" "wpn_shelleject_rifle_large" - "fx_shell_eject_attach" "shell" - "fx_shell_eject_attach_scoped" "shell_scoped" - - "fx_muzzle_flash_view" "wpn_muzzleflash_snp_hmn_FP" - "fx_muzzle_flash_world" "wpn_muzzleflash_snp_hmn" - "fx_muzzle_flash_attach" "muzzle_flash" - "fx_muzzle_flash_attach_scoped" "muzzle_flash_scoped" - - // Bolt info - "bolt_hitsize" "0.0" - "bolt_hitsize_grow1_time" "0.035" - "bolt_hitsize_grow1_size" "0.5" - "bolt_hitsize_grow2_time" "0.08" - "bolt_hitsize_grow2_size" "1.0" - "bolt_hitsize_growfinal_lerptime" "0.18" - "bolt_hitsize_growfinal_size" "2.0" - - "bolt_gravity_enabled" "1" - "bolt_gravity_amount" "0.2500"//0.500" - - "bolt_bounce_frac" "0.000" - "projectile_damage_reduction_per_bounce" "0.0" - "projectile_damages_owner" "0" - "projectile_ricochet_max_count" "0" - - "pass_through_depth" "64" - "pass_through_damage_preserved_scale" "1" - - "bolt_speed" "10000" - - // Damage - When Used by Players - "damage_flags" "DF_BULLET | DF_KNOCK_BACK | DF_DISMEMBERMENT" - "damage_type" "bullet" - - "damage_headshot_scale" "1.5" - - "impulse_force" "10" - - "ammo_clip_size" "4" - - "titanarmor_critical_hit_required" "1" - "critical_hit" "1" - - - MP_BASE - { - "ammo_default_total" "40" - "ammo_stockpile_max" "40" - "ammo_no_remove_from_stockpile" "1" - "ammo_min_to_fire" "1" - - - "damage_near_value" "350" - "damage_far_value" "350" - "damage_near_value_titanarmor" "430" - "damage_far_value_titanarmor" "430" - "damage_rodeo" "900" - "damage_near_distance" "2000" - "damage_far_distance" "15000" - - "red_crosshair_range" "15000" - - "critical_hit_damage_scale" "1" - - // Damage - When Used by NPCs - "npc_damage_near_value" "49" - "npc_damage_far_value" "49" - "npc_damage_near_value_titanarmor" "50" - "npc_damage_far_value_titanarmor" "25" - - "npc_accuracy_multiplier_pilot" "1.0" - - "npc_suppress_lsp_allowed" "0" - - "enable_highlight_networking_on_creation" "<KEEP_DEFAULT>" - - "damage_heavyarmor_nontitan_scale" "0.35" - - "zoom_toggle_lerp_time" "<KEEP_DEFAULT>" - "zoom_toggle_fov" "<KEEP_DEFAULT>" - } - - SP_BASE - { - "zoom_toggle_lerp_time" "0.2" - "zoom_toggle_fov" "7" - - "ammo_default_total" "12" - "ammo_stockpile_max" "28" - "ammo_no_remove_from_stockpile" "0" - "ammo_min_to_fire" "1" - - - "damage_near_value" "200" - "damage_far_value" "200" - "damage_near_value_titanarmor" "500" - "damage_far_value_titanarmor" "500" - "damage_rodeo" "900" - "damage_near_distance" "2000" - "damage_far_distance" "15000" - - "red_crosshair_range" "15000" - - "critical_hit_damage_scale" "1.5" - - // Damage - When Used by NPCs - "npc_damage_near_value" "49" - "npc_damage_far_value" "49" - "npc_damage_near_value_titanarmor" "50" - "npc_damage_far_value_titanarmor" "25" - - "npc_accuracy_multiplier_pilot" "3.0" - - "npc_suppress_lsp_allowed" "<KEEP_DEFAULT>" - - "enable_highlight_networking_on_creation" "1" - - "damage_heavyarmor_nontitan_scale" "1" - } - - // NPC - "proficiency_poor_spreadscale" "3.0" - "proficiency_average_spreadscale" "2.2" - "proficiency_good_spreadscale" "2.0" - "proficiency_very_good_spreadscale" "1.5" - - "npc_min_engage_range" "500" - "npc_max_engage_range" "8000" - "npc_min_engage_range_heavy_armor" "500" - "npc_max_engage_range_heavy_armor" "8000" - "npc_min_range" "0" - "npc_max_range" "8000" - - "npc_min_burst" "1" - "npc_max_burst" "1" - "npc_rest_time_between_bursts_min" "2.0" - "npc_rest_time_between_bursts_max" "3.0" - - "dof_zoom_nearDepthStart" "0" - "dof_zoom_nearDepthEnd" "0" - "dof_nearDepthStart" "4.750" - "dof_nearDepthEnd" "9" - - // Behavior - "fire_rate" "1.85" - "zoom_time_in" "0.4"//0.48"//1.1"//1.25"//0.45" - "zoom_time_out" "0.3" - "zoom_fov" "26.26" //3x zoom - "zoom_scope_frac_start" "0.2"//0.2" - "zoom_scope_frac_end" "0.7"//0.85" - "zoom_angle_shift_pitch" "0.3" - "zoom_angle_shift_yaw" "0.65" - "rechamber_time" "1.60"//1.30" - "reload_time" "2.5" - "reload_time_late1" "1.52" - "reload_time_late2" "0.63" - "reloadempty_time" "3.61" - "reloadempty_time_late1" "2.63" - "reloadempty_time_late2" "1.75" - "reloadempty_time_late3" "0.55" - "holster_time" "0.5" - "deploy_time" "0.8" - "lower_time" "0.25" - "raise_time" "0.3" - "vortex_refire_behavior" "bullet" - "allow_empty_fire" "0" - "reload_enabled" "1" - "allow_empty_click" "1" - "empty_reload_only" "0" - "trigger_snipercam" "1" - "allow_headshots" "1" - "ads_move_speed_scale" "0.5"//0.35" - "aimassist_disable_hipfire" "1" - "aimassist_disable_ads" "1" - "aimassist_disable_hipfire_titansonly" "1" - "aimassist_disable_ads_titansonly" "1" - "gamepad_use_yaw_speed_for_pitch_ads" "1" - "ads_fov_zoomfrac_start" "0.5" - "ads_fov_zoomfrac_end" "0.9" - - "sprint_fractional_anims" "0" - - // Spread - "spread_stand_hip" "10" - "spread_stand_hip_run" "12" - "spread_stand_ads" "0.0" //"0.1" - "spread_crouch_hip" "8" - "spread_crouch_ads" "0" - "spread_air_hip" "12" - "spread_air_ads" "0.0" //".15" - - "ammo_suck_behavior" "primary_weapons" - - // View Kick - "viewkick_spring" "sniper" - - "viewkick_pitch_base" "-0.5625"//"-1.25"// - "viewkick_pitch_random" "0.0225"//"0.05"// - "viewkick_pitch_softScale" "0.8" - "viewkick_pitch_hardScale" "2" - - "viewkick_yaw_base" "-0.135"//"-0.3"// - "viewkick_yaw_random" "0.045"//"0.1"// - "viewkick_yaw_softScale" "1.0" - "viewkick_yaw_hardScale" "1.5" - - "viewkick_roll_base" "0" - "viewkick_roll_randomMin" "0.5" - "viewkick_roll_randomMax" "0.5" - "viewkick_roll_softScale" "0.2" - "viewkick_roll_hardScale" "3.0" - - "viewkick_hipfire_weaponFraction" "0.4" - "viewkick_hipfire_weaponFraction_vmScale" "0.55" - "viewkick_ads_weaponFraction" "0.0"//"0.45"// - "viewkick_ads_weaponFraction_vmScale" "0.0"//"-0.3"// - - "viewkick_perm_pitch_base" "0.0" - "viewkick_perm_pitch_random" "0.0" - "viewkick_perm_pitch_random_innerexclude" "0.0" - "viewkick_perm_yaw_base" "0.0" - "viewkick_perm_yaw_random" "0.0" - "viewkick_perm_yaw_random_innerexclude" "0.0" - - // - "viewmodel_shake_forward" "0.5" - "viewmodel_shake_up" "0.1" - "viewmodel_shake_right" "0.0" - - // Bob - "bob_cycle_time" "0.4" - "bob_vert_dist" "0.19" - "bob_horz_dist" "0.1" - "bob_max_speed" "150" - "bob_pitch" "0.75" - "bob_yaw" "-1.7" - "bob_roll" "1.2" - - // Bob_Zoomed - "bob_cycle_time_zoomed" "0.4" - "bob_vert_dist_zoomed" "0.0025" - "bob_horz_dist_zoomed" "0.0025" - "bob_max_speed_zoomed" "150" - //"bob_pitch_zoomed" "0.002" - //"bob_yaw_zoomed" "-.002" - //"bob_roll_zoomed" ".002" - - // Rumble - "fire_rumble" "rumble_sniper" - - // Sway - "sway_rotate_attach" "SWAY_ROTATE" - "sway_min_x" "-0.5" - "sway_min_y" "-0.5" - "sway_min_z" "-0.6" - "sway_max_x" "0.5" - "sway_max_y" "0.5" - "sway_max_z" "0.6" - "sway_min_pitch" "-3" - "sway_min_yaw" "-2.5" - "sway_min_roll" "-4" - "sway_max_pitch" "3" - "sway_max_yaw" "2.5" - "sway_max_roll" "4" - "sway_translate_gain" "2.5" - "sway_rotate_gain" "7" - "sway_move_forward_translate_x" "-0.1" - "sway_move_forward_translate_z" "-0.5" - "sway_move_back_translate_x" "0.2" - "sway_move_back_translate_z" "-0.2" - "sway_move_left_translate_y" "-1" - "sway_move_left_translate_z" "-0.5" - "sway_move_left_rotate_roll" "-4" - "sway_move_right_translate_y" "1" - "sway_move_right_translate_z" "-0.5" - "sway_move_right_rotate_roll" "4" - "sway_move_up_translate_z" "-1" - "sway_move_down_translate_z" "1" - "sway_turn_left_rotate_yaw" "-2.5" - "sway_turn_right_rotate_yaw" "2.5" - - "sway_turn_left_translate_y" ".5" - "sway_turn_right_translate_y" "-.5" - "sway_turn_up_translate_z" ".2" - "sway_turn_down_translate_z" "-.2" - "sway_turn_up_translate_x" ".1" - "sway_turn_down_translate_x" "-.1" - - "sway_turn_left_rotate_roll" "4" - "sway_turn_right_rotate_roll" "-4" - "sway_turn_up_rotate_pitch" "3" - "sway_turn_down_rotate_pitch" "-3" - "sway_turn_up_rotate_roll" "-0.8" - "sway_turn_down_rotate_roll" "0.8" - - // Zoomed Sway - "sway_rotate_attach_zoomed" "jx_c_pov" - "sway_rotate_attach_blend_time_zoomed" "0.2" - "sway_rotate_gain_zoomed" "5" - - "sway_min_yaw_zoomed" "-0.085" - "sway_max_yaw_zoomed" "0.085" - "sway_turn_left_rotate_yaw_zoomed" "0.085" - "sway_turn_right_rotate_yaw_zoomed" "-0.085" - - "sway_min_roll_zoomed" "-1" - "sway_max_roll_zoomed" "1" - "sway_turn_left_rotate_roll_zoomed" "-1" - "sway_turn_right_rotate_roll_zoomed" "1" - - "sway_move_right_rotate_roll_zoomed" "0.2" - "sway_move_left_rotate_roll_zoomed" "-0.2" - - "sway_min_pitch_zoomed" "-0.25" - "sway_max_pitch_zoomed" "0.25" - "sway_turn_up_rotate_pitch_zoomed" "-0.25" - "sway_turn_down_rotate_pitch_zoomed" "0.25" - - // WeaponED Unhandled Key/Values and custom script Key/Values - "sprintcycle_time" ".55" - "is_sniper" "1" - - // Bodygroups: - "bodygroup1_name" "scope_dcom" - "bodygroup1_set" "1" - "bodygroup2_name" "scope_zoom" - "bodygroup2_set" "0" - "bodygroup3_name" "ammo" - "bodygroup3_set" "1" - "bodygroup4_name" "scope_outline" - "bodygroup4_set" "0" - "bodygroup5_name" "scope_oracle" - "bodygroup5_set" "0" - "bodygroup6_name" "proscreen" - "bodygroup6_set" "0" - // "bodygroup7_name" "suppressor_sq_lg" - // "bodygroup7_set" "0" - - "bodygroup_ads_scope_name" "ads_scopes" - "bodygroup_ads_scope_set" "3" - - - "anim_alt_idleAttack" "0" - - "clip_bodygroup" "at_rifle_magazine" - "clip_bodygroup_index_shown" "0" - "clip_bodygroup_index_hidden" "1" - "clip_bodygroup_show_for_milestone_0" "1" - "clip_bodygroup_show_for_milestone_1" "0" - "clip_bodygroup_show_for_milestone_2" "1" - "clip_bodygroup_show_for_milestone_3" "1" - - "bodygroup_ammo_index_count" "6" - - Mods - { - iron_sights - { - - } - scope_4x - { - //Use this for Variable Zoom - "ui7_enable" "1" - - "bodygroup1_set" "0" - "bodygroup2_set" "0" - "bodygroup4_set" "1" - "bodygroup5_set" "0" - "bodygroup_ads_scope_set" "2" - "zoom_toggle_lerp_time" "0.2" - "zoom_toggle_fov" "7" - //"ui6_enable" "1" - } - extended_ammo - { - "ammo_stockpile_max" "90" - "ammo_clip_size" "7" - "ammo_default_total" "90" - } - stabilizer - { - "bodygroup1_set" "0" - "bodygroup2_set" "0" - "bodygroup4_set" "0" - "bodygroup5_set" "1" - "bodygroup_ads_scope_set" "0" - - // "viewdrift_ads_stand_scale_pitch" "*0.5" - // "viewdrift_ads_crouch_scale_pitch" "*0.5" - // "viewdrift_ads_air_scale_pitch" "*0.5" - // "viewdrift_ads_air_scale_yaw" "*0.5" - // "viewdrift_ads_stand_scale_yaw" "*0.5" - // "viewdrift_ads_crouch_scale_yaw" "*0.5" - // "viewdrift_ads_speed_pitch" "*0.5" - // "viewdrift_ads_speed_yaw" "*0.5" - - "viewmodel_offset_ads" "0 -2.95 0.31" - //"viewmodel_offset_lerp_endFrac" "1" - - "ads_fov_zoomfrac_start" "0.3" - "ads_fov_zoomfrac_end" "0.8" - - "dof_zoom_nearDepthStart" "7.0" - "dof_zoom_nearDepthEnd" "7.2" - - "anim_alt_idleAttack" "1" - } - ricochet - { - "bolt_bounce_frac" "0.7" - "projectile_damage_reduction_per_bounce" "0.0" - "projectile_damages_owner" "0" - "projectile_ricochet_max_count" "2" - } - slammer - { - } - threat_scope - { - "bodygroup1_set" "0" - "bodygroup2_set" "1" - "bodygroup4_set" "0" - "bodygroup5_set" "0" - "bodygroup_ads_scope_set" "1" - - "threat_scope_enabled" "1" - "threat_scope_bounds_width" "1.5" - "threat_scope_bounds_height" "1.1" - "threat_scope_zoomfrac_start" "0.85" - "viewmodel_offset_ads" "0 0.5 0" - dof_zoom_focusArea_horizontal 0.068 - dof_zoom_focusArea_top 0.065 - dof_zoom_focusArea_bottom -0.046 - } - pro_screen - { - "ui8_enable" "1" - "bodygroup6_set" "1" - } - tactical_cdr_on_kill - { - - } - pas_fast_reload - { - "reload_time" "*0.7" - "reload_time_late1" "*0.7" - "reloadempty_time" "*0.7" - "reloadempty_time_late1" "*0.7" - } - pas_fast_ads - { - //Fast ADS - "zoom_time_in" "*0.5" - "zoom_time_out" "*0.6" - } - pas_fast_swap - { - //Fast Swap - "fast_swap_to" "1" - } - burn_mod_sniper - { - "is_burn_mod" "1" - //FX - "fx_muzzle_flash_view" "wpn_muzzleflash_snp_hmn_FP_burn" - "fx_muzzle_flash_world" "wpn_muzzleflash_snp_hmn_burn" - "projectile_trail_effect_0" "weapon_kraber_projectile_burn" - //"impact_effect_table" "titan_bullet_elec" - - "damage_near_value" "450" - "damage_far_value" "450" - "damage_near_value_titanarmor" "580" - "damage_far_value_titanarmor" "580" - - // reimplement tf1 amped kraber - "explosion_damage" "150" - "explosion_damage_heavy_armor" "150" - "explosion_inner_radius" "25" - "explosionradius" "75" - "explosion_shake_radius" "250" - "explosion_shake_amplitude" "10" - "explosion_shake_frequency" "50" - "explosion_shake_duration" "0.6" - "impact_effect_table" "exp_small" - } - pve_elite - { - //"ammo_stockpile_max" "90" - //"ammo_clip_size" "7" - //"ammo_default_total" "90" - //"reload_time" "0.1" - //"fire_rate" "0.1" - "npc_damage_near_value" "70" - "npc_damage_far_value" "70" - } - } - - "ui1_enable" "1" - UiData1 - { - "ui" "ui/kraber_ammo_counter" - "mesh" "models/weapons/attachments/kraber_rui_lower" - Args - { - vis player_zoomfrac - ammo weapon_ammo - clipSize weapon_clipSize - } - } - - "ui6_enable" "0" - UiData6 - { - "ui" "ui/red_dot_basic" - "mesh" "models/weapons/attachments/sniper_scope_rui_upper" - Args - { - vis player_zoomfrac - ammo weapon_ammo - clipSize weapon_clipSize - clipCount weapon_stockpileClipCount - } - } - - "ui7_enable" "0" - UiData7 - { - "ui" "ui/variable_zoom_crosshair" - "mesh" "models/weapons/attachments/attach_scope_ads_2_crosshair" - Args - { - vis player_zoomfrac - ammo weapon_ammo - clipSize weapon_clipSize - clipCount weapon_stockpileClipCount - } - } - - "ui8_enable" "0" - UiData8 - { - "ui" "ui/pro_screen_panel" - "mesh" "models/weapons/attachments/pro_screen_rui_upper" - Args - { - proValue proscreen_int0 - proOwnedByPlayer proscreen_owner_is_player - } - } - - active_crosshair_count "1" - rui_crosshair_index "0" - - RUI_CrosshairData - { - DefaultArgs - { - adjustedSpread weapon_spread - adsFrac player_zoomFrac - isSprinting player_is_sprinting - isReloading weapon_is_reloading - teamColor crosshair_team_color - isAmped weapon_is_amped - crosshairMovementX crosshair_movement_x - crosshairMovementY crosshair_movement_y - } - - Crosshair_1 - { - "ui" "ui/crosshair_sniper_amped" - "base_spread" "10" - Args - { - isFiring weapon_is_firing - } - } - } -} diff --git a/Northstar.Custom/vpk/client_mp_northstar_common.bsp.pak000_000.vpk b/Northstar.Custom/vpk/client_mp_northstar_common.bsp.pak000_000.vpk Binary files differindex 1b8ef396..35313d15 100644 --- a/Northstar.Custom/vpk/client_mp_northstar_common.bsp.pak000_000.vpk +++ b/Northstar.Custom/vpk/client_mp_northstar_common.bsp.pak000_000.vpk diff --git a/Northstar.Custom/vpk/englishclient_mp_northstar_common.bsp.pak000_dir.vpk b/Northstar.Custom/vpk/englishclient_mp_northstar_common.bsp.pak000_dir.vpk Binary files differindex 4d71f977..2d5cd687 100644 --- a/Northstar.Custom/vpk/englishclient_mp_northstar_common.bsp.pak000_dir.vpk +++ b/Northstar.Custom/vpk/englishclient_mp_northstar_common.bsp.pak000_dir.vpk diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json index 547a1b8c..ac826d1a 100644 --- a/Northstar.CustomServers/mod.json +++ b/Northstar.CustomServers/mod.json @@ -10,6 +10,16 @@ { "Name": "ns_should_return_to_lobby", "DefaultValue": "1" + }, + + { + "Name": "ns_private_match_last_mode", + "DefaultValue": "aitdm" + }, + + { + "Name": "ns_private_match_last_map", + "DefaultValue": "mp_forwardbase_kodai" } ], diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut index 2b7b90b3..58d38ce7 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut @@ -221,14 +221,12 @@ bool function ClientCommandCallback_SetFactionChoicePersistenceSlot( entity play bool function ClientCommandCallback_LoadoutMenuClosed( entity player, array<string> args ) { - SavePdataForEntityIndex( player.GetPlayerIndex() ) TryGivePilotLoadoutForGracePeriod( player ) return true } bool function ClientCommandCallback_InGameMPMenuClosed( entity player, array<string> args ) { - SavePdataForEntityIndex( player.GetPlayerIndex() ) //TryGivePilotLoadoutForGracePeriod( player ) return true } diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut index c116ac33..d0820dd6 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut @@ -7,11 +7,18 @@ void function MenuCallbacks_Init() bool function ClientCommandCallback_LeaveMatch( entity player, array<string> args ) { - // todo: ideally, it'd be nice to get clients to return to lobby here, rather than just dcing them - // kind of a pain tho, since we'd have to get it to call script code without a remote func, since that'd break compatibility + thread WritePersistenceAndLeave( player ) + return true +} - ClientCommand( player, "disconnect" ) - //ClientCommand( player, "setplaylist tdm; map mp_lobby" ) +void function WritePersistenceAndLeave( entity player ) +{ + // write player persistence before we leave, since leaving player might load local lobby before server writes persistence, so they won't get newest + // not super essential, but a nice qol thing + NSEarlyWritePlayerPersistenceForLeave( player ) + while ( NSIsWritingPlayerPersistence() ) + WaitFrame() - return true + // this is a custom concommand which can be called on clients, it causes them to leave and doesn't have issues if they're host + ClientCommand( player, "ns_leave_to_lobby" ) }
\ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut index ba473cae..c0242cc1 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut @@ -1,315 +1,360 @@ untyped - global function Evac_Init -global function Evac_AddLocation -global function Evac_SetSpacePosition -global function Evac_SetEnabled -global function Evac_IsEnabled +global function AddEvacNode +global function SetEvacSpaceNode global function IsEvacDropship -global function EvacMain +global function EvacEpilogueSetup +global function Evac + +const float EVAC_INITIAL_WAIT = 5.0 const float EVAC_ARRIVAL_TIME = 40.0 const float EVAC_WAIT_TIME = 18.0 -struct { - bool enabled = true +// we don't use these because they're busted, just keeping them +const array<string> EVAC_EMBARK_ANIMS_1P = [ + "ptpov_e3_rescue_side_embark_A", + "ptpov_e3_rescue_side_embark_B", + "ptpov_e3_rescue_side_embark_C", + "ptpov_e3_rescue_side_embark_D", + "ptpov_e3_rescue_side_embark_E", + "ptpov_e3_rescue_side_embark_F", + "ptpov_e3_rescue_side_embark_G", + "ptpov_e3_rescue_side_embark_H" +] + +const array<string> EVAC_EMBARK_ANIMS_3P = [ + "pt_e3_rescue_side_embark_A", + "pt_e3_rescue_side_embark_B", + "pt_e3_rescue_side_embark_C", + "pt_e3_rescue_side_embark_D", + "pt_e3_rescue_side_embark_E", + "pt_e3_rescue_side_embark_F", + "pt_e3_rescue_side_embark_G", + "pt_e3_rescue_side_embark_H" +] - array<Point> evacPoints - Point spacePosition +const array<string> EVAC_IDLE_ANIMS_1P = [ + "ptpov_e3_rescue_side_embark_A_idle", + "ptpov_e3_rescue_side_embark_B_idle", + "ptpov_e3_rescue_side_embark_C_idle", + "ptpov_e3_rescue_side_embark_D_idle", + "ptpov_e3_rescue_side_embark_E_idle", + "ptpov_e3_rescue_side_embark_F_idle", + "ptpov_e3_rescue_side_embark_G_idle", + "ptpov_e3_rescue_side_embark_H_idle" +] + +const array<string> EVAC_IDLE_ANIMS_3P = [ + "pt_e3_rescue_side_idle_A", + "pt_e3_rescue_side_idle_B", + "pt_e3_rescue_side_idle_C", + "pt_e3_rescue_side_idle_D", + "pt_e3_rescue_side_idle_E", + "pt_e3_rescue_side_idle_F", + "pt_e3_rescue_side_idle_G", + "pt_e3_rescue_side_idle_H" +] + +struct { + array<entity> evacNodes + entity spaceNode entity evacDropship - array<entity> evacPlayers + entity evacIcon } file void function Evac_Init() { EvacShared_Init() - - AddCallback_GameStateEnter( eGameState.Epilogue, Evac_OnEpilogue ) } -void function Evac_SetEnabled( bool enabled ) +void function AddEvacNode( entity evacNode ) { - file.enabled = enabled + file.evacNodes.append( evacNode ) } -bool function Evac_IsEnabled() +void function SetEvacSpaceNode( entity spaceNode ) { - return false // shit is busted rn lol - //return file.enabled && GetClassicMPMode() && !IsRoundBased() + file.spaceNode = spaceNode } -void function Evac_AddLocation( vector origin, vector angles ) +bool function IsEvacDropship( entity ent ) { - Point evacPoint - evacPoint.origin = origin - evacPoint.angles = angles - - file.evacPoints.append( evacPoint ) + return file.evacDropship == ent && IsValid( file.evacDropship ) } -void function Evac_SetSpacePosition( vector origin, vector angles ) +// evac epilogue +void function EvacEpilogueSetup() { - file.spacePosition.origin = origin - file.spacePosition.angles = angles + AddCallback_GameStateEnter( eGameState.Epilogue, EvacEpilogue ) } -bool function IsEvacDropship( entity ent ) +void function EvacEpilogue() { - return file.evacDropship == ent && IsValid( file.evacDropship ) + thread Evac( GetPlayerArray()[0].GetTeam(), EVAC_INITIAL_WAIT, EVAC_ARRIVAL_TIME, EVAC_WAIT_TIME, EvacEpiloguePlayerCanBoard, EvacEpilogueShouldLeaveEarly, EvacEpilogueCompleted ) } -void function Evac_OnEpilogue() +bool function EvacEpiloguePlayerCanBoard( entity dropship, entity player ) { - if ( Evac_IsEnabled() ) - thread EvacMain( GetOtherTeam( GameScore_GetWinningTeam() ) ) + // can't board a dropship on a different team + if ( dropship.GetTeam() != player.GetTeam() ) + return false + + // check if there are any free slots on the dropship, if there are then they can board + foreach ( entity player in dropship.s.evacSlots ) + if ( !IsValid( player ) ) + return true + + // no empty slots + return false } -void function EvacMain( int winningTeam ) +bool function EvacEpilogueShouldLeaveEarly( entity dropship ) { - if ( file.evacPoints.len() == 0 ) + int numEvacing + foreach ( entity player in dropship.s.evacSlots ) + if ( IsValid( player ) ) + numEvacing++ + + return GetPlayerArrayOfTeam( dropship.GetTeam() ).len() == numEvacing || numEvacing == dropship.s.evacSlots.len() +} + +void function EvacEpilogueCompleted( entity dropship ) +{ + wait 5.0 + print( dropship ) + + foreach ( entity player in dropship.s.evacSlots ) { - // automatically add evac locations if they aren't registered yet - int i = 1 - entity current = null - while ( true ) - { - current = GetEnt( "escape_node" + i ) - print( current ) - - if ( current != null ) - Evac_AddLocation( current.GetOrigin(), current.GetAngles() ) - else - break - - i++ - } + if ( !IsValid( player ) ) + continue - if ( file.evacPoints.len() == 0 ) - unreachable + ScreenFadeToBlackForever( player, 2.0 ) } - if ( file.spacePosition.origin == < 0, 0, 0 > ) + wait 2.0 + + SetGameState( eGameState.Postmatch ) +} + +// global evac func, anything can call this, it's not necessarily an epilogue thing +void function Evac( int evacTeam, float initialWait, float arrivalTime, float waitTime, bool functionref( entity, entity ) canBoardCallback, bool functionref( entity ) shouldLeaveEarlyCallback, void functionref( entity ) completionCallback ) +{ + wait initialWait + + // setup evac nodes if not manually registered + if ( file.evacNodes.len() == 0 ) { - // automatically add a space node if not registered yet - entity defaultSpaceNode = GetEnt( "spaceNode" ) - if ( defaultSpaceNode == null ) - unreachable - - Evac_SetSpacePosition( defaultSpaceNode.GetOrigin(), defaultSpaceNode.GetAngles() ) + for ( int i = 1; ; i++ ) + { + entity newNode = GetEnt( "escape_node" + i ) + if ( !IsValid( newNode ) ) + break + + file.evacNodes.append( newNode ) + } } - Point evacPoint = file.evacPoints[ RandomInt( file.evacPoints.len() ) ] + // setup space node if not manually registered + if ( !IsValid( file.spaceNode ) ) + file.spaceNode = GetEnt( "spaceNode" ) + + entity evacNode = file.evacNodes.getrandom() + + // setup client evac position + file.evacIcon = CreateEntity( "info_target" ) + file.evacIcon.SetOrigin( evacNode.GetOrigin() ) + file.evacIcon.kv.spawnFlags = SF_INFOTARGET_ALWAYS_TRANSMIT_TO_CLIENT + DispatchSpawn( file.evacIcon ) + file.evacIcon.DisableHibernation() + + wait 0.5 // need to wait here, or the target won't appear on clients for some reason + // eta until arrive + SetTeamActiveObjective( evacTeam, "EG_DropshipExtract", Time() + arrivalTime, file.evacIcon ) + SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtract", Time() + arrivalTime, file.evacIcon ) - // create an entity for the evac point that clients will get - entity evacPointEntity = CreateEntity( MARKER_ENT_CLASSNAME ) - evacPointEntity.SetOrigin( evacPoint.origin ) - evacPointEntity.kv.spawnflags = SF_INFOTARGET_ALWAYS_TRANSMIT_TO_CLIENT - DispatchSpawn( evacPointEntity ) - evacPointEntity.DisableHibernation() - - // set objectives - //SetTeamActiveObjective( winningTeam, "EG_DropshipExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity ) - //SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity ) - - // wanted to do this with an actual dropship to calculate embarkStartDelay but spawning it before it should exist ingame is weird - // could probably do it with a dummy entity but effort - wait EVAC_ARRIVAL_TIME - 4.33333//embarkStartDelay - - // create dropship - entity dropship = CreateDropship( winningTeam, evacPoint.origin, evacPoint.angles ) - file.evacDropship = dropship + // would've liked to use cd_dropship_rescue_side_start length here, but can't since this is done before dropship spawn, can't + wait arrivalTime - 4.33333 + entity dropship = CreateDropship( evacTeam, evacNode.GetOrigin(), evacNode.GetAngles() ) + dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) + dropship.SetValueForModelKey( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) DispatchSpawn( dropship ) - dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) // gotta do this after dispatch for some reason - vector startPos = dropship.Anim_GetStartForRefEntity( "cd_dropship_rescue_side_start", evacPointEntity, "origin" ).origin - dropship.SetOrigin( startPos ) // set origin so the dropship isn't in the map + dropship.s.evacSlots <- [ null, null, null, null, null, null, null, null ] + dropship.EndSignal( "OnDestroy" ) + OnThreadEnd( function() : ( evacTeam, completionCallback, dropship ) + { + if ( "evacTrigger" in dropship.s ) + dropship.s.evacTrigger.Destroy() + + // this should be for both teams + SetTeamActiveObjective( evacTeam, "EG_DropshipExtractDropshipDestroyed" ) + SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_DropshipExtractDropshipDestroyed" ) - // calculate time until idle + foreach ( entity player in dropship.s.evacSlots ) + { + if ( !IsValid( player ) ) + continue + + player.ClearInvulnerable() + } + + // this is called whether dropship is destroyed or evac finishes, callback can handle this itself + thread completionCallback( dropship ) + }) + + // flyin + thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacNode ) + + // calculate time until idle start float sequenceDuration = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) float cycleFrac = dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) - float embarkStartDelay = sequenceDuration * cycleFrac + wait sequenceDuration * cycleFrac + + thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", evacNode ) + + // eta until leave + SetTeamActiveObjective( evacTeam, "EG_DropshipExtract2", Time() + EVAC_WAIT_TIME, file.evacIcon ) + SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtract2", Time() + EVAC_WAIT_TIME, file.evacIcon ) + + // setup evac trigger + entity trigger = CreateEntity( "trigger_cylinder" ) + trigger.SetRadius( 150 ) + trigger.SetAboveHeight( 100 ) + trigger.SetBelowHeight( 100 ) + trigger.SetOrigin( dropship.GetOrigin() ) + trigger.SetParent( dropship, "ORIGIN" ) + DispatchSpawn( trigger ) + // have to do this inline since we capture the completionCallback + trigger.SetEnterCallback( void function( entity trigger, entity player ) : ( canBoardCallback, dropship ) + { + if ( !player.IsPlayer() || !IsAlive( player ) || !canBoardCallback( dropship, player ) || PlayerInDropship( player, dropship ) ) + return - // play anim - thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacPointEntity ) - wait embarkStartDelay - - print( "evac flyin done! ready to load players" ) + thread AddPlayerToEvacDropship( dropship, player ) + }) - // set objectives again - SetTeamActiveObjective( winningTeam, "EG_DropshipExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity ) - SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity ) - - thread EvacShipThink( dropship ) // let people enter it + dropship.s.evacTrigger <- trigger + + float waitStartTime = Time() + while ( Time() - waitStartTime < waitTime ) + { + if ( shouldLeaveEarlyCallback( dropship ) ) + break + + WaitFrame() + } - wait EVAC_WAIT_TIME + // holster all weapons + foreach ( entity player in dropship.s.evacSlots ) + if ( IsValid( player ) ) + player.HolsterWeapon() // fly away - thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacPointEntity ) + thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacNode ) + + SetTeamActiveObjective( evacTeam, "EG_DropshipExtractDropshipFlyingAway" ) + SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtractDropshipFlyingAway" ) - // set objectives again - SetTeamActiveObjective( winningTeam, "EG_DropshipExtractDropshipFlyingAway" ) - SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtractDropshipFlyingAway" ) + // todo: play the warpout effect somewhere here wait dropship.GetSequenceDuration( "cd_dropship_rescue_side_end" ) - WARPINFXTIME - foreach ( entity player in file.evacPlayers ) - { - Remote_CallFunction_Replay( player, "ServerCallback_PlayScreenFXWarpJump" ) - } + foreach ( entity player in dropship.s.evacSlots ) + if ( IsValid( player ) ) + Remote_CallFunction_NonReplay( player, "ServerCallback_PlayScreenFXWarpJump" ) - // todo screen effects and shit - //WaittillAnimDone( dropship ) wait WARPINFXTIME - // space - dropship.SetOrigin( file.spacePosition.origin ) - dropship.SetAngles( file.spacePosition.angles ) - thread PlayAnim( dropship, "ds_space_flyby_dropshipA" ) - - // display player [Evacuated] in killfeed - foreach ( entity player in GetPlayerArray() ) - { - foreach ( entity evacPlayer in file.evacPlayers ) - Remote_CallFunction_NonReplay( player, "ServerCallback_EvacObit", evacPlayer.GetEncodedEHandle() ) - } - - foreach ( entity player in file.evacPlayers ) - { - // set skybox to space for all evac players + // go to space + // hardcoded angles here are a hack, spacenode position doesn't face the planet in the skybox, for some reason + file.spaceNode.SetAngles( < 30, -75, 20 >) + dropship.SetOrigin( file.spaceNode.GetOrigin() ) + dropship.SetAngles( file.spaceNode.GetAngles() ) + dropship.SetInvulnerable() + thread PlayAnim( dropship, "ds_space_flyby_dropshipA", file.spaceNode ) + + foreach( entity player in GetPlayerArray() ) + { + // evac-ed players only beyond this point + if ( !PlayerInDropship( player, dropship ) ) + { + if ( player.GetTeam() == dropship.GetTeam() ) + SetPlayerActiveObjective( player, "EG_DropshipExtractFailedEscape" ) + + return + } + + SetPlayerActiveObjective( player, "EG_DropshipExtractSuccessfulEscape" ) + + // skybox player.SetSkyCamera( GetEnt( "skybox_cam_intro" ) ) Remote_CallFunction_NonReplay( player, "ServerCallback_DisableHudForEvac" ) + Remote_CallFunction_NonReplay( player, "ServerCallback_SetClassicSkyScale", dropship.GetEncodedEHandle(), 0.7 ) + Remote_CallFunction_NonReplay( player, "ServerCallback_SetMapSettings", 4.0, false, 0.4, 0.125 ) + + // display player [Evacuated] in killfeed + foreach ( entity otherPlayer in GetPlayerArray() ) + Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_EvacObit", player.GetEncodedEHandle() ) } - wait 5.0 - - foreach ( entity player in GetPlayerArray() ) - ScreenFadeToBlackForever( player, 2.0 ) - - wait 2.0 - - // end game lol - SetGameState( eGameState.Postmatch ) } -void function EvacShipThink( entity dropship ) +void function AddPlayerToEvacDropship( entity dropship, entity player ) { - dropship.EndSignal( "OnDestroy" ) - - // this is the easiest way i could figure out to get a bounding box that's parented to the dropship - entity mover1 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) - mover1.SetParent( dropship ) - mover1.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> ) - - entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) - mover2.SetParent( dropship ) - mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100 > ) - - while ( true ) + int slot = RandomInt( dropship.s.evacSlots.len() ) + for ( int i = 0; i < dropship.s.evacSlots.len(); i++ ) { - foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) ) + if ( !IsValid( dropship.s.evacSlots[ slot ] ) ) { - if ( file.evacPlayers.contains( player ) || !IsAlive( player ) ) - continue - - vector playerPos = player.GetOrigin() - - vector mover1Pos = mover1.GetOrigin() - vector mover2Pos = mover2.GetOrigin() - vector maxPos - maxPos.x = mover1Pos.x > mover2Pos.x ? mover1Pos.x : mover2Pos.x - maxPos.y = mover1Pos.y > mover2Pos.y ? mover1Pos.y : mover2Pos.y - maxPos.z = mover1Pos.z > mover2Pos.z ? mover1Pos.z : mover2Pos.z - - vector minPos - minPos.x = mover1Pos.x < mover2Pos.x ? mover1Pos.x : mover2Pos.x - minPos.y = mover1Pos.y < mover2Pos.y ? mover1Pos.y : mover2Pos.y - minPos.z = mover1Pos.z < mover2Pos.z ? mover1Pos.z : mover2Pos.z - - print( "\n" ) - print( player ) - print( playerPos ) - print( minPos ) - print( maxPos ) - - if ( playerPos.x > minPos.x && playerPos.y > minPos.y && playerPos.z > minPos.z && - playerPos.x < maxPos.x && playerPos.y < maxPos.y && playerPos.z < maxPos.z ) - { - print( player + " is evacuating!" ) - - file.evacPlayers.append( player ) - player.SetParent( dropship ) - - // super duper temp - player.SetLocalOrigin( dropship.GetOrigin() - < 0, 10, 80 > ) - } + dropship.s.evacSlots[ slot ] = player + break } - - WaitFrame() - } -} - -/*void function TestEvac() -{ - if ( file.evacShipSpawns.len() == 0 ) - Evac_AddLocation( GetEnt( "escape_node1" ).GetOrigin(), GetEnt( "escape_node1" ).GetAngles() ) - - Point shipSpawn = file.evacShipSpawns[ RandomInt( file.evacShipSpawns.len() ) ] - - entity dropship = CreateDropship( GetPlayerArray()[0].GetTeam(), shipSpawn.origin, shipSpawn.angles ) - file.evacDropship = dropship - DispatchSpawn( dropship ) - - dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) - - print( dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) ) - print( dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) ) - float embarkStart = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) * dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) - print( embarkStart ) + slot = ( slot + 1 ) % expect int( dropship.s.evacSlots.len() ) + } - thread PlayAnim( dropship, "cd_dropship_rescue_side_start" ) - wait embarkStart - print( "evac start anim done" ) - thread TestEvacThink( dropship ) - SetTeamActiveObjective( GetPlayerArray()[0].GetTeam(), "EG_DropshipExtract2", Time() + 30, dropship ) + // no slots available + if ( !PlayerInDropship( player, dropship ) ) + return + + player.SetInvulnerable() + player.UnforceCrouch() + player.ForceStand() - thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", GetEnt( "escape_node1" ) ) + FirstPersonSequenceStruct fp + //fp.firstPersonAnim = EVAC_EMBARK_ANIMS_1P[ slot ] + fp.thirdPersonAnim = EVAC_EMBARK_ANIMS_3P[ slot ] + fp.attachment = "RESCUE" + fp.teleport = true + fp.thirdPersonCameraAttachments = [ "VDU" ] // this seems wrong, firstperson anim has better angles, but no head + + EmitSoundOnEntityOnlyToPlayer( player, player, SHIFTER_START_SOUND_3P ) + // should play SHIFTER_START_SOUND_1P when they actually arrive in the ship i think, unsure how this is supposed to be done + PlayPhaseShiftDisappearFX( player ) + waitthread FirstPersonSequence( fp, player, dropship ) + + FirstPersonSequenceStruct idleFp + idleFp.firstPersonAnimIdle = EVAC_IDLE_ANIMS_1P[ slot ] + idleFp.thirdPersonAnimIdle = EVAC_IDLE_ANIMS_3P[ slot ] + idleFp.attachment = "RESCUE" + idleFp.teleport = true + idleFp.hideProxy = true + idleFp.viewConeFunction = ViewConeWide + + thread FirstPersonSequence( idleFp, player, dropship ) + ViewConeWide( player ) // gotta do this after for some reason, adding it to idleFp does not work for some reason } -void function TestEvacThink( entity dropship ) +bool function PlayerInDropship( entity player, entity dropship ) { - dropship.EndSignal( "OnDestroy" ) - - // these numbers are probably innacurate but there's no real way of getting accurate ones and these are good enough - entity mover = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) - mover.SetParent( dropship ) - mover.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> ) - - entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) - mover2.SetParent( dropship ) - mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100> ) - - while ( true ) - { - foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) ) - { - if ( !IsAlive( player ) ) - continue - - vector playerOrigin = player.GetOrigin() - - vector dropshipMax = mover.GetOrigin() - vector dropshipMin = mover2.GetOrigin() + // couldn't get "player in dropship.s.evacSlots" to work for some reason, likely due to static typing? + foreach ( entity dropshipPlayer in dropship.s.evacSlots ) + if ( dropshipPlayer == player ) + return true - // temp, might be permenant but idk if box triggers are a thing in script - if ( playerOrigin.x > dropshipMin.x && playerOrigin.y > dropshipMin.y && playerOrigin.z > dropshipMin.z && - playerOrigin.x < dropshipMax.x && playerOrigin.y < dropshipMax.y && playerOrigin.z < dropshipMax.z ) - player.Die() - } - - WaitFrame() - } -}*/
\ No newline at end of file + return false +}
\ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut index 932f14b7..85b4aefb 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut @@ -2,7 +2,7 @@ global function FFA_Init void function FFA_Init() { - Evac_SetEnabled( false ) + ClassicMP_ForceDisableEpilogue( true ) AddCallback_OnPlayerKilled( OnPlayerKilled ) } diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut index 60daa452..63b2c81a 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut @@ -13,6 +13,11 @@ void function PrivateLobby_Init() print( "PrivateLobby_Init()" ) //ClearPlaylistVarOverrides() + file.map = GetConVarString( "ns_private_match_last_map" ) + file.mode = GetConVarString( "ns_private_match_last_mode" ) + + thread SetupPrivateMatchUIVarsWhenReady() + AddClientCommandCallback( "PrivateMatchLaunch", ClientCommandCallback_PrivateMatchLaunch ) AddClientCommandCallback( "PrivateMatchSetMode", ClientCommandCallback_PrivateMatchSetMode ) AddClientCommandCallback( "SetCustomMap", ClientCommandCallback_SetCustomMap ) @@ -22,6 +27,14 @@ void function PrivateLobby_Init() AddClientCommandCallback( "ResetMatchSettingsToDefault", ClientCommandCallback_ResetMatchSettingsToDefault ) } +void function SetupPrivateMatchUIVarsWhenReady() +{ + // have to wait until end of first frame for SetUIVar to work + WaitEndFrame() + SetUIVar( level, "privatematch_map", GetPrivateMatchMapIndex( file.map ) ) + SetUIVar( level, "privatematch_mode", GetPrivateMatchModeIndex( file.mode ) ) +} + bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<string> args ) { if ( file.startState == ePrivateMatchStartState.STARTING ) @@ -127,6 +140,8 @@ void function StartMatch() RefreshPlayerTeams() + SetConVarString( "ns_private_match_last_map", file.map ) + SetConVarString( "ns_private_match_last_mode", file.mode ) SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp? // TEMP for now: start game diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut index 2c02ebdc..605b23fd 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut @@ -189,11 +189,32 @@ void function AddPrivateMatchModeSettingEnumEx( string category, string playlist #endif } -array< string > function GetPrivateMatchSettingCategories() +array< string > function GetPrivateMatchSettingCategories( bool uiAllowAllModeCategories = false ) { array< string > categories foreach ( string k, v in file.customMatchSettingsByCategory ) + { + // can only do this in ui because it relies on GetUIVar + #if UI + bool gamemode = k.find( "#GAMEMODE_" ) == 0 + if ( !uiAllowAllModeCategories && ( gamemode || k.find( "#PL_" ) == 0 ) ) + { + if ( gamemode ) + { + if ( k.slice( 10 ) != PrivateMatch_GetSelectedMode() ) + { + continue + } + } + else if ( k.slice( 4 ) != PrivateMatch_GetSelectedMode() ) + { + continue + } + } + #endif + categories.append( k ) + } return categories } 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 8991ebb0..5cd4de50 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 @@ -4,6 +4,8 @@ void function PrivateMatchModesInit() { // match settings // super temp: do localisation strings later + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_MATCH", "classic_mp", [ "Disabled", "Enabled" ], "1" ) + AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_MATCH", "run_epilogue", [ "Disabled", "Enabled" ], "1" ) AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "scorelimit", "5" ) //, "Score Limit" ) AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "roundscorelimit", "0" ) //, "Score Limit (round-based modes)" ) AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "timelimit", "12" ) //, "Time Limit" ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut index ac0c309b..4cbab84c 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut @@ -30,12 +30,12 @@ bool function IsAutoPopulateEnabled( var team = null ) return true } -void function SPMP_UpdateNPCProficiency(entity ent) +void function SPMP_UpdateNPCProficiency( entity ent ) { } -bool function SPMP_Callback_ForceAIMissPlayer(entity npc, entity player) +bool function SPMP_Callback_ForceAIMissPlayer( entity npc, entity player ) { return true }
\ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut index d7db601b..38803e04 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut @@ -219,6 +219,7 @@ void function CodeCallback_OnPlayerRespawned( entity player ) player.s.respawnTime = Time() Loadouts_TryGivePilotLoadout( player ) + SetHumanRagdollImpactTable( player ) foreach ( void functionref( entity ) callback in svGlobal.onPlayerRespawnedCallbacks ) callback( player ) diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut index ac8a397f..66bb3d6a 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut @@ -1,53 +1,80 @@ untyped global function ClassicMp_Init -global function ClassicMP_TryDefaultIntroSetup // called in mp_sh_init +global function ClassicMP_TryDefaultIntroSetup + +// intro setups +global function ClassicMP_SetLevelIntro global function ClassicMP_SetCustomIntro +global function ClassicMP_SetupIntro + +// intro funcs global function ClassicMP_OnIntroStarted global function ClassicMP_OnIntroFinished global function ClassicMP_GetIntroLength + +// epilogue setups +global function ClassicMP_ForceDisableEpilogue +global function ClassicMP_SetEpilogue +global function ClassicMP_SetupEpilogue +global function ClassicMP_ShouldRunEpilogue + global function GetClassicMPMode struct { - void functionref() introSetupFunc - float introLength + // level intros have a lower priority than custom intros + // level intros are used only if a custom intro was not specified + void functionref() levelIntroSetupFunc + float levelIntroLength + + void functionref() customIntroSetupFunc + float customIntroLength + + bool epilogueForceDisabled = false + void functionref() epilogueSetupFunc } file void function ClassicMp_Init() { - // literally nothing to do here atm lol + // default level intros + if ( IsFFAGame() ) + ClassicMP_SetLevelIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() ) + else + ClassicMP_SetLevelIntro( ClassicMP_DefaultDropshipIntro_Setup, DROPSHIP_INTRO_LENGTH ) } +// stub func, called in mp_sh_init void function ClassicMP_TryDefaultIntroSetup() { - if ( file.introSetupFunc == null ) - { - if ( IsFFAGame() ) - ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() ) - else - ClassicMP_SetCustomIntro( ClassicMP_DefaultDropshipIntro_Setup, DROPSHIP_INTRO_LENGTH ) - } - - thread DelayedDoDefaultIntroSetup() + } -void function DelayedDoDefaultIntroSetup() +void function ClassicMP_SetLevelIntro( void functionref() setupFunc, float introLength ) { - // wait a frame for CodeCallback_MapInit to run which generally sets custom intros - WaitFrame() - file.introSetupFunc() + file.levelIntroSetupFunc = setupFunc + file.levelIntroLength = introLength } void function ClassicMP_SetCustomIntro( void functionref() setupFunc, float introLength ) { - file.introSetupFunc = setupFunc - file.introLength = introLength + file.customIntroSetupFunc = setupFunc + file.customIntroLength = introLength +} + +void function ClassicMP_SetupIntro() +{ + if ( file.customIntroSetupFunc != null ) + file.customIntroSetupFunc() + else + file.levelIntroSetupFunc() } void function ClassicMP_OnIntroStarted() { print( "started intro!" ) - SetServerVar( "gameStartTime", Time() + file.introLength ) - SetServerVar( "roundStartTime", Time() + file.introLength ) + + float introLength = ClassicMP_GetIntroLength() + SetServerVar( "gameStartTime", Time() + introLength ) + SetServerVar( "roundStartTime", Time() + introLength ) } void function ClassicMP_OnIntroFinished() @@ -58,10 +85,37 @@ void function ClassicMP_OnIntroFinished() float function ClassicMP_GetIntroLength() { - return file.introLength + if ( file.customIntroSetupFunc != null ) + return file.customIntroLength + + return file.levelIntroLength +} + +void function ClassicMP_ForceDisableEpilogue( bool disabled ) +{ + file.epilogueForceDisabled = disabled +} + +void function ClassicMP_SetEpilogue( void functionref() setupFunc ) +{ + file.epilogueSetupFunc = setupFunc +} + +void function ClassicMP_SetupEpilogue() +{ + if ( file.epilogueSetupFunc == null ) // default is evac + ClassicMP_SetEpilogue( EvacEpilogueSetup ) + + file.epilogueSetupFunc() } bool function GetClassicMPMode() { return GetCurrentPlaylistVarInt( "classic_mp", 1 ) == 1 +} + +bool function ClassicMP_ShouldRunEpilogue() +{ + // note: there is a run_evac playlist var, but it's unused, and default 0, so use a new one + return !file.epilogueForceDisabled && GetClassicMPMode() && !IsRoundBased() && GetCurrentPlaylistVarInt( "run_epilogue", 1 ) == 1 }
\ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut index 197ac5e9..e3f7e0b0 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut @@ -92,7 +92,8 @@ void function SetGameState( int newState ) void function GameState_EntitiesDidLoad() { - // nothing of importance to put here, this is referenced in _gamestate though so need it + if ( GetClassicMPMode() ) + ClassicMP_SetupIntro() } void function WaittillGameStateOrHigher( int gameState ) @@ -185,9 +186,29 @@ void function GameStateEnter_Prematch() int timeLimit = GameMode_GetTimeLimit( GAMETYPE ) * 60 if ( file.switchSidesBased ) timeLimit /= 2 // endtime is half of total per side - + SetServerVar( "gameEndTime", Time() + timeLimit + ClassicMP_GetIntroLength() ) SetServerVar( "roundEndTime", Time() + ClassicMP_GetIntroLength() + GameMode_GetRoundTimeLimit( GAMETYPE ) * 60 ) + + if ( !GetClassicMPMode() ) + thread StartGameWithoutClassicMP() +} + +void function StartGameWithoutClassicMP() +{ + WaitFrame() // wait for callbacks to finish + + // need these otherwise game will complain + SetServerVar( "gameStartTime", Time() ) + SetServerVar( "roundStartTime", Time() ) + + foreach ( entity player in GetPlayerArray() ) + { + RespawnAsPilot( player ) + ScreenFadeFromBlack( player, 0 ) + } + + SetGameState( eGameState.Playing ) } @@ -246,38 +267,53 @@ void function GameStateEnter_WinnerDetermined() void function GameStateEnter_WinnerDetermined_Threaded() { - bool killcamsWereEnabled = KillcamsEnabled() - if ( killcamsWereEnabled ) // dont want killcams to interrupt stuff - SetKillcamsEnabled( false ) - + // do win announcement + int winningTeam = GetWinningTeam() + + foreach ( entity player in GetPlayerArray() ) + { + int announcementSubstr + if ( winningTeam != TEAM_UNASSIGNED ) + announcementSubstr = player.GetTeam() == winningTeam ? file.announceRoundWinnerWinningSubstr : file.announceRoundWinnerLosingSubstr + + if ( IsRoundBased() ) + Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceRoundWinner", GetWinningTeam(), announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME, GameRules_GetTeamScore2( TEAM_MILITIA ), GameRules_GetTeamScore2( TEAM_IMC ) ) + else + Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceWinner", GetWinningTeam(), announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME ) + } + WaitFrame() // wait a frame so other scripts can setup killreplay stuff entity replayAttacker = file.roundWinningKillReplayAttacker - bool doReplay = Replay_IsEnabled() && !( !IsRoundBased() && Evac_IsEnabled() ) && IsRoundWinningKillReplayEnabled() && IsValid( replayAttacker ) + bool doReplay = Replay_IsEnabled() && !ClassicMP_ShouldRunEpilogue() && IsRoundWinningKillReplayEnabled() && IsValid( replayAttacker ) && Time() - file.roundWinningKillReplayTime <= ROUND_WINNING_KILL_REPLAY_LENGTH_OF_REPLAY float replayLength = 2.0 // extra delay if no replay if ( doReplay ) { + bool killcamsWereEnabled = KillcamsEnabled() + if ( killcamsWereEnabled ) // dont want killcams to interrupt stuff + SetKillcamsEnabled( false ) + replayLength = ROUND_WINNING_KILL_REPLAY_LENGTH_OF_REPLAY if ( "respawnTime" in replayAttacker.s && Time() - replayAttacker.s.respawnTime < replayLength ) replayLength += Time() - expect float ( replayAttacker.s.respawnTime ) SetServerVar( "roundWinningKillReplayEntHealthFrac", file.roundWinningKillReplayHealthFrac ) - } - - foreach ( entity player in GetPlayerArray() ) - thread PlayerWatchesRoundWinningKillReplay( player, doReplay, replayLength ) - - wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME - CleanUpEntitiesForRoundEnd() // fade should be done by this point, so cleanup stuff now when people won't see - wait replayLength - - WaitFrame() // prevent a race condition with PlayerWatchesRoundWinningKillReplay - file.roundWinningKillReplayAttacker = null // clear this + + foreach ( entity player in GetPlayerArray() ) + thread PlayerWatchesRoundWinningKillReplay( player, doReplay, replayLength ) - if ( killcamsWereEnabled ) - SetKillcamsEnabled( true ) + wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME + CleanUpEntitiesForRoundEnd() // fade should be done by this point, so cleanup stuff now when people won't see + wait replayLength + + WaitFrame() // prevent a race condition with PlayerWatchesRoundWinningKillReplay + file.roundWinningKillReplayAttacker = null // clear this + + if ( killcamsWereEnabled ) + SetKillcamsEnabled( true ) + } if ( IsRoundBased() ) { @@ -299,8 +335,11 @@ void function GameStateEnter_WinnerDetermined_Threaded() } else { - if ( Evac_IsEnabled() ) + if ( ClassicMP_ShouldRunEpilogue() ) + { + ClassicMP_SetupEpilogue() SetGameState( eGameState.Epilogue ) + } else SetGameState( eGameState.Postmatch ) } @@ -309,18 +348,8 @@ void function GameStateEnter_WinnerDetermined_Threaded() void function PlayerWatchesRoundWinningKillReplay( entity player, bool doReplay, float replayLength ) { player.FreezeControlsOnServer() - - int winningTeam = GetWinningTeam() - int announcementSubstr - if ( winningTeam != TEAM_UNASSIGNED ) - announcementSubstr = player.GetTeam() == winningTeam ? file.announceRoundWinnerWinningSubstr : file.announceRoundWinnerLosingSubstr - - if ( IsRoundBased() ) - Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceRoundWinner", winningTeam, announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME, GameRules_GetTeamScore2( TEAM_MILITIA ), GameRules_GetTeamScore2( TEAM_IMC ) ) - else - Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceWinner", winningTeam, announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME ) - if ( IsRoundBased() || !Evac_IsEnabled() ) // if we're doing evac, then no fades or killreplay + if ( IsRoundBased() || !ClassicMP_ShouldRunEpilogue() ) // if we're doing evac, then no fades or killreplay { ScreenFadeToBlackForever( player, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME ) wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut index d61d6baa..178b6560 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut @@ -4,5 +4,5 @@ global function SetupLiveFireMaps void function SetupLiveFireMaps() { Riff_ForceTitanAvailability( eTitanAvailability.Never ) - ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() ) + ClassicMP_SetLevelIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() ) }
\ No newline at end of file diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut index 68b49ad5..87c9ea98 100644 --- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut +++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut @@ -2,12 +2,12 @@ global function CodeCallback_MapInit void function CodeCallback_MapInit() { - Evac_AddLocation( < 2527.889893, -2865.360107, 753.002991 >, < 0, -80.54, 0 > ) - Evac_AddLocation( < 1253.530029, -554.075012, 811.125 >, < 0, 180, 0 > ) - Evac_AddLocation( < 2446.989990, 809.364014, 576.0 >, < 0, 90.253, 0 > ) - Evac_AddLocation( < -2027.430054, 960.395020, 609.007996 >, < 0, 179.604, 0 > ) + AddEvacNode( CreateScriptRef( < 2527.889893, -2865.360107, 753.002991 >, < 0, -80.54, 0 > ) ) + AddEvacNode( CreateScriptRef( < 1253.530029, -554.075012, 811.125 >, < 0, 180, 0 > ) ) + AddEvacNode( CreateScriptRef( < 2446.989990, 809.364014, 576.0 >, < 0, 90.253, 0 > ) ) + AddEvacNode( CreateScriptRef( < -2027.430054, 960.395020, 609.007996 >, < 0, 179.604, 0 > ) ) - Evac_SetSpacePosition( < -1700, -5500, -7600 >, < -3.620642, 270.307129, 0 > ) + SetEvacSpaceNode( CreateScriptRef( < -1700, -5500, -7600 >, < -3.620642, 270.307129, 0 > ) ) // todo: also we need to change the powerup spawns on this map, they use a version from an older patch |