aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts/vscripts/lobby
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/mod/scripts/vscripts/lobby')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/_lobby.gnut37
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut194
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut495
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut55
4 files changed, 781 insertions, 0 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_lobby.gnut
new file mode 100644
index 00000000..fd877f8c
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_lobby.gnut
@@ -0,0 +1,37 @@
+untyped
+global function Lobby_Init
+global function Lobby_OnClientConnectionStarted
+global function Lobby_OnClientConnectionCompleted
+
+void function Lobby_Init()
+{
+ // need to prevent a crash
+ Music_Init()
+
+ if ( IsPrivateMatch() || GetCurrentPlaylistName() == "private_match" ) // IsPrivateMatch() doesn't seem to be reliable on local server start
+ PrivateLobby_Init()
+ else
+ {
+ // non-private lobby clientcommands
+ AddClientCommandCallback( "StartPrivateMatchSearch", ClientCommandCallback_StartPrivateMatchSearch )
+ }
+}
+
+void function Lobby_OnClientConnectionStarted( entity player )
+{
+
+}
+
+void function Lobby_OnClientConnectionCompleted( entity player )
+{
+ FinishClientScriptInitialization( player )
+}
+
+bool function ClientCommandCallback_StartPrivateMatchSearch( entity player, array<string> args )
+{
+ // open lobby in private match mode
+ SetCurrentPlaylist( "private_match" ) // required for private match lobby to start properly
+ ServerCommand( "changelevel mp_lobby" )
+
+ return true
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
new file mode 100644
index 00000000..60daa452
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
@@ -0,0 +1,194 @@
+// TODO: could probably add some checks for whether player setting stuff is player 0 to check for host, might fail in dedicated tho
+
+global function PrivateLobby_Init
+
+struct {
+ int startState
+ string map = "mp_forwardbase_kodai"
+ string mode = "aitdm"
+} file
+
+void function PrivateLobby_Init()
+{
+ print( "PrivateLobby_Init()" )
+ //ClearPlaylistVarOverrides()
+
+ AddClientCommandCallback( "PrivateMatchLaunch", ClientCommandCallback_PrivateMatchLaunch )
+ AddClientCommandCallback( "PrivateMatchSetMode", ClientCommandCallback_PrivateMatchSetMode )
+ AddClientCommandCallback( "SetCustomMap", ClientCommandCallback_SetCustomMap )
+ AddClientCommandCallback( "PrivateMatchSwitchTeams", ClientCommandCallback_PrivateMatchSwitchTeams )
+
+ AddClientCommandCallback( "PrivateMatchSetPlaylistVarOverride", ClientCommandCallback_PrivateMatchSetPlaylistVarOverride )
+ AddClientCommandCallback( "ResetMatchSettingsToDefault", ClientCommandCallback_ResetMatchSettingsToDefault )
+}
+
+bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<string> args )
+{
+ if ( file.startState == ePrivateMatchStartState.STARTING )
+ {
+ // cancel start if we're already mid-countdown
+ file.startState = ePrivateMatchStartState.READY
+ SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.READY )
+ SetUIVar( level, "gameStartTime", null )
+ }
+ else
+ {
+ // start match
+ file.startState = ePrivateMatchStartState.STARTING
+ thread StartMatch()
+ }
+
+ return true
+}
+
+bool function ClientCommandCallback_PrivateMatchSetMode( entity player, array<string> args )
+{
+ if ( file.startState == ePrivateMatchStartState.STARTING )
+ return true
+
+ if ( args.len() != 1 )
+ return true
+
+ // todo: need to verify this value
+ file.mode = args[0]
+ //GameRules_SetGameMode( args[0] ) // can't do this here due to out of sync errors with new clients
+
+ RefreshPlayerTeams()
+
+ SetUIVar( level, "privatematch_mode", GetPrivateMatchModeIndex( args[0] ) )
+ return true
+}
+
+bool function ClientCommandCallback_SetCustomMap( entity player, array<string> args )
+{
+ if ( file.startState == ePrivateMatchStartState.STARTING )
+ return true
+
+ if ( args.len() != 1 )
+ return true
+
+ // todo: need to verify this value
+ file.map = args[0]
+
+ // todo: this should NOT be necessary, private matches should use an api to register maps in the future rather than hardcoded ids
+ // should be removed whenever possible really
+ SetUIVar( level, "privatematch_map", GetPrivateMatchMapIndex( args[0] ) )
+ return true
+}
+
+bool function ClientCommandCallback_PrivateMatchSwitchTeams( entity player, array<string> args )
+{
+ if ( file.startState == ePrivateMatchStartState.STARTING )
+ return true
+
+ // currently only support 2 teams in private matches
+ SetTeam( player, player.GetTeam() == 2 ? 3 : 2 )
+ return true
+}
+
+void function StartMatch()
+{
+ // set starting uivar
+ SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.STARTING )
+
+ // start countdown
+ SetUIVar( level, "gameStartTime", Time() + 15 )
+ float countdownEndTime = Time() + 15.0
+
+ // can't use start here because we need to check stuff
+ while ( Time() < countdownEndTime )
+ {
+ // stop if the countdown's been cancelled
+ if ( file.startState != ePrivateMatchStartState.STARTING)
+ return
+
+ WaitFrame()
+ }
+
+ if ( file.mode in GAMETYPE_TEXT )
+ GameRules_SetGameMode( file.mode )
+ else
+ GameRules_SetGameMode( GetPlaylistGamemodeByIndex( file.mode, 0 ) )
+
+ try
+ {
+ // todo: not every gamemode uses the same playlist as their name! need some code to resolve these manually
+ // would be nice if the gamemode api got some tweaks to allow for registering private match gamemodes maybe
+ SetCurrentPlaylist( file.mode )
+ }
+ catch ( exception )
+ {
+ // temp
+ if ( file.mode == "speedball" )
+ SetCurrentPlaylist( "lf" )
+
+ print( "couldn't find playlist for gamemode " + file.mode )
+ }
+
+ RefreshPlayerTeams()
+
+ SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp?
+
+ // TEMP for now: start game
+ ServerCommand( "changelevel " + file.map )
+}
+
+void function RefreshPlayerTeams()
+{
+ int maxTeams = GetGamemodeVarOrUseValue( file.mode, "max_teams", "2" ).tointeger()
+ int maxPlayers = GetGamemodeVarOrUseValue( file.mode, "max_players", "12" ).tointeger()
+
+ // special case for situations where we wrongly assume ffa teams because there's 2 teams/2 players
+ if ( maxPlayers == maxTeams && maxTeams > 2 )
+ {
+ array<entity> players = GetPlayerArray()
+ for ( int i = 0; i < players.len(); i++ )
+ SetTeam( players[ i ], i + 7 ) // 7 is the lowest ffa team
+ }
+ else
+ {
+ bool lastSetMilitia = false
+ foreach ( entity player in GetPlayerArray() )
+ {
+ if ( player.GetTeam() == TEAM_MILITIA || player.GetTeam() == TEAM_IMC )
+ continue
+
+ if ( lastSetMilitia ) // ensure roughly evenish distribution
+ SetTeam( player, TEAM_IMC )
+ else
+ SetTeam( player, TEAM_MILITIA )
+
+ lastSetMilitia = !lastSetMilitia
+ }
+ }
+}
+
+bool function ClientCommandCallback_PrivateMatchSetPlaylistVarOverride( entity player, array<string> args )
+{
+ if ( args.len() < 2 )
+ return true
+
+ bool found = false
+ foreach ( string category in GetPrivateMatchSettingCategories() )
+ {
+ foreach ( CustomMatchSettingContainer setting in GetPrivateMatchCustomSettingsForCategory( category ) )
+ {
+ if ( args[ 0 ] == setting.playlistVar )
+ {
+ found = true
+ break
+ }
+ }
+ }
+
+ if ( found )
+ SetPlaylistVarOverride( args[0], args[1] )
+
+ return true
+}
+
+bool function ClientCommandCallback_ResetMatchSettingsToDefault( entity player, array<string> args )
+{
+ ClearPlaylistVarOverrides()
+ return true
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut
new file mode 100644
index 00000000..2c02ebdc
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut
@@ -0,0 +1,495 @@
+globalize_all_functions
+
+const string PRIVATE_MATCH_PLAYLIST = "private_match"
+
+global struct CustomMatchSettingContainer
+{
+ string playlistVar
+ string defaultValue
+ string localizedName
+ bool isEnumSetting
+
+ // enum setting
+ array< string > enumNames
+ array< string > enumValues
+ //table< string, string > enumValuePairs
+}
+
+struct {
+ array<string> modes = [ // default modes in vanilla
+ "aitdm",
+ "tdm",
+ "cp",
+ "at",
+ "ctf",
+ "lts",
+ "ps",
+ "speedball",
+ "mfd",
+ "ttdm",
+ "fd_easy",
+ "fd_normal",
+ "fd_hard",
+ "fd_master",
+ "fd_insane"
+ ]
+
+ array<string> maps = [ // default maps in vanilla
+ "mp_forwardbase_kodai",
+ "mp_grave",
+ "mp_homestead",
+ "mp_thaw",
+ "mp_black_water_canal",
+ "mp_eden",
+ "mp_drydock",
+ "mp_crashsite3",
+ "mp_complex3",
+ "mp_angel_city",
+ "mp_colony02",
+ "mp_glitch",
+ "mp_relic02",
+ "mp_wargames",
+ "mp_rise",
+ "mp_lf_stacks",
+ "mp_lf_deck",
+ "mp_lf_meadow",
+ "mp_lf_traffic",
+ "mp_lf_township",
+ "mp_lf_uma"
+ ]
+
+ table< string, array< CustomMatchSettingContainer > > customMatchSettingsByCategory // we set these up in sh_private_lobby_modes_init
+} file
+
+
+void function AddPrivateMatchMode( string mode )
+{
+ if ( !file.modes.contains( mode ) )
+ file.modes.append( mode )
+
+ #if CLIENT
+ // call this on ui too so the client and ui states are the same
+ RunUIScript( "AddPrivateMatchMode", mode )
+ #endif
+}
+
+void function AddPrivateMatchMap( string map )
+{
+ if ( !file.maps.contains( map ) )
+ file.maps.append( map )
+
+ #if CLIENT
+ // call this on ui too so the client and ui states are the same
+ RunUIScript( "AddPrivateMatchMap", map )
+ #endif
+}
+
+
+void function AddPrivateMatchModeSettingArbitrary( string category, string playlistVar, string defaultValue, string localizedName = "" )
+{
+ if ( localizedName == "" )
+ localizedName = "#" + playlistVar
+
+ if ( !( category in file.customMatchSettingsByCategory ) )
+ file.customMatchSettingsByCategory[ category ] <- []
+
+ bool found = false
+ foreach ( CustomMatchSettingContainer setting in file.customMatchSettingsByCategory[ category ] )
+ {
+ if ( setting.playlistVar == playlistVar )
+ {
+ found = true
+ break
+ }
+ }
+
+ if ( !found )
+ {
+ CustomMatchSettingContainer setting
+ setting.playlistVar = playlistVar
+ setting.defaultValue = defaultValue
+ setting.localizedName = localizedName
+ setting.isEnumSetting = false
+
+ file.customMatchSettingsByCategory[ category ].append( setting )
+ }
+
+ #if CLIENT
+ // call this on ui too so the client and ui states are the same
+ RunUIScript( "AddPrivateMatchModeSettingArbitrary", category, playlistVar, defaultValue, localizedName )
+ #endif
+}
+
+void function AddPrivateMatchModeSettingEnum( string category, string playlistVar, array< string > enums, string defaultValue, string localizedName = "" )
+{
+ table< string, string > pairs
+ for ( int i = 0; i < enums.len(); i++ )
+ pairs[ enums[ i ] ] <- i.tostring()
+
+ AddPrivateMatchModeSettingEnumEx( category, playlistVar, pairs, defaultValue, localizedName )
+}
+
+void function AddPrivateMatchModeSettingEnumUIHack( string category, string playlistVar, string serializedEnumPairs, string defaultValue, string localizedName )
+{
+ // this fucking sucks, but RunUIScript won't take tables, so we serialize to a string
+ // we use \n as a delimeter and basically serialize to an array
+ array< string > serializedArray = split( serializedEnumPairs, "\n" )
+ table< string, string > enumPairs
+
+ for ( int i = 0; i < serializedArray.len(); i += 2 )
+ enumPairs[ serializedArray[ i ] ] <- serializedArray[ i + 1 ]
+
+ AddPrivateMatchModeSettingEnumEx( category, playlistVar, enumPairs, defaultValue, localizedName )
+}
+
+void function AddPrivateMatchModeSettingEnumEx( string category, string playlistVar, table< string, string > enumPairs, string defaultValue, string localizedName = "" )
+{
+ if ( localizedName == "" )
+ localizedName = "#" + playlistVar
+
+ if ( !( category in file.customMatchSettingsByCategory ) )
+ file.customMatchSettingsByCategory[ category ] <- []
+
+ bool found = false
+ foreach ( CustomMatchSettingContainer setting in file.customMatchSettingsByCategory[ category ] )
+ {
+ if ( setting.playlistVar == playlistVar )
+ {
+ found = true
+ break
+ }
+ }
+
+ if ( !found )
+ {
+ CustomMatchSettingContainer setting
+ setting.playlistVar = playlistVar
+ setting.defaultValue = defaultValue
+ setting.localizedName = localizedName
+ setting.isEnumSetting = true
+ //setting.enumValuePairs = enumPairs
+
+ foreach ( string name, string value in enumPairs )
+ {
+ setting.enumNames.append( name )
+ setting.enumValues.append( value )
+ }
+
+ file.customMatchSettingsByCategory[ category ].append( setting )
+ }
+
+ #if CLIENT
+ // call this on ui too so the client and ui states are the same
+ // note: RunUIScript can't take tables, so manually serialize ( sucks, but just how it is ), using \n as a delimeter since i dont believe its ever used in vars
+ string serializedString
+ foreach ( string k, string v in enumPairs )
+ serializedString += k + "\n" + v + "\n"
+
+ RunUIScript( "AddPrivateMatchModeSettingEnumUIHack", category, playlistVar, serializedString, defaultValue, localizedName )
+ #endif
+}
+
+array< string > function GetPrivateMatchSettingCategories()
+{
+ array< string > categories
+ foreach ( string k, v in file.customMatchSettingsByCategory )
+ categories.append( k )
+
+ return categories
+}
+
+array< CustomMatchSettingContainer > function GetPrivateMatchCustomSettingsForCategory( string category )
+{
+ return file.customMatchSettingsByCategory[ category ]
+}
+
+
+array<string> function GetPrivateMatchModes()
+{
+ //array<string> modesArray
+ //
+ //int numModes = GetPlaylistGamemodesCount( PRIVATE_MATCH_PLAYLIST )
+ //for ( int modeIndex = 0; modeIndex < numModes; modeIndex++ )
+ //{
+ // modesArray.append( GetPlaylistGamemodeByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex ) )
+ //}
+
+ //return modesArray
+
+ return file.modes
+}
+
+int function GetPrivateMatchModeIndex( string modeName )
+{
+ //int indexForName = 0
+ //
+ //int numModes = GetPlaylistGamemodesCount( PRIVATE_MATCH_PLAYLIST )
+ //for ( int modeIndex = 0; modeIndex < numModes; modeIndex++ )
+ //{
+ // if ( GetPlaylistGamemodeByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex ) != modeName )
+ // continue
+ //
+ // indexForName = modeIndex;
+ // break
+ //}
+ //
+ //return indexForName
+
+ return file.modes.find( modeName )
+}
+
+
+array<string> function GetPrivateMatchMapsForMode( string modeName )
+{
+ //array<string> mapsArray
+ //
+ //int modeIndex = GetPrivateMatchModeIndex( modeName )
+ //int numMaps = GetPlaylistGamemodeByIndexMapsCount( PRIVATE_MATCH_PLAYLIST, modeIndex )
+ //for ( int mapIndex = 0; mapIndex < numMaps; mapIndex++ )
+ //{
+ // mapsArray.append( GetPlaylistGamemodeByIndexMapByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex, mapIndex ) )
+ //}
+ //
+ //return mapsArray
+
+ array<string> maps
+
+ // use the private match playlist for this if the gamemode is in it already
+ int privatePlaylistModeIndex = GetPrivateMatchModeIndex( modeName )
+ if ( privatePlaylistModeIndex < GetPlaylistGamemodesCount( PRIVATE_MATCH_PLAYLIST ) )
+ {
+ for ( int i = 0; i < GetPlaylistGamemodeByIndexMapsCount( PRIVATE_MATCH_PLAYLIST, privatePlaylistModeIndex ); i++ )
+ maps.append( GetPlaylistGamemodeByIndexMapByIndex( PRIVATE_MATCH_PLAYLIST, privatePlaylistModeIndex, i ) )
+ }
+ else
+ {
+ int numMaps = GetPlaylistGamemodeByIndexMapsCount( modeName, 0 )
+ for ( int i = 0; i < numMaps; i++ )
+ maps.append( GetPlaylistGamemodeByIndexMapByIndex( modeName, 0, i ) )
+ }
+
+ return maps
+}
+
+// never called
+/*array<string> function GetPrivateMatchModesForMap( string mapName )
+{
+ array<string> modesArray
+
+ int numModes = GetPlaylistGamemodesCount( PRIVATE_MATCH_PLAYLIST )
+ for ( int modeIndex = 0; modeIndex < numModes; modeIndex++ )
+ {
+ int numMaps = GetPlaylistGamemodeByIndexMapsCount( PRIVATE_MATCH_PLAYLIST, modeIndex )
+ for ( int mapIndex = 0; mapIndex < numMaps; mapIndex++ )
+ {
+ if ( GetPlaylistGamemodeByIndexMapByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex, mapIndex ) != mapName )
+ continue
+
+ modesArray.append( GetPlaylistGamemodeByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex ) )
+ }
+ }
+
+ return modesArray
+}*/
+
+
+string function GetPrivateMatchMapForIndex( int index )
+{
+ array<string> mapsArray = GetPrivateMatchMaps()
+
+ if ( index >= mapsArray.len() || index < 0 )
+ return ""
+
+ return mapsArray[index]
+}
+
+string function GetPrivateMatchModeForIndex( int index )
+{
+ array<string> modesArray = GetPrivateMatchModes()
+
+ if ( index >= modesArray.len() || index < 0 )
+ return ""
+
+ return modesArray[index]
+}
+
+int function GetPrivateMatchMapIndex( string mapName )
+{
+ array<string> mapsArray = GetPrivateMatchMaps()
+ for ( int index = 0; index < mapsArray.len(); index++ )
+ {
+ if ( mapsArray[index] == mapName )
+ return index
+ }
+
+ return 0
+}
+/*
+int function GetPrivateMatchModeIndex( string modeName )
+{
+ array<string> modesArray = GetPrivateMatchModes()
+ for ( int index = 0; index < modesArray.len(); index++ )
+ {
+ if ( modesArray[index] == modeName )
+ return index
+ }
+
+ return 0
+}
+*/
+
+array<string> function GetPrivateMatchMaps()
+{
+ //array<string> mapsArray
+ //
+ //int numModes = GetPlaylistGamemodesCount( PRIVATE_MATCH_PLAYLIST )
+ //for ( int modeIndex = 0; modeIndex < numModes; modeIndex++ )
+ //{
+ // int numMaps = GetPlaylistGamemodeByIndexMapsCount( PRIVATE_MATCH_PLAYLIST, modeIndex )
+ // for ( int mapIndex = 0; mapIndex < numMaps; mapIndex++ )
+ // {
+ // string mapName = GetPlaylistGamemodeByIndexMapByIndex( PRIVATE_MATCH_PLAYLIST, modeIndex, mapIndex )
+ // if ( mapsArray.contains( mapName ) )
+ // continue
+ //
+ // mapsArray.append( mapName )
+ // }
+ //}
+ //
+ //return mapsArray
+
+ return file.maps
+}
+
+
+
+array<string> function GetPlaylistMaps( string playlistName )
+{
+ array<string> mapsArray
+
+ int numModes = GetPlaylistGamemodesCount( playlistName )
+ for ( int modeIndex = 0; modeIndex < numModes; modeIndex++ )
+ {
+ int numMaps = GetPlaylistGamemodeByIndexMapsCount( playlistName, modeIndex )
+ for ( int mapIndex = 0; mapIndex < numMaps; mapIndex++ )
+ {
+ string mapName = GetPlaylistGamemodeByIndexMapByIndex( playlistName, modeIndex, mapIndex )
+ if ( mapsArray.contains( mapName ) )
+ continue
+
+ mapsArray.append( mapName )
+ }
+ }
+
+ return mapsArray
+}
+
+
+bool function MapSettings_SupportsTitans( string mapName )
+{
+ if ( mapName.find( "mp_lf_") != null )
+ return false
+
+ if ( mapName.find( "coliseum" ) != null )
+ return false;
+
+ return true
+}
+
+bool function MapSettings_SupportsAI( string mapName )
+{
+ if ( mapName.find( "mp_lf_") != null )
+ return false
+
+ if ( mapName.find( "coliseum" ) != null )
+ return false;
+
+ return true
+}
+
+
+bool function ModeSettings_RequiresTitans( string modeName )
+{
+ switch ( modeName )
+ {
+ case "lts":
+ return true
+ }
+
+ return false
+}
+
+bool function ModeSettings_RequiresAI( string modeName )
+{
+ switch ( modeName )
+ {
+ case "aitdm":
+ case "at":
+ return true
+ }
+
+ if ( modeName.find( "fd" ) == 0 ) // bob edit: unsure if this keeps vanilla compatibility, but just make sure fd modes are counted as requiring ai
+ return true
+
+ return false
+}
+
+#if !CLIENT
+string function PrivateMatch_GetSelectedMap()
+{
+ var mapIndex = level.ui.privatematch_map
+ string mapName = GetPrivateMatchMapForIndex( expect int(mapIndex) )
+
+ return mapName
+}
+
+
+string function PrivateMatch_GetSelectedMode()
+{
+ var modeIndex = level.ui.privatematch_mode
+ string modeName = GetPrivateMatchModeForIndex( expect int(modeIndex) )
+
+ return modeName
+}
+#endif
+
+bool function PrivateMatch_IsValidMapModeCombo( string mapName, string modeName )
+{
+ array<string> mapsForMode = GetPrivateMatchMapsForMode( modeName )
+
+ return mapsForMode.contains( mapName )
+}
+
+// end private match stuff
+
+int function Player_GetMaxMatchmakingDelay( entity player )
+{
+ // return GetCurrentPlaylistVarInt( "matchmaking_delay", 0 )
+ return 300
+}
+
+int function Player_GetRemainingMatchmakingDelay( entity player )
+{
+ int lastLeaveTime = player.GetPersistentVarAsInt( PERSISTENCE_LAST_LEAVE_TIME )
+
+ return Player_GetMaxMatchmakingDelay( player ) - (GetCurrentTimeForPersistence() - lastLeaveTime)
+}
+
+int function Player_NextAvailableMatchmakingTime( entity player )
+{
+ #if MP
+ int lastLeaveTime = player.GetPersistentVarAsInt( PERSISTENCE_LAST_LEAVE_TIME )
+ if ( GetCurrentTimeForPersistence() - lastLeaveTime < Player_GetMaxMatchmakingDelay( player ) )
+ {
+ return Player_GetRemainingMatchmakingDelay( player )
+ }
+ #endif
+
+ return 0
+}
+
+int function GetCurrentTimeForPersistence()
+{
+ // Returns the unix timestap offset to the timezone we want to use
+ return GetUnixTimestamp() + DAILY_RESET_TIME_ZONE_OFFSET * SECONDS_PER_HOUR
+}
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
new file mode 100644
index 00000000..41806e16
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
@@ -0,0 +1,55 @@
+global function PrivateMatchModesInit
+
+void function PrivateMatchModesInit()
+{
+ // match settings
+ // super temp: do localisation strings later
+ AddPrivateMatchModeSettingArbitrary( "Match", "scorelimit", "5" ) //, "Score Limit" )
+ AddPrivateMatchModeSettingArbitrary( "Match", "roundscorelimit", "0" ) //, "Score Limit (round-based modes)" )
+ AddPrivateMatchModeSettingArbitrary( "Match", "timelimit", "12" ) //, "Time Limit" )
+ AddPrivateMatchModeSettingArbitrary( "Match", "roundtimelimit", "0" ) //, "Time Limit (round-based modes)" )
+
+ AddPrivateMatchModeSettingArbitrary( "Pilot", "pilot_health_multiplier", "1.0" )
+ AddPrivateMatchModeSettingArbitrary( "Pilot", "respawn_delay", "0.0" )
+ AddPrivateMatchModeSettingEnum( "Pilot", "boosts_enabled", [ "Default", "Disabled" ], "1" )
+ AddPrivateMatchModeSettingEnum( "Pilot", "earn_meter_pilot_overdrive", [ "Disabled", "Enabled", "Only" ], "1" )
+ AddPrivateMatchModeSettingArbitrary( "Pilot", "earn_meter_pilot_multiplier", "1.0" )
+
+ AddPrivateMatchModeSettingArbitrary( "Titan", "earn_meter_titan_multiplier", "1.0" )
+ AddPrivateMatchModeSettingEnum( "Titan", "aegis_upgrades", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Titan", "infinite_doomed_state", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Titan", "titan_shield_regen", [ "Disabled", "Enabled" ], "0" )
+
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "riff_floorislava", [ "Default", "Enabled", "Disabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_all_holopilot", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_all_grapple", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_all_phase", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_all_ticks", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_tactikill", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_amped_tacticals", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_rocket_arena", [ "Disabled", "Enabled" ], "0" )
+ AddPrivateMatchModeSettingEnum( "Riff Settings", "featured_mode_shotguns_snipers", [ "Disabled", "Enabled" ], "0" )
+
+ // gamemode settings
+ AddPrivateMatchModeSettingEnum( "#GAMEMODE_cp", "amped_capture_points", [ "Disabled", "Enabled" ], "0" )
+
+ AddPrivateMatchModeSettingEnum( "#GAMEMODE_coliseum", "coliseum_loadouts_enabled", [ "Disabled", "Enabled" ], "1" )
+
+
+ // modes
+ AddPrivateMatchMode( "ffa" )
+ AddPrivateMatchMode( "fra" )
+ AddPrivateMatchMode( "coliseum" )
+
+ // playlists
+ AddPrivateMatchMode( "attdm" )
+ AddPrivateMatchMode( "turbo_ttdm" )
+ AddPrivateMatchMode( "alts" )
+ AddPrivateMatchMode( "turbo_lts" )
+ AddPrivateMatchMode( "rocket_lf" )
+ AddPrivateMatchMode( "holopilot_lf" )
+
+ // maps
+ AddPrivateMatchMap( "mp_coliseum" )
+ AddPrivateMatchMap( "mp_coliseum_column" )
+} \ No newline at end of file