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 } struct { array modes = [ // default modes in vanilla "tdm", "aitdm", "cp", "at", "ctf", "lts", "ps", "speedball", "mfd", "ttdm", "fd_easy", "fd_normal", "fd_hard", "fd_master", "fd_insane" ] array 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 enums, 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 foreach ( int i, value in enums ) { setting.enumNames.append( value ) setting.enumValues.append( string( i ) ) } 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 ( int i, value in enums ) serializedString += value + "\n" + string( i ) + "\n" RunUIScript( "AddPrivateMatchModeSettingEnumUIHack", category, playlistVar, serializedString, defaultValue, localizedName ) #endif } 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 serializedArray = split( serializedEnumPairs, "\n" ) array enums = [] for ( int i = 0; i < serializedArray.len(); i += 2 ) { enums.append( serializedArray[i] ) } AddPrivateMatchModeSettingEnum( category, playlistVar, enums, defaultValue, localizedName ) } // Sorts specific gamemode settings to the end of the list int function SortMatchSettings( string categoryA, string categoryB ) { if ( StartsWith( categoryA, "#PL_" ) || StartsWith( categoryA, "#GAMEMODE_" ) ) return 1 else if ( StartsWith( categoryB, "#PL_" ) || StartsWith( categoryB, "#GAMEMODE_" ) ) return 0 return 0 } array< string > function GetPrivateMatchSettingCategories( bool uiAllowAllModeCategories = false ) { array< string > categories foreach ( string k, v in file.customMatchSettingsByCategory ) { #if UI bool differentPlaylist = StartsWith( k, "#PL_" ) && k.slice( 4 ) != PrivateMatch_GetSelectedMode() bool differentGamemode = StartsWith( k, "#GAMEMODE_" ) && k.slice( 10 ) != PrivateMatch_GetSelectedMode() if ( differentPlaylist || differentGamemode ) continue #endif categories.append( k ) } categories.sort( SortMatchSettings ) return categories } array< CustomMatchSettingContainer > function GetPrivateMatchCustomSettingsForCategory( string category ) { return file.customMatchSettingsByCategory[ category ] } array function GetPrivateMatchModes() { //array 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 function GetPrivateMatchMapsForMode( string modeName ) { //array 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 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 function GetPrivateMatchModesForMap( string mapName ) { array 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 mapsArray = GetPrivateMatchMaps() if ( index >= mapsArray.len() || index < 0 ) return "" return mapsArray[index] } string function GetPrivateMatchModeForIndex( int index ) { array modesArray = GetPrivateMatchModes() if ( index >= modesArray.len() || index < 0 ) return "" return modesArray[index] } int function GetPrivateMatchMapIndex( string mapName ) { array mapsArray = GetPrivateMatchMaps() for ( int index = 0; index < mapsArray.len(); index++ ) { if ( mapsArray[index] == mapName ) return index } return 0 } /* int function GetPrivateMatchModeIndex( string modeName ) { array modesArray = GetPrivateMatchModes() for ( int index = 0; index < modesArray.len(); index++ ) { if ( modesArray[index] == modeName ) return index } return 0 } */ array function GetPrivateMatchMaps() { //array 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 function GetPlaylistMaps( string playlistName ) { array 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 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 }