aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-07 22:25:59 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-07-07 22:25:59 +0100
commit07b7eafd5c1845c70510b695446c23973fed1d4d (patch)
tree8452fd02d8356a65f07089c20318a8de95975125 /Northstar.CustomServers
parent53194543e43f8a645ba83ddb464028ba0c3b9d70 (diff)
downloadNorthstarMods-07b7eafd5c1845c70510b695446c23973fed1d4d.tar.gz
NorthstarMods-07b7eafd5c1845c70510b695446c23973fed1d4d.zip
add fra, featured modes and some private lobby v2 stuff
Diffstat (limited to 'Northstar.CustomServers')
-rw-r--r--Northstar.CustomServers/mod.json21
-rw-r--r--Northstar.CustomServers/scripts/vscripts/_powerup.gnut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_featured_mode_settings.gnut121
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_coliseum.nut87
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_fra.nut25
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemodes.gnut5
-rw-r--r--Northstar.CustomServers/scripts/vscripts/lobby/_private_lobby.gnut6
-rw-r--r--Northstar.CustomServers/scripts/vscripts/lobby/sh_lobby.gnut356
-rw-r--r--Northstar.CustomServers/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut21
-rw-r--r--Northstar.CustomServers/scripts/vscripts/sh_northstar_utils.gnut49
10 files changed, 687 insertions, 6 deletions
diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json
index a9e4f36d3..6e4d2d58f 100644
--- a/Northstar.CustomServers/mod.json
+++ b/Northstar.CustomServers/mod.json
@@ -24,6 +24,11 @@
},
{
+ "Path": "sh_northstar_utils.gnut",
+ "RunOn": "CLIENT || SERVER || UI",
+ },
+
+ {
"Path": "mp/levels/_lf_maps_shared.gnut",
"RunOn": "SERVER && MP"
},
@@ -32,11 +37,20 @@
"Path": "gamemodes/sh_gamemodes_custom.gnut",
"RunOn": "(CLIENT || SERVER) && MP"
},
-
{
"Path": "sh_remote_functions_mp_custom.gnut",
"RunOn": "(CLIENT || SERVER) && MP"
},
+ {
+ "Path": "gamemodes/_gamemode_fra.nut",
+ "RunOn": "SERVER && MP",
+ "ServerPreCallback": "GamemodeFRA_AddAdditionalInitCallback"
+ },
+ {
+ "Path": "gamemodes/_featured_mode_settings.gnut",
+ "RunOn": "SERVER && MP",
+ "ServerCallback": "FeaturedModeSettings_Init"
+ },
{
"Path": "mp/_classic_mp_dropship_intro.gnut",
@@ -52,5 +66,10 @@
"RunOn": "SERVER && MP",
"ServerCallback": "SvLoadoutsMP_Init"
},
+
+ {
+ "Path": "lobby/sh_private_lobby_modes_init.gnut",
+ "RunOn": "( SERVER || CLIENT ) && MP",
+ },
]
} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/_powerup.gnut b/Northstar.CustomServers/scripts/vscripts/_powerup.gnut
index a6a117afb..03b9fcfc7 100644
--- a/Northstar.CustomServers/scripts/vscripts/_powerup.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/_powerup.gnut
@@ -81,7 +81,7 @@ bool function OnPowerupCollected( entity player, entity healthpack )
{
// hack because i couldn't figure out any other way to do this without modifying sh_powerup
// ensure we don't kill the powerup if it's a battery the player can't pickup
- if ( ( powerup.index == ePowerUps.titanTimeReduction || powerup.index == ePowerUps.LTS_TitanTimeReduction ) && PlayerHasBattery( player ) )
+ if ( ( powerup.index == ePowerUps.titanTimeReduction || powerup.index == ePowerUps.LTS_TitanTimeReduction ) && ( player.IsTitan() || PlayerHasMaxBatteryCount( player ) ) )
return false
// idk why the powerup.destroyFunc doesn't just return a bool? would mean they could just handle stuff like this in powerup code
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_featured_mode_settings.gnut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_featured_mode_settings.gnut
new file mode 100644
index 000000000..272043804
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_featured_mode_settings.gnut
@@ -0,0 +1,121 @@
+untyped
+global function FeaturedModeSettings_Init
+
+void function FeaturedModeSettings_Init()
+{
+ // if it's not super obvious at a glance this script is used for playlist vars with the prefix "featured_mode_"
+ // these often set loadouts and shit so they need a script
+ // note: for turbo_titans, the core multiplier is set in playlist
+
+ AddCallback_OnPlayerRespawned( FeaturedModeSettingsSetupPilotLoadouts )
+ AddCallback_OnPilotBecomesTitan( FeaturedModeSettingsSetupTitanLoadouts )
+}
+
+bool function IsFeaturedMode( string modeName )
+{
+ return GetCurrentPlaylistVar( "featured_mode_" + modeName ) == "1"
+}
+
+void function FeaturedModeSettingsSetupPilotLoadouts( entity player )
+{
+ bool shouldChangeLoadout = false
+
+ // create loadout struct
+ PilotLoadoutDef modifiedLoadout = clone GetActivePilotLoadout( player )
+
+ if ( IsFeaturedMode( "all_holopilot" ) )
+ {
+ shouldChangeLoadout = true
+
+ modifiedLoadout.special = "mp_ability_holopilot"
+ }
+
+ if ( IsFeaturedMode( "all_grapple" ) )
+ {
+ shouldChangeLoadout = true
+
+ modifiedLoadout.special = "mp_ability_grapple"
+ modifiedLoadout.specialMods = [ "all_grapple" ]
+ }
+
+ if ( IsFeaturedMode( "all_phase" ) )
+ {
+ shouldChangeLoadout = true
+
+ modifiedLoadout.special = "mp_ability_shifter"
+ modifiedLoadout.specialMods = [ "all_phase" ]
+ }
+
+ if ( IsFeaturedMode( "all_ticks" ) )
+ {
+ shouldChangeLoadout = true
+
+ modifiedLoadout.ordnance = "mp_weapon_frag_drone"
+ modifiedLoadout.ordnanceMods = [ "all_ticks" ]
+ }
+
+ if ( IsFeaturedMode( "rocket_arena" ) )
+ {
+ shouldChangeLoadout = true
+
+ modifiedLoadout.primary = "mp_weapon_epg"
+ modifiedLoadout.primaryMods = [ "rocket_arena" ]
+
+ // set secondary to whatever one is pistol
+ if ( GetWeaponInfoFileKeyField_Global( player.GetMainWeapons()[ 1 ].GetWeaponClassName(), "menu_category" ) == "at" )
+ {
+ modifiedLoadout.weapon3 = "mp_weapon_autopistol"
+ modifiedLoadout.weapon3Mods = [ "rocket_arena" ]
+ }
+ else
+ {
+ modifiedLoadout.secondary = "mp_weapon_autopistol"
+ modifiedLoadout.secondaryMods = [ "rocket_arena" ]
+ }
+ }
+
+ if ( IsFeaturedMode( "shotguns_snipers" ) )
+ {
+
+ shouldChangeLoadout = true
+
+ // this one was never released, assuming it just gives you a mastiff and a kraber with quick swap
+ modifiedLoadout.primary = "mp_weapon_sniper"
+ modifiedLoadout.primaryMods = [ "pas_fast_swap", "pas_fast_ads" ]
+
+ // set secondary to whatever one is pistol
+ if ( GetWeaponInfoFileKeyField_Global( player.GetMainWeapons()[ 1 ].GetWeaponClassName(), "menu_category" ) == "at" )
+ {
+ modifiedLoadout.weapon3 = "mp_weapon_mastiff"
+ modifiedLoadout.weapon3Mods = [ "pas_fast_swap", "pas_run_and_gun" ]
+ }
+ else
+ {
+ modifiedLoadout.secondary = "mp_weapon_mastiff"
+ modifiedLoadout.secondaryMods = [ "pas_fast_swap", "pas_run_and_gun" ]
+ }
+ }
+
+ // dont wanna give a new loadout if it's not necessary, could break other callbacks
+ if ( shouldChangeLoadout )
+ GivePilotLoadout( player, modifiedLoadout )
+
+ if ( IsFeaturedMode( "tactikill" ) )
+ player.GiveExtraWeaponMod( "tactical_cdr_on_kill" )
+
+ if ( IsFeaturedMode( "amped_tacticals" ) )
+ player.GiveExtraWeaponMod( "amped_tacticals" )
+}
+
+void function FeaturedModeSettingsSetupTitanLoadouts( entity player, entity titan )
+{
+ // this doesn't work atm, figure out how it should work and fix at some point
+ entity soul = player.GetTitanSoul()
+ if ( IsFeaturedMode( "turbo_titans" ) )
+ {
+ if ( GetSoulTitanSubClass( soul ) == "stryder" || GetSoulTitanSubClass( soul ) == "atlas" )
+ GivePassive( player, ePassives.PAS_MOBILITY_DASH_CAPACITY )
+ else
+ GivePassive( player, ePassives.PAS_DASH_RECHARGE )
+ }
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_coliseum.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_coliseum.nut
index d8ccfc424..b358cfe82 100644
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_coliseum.nut
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_coliseum.nut
@@ -1,12 +1,95 @@
+untyped
+
global function GamemodeColiseum_Init
global function GamemodeColiseum_CustomIntro
+bool hasShownIntroScreen = false
+
void function GamemodeColiseum_Init()
{
+ // gamemode settings
+ SetRoundBased( true )
+ SetRespawnsEnabled( false )
+ SetShouldUseRoundWinningKillReplay( true )
+ Riff_ForceTitanAvailability( eTitanAvailability.Never )
+ Riff_ForceBoostAvailability( eBoostAvailability.Disabled )
+ Riff_ForceSetEliminationMode( eEliminationMode.Pilots )
+ SetLoadoutGracePeriodEnabled( false ) // prevent modifying loadouts with grace period
+ SetWeaponDropsEnabled( false )
+
+ ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
+ AddCallback_GameStateEnter( eGameState.Prematch, ShowColiseumIntroScreen )
+ AddCallback_OnPlayerRespawned( GivePlayerColiseumLoadout )
+}
+
+// stub function referenced in sh_gamemodes_mp
+void function GamemodeColiseum_CustomIntro( entity player )
+{}
+void function ShowColiseumIntroScreen()
+{
+ if ( !hasShownIntroScreen )
+ thread ShowColiseumIntroScreenThreaded()
+
+ hasShownIntroScreen = true
}
-void function GamemodeColiseum_CustomIntro(entity _0)
+void function ShowColiseumIntroScreenThreaded()
{
+ wait 5
+
+ foreach ( entity player in GetPlayerArray() )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_ColiseumIntro", 1, 1, 1 ) // stub numbers atm because lazy
+}
+
+void function GivePlayerColiseumLoadout( entity player )
+{
+ // create loadout struct
+ PilotLoadoutDef coliseumLoadout = clone GetActivePilotLoadout( player )
+
+ /* from playlists.txt
+ coliseum_primary "mp_weapon_lstar"
+ coliseum_primary_attachment ""
+ coliseum_primary_mod1 ""
+ coliseum_primary_mod2 ""
+ coliseum_primary_mod3 ""
+ coliseum_secondary "mp_weapon_softball"
+ coliseum_secondary_mod1 ""
+ coliseum_secondary_mod2 ""
+ coliseum_secondary_mod3 ""
+ coliseum_weapon3 ""
+ coliseum_weapon3_mod1 ""
+ coliseum_weapon3_mod2 ""
+ coliseum_weapon3_mod3 ""
+ coliseum_melee "melee_pilot_emptyhanded"
+ coliseum_special "mp_ability_heal"
+ coliseum_ordnance "mp_weapon_frag_drone"
+ coliseum_passive1 "pas_fast_health_regen"
+ coliseum_passive2 "pas_wallhang"*/
+
+ coliseumLoadout.primary = GetColiseumItem( "primary" )
+ coliseumLoadout.primaryMods = [ GetColiseumItem( "primary_attachment" ), GetColiseumItem( "primary_mod1" ), GetColiseumItem( "primary_mod2" ), GetColiseumItem( "primary_mod3" ) ]
+
+ coliseumLoadout.secondary = GetColiseumItem( "secondary" )
+ coliseumLoadout.secondaryMods = [ GetColiseumItem( "secondary_mod1" ), GetColiseumItem( "secondary_mod2" ), GetColiseumItem( "secondary_mod3" ) ]
+
+ coliseumLoadout.weapon3 = GetColiseumItem( "weapon3" )
+ coliseumLoadout.weapon3Mods = [ GetColiseumItem( "weapon3_mod1" ), GetColiseumItem( "weapon3_mod2" ), GetColiseumItem( "weapon3_mod3" ) ]
+
+ coliseumLoadout.melee = GetColiseumItem( "melee" )
+ coliseumLoadout.special = GetColiseumItem( "special" )
+ coliseumLoadout.ordnance = GetColiseumItem( "ordnance" )
+ coliseumLoadout.passive1 = GetColiseumItem( "passive1" )
+ coliseumLoadout.passive2 = GetColiseumItem( "passive2" )
+
+ coliseumLoadout.setFile = GetSuitAndGenderBasedSetFile( "coliseum", coliseumLoadout.race == RACE_HUMAN_FEMALE ? "female" : "male" )
+
+ GivePilotLoadout( player, coliseumLoadout )
+}
+
+string function GetColiseumItem( string name )
+{
+ return expect string ( GetCurrentPlaylistVar( "coliseum_" + name ) )
+}
-} \ No newline at end of file
+// todo this needs the outro: unsure what anims it uses \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_fra.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_fra.nut
new file mode 100644
index 000000000..15f749ac7
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_fra.nut
@@ -0,0 +1,25 @@
+global function GamemodeFRA_AddAdditionalInitCallback
+
+// fra doesn't register a gamemode init by default, adding one just so we can set stuff up for it
+void function GamemodeFRA_AddAdditionalInitCallback()
+{
+ AddCallback_OnCustomGamemodesInit( GamemodeFRA_AddAdditionalInit )
+}
+
+void function GamemodeFRA_AddAdditionalInit()
+{
+ GameMode_AddServerInit( FREE_AGENCY, GamemodeFRA_Init )
+}
+
+void function GamemodeFRA_Init()
+{
+ // need a way to disable passive earnmeter gain
+ ScoreEvent_SetEarnMeterValues( "PilotBatteryPickup", 0.0, 0.34 )
+
+ AddCallback_OnPlayerKilled( FRARemoveEarnMeter )
+}
+
+void function FRARemoveEarnMeter( entity victim, entity attacker, var damageInfo )
+{
+ PlayerEarnMeter_Reset( victim )
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemodes.gnut b/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemodes.gnut
index df7acb78e..9114fcadd 100644
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemodes.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemodes.gnut
@@ -415,7 +415,10 @@ void function GameModes_Init()
#endif
#if SERVER || CLIENT
- InitCustomGamemodes()
+ // add modes/maps/playlists to private lobby that aren't there by default
+ PrivateMatchModesInit()
+
+ InitCustomGamemodes() // do custom gamemode callbacks
GameModes_Init_SV_CL()
#endif
diff --git a/Northstar.CustomServers/scripts/vscripts/lobby/_private_lobby.gnut b/Northstar.CustomServers/scripts/vscripts/lobby/_private_lobby.gnut
index c428d3095..8d803da1d 100644
--- a/Northstar.CustomServers/scripts/vscripts/lobby/_private_lobby.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/lobby/_private_lobby.gnut
@@ -102,7 +102,11 @@ void function StartMatch()
WaitFrame()
}
- GameRules_SetGameMode( file.mode )
+ 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
diff --git a/Northstar.CustomServers/scripts/vscripts/lobby/sh_lobby.gnut b/Northstar.CustomServers/scripts/vscripts/lobby/sh_lobby.gnut
new file mode 100644
index 000000000..24436017f
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/lobby/sh_lobby.gnut
@@ -0,0 +1,356 @@
+globalize_all_functions
+
+const string PRIVATE_MATCH_PLAYLIST = "private_match"
+
+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"
+ ]
+} 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
+}
+
+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() )
+ return ""
+
+ return mapsArray[index]
+}
+
+string function GetPrivateMatchModeForIndex( int index )
+{
+ array<string> modesArray = GetPrivateMatchModes()
+
+ if ( index >= modesArray.len() )
+ 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
+ }
+
+ 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/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut b/Northstar.CustomServers/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
new file mode 100644
index 000000000..b1474a15a
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
@@ -0,0 +1,21 @@
+global function PrivateMatchModesInit
+
+void function PrivateMatchModesInit()
+{
+ // 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
diff --git a/Northstar.CustomServers/scripts/vscripts/sh_northstar_utils.gnut b/Northstar.CustomServers/scripts/vscripts/sh_northstar_utils.gnut
new file mode 100644
index 000000000..15eed9b21
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/sh_northstar_utils.gnut
@@ -0,0 +1,49 @@
+globalize_all_functions
+
+enum eNorthstarLobbyType
+{
+ PrivateMatchLobby, // normal vanilla private lobby
+ IntermissionLobby, // similar to tf1's intermission lobby, chooses next map automatically
+ CompetitiveLobby // similar to vanilla privates, but with ready up system
+}
+
+// whether the server is a modded, northstar server
+bool function IsNorthstarServer()
+{
+ bool isModded = true // TEMP for testing
+ try
+ {
+ // need this in a trycatch because the var might not exist atm
+ isModded = GetConVarInt( "northstar_is_modded_server" ) == 1
+ } catch ( ex ) {}
+
+ return isModded
+}
+
+// whether the game should return to the lobby on GameRules_EndMatch()
+bool function ShouldReturnToLobby()
+{
+ bool shouldReturnToLobby = false
+ try
+ {
+ // need this in a trycatch because the var might not exist atm
+ shouldReturnToLobby = GetConVarInt( "northstar_should_return_to_lobby" ) == 1
+ } catch ( ex ) {}
+
+ return shouldReturnToLobby
+}
+
+int function GetNorthstarLobbyType()
+{
+ if ( !IsNorthstarServer() )
+ return eNorthstarLobbyType.PrivateMatchLobby
+
+ int lobbyType = eNorthstarLobbyType.PrivateMatchLobby
+ try
+ {
+ // need this in a trycatch because the var might not exist atm
+ lobbyType = GetConVarInt( "northstar_lobby_type" )
+ } catch ( ex ) {}
+
+ return lobbyType
+} \ No newline at end of file