aboutsummaryrefslogtreecommitdiff
path: root/bobthebob.testing
diff options
context:
space:
mode:
Diffstat (limited to 'bobthebob.testing')
-rw-r--r--bobthebob.testing/mod.json40
-rw-r--r--bobthebob.testing/scripts/vscripts/_bobtestingfunctions_mp.gnut239
-rw-r--r--bobthebob.testing/scripts/vscripts/_bobtestingfunctions_sp.gnut13
-rw-r--r--bobthebob.testing/scripts/vscripts/lobby/sh_lobby.gnut356
-rw-r--r--bobthebob.testing/scripts/vscripts/mp/levels/mp_box.nut24
-rw-r--r--bobthebob.testing/scripts/vscripts/mp/sh_revive.gnut19
-rw-r--r--bobthebob.testing/scripts/vscripts/sh_bleedout_test.gnut34
-rw-r--r--bobthebob.testing/scripts/vscripts/sh_bobtestingfunctions_mp.gnut128
-rw-r--r--bobthebob.testing/scripts/vscripts/sh_northstar_utils.gnut49
-rw-r--r--bobthebob.testing/scripts/vscripts/ui/menu_dev.nut707
-rw-r--r--bobthebob.testing/scripts/vscripts/ui/menu_map_select.nut200
-rw-r--r--bobthebob.testing/scripts/vscripts/ui/menu_mode_select.nut138
-rw-r--r--bobthebob.testing/scripts/vscripts/ui/menu_team_titan_select.nut722
13 files changed, 2669 insertions, 0 deletions
diff --git a/bobthebob.testing/mod.json b/bobthebob.testing/mod.json
new file mode 100644
index 00000000..f79cb091
--- /dev/null
+++ b/bobthebob.testing/mod.json
@@ -0,0 +1,40 @@
+{
+ "ApiId" : "bobthebob.testing",
+ "Name" : "bobthebob.testing",
+ "Description" : "a place to put custom testing/debug functions and shit, shouldn't mess with game core behaviour at all",
+ "Authors" : [
+ "BobTheBob"
+ ],
+ "Contacts" : [
+ "BobTheBob#1150"
+ ],
+ "Version" : "0.1",
+ "CustomScripts": [
+ {
+ "Path": "sh_bobtestingfunctions_mp.gnut",
+ "RunOn": "( CLIENT || SERVER ) && MP"
+ },
+ {
+ "Path": "_bobtestingfunctions_sp.gnut",
+ "RunOn": "SERVER && SP"
+ },
+ {
+ "Path": "_bobtestingfunctions_mp.gnut",
+ "RunOn": "SERVER && MP",
+ "ServerPreCallback": "SvTestingMPInit"
+ },
+
+ {
+ "Path": "sh_bleedout_test.gnut",
+ "RunOn": "( CLIENT || SERVER ) && MP",
+ "ServerPreCallback": "BleedoutTest_Init",
+ "ClientPreCallback": "BleedoutTest_Init",
+ },
+
+ {
+ "Path": "sh_northstar_utils.gnut",
+ "RunOn": "CLIENT || SERVER || UI",
+ }
+
+ ]
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_mp.gnut b/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_mp.gnut
new file mode 100644
index 00000000..b782243a
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_mp.gnut
@@ -0,0 +1,239 @@
+untyped
+globalize_all_functions
+
+void function SvTestingMPInit()
+{
+ Bleedout_Init()
+ AddCallback_EntitiesDidLoad( CreateSpawns )
+}
+
+void function CreateSpawns()
+{
+ //thread CreateSpawns_Threaded()
+}
+
+void function CreateSpawns_Threaded()
+{
+ WaitEndFrame() // wait for spawns to get cleared, game ctds if we don't do this
+ entity validSpawn = GetEntArrayByClass_Expensive( "info_spawnpoint_human" )[ 0 ]
+
+ for ( int i = 0; i < 50; i++ )
+ {
+ entity newSpawn = CreateEntity( "info_spawnpoint_human" )
+ newSpawn.SetOrigin( validSpawn.GetOrigin() )
+ DispatchSpawn( newSpawn )
+ }
+}
+
+void function TestSpawnpoints( bool titan = false )
+{
+ entity player = GetPlayerArray()[0]
+ array<entity> spawnpoints
+ if ( !titan )
+ spawnpoints = SpawnPoints_GetPilotStart( player.GetTeam() )
+ else
+ spawnpoints = SpawnPoints_GetTitanStart( player.GetTeam() )
+
+ SpawnPoints_InitRatings( player, player.GetTeam() )
+
+ foreach ( entity spawnpoint in spawnpoints )
+ spawnpoint.CalculateRating( titan ? TD_TITAN : TD_PILOT, player.GetTeam(), RandomFloat( 7.0 ) - 3.5, RandomFloat( 7.0 ) - 3.5 )
+
+ if ( !titan )
+ {
+ SpawnPoints_SortPilotStart()
+ spawnpoints = SpawnPoints_GetPilotStart( player.GetTeam() )
+ }
+ else
+ {
+ SpawnPoints_SortTitanStart()
+ spawnpoints = SpawnPoints_GetTitanStart( player.GetTeam() )
+ }
+
+ entity chosenPoint
+ foreach ( entity spawnpoint in spawnpoints )
+ if ( IsSpawnpointValid( spawnpoint, player.GetTeam() ) )
+ {
+ chosenPoint = spawnpoint
+ break
+ }
+
+ player.SetOrigin( chosenPoint.GetOrigin() )
+ player.SetAngles( chosenPoint.GetAngles() )
+
+ //SpawnPoints_DiscardRatings() // somehow the game seems to call this automatically so unneeded
+}
+
+bool function IsSpawnpointValid( entity spawnpoint, int team )
+{
+ if ( GameModeRemove( spawnpoint ) )
+ return false
+
+ // ultra temp
+ print( spawnpoint.GetTeam() )
+ if ( spawnpoint.GetTeam() == 0 )
+ return false
+
+ if ( spawnpoint.GetTeam() > 0 && spawnpoint.GetTeam() != team )
+ return false
+
+
+
+ return true
+}
+
+void function TestScoreEvent( entity player, int id )
+{
+ ScoreEvent event = ScoreEvent_FromId( id )
+
+ Remote_CallFunction_NonReplay( player, "ServerCallback_ScoreEvent", id, event.pointValue, event.displayType, player.GetEncodedEHandle(), event.earnMeterOwnValue, event.earnMeterEarnValue )
+}
+
+void function TestDrop( entity player )
+{
+ thread CreateTitanForPlayerAndHotdrop( player, GetTitanReplacementPoint( player, false ) )
+}
+
+void function WarpThroughSpawnpoints( string modeOverride = "" )
+{
+ if ( !modeOverride.len() )
+ modeOverride = GAMETYPE
+
+ entity player = GetPlayerArray()[0]
+
+ array<entity> spawnpoints = GetEntArrayByClass_Expensive( "info_hardpoint" ) //SpawnPoints_GetPilot()
+ foreach ( entity spawnpoint in spawnpoints )
+ {
+ //string gamemodeKey = "gamemode_" + modeOverride
+ //if ( spawnpoint.HasKey( gamemodeKey ) && ( spawnpoint.kv[ gamemodeKey ] == "0" || spawnpoint.kv[ gamemodeKey ] == "" ) )
+ // continue
+ //
+ //if ( !spawnpoint.HasKey( gamemodeKey ) )
+ // continue
+
+ if ( spawnpoint.HasKey( "hardpointGroup" ) )
+ print( spawnpoint.kv.hardpointGroup )
+
+ player.SetOrigin( spawnpoint.GetOrigin() )
+ player.SetAngles( spawnpoint.GetAngles() )
+
+ wait 0.5
+ }
+}
+
+void function AttemptSpawnBuddyTitan()
+{
+ PrecacheModel( $"models/titans/buddy/titan_buddy.mdl" )
+ PrecacheModel( $"models/weapons/arms/buddypov.mdl" )
+
+ entity player = GetPlayerArray()[0]
+ entity titan = CreateNPCTitan( "titan_buddy", player.GetTeam(), player.GetOrigin(), <0, 0, 0> )
+ SetSpawnOption_AISettings( titan, "npc_titan_buddy" )
+ SetSpawnOption_Weapon( titan, "mp_titanweapon_xo16_vanguard", [ ] )
+
+ DispatchSpawn( titan )
+
+ player.SetPetTitan( titan )
+ titan.SetOwner( player )
+ titan.SetUsable()
+}
+
+
+void function SetPlayerCameraToHead()
+{
+ entity viewControl = CreateEntity( "point_viewcontrol" )
+ viewControl.kv.spawnflags = 56
+ DispatchSpawn( viewControl )
+
+ viewControl.SetParent( GetPlayerArray()[0], "headshot" )
+ viewControl.SetOrigin( < 4, 0, 1 > )
+ viewControl.SetAngles( < 0, 0, 0 > )
+ GetPlayerArray()[0].SetViewEntity( viewControl, true )
+}
+
+void function CreateTestControlPanel()
+{
+ entity player = GetPlayerArray()[0]
+
+ entity panel = CreateEntity( "prop_control_panel" )
+ panel.SetValueForModelKey( $"models/communication/terminal_usable_imc_01.mdl" )
+ panel.SetOrigin( player.GetOrigin() )
+ panel.SetAngles( player.GetAngles() )
+ panel.kv.solid = SOLID_VPHYSICS
+ SetTargetName( panel, "cpanel" )
+ DispatchSpawn( panel )
+
+ panel.SetModel( $"models/communication/terminal_usable_imc_01.mdl" )
+ panel.s.onPlayerFinishesUsing_func = TestOnPanelHacked
+
+}
+
+function TestOnPanelHacked( panel, player, success )
+{
+ expect entity( panel )
+ expect entity( player )
+ expect bool( success )
+
+ if ( !success )
+ return
+
+ print( panel + " was hacked by " + player )
+ PanelFlipsToPlayerTeamAndUsableByEnemies( panel, player )
+}
+
+void function TestFastball()
+{
+ PrecacheModel( $"models/titans/buddy/titan_buddy.mdl" )
+ RegisterSignal( "fastball_start_throw" )
+ RegisterSignal( "fastball_release" )
+ PrecacheParticleSystem( $"P_BT_eye_SM" )
+
+ entity player = GetPlayerArray()[0]
+
+ entity prop = CreatePropDynamic( $"models/titans/buddy/titan_buddy.mdl", player.GetOrigin(), player.GetAngles() )
+ thread PlayAnim( prop, "bt_beacon_fastball_throw_end" )
+
+ player.ContextAction_SetFastball()
+ FirstPersonSequenceStruct throwSequence
+ throwSequence.attachment = "REF"
+ throwSequence.useAnimatedRefAttachment = true
+ throwSequence.hideProxy = true
+ throwSequence.firstPersonAnim = "ptpov_beacon_fastball_throw_end"
+ //throwSequence.thirdPersonAnim = "pt_beacon_fastball_throw_end"
+ throwSequence.firstPersonBlendOutTime = 0.0
+
+ thread FirstPersonSequence( throwSequence, player, prop )
+ player.HolsterWeapon()
+
+ EmitSoundOnEntityOnlyToPlayer( player, player, "Music_Beacon_14_BTThrowThruFirstCrane" )
+
+ prop.WaitSignal( "fastball_start_throw" )
+ float duration = EmitSoundOnEntity( prop, "diag_sp_spoke1_BE117_04_01_mcor_bt" ) // trust me
+ vector eyeAngles = player.EyeAngles()
+
+ // particle effect
+ StartParticleEffectOnEntity( prop, GetParticleSystemIndex( $"P_BT_eye_SM" ), FX_PATTACH_POINT_FOLLOW, prop.LookupAttachment( "EYEGLOW" ) )
+ wait duration
+
+ prop.WaitSignal( "fastball_release" )
+ player.ContextAction_ClearFastball()
+ player.ClearParent()
+ ClearPlayerAnimViewEntity( player )
+ player.SetVelocity( AnglesToForward( eyeAngles ) * 1250 )
+ player.DeployWeapon()
+
+ wait 0.5
+ prop.Destroy()
+}
+
+void function TestPlanetExplosion() // won't look good until we can load textures from rpak for these models
+{
+ PrecacheModel( $"models/vistas/planet_ex_static.mdl" )
+ PrecacheModel( $"models/vistas/planet_explosion_animated.mdl" )
+
+ entity cam = GetEnt( "skybox_cam_level" )
+ cam.SetOrigin( < 7000, 7000, 7000 > ) // arbitrary point
+ CreatePropDynamic( $"models/vistas/planet_ex_static.mdl", cam.GetOrigin(), cam.GetAngles() )
+ entity explosion = CreatePropDynamic( $"models/vistas/planet_explosion_animated.mdl", cam.GetOrigin(), cam.GetAngles() )
+ thread PlayAnim( explosion, "planet_ex_ending" )
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_sp.gnut b/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_sp.gnut
new file mode 100644
index 00000000..2ad814fe
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/_bobtestingfunctions_sp.gnut
@@ -0,0 +1,13 @@
+globalize_all_functions
+
+void function TestPlanetExplosion()
+{
+ PrecacheModel( $"models/vistas/planet_ex_static.mdl" )
+ PrecacheModel( $"models/vistas/planet_explosion_animated.mdl" )
+
+ entity cam = GetEnt( "skybox_cam_level" )
+ cam.SetOrigin( < 7000, 7000, 7000 > ) // arbitrary point
+ CreatePropDynamic( $"models/vistas/planet_ex_static.mdl", cam.GetOrigin(), cam.GetAngles() )
+ entity explosion = CreatePropDynamic( $"models/vistas/planet_explosion_animated.mdl", cam.GetOrigin(), cam.GetAngles() )
+ thread PlayAnim( explosion, "planet_ex_ending" )
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/lobby/sh_lobby.gnut b/bobthebob.testing/scripts/vscripts/lobby/sh_lobby.gnut
new file mode 100644
index 00000000..24436017
--- /dev/null
+++ b/bobthebob.testing/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/bobthebob.testing/scripts/vscripts/mp/levels/mp_box.nut b/bobthebob.testing/scripts/vscripts/mp/levels/mp_box.nut
new file mode 100644
index 00000000..aa94be52
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/mp/levels/mp_box.nut
@@ -0,0 +1,24 @@
+/*global function CodeCallback_MapInit
+global function SpawnGamemodeObjects
+
+void function CodeCallback_MapInit()
+{
+ AddCallback_EntitiesDidLoad( SpawnGamemodeObjects )
+}
+
+void function SpawnGamemodeObjects()
+{
+ thread SpawnGamemodeObjects_Threaded()
+
+}
+
+void function SpawnGamemodeObjects_Threaded()
+{
+ WaitEndFrame()
+ entity liveFireFlagSpawn = CreateEntity( "script_ref" )
+ liveFireFlagSpawn.kv.editorclass = "info_speedball_flag"
+ liveFireFlagSpawn.kv.origin = < 0.0, -382.0, 60.0 >
+ liveFireFlagSpawn.kv.angles = < 0, 0, 0 >
+ DispatchSpawn( liveFireFlagSpawn )
+ liveFireFlagSpawn.kv.editorclass = "info_speedball_flag"
+}*/ \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/mp/sh_revive.gnut b/bobthebob.testing/scripts/vscripts/mp/sh_revive.gnut
new file mode 100644
index 00000000..8caa2a82
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/mp/sh_revive.gnut
@@ -0,0 +1,19 @@
+#if SERVER
+global const REVIVE_ENABLED = true // currently not used anywhere
+global function ReviveEnabled
+
+bool function ReviveEnabled()
+{
+ return GetCurrentPlaylistVarInt( "player_revive_enabled", 0 ) == 1
+}
+#elseif true
+global const REVIVE_ENABLED = false // currently not used anywhere
+global function ReviveEnabled
+
+bool function ReviveEnabled()
+{
+ // client version of this doesn't work lol
+ return false
+ //return GetCurrentPlaylistVarInt( "player_revive_enabled", 0 ) == 1
+}
+#endif \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/sh_bleedout_test.gnut b/bobthebob.testing/scripts/vscripts/sh_bleedout_test.gnut
new file mode 100644
index 00000000..42727adc
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/sh_bleedout_test.gnut
@@ -0,0 +1,34 @@
+global function BleedoutTest_Init
+
+void function BleedoutTest_Init()
+{
+ return // not in use rn
+
+ AddCallback_OnRegisteringCustomNetworkVars( RegisterBleedoutVars )
+
+ BleedoutShared_Init( 30.0, 3.0, -1.0, 1.0, 0.0, false, false )
+
+ #if SERVER
+ Bleedout_Init()
+ if ( ReviveEnabled() )
+ AddCallback_OnPlayerKilled( StartRevive )
+ #elseif CLIENT
+ BleedoutClient_Init()
+ #endif
+}
+
+#if SERVER
+void function StartRevive( entity victim, entity attacker, var damageInfo )
+{
+ DeathPackage_PlayerRevive( victim )
+ thread PlayerRevivesOrBleedsOut( victim )
+}
+#endif
+
+void function RegisterBleedoutVars()
+{
+ Remote_RegisterFunction( "ServerCallback_BLEEDOUT_StartFirstAidProgressBar" )
+ Remote_RegisterFunction( "ServerCallback_BLEEDOUT_StopFirstAidProgressBar" )
+ Remote_RegisterFunction( "ServerCallback_BLEEDOUT_ShowWoundedMarker" )
+ Remote_RegisterFunction( "ServerCallback_BLEEDOUT_HideWoundedMarker" )
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/sh_bobtestingfunctions_mp.gnut b/bobthebob.testing/scripts/vscripts/sh_bobtestingfunctions_mp.gnut
new file mode 100644
index 00000000..124c7a54
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/sh_bobtestingfunctions_mp.gnut
@@ -0,0 +1,128 @@
+globalize_all_functions
+
+void function DumpPdefEnum( string pdefEnum )
+{
+ for ( int i = 0; i < PersistenceGetEnumCount( pdefEnum ); i++ )
+ print( PersistenceGetEnumItemNameForIndex( pdefEnum, i ) )
+}
+
+void function ListPlayers()
+{
+ foreach ( entity player in GetPlayerArray() )
+ {
+ if ( player == null )
+ continue
+
+ print( "player " + player.GetPlayerName() + ": G" + player.GetGen() + "." + player.GetLevel() )
+ }
+}
+
+void function DumpPdefTable()
+{
+ foreach ( key0, value0 in shGlobalMP.playerStatVars )
+ {
+ foreach ( key1, value1 in value0 )
+ {
+ foreach ( key2, statData in value1 )
+ {
+ print ( statData.statVar )
+ }
+ }
+ }
+}
+
+void function DumpModels()
+{
+ for ( int i = 0; i < 2048; i++ )
+ if ( GetEntByIndex( i ) != null && GetEntByIndex( i ).GetModelName() != $"?" )
+ print( i + ": " + GetEntByIndex( i ).GetModelName() )
+}
+
+void function DumpScoreEvents()
+{
+ int i = 0;
+ while ( true )
+ {
+ ScoreEvent event
+ try event = ScoreEvent_FromId( i ) catch ( exception ) break
+
+ print( "event " + i + ":" )
+ print( "name: " + event.name )
+ print( "splashText: " + event.splashText )
+
+ // get string representation of displaytype
+ // if squirrel has a better way to do this i don't know it
+ string displayType
+
+ if ( event.displayType & eEventDisplayType.HIDDEN )
+ displayType += "HIDDEN, "
+ if ( event.displayType & eEventDisplayType.CENTER )
+ displayType += "CENTER, "
+ if ( event.displayType & eEventDisplayType.MEDAL )
+ displayType += "MEDAL, "
+ if ( event.displayType & eEventDisplayType.CALLINGCARD )
+ displayType += "CALLINGCARD, "
+ if ( event.displayType & eEventDisplayType.ATTRITION )
+ displayType += "ATTRITION, "
+ if ( event.displayType & eEventDisplayType.BIG )
+ displayType += "BIG, "
+ if ( event.displayType & eEventDisplayType.GAMEMODE )
+ displayType += "GAMEMODE, "
+ if ( event.displayType & eEventDisplayType.CHALLENGE )
+ displayType += "CHALLENGE, "
+ if ( event.displayType & eEventDisplayType.MEDAL_FORCED )
+ displayType += "MEDAL_FORCED, "
+ if ( event.displayType & eEventDisplayType.SHOW_SCORE )
+ displayType += "SHOW_SCORE, "
+
+ print( "displayType: " + displayType )
+ print( " " ) // newline
+
+ i++
+ }
+
+ print( "got " + i + " events!" )
+}
+
+void function DumpConversations()
+{
+ foreach ( string k, v in GetConversationToIndexTable() )
+ print( k )
+}
+
+#if CLIENT
+void function TestMarkRUI()
+{
+ var rui = CreateCockpitRui( $"ui/speedball_flag_marker.rpak", 200 )
+ RuiSetBool( rui, "isVisible", true )
+ RuiSetFloat3( rui, "pos", GetLocalViewPlayer().GetOrigin() )
+ RuiSetBool( rui, "playerIsCarrying", false )
+ RuiSetInt( rui, "teamRelation", TEAM_IMC )
+ RuiSetBool( rui, "isCarried", false )
+}
+
+void function TestObjectiveRUIHunted()
+{
+ var rui = CreateCockpitRui( $"ui/hunted_objective.rpak", 200 )
+ RuiSetGameTime( rui, "startTime", Time() )
+ RuiSetGameTime( rui, "endTime", Time() + 20.0 )
+ RuiSetString( rui, "objectiveTitleText", "#HUNTED_OBJECTIVE_TITLE" )
+ RuiSetFloat( rui, "blingDuration", 5.0 )
+ RuiSetBool( rui, "showAll", true )
+}
+
+void function TestObjectiveRUIFW()
+{
+ var rui = CreateCockpitRui( $"ui/fw_objective_text.rpak" )
+ RuiSetString( rui, "objective", "deez nuts" )
+
+ float time = Time() + 10.0
+ while ( time > Time() )
+ {
+ RuiSetString( rui, "objective", "deez nuts " + ( time - Time() ) )
+ WaitFrame()
+ }
+
+ RuiDestroy( rui )
+}
+#endif \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/sh_northstar_utils.gnut b/bobthebob.testing/scripts/vscripts/sh_northstar_utils.gnut
new file mode 100644
index 00000000..15eed9b2
--- /dev/null
+++ b/bobthebob.testing/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
diff --git a/bobthebob.testing/scripts/vscripts/ui/menu_dev.nut b/bobthebob.testing/scripts/vscripts/ui/menu_dev.nut
new file mode 100644
index 00000000..d9b9234b
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/ui/menu_dev.nut
@@ -0,0 +1,707 @@
+untyped
+
+global function InitDevMenu
+global function GetActionBlocks
+global function SetDevMenu_SinglePlayer
+global function SetupDevCommand // for dev
+global function SetupDevFunc // for dev
+global function SetDevMenu_SpawnNPCWithWeapon
+global function RepeatLastDevCommand
+global function SetDevMenu_ArmedNPC
+global function UpdatePrecachedSPWeapons
+
+struct DevCommand
+{
+ string label
+ string command
+ var opParm
+ void functionref( var ) func
+ bool storeAsLastCommand = true
+}
+
+
+struct
+{
+ void functionref() devMenuFunc
+ void functionref( var ) devMenuFuncWithOpParm
+ var devMenuOpParm
+ array<var> buttons
+ array actionBlocks
+ array<DevCommand> devCommands
+ DevCommand& lastDevCommand
+ bool lastDevCommandAssigned
+ bool precachedWeapons
+} file
+
+void function OnOpenDevMenu()
+{
+ file.devMenuFunc = null
+ file.devMenuFuncWithOpParm = null
+ file.devMenuOpParm = null
+ if ( IsMultiplayer() )
+ SetDevMenu_MP()
+ else
+ SetDevMenu_Default()
+}
+
+void function InitDevMenu()
+{
+ var menu = GetMenu( "DevMenu" )
+
+ AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenDevMenu )
+
+
+ AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
+ AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
+
+ OnOpenDevMenu()
+
+ file.buttons = GetElementsByClassname( menu, "DevButtonClass" )
+ foreach ( button in file.buttons )
+ {
+ Hud_AddEventHandler( button, UIE_CLICK, OnDevButton_Activate )
+
+ RuiSetString( Hud_GetRui( button ), "buttonText", "" )
+ Hud_SetEnabled( button, false )
+ }
+
+}
+
+function UpdateDevMenuButtons()
+{
+ file.devCommands.clear()
+ if ( developer() == 0 )
+ return
+
+ if ( file.devMenuOpParm != null )
+ file.devMenuFuncWithOpParm( file.devMenuOpParm )
+ else
+ file.devMenuFunc()
+
+ foreach ( index, button in file.buttons )
+ {
+ int buttonID = int( Hud_GetScriptID( button ) )
+
+ if ( buttonID < file.devCommands.len() )
+ {
+ RuiSetString( Hud_GetRui( button ), "buttonText", file.devCommands[buttonID].label )
+ Hud_SetEnabled( button, true )
+ }
+ else
+ {
+ RuiSetString( Hud_GetRui( button ), "buttonText", "" )
+ Hud_SetEnabled( button, false )
+ }
+ }
+}
+
+void function SetDevMenu_Default()
+{
+ file.devMenuFunc = SetupDefaultDevCommands
+ UpdateDevMenuButtons()
+}
+
+
+void function SetDevMenu_MP()
+{
+ file.devMenuFunc = SetupDefaultDevCommandsMP
+ UpdateDevMenuButtons()
+}
+
+void function ChangeToThisMenu( void functionref() menuFunc )
+{
+ file.devMenuFunc = menuFunc
+ file.devMenuFuncWithOpParm = null
+ file.devMenuOpParm = null
+ UpdateDevMenuButtons()
+}
+
+void function ChangeToThisMenu_WithOpParm( void functionref( var ) menuFuncWithOpParm, opParm = null )
+{
+ file.devMenuFunc = null
+ file.devMenuFuncWithOpParm = menuFuncWithOpParm
+ file.devMenuOpParm = opParm
+ UpdateDevMenuButtons()
+}
+
+void function SetDevMenu_SinglePlayer( var _ )
+{
+ CloseAllInGameMenus()
+ AdvanceMenu( GetMenu( "SinglePlayerDevMenu" ), true )
+}
+
+void function SetupDefaultDevCommands()
+{
+ SetupDevFunc( "Frontier Defense", SetDevMenu_FrontierDefense )
+ // SetupDevFunc( "Difficulty", SetDevMenu_Difficulty )
+ SetupDevFunc( "Single Player", SetDevMenu_SinglePlayer )
+ if ( GetStartPointsForMap( GetActiveLevel() ).len() )
+ {
+ SetupDevFunc( "Start Points", SetDevMenu_StartPoints )
+ }
+ SetupDevFunc( "Level Commands", SetDevMenu_LevelCommands )
+
+ SetupRepeatLastDevCommand()
+ SetupDevFunc( "Spawn IMC NPC", SetDevMenu_AISpawn, 2 )
+ SetupDevFunc( "Spawn IMC Boss Titan", SetDevMenu_BossTitans )
+ SetupDevFunc( "Spawn Militia NPC", SetDevMenu_AISpawn, 3 )
+ SetupDevFunc( "Spawn Team 4 NPC", SetDevMenu_AISpawn, 4 )
+
+ if ( IsSingleplayer() )
+ {
+ SetupDevCommand( "Spawn BT", "script thread DEV_SpawnBTAtCrosshair( false )" )
+ SetupDevCommand( "Hotdrop BT", "script thread DEV_SpawnBTAtCrosshair( true )" )
+ }
+
+ SetupDevFunc( "Spawn Titan Weapon", SetDevMenu_TitanWeapons )
+ SetupDevFunc( "Spawn Pilot Weapons", SetDevMenu_PilotWeapons )
+ SetupDevFunc( "Spawn Pilot Offhands", SetDevMenu_PilotOffhands )
+
+ SetupDevFunc( "AI Commands", SetDevMenu_AICommands )
+ SetupDevCommand( "Toggle Model Viewer", "script thread ToggleModelViewer()" )
+ SetupDevCommand( "AI Titan Duel", "script DEV_AITitanDuel()" )
+ SetupDevCommand( "Free Titans for everybody", "script GiveAllTitans()" )
+
+ if ( IsSingleplayer() )
+ {
+ SetupDevCommand( "Checkpoint", "script CheckPoint_Forced()" )
+ SetupDevCommand( "Test Next Checkpoint Spawnpoint", "script TestDevSpawnPoint()" )
+ }
+
+ SetupDevCommand( "Disable NPCs", "script disable_npcs()" )
+ // SetupDevCommand( "Disable New NPCs", "script disable_new_npcs()" )
+
+ if ( IsMultiplayer() )
+ {
+ SetupDevCommand( "Swap the teams", "script teamswap()" )
+ SetupDevCommand( "Force time limit", "script ForceTimeLimitDone()" )
+ SetupDevCommand( "Force My Team Win", "script_client GetLocalClientPlayer().ClientCommand(\"ForceMyTeamWin\")" )
+ SetupDevCommand( "Force My Team Lose", "script_client GetLocalClientPlayer().ClientCommand(\"ForceMyTeamLose\")" )
+ SetupDevCommand( "Force Match End", "script ForceMatchEnd()" )
+ SetupDevCommand( "Force Draw", "script ForceDraw()" )
+ }
+
+ SetupDevCommand( "Toggle Friendly Highlights", "script DEV_ToggleFriendlyHighlight()" )
+ SetupDevCommand( "Export precache script", "script_ui Dev_CommandLineAddParm( \"-autoprecache\", \"\" ); script_ui Dev_CommandLineRemoveParm( \"" + STARTPOINT_DEV_STRING + "\" ); reload" )
+ // SetupDevCommand( "Toggle Blood Spray Decals", "script_client BloodSprayDecals_Toggle()" )
+
+ //SetupDevCommand( "PlaySpyglassVDU", "script ForcePlayConversationToAll(\"SpyglassVDU\")" )
+ //SetupDevCommand( "PlayGravesVDU", "script ForcePlayConversationToAll(\"GravesVDU\")" )
+ //SetupDevCommand( "PlayBliskVDU", "script ForcePlayConversationToAll(\"BliskVDU\")" )
+ //SetupDevCommand( "PlaySarahVDU", "script ForcePlayConversationToAll(\"SarahVDU\")" )
+ //SetupDevCommand( "PlayMacVDU", "script ForcePlayConversationToAll(\"MacVDU\")" )
+ //SetupDevCommand( "PlayBishVDU", "script ForcePlayConversationToAll(\"BishVDU\")" )
+ //SetupDevCommand( "PlayMCORGruntBattleRifleVDU", "script ForcePlayConversationToAll(\"MCORGruntBattleRifleVDU\")" )
+ //SetupDevCommand( "PlayMCORGruntAntiTitanVDU", "script ForcePlayConversationToAll(\"MCORGruntAntiTitanVDU\")" )
+ //SetupDevCommand( "PlayIMCSoldierBattleRifleVDU", "script ForcePlayConversationToAll(\"IMCSoldierBattleRifleVDU\")" )
+ SetupDevCommand( "Doom my titan", "script_client GetLocalViewPlayer().ClientCommand( \"DoomTitan\" )" )
+ SetupDevCommand( "DoF debug (ads)", "script_client ToggleDofDebug()" )
+
+ SetupDevCommand( "ToggleTitanCallInEffects", "script FlagToggle( \"EnableIncomingTitanDropEffects\" )" )
+ //SetupDevCommand( "TrailerTitanDrop", "script_client GetLocalViewPlayer().ClientCommand( \"TrailerTitanDrop\" )" )
+ //SetupDevCommand( "AI Chatter: aichat_callout_pilot_dev", "script playconvtest(\"aichat_callout_pilot_dev\")" )
+ SetupDevCommand( "Spawn IMC grunt", "SpawnViewGrunt " + TEAM_IMC )
+ SetupDevCommand( "Spawn Militia grunt", "SpawnViewGrunt " + TEAM_MILITIA )
+ SetupDevCommand( "Enable titan-always-executes-titan", "script FlagSet( \"ForceSyncedMelee\" )" )
+ //SetupDevCommand( "Display Embark times", "script DebugEmbarkTimes()" )
+ SetupDevCommand( "Kill All Titans", "script killtitans()" )
+ SetupDevCommand( "Kill All Minions", "script killminions()" )
+ if ( IsSingleplayer() )
+ SetupDevCommand( "Kill All Enemies", "script KillAllBadguys()" )
+
+ SetupDevCommand( "Export leveled_weapons.def / r2_weapons.fgd", "script thread LeveledWeaponDump()" )
+
+
+ if ( IsMultiplayer() )
+ {
+ SetupDevCommand( "Summon Players to player 0", "script summonplayers()" )
+ SetupDevCommand( "Display Titanfall spots", "script thread ShowAllTitanFallSpots()" )
+ SetupDevCommand( "Toggle check inside Titanfall Blocker", "script thread DevCheckInTitanfallBlocker()" )
+ SetupDevCommand( "Simulate Game Scoring", "script thread SimulateGameScore()" )
+ SetupDevCommand( "Test Dropship Intro Spawns with Bots", "script thread DebugTestDropshipStartSpawnsForAll()" )
+ SetupDevCommand( "Preview Dropship Spawn at this location", "script SetCustomPlayerDropshipSpawn()" )
+ SetupDevCommand( "Test Dropship Spawn at this location", "script thread DebugTestCustomDropshipSpawn()" )
+ SetupDevCommand( "Max Activity (Pilots)", "script SetMaxActivityMode(1)" )
+ SetupDevCommand( "Max Activity (Titans)", "script SetMaxActivityMode(2)" )
+ SetupDevCommand( "Max Activity (Conger Mode)", "script SetMaxActivityMode(4)" )
+ SetupDevCommand( "Max Activity (Disabled)", "script SetMaxActivityMode(0)" )
+ }
+ else
+ {
+ SetupDevCommand( "Reset Collectibles Progress (level)", "script Dev_ResetCollectiblesProgress_Level()" )
+ SetupDevCommand( "Reset Collectibles Progress (all)", "script ResetCollectiblesProgress_All()" )
+
+ SetupDevCommand( "BT Loadouts - Reset", "script SetBTLoadoutsUnlockedBitfield( 1 )" )
+ SetupDevCommand( "BT Loadouts - Unlock All", "script SetBTLoadoutsUnlockedBitfield( 65535 )" )
+ SetupDevCommand( "BT Loadouts - Spawn Unlock Pickup", "script SPTitanLoadout_SpawnAtCrosshairDEV( -1 )" )
+ }
+
+ SetupDevCommand( "Toggle Skybox View", "script thread ToggleSkyboxView()" )
+ //SetupDevCommand( "Toggle Bubble Shield", "ToggleBubbleShield" )
+ //SetupDevCommand( "Toggle Grenade Indicators", "script_client ToggleGrenadeIndicators()" )
+ SetupDevCommand( "Toggle HUD", "ToggleHUD" )
+ SetupDevCommand( "Toggle Offhand Low Recharge", "ToggleOffhandLowRecharge" )
+ SetupDevCommand( "Map Metrics Toggle", "script_client GetLocalClientPlayer().ClientCommand( \"toggle map_metrics 0 1 2 3\" )" )
+ SetupDevCommand( "Toggle Pain Death sound debug", "script TogglePainDeathDebug()" )
+ SetupDevCommand( "Jump Randomly Forever", "script_client thread JumpRandomlyForever()" )
+}
+
+
+void function SetupDefaultDevCommandsMP()
+{
+ SetupRepeatLastDevCommand()
+
+ SetupDevFunc( "Frontier Defense", SetDevMenu_FrontierDefense )
+
+ SetupDevFunc( "Spawn IMC NPC", SetDevMenu_AISpawn, 2 )
+ SetupDevFunc( "Spawn IMC Boss Titan", SetDevMenu_BossTitans )
+ SetupDevFunc( "Spawn Militia NPC", SetDevMenu_AISpawn, 3 )
+ SetupDevFunc( "Spawn Team 4 NPC", SetDevMenu_AISpawn, 4 )
+
+ SetupDevFunc( "Spawn Titan Weapon", SetDevMenu_TitanWeapons )
+ SetupDevFunc( "Spawn Pilot Weapons", SetDevMenu_PilotWeapons )
+ SetupDevFunc( "Spawn Pilot Offhands", SetDevMenu_PilotOffhands )
+
+ SetupDevFunc( "AI Commands", SetDevMenu_AICommands )
+ SetupDevCommand( "Toggle Model Viewer", "script thread ToggleModelViewer()" )
+ SetupDevCommand( "AI Titan Duel", "script DEV_AITitanDuel()" )
+ SetupDevCommand( "Free Titans for everybody", "script GiveAllTitans()" )
+
+ SetupDevCommand( "Disable NPCs", "script disable_npcs()" )
+ // SetupDevCommand( "Disable New NPCs", "script disable_new_npcs()" )
+
+ SetupDevCommand( "Swap the teams", "script teamswap()" )
+ SetupDevCommand( "Force time limit", "script ForceTimeLimitDone()" )
+ SetupDevCommand( "Force My Team Win", "script_client GetLocalClientPlayer().ClientCommand(\"ForceMyTeamWin\")" )
+ SetupDevCommand( "Force My Team Lose", "script_client GetLocalClientPlayer().ClientCommand(\"ForceMyTeamLose\")" )
+ SetupDevCommand( "Force Match End", "script ForceMatchEnd()" )
+ SetupDevCommand( "Force Draw", "script ForceDraw()" )
+
+ SetupDevCommand( "Toggle Friendly Highlights", "script DEV_ToggleFriendlyHighlight()" )
+ SetupDevCommand( "Export precache script", "script_ui Dev_CommandLineAddParm( \"-autoprecache\", \"\" ); script_ui Dev_CommandLineRemoveParm( \"" + STARTPOINT_DEV_STRING + "\" ); reload" )
+
+ SetupDevCommand( "Doom my titan", "script_client GetLocalViewPlayer().ClientCommand( \"DoomTitan\" )" )
+ SetupDevCommand( "DoF debug (ads)", "script_client ToggleDofDebug()" )
+
+ SetupDevCommand( "ToggleTitanCallInEffects", "script FlagToggle( \"EnableIncomingTitanDropEffects\" )" )
+
+ SetupDevCommand( "Spawn IMC grunt", "SpawnViewGrunt " + TEAM_IMC )
+ SetupDevCommand( "Spawn Militia grunt", "SpawnViewGrunt " + TEAM_MILITIA )
+
+ SetupDevCommand( "Enable titan-always-executes-titan", "script FlagSet( \"ForceSyncedMelee\" )" )
+
+ SetupDevCommand( "Kill All Titans", "script killtitans()" )
+ SetupDevCommand( "Kill All Minions", "script killminions()" )
+
+ SetupDevCommand( "Export leveled_weapons.def / r2_weapons.fgd", "script thread LeveledWeaponDump()" )
+
+ SetupDevCommand( "Summon Players to player 0", "script summonplayers()" )
+ SetupDevCommand( "Display Titanfall spots", "script thread ShowAllTitanFallSpots()" )
+ SetupDevCommand( "Toggle check inside Titanfall Blocker", "script thread DevCheckInTitanfallBlocker()" )
+ SetupDevCommand( "Simulate Game Scoring", "script thread SimulateGameScore()" )
+ SetupDevCommand( "Test Dropship Intro Spawns with Bots", "script thread DebugTestDropshipStartSpawnsForAll()" )
+ SetupDevCommand( "Preview Dropship Spawn at this location", "script SetCustomPlayerDropshipSpawn()" )
+ SetupDevCommand( "Test Dropship Spawn at this location", "script thread DebugTestCustomDropshipSpawn()" )
+ SetupDevCommand( "Max Activity (Pilots)", "script SetMaxActivityMode(1)" )
+ SetupDevCommand( "Max Activity (Titans)", "script SetMaxActivityMode(2)" )
+ SetupDevCommand( "Max Activity (Conger Mode)", "script SetMaxActivityMode(4)" )
+ SetupDevCommand( "Max Activity (Disabled)", "script SetMaxActivityMode(0)" )
+
+ SetupDevCommand( "Toggle Skybox View", "script thread ToggleSkyboxView()" )
+ SetupDevCommand( "Toggle HUD", "ToggleHUD" )
+ SetupDevCommand( "Toggle Offhand Low Recharge", "ToggleOffhandLowRecharge" )
+ SetupDevCommand( "Map Metrics Toggle", "script_client GetLocalClientPlayer().ClientCommand( \"toggle map_metrics 0 1 2 3\" )" )
+ SetupDevCommand( "Toggle Pain Death sound debug", "script TogglePainDeathDebug()" )
+ SetupDevCommand( "Jump Randomly Forever", "script_client thread JumpRandomlyForever()" )
+}
+
+
+void function SetupRepeatLastDevCommand()
+{
+ DevCommand cmd
+ cmd.label = "Repeat Last Dev Command"
+ cmd.func = RepeatLastDevCommand
+ cmd.storeAsLastCommand = false
+
+ file.devCommands.append( cmd )
+}
+
+void function SetDevMenu_LevelCommands( var _ )
+{
+ ChangeToThisMenu( SetupLevelDevCommands )
+}
+
+void function SetupLevelDevCommands()
+{
+ string activeLevel = GetActiveLevel()
+ if ( activeLevel == "" )
+ return
+
+ switch ( activeLevel )
+ {
+ case "mp_titan_rodeo":
+ SetupDevCommand( "Atlas titans", "script thread TitanTypes( \"titan_atlas_stickybomb\")" )
+ SetupDevCommand( "Ogre titans", "script thread TitanTypes( \"titan_ogre_meteor\")" )
+ SetupDevCommand( "Stryder titans", "script thread TitanTypes( \"titan_stryder_leadwall\")" )
+ break
+
+ case "model_viewer":
+ SetupDevCommand( "Toggle Rebreather Masks", "script ToggleRebreatherMasks()" )
+ break
+
+ case "sp_grunt_arena":
+ SetupDevCommand( "Toggle health pickups", "script ToggleHealthRegen(); reload" )
+ break
+ }
+}
+
+void function SetDevMenu_SpawnNPCWithWeapon( var parms )
+{
+ ChangeToThisMenu_WithOpParm( SetupMenu_SpawnNPCWithWeapons, parms )
+}
+
+
+void function SetDevMenu_StartPoints( var _ )
+{
+ string currentMap = GetActiveLevel()
+ array<StartPointCSV> foundStartPoints = GetStartPointsForMap( currentMap )
+// foreach ( index, startPointEnum in foundStartPoints )
+// {
+// table parms = { currentMap = currentMap, startPointEnum = startPointEnum }
+// SetupDevCommand( "#" + startPointEnum, SetDevMenu_SelectStartPointDifficulty, parms )
+// //SetupDevCommand( "#" + startPointEnum, "script PickStartPoint( \"" + currentMap + "\", \"" + startPointEnum + "\" )" )
+// }
+
+ CloseAllInGameMenus()
+ AdvanceMenu( GetMenu( "SinglePlayerDevMenu" ), true )
+ DisplayStartPointButtons( currentMap, foundStartPoints )
+}
+
+
+void function SetDevMenu_ActionBlocks()
+{
+ ChangeToThisMenu( SetupActionBlocks )
+}
+
+function DefineActionBlocks()
+{
+ file.actionBlocks = []
+
+ /* [Menu name] [action block name] [owner] [description] [load commands] */
+ AddActionBlock( "Week 1", "Timed Switch Panel Run", "Sean", "Test your wallrunning abilities by jumping on timed platforms", "playlist Load a map on the command line; map sp_platform_test01" )
+ AddActionBlock( "Week 1", "Energon Room", "Mackey", "Combat test arena. Collect all Energon Spheres to win", "playlist Load a map on the command line; map sp_abmac1" )
+ AddActionBlock( "Week 1", "Titan Buddy + Turret Columns", "Carlos", null, "playlist Load a map on the command line; map carlos_test" )
+ AddActionBlock( "Week 1", "Titan Maze", "Soupy", null, "playlist Load a map on the command line; map sp_act-block_maze" )
+ AddActionBlock( "Week 1", "Catch me if you Can", "Chin", "Catch up to a moving pilot and kill him to win", "launchplaylist catchmeifyoucan" )
+ AddActionBlock( "Week 1", "Jumping Puzzles", "ChadG", "Various pilot jumping puzzles with moving platforms", "playlist Load a map on the command line; mp_gamemode at; map mp_chad" )
+ AddActionBlock( "Week 1", "FLANKER BOOST loadout basics", "Brent", "Non-wallrunning pilot jumping basics", "playlist Load a map on the command line; mp_gamemode at; map mp_ab_test" )
+ AddActionBlock( "Week 1", "Flee Titan Attack by wallrunning", "Roger", null, "playlist Load a map on the command line; map sp_ab_flee" )
+ AddActionBlock( "Week 1", "Protect Grunt squad from Mortar fire", "Roger", null, "playlist Load a map on the command line; map sp_ab_vortex" )
+ AddActionBlock( "Week 1", "Catch me if you Can Part 2", "Soupy", null, "playlist catchmeifyoucan;mp_gamemode ps; map mp_catchme" )
+ AddActionBlock( "Week 2", "Environment Puzzles", "ChadG", "Get your titan to the exit by solving some puzzles", "playlist Load a map on the command line; mp_gamemode at; map mp_chad2" )
+// AddActionBlock( "Week 2", "Fun House - survive to the end", "Mo", null, "playlist Load a map on the command line; map mp_ab_funhouse" )
+ AddActionBlock( "Week 2", "Assassin Arena - boss fight with the Assassin", "Mo", null, "playlist Load a map on the command line; map sp_ab_assassin" )
+ AddActionBlock( "Week 2", "Creature Ship", "LumberJake", "Explore a crashed ship with mysterious cargo", "playlist Load a map on the command line; mp_gamemode at; map mp_actionblockjake01" )
+ AddActionBlock( "Week 2", "Titan/Pilot Puzzles", "RyanR", "Get your titan to the green room", "playlist Load a map on the command line; mp_gamemode at; map mp_ryanr_actionblock_01" )
+ AddActionBlock( "Week 2", "Titan/Pilot Core Combat", "Carlos", null, "playlist Load a map on the command line; map sp_ammo_pickup" )
+ AddActionBlock( "Week 2", "Titan Overwatch", "Roger", "Your sniping titan will cover you as you advance to the bunker", "playlist Load a map on the command line; map sp_ab_titanbuddy" )
+ AddActionBlock( "Week 2", "Rodeo Express", "Chin", "Use your titan to get you through a pilot hazard area", "playlist lava; mp_gamemode at; map mp_chin_rodeo_express" )
+ AddActionBlock( "Week 2", "Wallrun Gauntlet", "McCord", "Wallrun through the geo and don't fall to your death", "playlist Load a map on the command line; map sp_zipline_action_block01" )
+ AddActionBlock( "Week 2", "Titan Mortar Targeting Test", "Soupy", null, "playlist Load a map on the command line; map sp_mortar_targeting_test" )
+ AddActionBlock( "Week 2", "Tremors", "David", null, "playlist Load a map on the command line; map sp_tremors" )
+ AddActionBlock( "Week 2", "Titan Combat Blok", "Mackey", "Combat arena. Kill all enemies.", "playlist Load a map on the command line; map sp_abmac3" )
+ AddActionBlock( "Week 2", "Smart Targeted Switch Panels", "Sean", "Wallrun from wall to wall while activating switches", "playlist Load a map on the command line; map sp_platform_test02" )
+ AddActionBlock( "Week 3", "Combat Canyon", "Mo", "Kill enemies in the canyon and extract", "playlist Load a map on the command line; map sp_ab_ski" )
+ AddActionBlock( "Week 3", "Titan v Titan", "Roger", "Test Titan vs Titan combat against various titan AI", "playlist Load a map on the command line; map sp_ab_tvt" )
+ AddActionBlock( "Week 3", "Train Raid", "ChadG", "Board a speeding train and hack the explosives on board", "playlist Load a map on the command line; map sp_ab_trainride01" )
+ AddActionBlock( "Week 3", "Super Spectre Bros", "David", "Survive 6 waves against super spectres", "playlist Load a map on the command line; map mp_ab_super_spectre_bros" )
+ AddActionBlock( "Week 4", "Nightshot", "David", "Help your titan buddy hunt in the dark.", "playlist Load a map on the command line; map sp_ab_nightshot" )
+ //AddActionBlock( "Week 4", "Space Battle", "Mo", "Pilot a ship in space. \n -Play with Always run OFF. \n -Use low sensitivity. \n -Use bug_reproNum 1 to invert flight controls.\n -Use bug_reproNum 2 for PRO flight controls. (free look) \n -Use bug_reproNum 3 for inverted PRO flight controls.", "playlist Load a map on the command line; map sp_ab_week4" )
+ AddActionBlock( "Week 4", "Buddy Fight", "Mackey", "Arena fight with buddy Titan", "playlist Load a map on the command line; map sp_buddy_fight" )
+ AddActionBlock( "Week 4", "Fastball Special", "Slayback/McCord", "Use a new Titan ability to hurl yourself to new heights.", "playlist Load a map on the command line; map sp_fastball" )
+ AddActionBlock( "Week 4", "Time Travel Mechanic", "LumberJake", "Travel back and forth through time to complete your mission.", "playlist Load a map on the command line; map sp_actionblockjake02" )
+ AddActionBlock( "Week 5", "Titan Ability: Death Blossom", "Mo", "Use Up on D-Pad to use Death Blossom\n\nUse your new ability to defeat the enemies", "playlist Load a map on the command line; bug_reproNum 0; map sp_ab_blossom" )
+ AddActionBlock( "Week 5", "Titan Ability: Arc Blast", "Mo", "Use Down on D-Pad to use Arc Blast\n\nUse your new ability to defeat the enemies", "playlist Load a map on the command line; bug_reproNum 1; map sp_ab_blossom" )
+ AddActionBlock( "Week 5", "Titan Abilities: Death Blossom + Arc Blast", "Mo", "D-Pad Up = Death Blossom\nD-Pad Down = Arc Blast\n\nUse your new abilities to defeat the enemies", "playlist Load a map on the command line; bug_reproNum 2; map sp_ab_blossom" )
+ AddActionBlock( "Week 5", "Time Stasis Gun", "LumberJake", "Titan freezes enemies allowing the Pilot \nto do a one-shot kill", "playlist Load a map on the command line; map sp_actionblockjake03" )
+ AddActionBlock( "Week 5", "Fastball Mortar Battle", "McCord/Slayback", "Freeform Buddy Titan arena battle. \n - Fastball Special \n - Mortar Crews \n - Buddy Hibernation \n - Harvester Defense", "playlist Load a map on the command line; map sp_ab_mortar_battle01" )
+ AddActionBlock( "Week 5", "Zipline Gun", "ChadG", "Create permanent ziplines in the map", "playlist Load a map on the command line; mp_gamemode tdm; bug_reproNum 1234; map mp_angel_city" )
+ AddActionBlock( "Week 6", "Titan Hulk", "David", "Buddy Titan hulks out and throws things.", "playlist Load a map on the command line; map sp_ab_titan_thrower" )
+ AddActionBlock( "Week 6", "Player & Titan vs Enemy Titan", "Roger", "Bare bones Pilot & Auto Titan vs Enemy Titan", "playlist Load a map on the command line; map sp_ab_ptvt" )
+ AddActionBlock( "Week 6", "Pilot Stasis Gun", "Soupy", "Pilot has a Stasis gun to help a friendly Titan out", "playlist Load a map on the command line; map sp_ab_synergy" )
+ AddActionBlock( "Week 6", "Acid Rain", "LumberJake", "- Destroy 3 harvesters in a poison rain storm\n- Avoid poison rain by staying in your Titan or indoors\n- Collect powerups to get rain immunity", "map sp_actionblockjake04" )
+ AddActionBlock( "Week 6", "Freeform Hallway Fight", "McCord/Slayback", "Move through the tight hallways with your Titan Buddy.", "playlist Load a map on the command line; map sp_ab_hallway_fight01" )
+ AddActionBlock( "Week 6", "Stealth Town", "Carlos", "Stealth through a group of enemy titans", "playlist Load a map on the command line; map sp_titan_stealth" )
+ AddActionBlock( "Week 6", "Titan Attack Command", "Mo", "Command your buddy titan to attack a position.", "playlist Load a map on the command line; map sp_ab_break" )
+ AddActionBlock( "Week 7", "SP Shell", "Chad/McCord", "", "playlist Load a map on the command line; map sp_shell1" )
+ AddActionBlock( "Week 7", "Smart Pistol Progression", "Soupy", "Try different smart pistol mods in different combat situations", "playlist Load a map on the command line; map sp_ab_smart_pistol_ramp" )
+}
+
+
+function AddActionBlock( subMenu, actionBlockName, owner, description, command )
+{
+ local subMenuIndex = null
+ foreach( i, Table in file.actionBlocks )
+ {
+ if ( Table.name == subMenu )
+ subMenuIndex = i
+ }
+ if ( subMenuIndex == null )
+ {
+ file.actionBlocks.append( { name = subMenu, actionBlocks = [] } )
+ subMenuIndex = file.actionBlocks.len() - 1
+ }
+
+ local Table = {}
+ Table.name <- actionBlockName
+ Table.owner <- owner
+ Table.description <- description
+ Table.command <- command
+
+ file.actionBlocks[ subMenuIndex ].actionBlocks.append( Table )
+}
+
+function GetActionBlocks()
+{
+ DefineActionBlocks()
+ return file.actionBlocks
+}
+
+void function SetupActionBlocks()
+{
+ DefineActionBlocks()
+
+ // For the in-game dev menu we only add the current week of action blocks
+ foreach ( week, actionBlock in file.actionBlocks )
+ {
+ SetupDevFunc( "Week " + ( week + 1 ), SetDevMenu_Week, week )
+ }
+}
+
+void function SetDevMenu_Week( var week )
+{
+ ChangeToThisMenu_WithOpParm( SetupActionBlocksByWeek, week )
+}
+
+void function SetupActionBlocksByWeek( var week )
+{
+ foreach ( actionBlock in file.actionBlocks[ week ].actionBlocks )
+ {
+ SetupDevCommand( actionBlock.name + " - " + actionBlock.owner, expect string( actionBlock.command ) )
+ }
+}
+
+void function SetDevMenu_AICommands( var _ )
+{
+ ChangeToThisMenu( SetupAIDevCommands )
+}
+
+void function SetDevMenu_AISpawn( var enemy )
+{
+#if DEV
+ InitNpcSettingsFileNamesForDevMenu()
+ ChangeToThisMenu_WithOpParm( SetupSpawnAIButtons, enemy )
+#endif
+}
+
+void function SetDevMenu_BossTitans( var _ )
+{
+#if DEV
+ InitNpcSettingsFileNamesForDevMenu()
+ ChangeToThisMenu( SetupSpawnBossTitans )
+#endif
+}
+
+void function SetDevMenu_FrontierDefense( var _ )
+{
+ #if DEV
+ thread ChangeToThisMenu( SetupFrontierDefense )
+ #endif
+}
+
+void function SetDevMenu_TitanWeapons( var _ )
+{
+#if DEV
+ thread ChangeToThisMenu_PrecacheWeapons( SetupTitanWeapon )
+#endif
+}
+
+void function SetDevMenu_ArmedNPC( var data )
+{
+#if DEV
+ thread ChangeToThisMenu_PrecacheWeapons_WithOpParm( SetupSpawnArmedNPC, data )
+#endif
+}
+
+void function SetDevMenu_PilotWeapons( var _ )
+{
+#if DEV
+ thread ChangeToThisMenu_PrecacheWeapons_WithOpParm( SetupPilotWeaponsFromFields, "not_set" )
+#endif
+}
+
+void function SetDevMenu_PilotOffhands( var _ )
+{
+#if DEV
+ thread ChangeToThisMenu_PrecacheWeapons_WithOpParm( SetupPilotWeaponsFromFields, "offhand" )
+#endif
+}
+
+void function ChangeToThisMenu_PrecacheWeapons( void functionref() menuFunc )
+{
+ waitthread PrecacheWeaponsIfNecessary()
+
+ file.devMenuFunc = menuFunc
+ file.devMenuFuncWithOpParm = null
+ file.devMenuOpParm = null
+ UpdateDevMenuButtons()
+}
+
+void function ChangeToThisMenu_PrecacheWeapons_WithOpParm( void functionref( var ) menuFuncWithOpParm, opParm = null )
+{
+ waitthread PrecacheWeaponsIfNecessary()
+
+ file.devMenuFunc = null
+ file.devMenuFuncWithOpParm = menuFuncWithOpParm
+ file.devMenuOpParm = opParm
+ UpdateDevMenuButtons()
+}
+
+void function PrecacheWeaponsIfNecessary()
+{
+ if ( file.precachedWeapons )
+ return
+
+ file.precachedWeapons = true
+ CloseAllInGameMenus()
+
+ DisablePrecacheErrors()
+ wait 0.1
+ ClientCommand( "script PrecacheSPWeapons()" )
+ wait 0.1
+ ClientCommand( "script_client PrecacheSPWeapons()" )
+ wait 0.1
+ RestorePrecacheErrors()
+
+ AdvanceMenu( GetMenu( "DevMenu" ) )
+}
+
+void function UpdatePrecachedSPWeapons()
+{
+ file.precachedWeapons = IsMultiplayer()
+}
+
+void function SetupMenu_SpawnNPCWithWeapons( parms )
+{
+ string weaponCapacity = expect string( parms.weaponCapacity )
+ string baseClass = expect string( parms.baseClass )
+ string aiSettings = expect string( parms.aiSettings )
+ int team = expect int( parms.team )
+
+ array<int> itemTypes
+ switch ( weaponCapacity )
+ {
+ case "PilotMainWeapons":
+ itemTypes = [ eItemTypes.PILOT_PRIMARY, eItemTypes.PILOT_SECONDARY ]
+ break
+
+ case "TitanMainWeapons":
+ itemTypes = [ eItemTypes.TITAN_PRIMARY ]
+ break
+
+ default:
+ Assert( 0, "Unknown weapon capacity " + weaponCapacity )
+ break
+ }
+
+ array<string> itemNames
+ foreach ( itemType in itemTypes )
+ {
+ array<string> items = GetAllItemRefsOfType( itemType )
+ foreach ( item in items )
+ {
+ itemNames.append( item )
+ }
+ }
+
+ foreach ( ref in itemNames )
+ {
+ string weaponName = expect string( GetWeaponInfoFileKeyField_GlobalNotNull( ref, "printname" ) )
+
+ string cmd = "thread DEV_SpawnNPCWithWeaponAtCrosshair( \"" + baseClass + "\", \"" + aiSettings + "\", " + team + ", \"" + ref + "\" )"
+ SetupDevCommand( weaponName, "script " + cmd )
+ }
+}
+
+void function SetupAIDevCommands()
+{
+}
+
+void function SetDevMenu_titanSelection( var _ )
+{
+ ChangeToThisMenu( SetupTitanSelection )
+}
+
+void function SetupTitanSelection()
+{
+}
+
+void function SetupDevCommand( string label, string command )
+{
+ DevCommand cmd
+ cmd.label = label
+ cmd.command = command
+
+ file.devCommands.append( cmd )
+}
+
+void function SetupDevFunc( string label, void functionref( var ) func, var opParm = null )
+{
+ DevCommand cmd
+ cmd.label = label
+ cmd.func = func
+ cmd.opParm = opParm
+
+ file.devCommands.append( cmd )
+}
+
+function OnDevButton_Activate( button )
+{
+ //if ( level.ui.disableDev )
+ //{
+ // CodeWarning( "Dev commands disabled on matchmaking servers." )
+ // return
+ //}
+
+ int buttonID = int( Hud_GetScriptID( button ) )
+ DevCommand cmd = file.devCommands[buttonID]
+
+ RunDevCommand( cmd )
+}
+
+void function RunDevCommand( DevCommand cmd )
+{
+ if ( cmd.storeAsLastCommand )
+ {
+ file.lastDevCommand = cmd
+ file.lastDevCommandAssigned = true
+ }
+
+ if ( cmd.command != "" )
+ {
+ ClientCommand( cmd.command )
+ CloseAllInGameMenus()
+ }
+ else
+ {
+ cmd.func( cmd.opParm )
+ }
+}
+
+void function RepeatLastDevCommand( var _ )
+{
+ if ( !file.lastDevCommandAssigned )
+ return
+
+ RunDevCommand( file.lastDevCommand )
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/ui/menu_map_select.nut b/bobthebob.testing/scripts/vscripts/ui/menu_map_select.nut
new file mode 100644
index 00000000..7263a9fa
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/ui/menu_map_select.nut
@@ -0,0 +1,200 @@
+untyped
+
+
+global function MenuMapSelect_Init
+
+global function InitMapsMenu
+
+const int MAPS_PER_PAGE = 21
+
+const MAP_LIST_VISIBLE_ROWS = 21
+const MAP_LIST_SCROLL_SPEED = 0
+
+struct {
+ var menu = null
+ array<var> buttons
+ int numMapButtonsOffScreen
+ int mapListScrollState = 0
+} file
+
+// note: this does have a scrolling system in vanilla, but it's honestly really weird and jank and i don't like it
+// so for parity with menu_mode_select i'm removing it in favour of a page system
+
+function MenuMapSelect_Init()
+{
+ RegisterSignal( "OnCloseMapsMenu" )
+}
+
+void function InitMapsMenu()
+{
+ file.menu = GetMenu( "MapsMenu" )
+ var menu = file.menu
+
+ AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenMapsMenu )
+ AddMenuEventHandler( menu, eUIEvent.MENU_CLOSE, OnCloseMapsMenu )
+
+ AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_GET_FOCUS, MapButton_Focused )
+ AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_LOSE_FOCUS, MapButton_LostFocus )
+ AddEventHandlerToButtonClass( menu, "MapButtonClass", UIE_CLICK, MapButton_Activate )
+ //AddEventHandlerToButtonClass( menu, "MapListScrollUpClass", UIE_CLICK, OnMapListScrollUp_Activate )
+ //AddEventHandlerToButtonClass( menu, "MapListScrollDownClass", UIE_CLICK, OnMapListScrollDown_Activate )
+
+ AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
+ AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
+
+ file.buttons = GetElementsByClassname( menu, "MapButtonClass" )
+
+ AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack, IsNorthstarServer )
+ AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward, IsNorthstarServer )
+}
+
+void function OnOpenMapsMenu()
+{
+ array<var> buttons = file.buttons
+ array<string> mapsArray = GetPrivateMatchMaps()
+
+ file.numMapButtonsOffScreen = int( max( mapsArray.len() - MAP_LIST_VISIBLE_ROWS, 0 ) )
+// Assert( file.numMapButtonsOffScreen >= 0 )
+
+ foreach ( button in buttons )
+ {
+ int buttonID = int( Hud_GetScriptID( button ) )
+
+ if ( buttonID >= 0 && buttonID < mapsArray.len() )
+ {
+ string name = mapsArray[buttonID]
+ SetButtonRuiText( button, GetMapDisplayName( name ) )
+ Hud_SetEnabled( button, true )
+
+ if ( IsItemInEntitlementUnlock( name ) && IsValid( GetUIPlayer() ) )
+ {
+ if ( IsItemLocked( GetUIPlayer(), name ) && GetCurrentPlaylistVarInt( name + "_available" , 0 ) == 0 )
+ {
+ SetButtonRuiText( button, Localize( "#MAP_LOCKED", Localize( GetMapDisplayName( name ) ) ) )
+ }
+ }
+
+ bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( name, PrivateMatch_GetSelectedMode() )
+ Hud_SetLocked( button, !mapSupportsMode )
+
+ if ( !mapSupportsMode )
+ SetButtonRuiText( button, Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetMapDisplayName( name ) ) ) )
+ }
+ else
+ {
+ SetButtonRuiText( button, "" )
+ Hud_SetEnabled( button, false )
+ }
+
+ if ( buttonID == level.ui.privatematch_map )
+ {
+ printt( buttonID, mapsArray[buttonID] )
+ Hud_SetFocused( button )
+ }
+ }
+
+ //RegisterButtonPressedCallback( MOUSE_WHEEL_UP, OnMapListScrollUp_Activate )
+ //RegisterButtonPressedCallback( MOUSE_WHEEL_DOWN, OnMapListScrollDown_Activate )
+}
+
+void function OnCloseMapsMenu()
+{
+ //DeregisterButtonPressedCallback( MOUSE_WHEEL_UP, OnMapListScrollUp_Activate )
+ //DeregisterButtonPressedCallback( MOUSE_WHEEL_DOWN, OnMapListScrollDown_Activate )
+
+ Signal( uiGlobal.signalDummy, "OnCloseMapsMenu" )
+}
+
+void function MapButton_Focused( var button )
+{
+ int buttonID = int( Hud_GetScriptID( button ) )
+
+ var menu = file.menu
+ var nextMapImage = Hud_GetChild( menu, "NextMapImage" )
+ var nextMapName = Hud_GetChild( menu, "NextMapName" )
+ var nextMapDesc = Hud_GetChild( menu, "NextMapDesc" )
+
+ array<string> mapsArray = GetPrivateMatchMaps()
+ string mapName = mapsArray[buttonID]
+
+ asset mapImage = GetMapImageForMapName( mapName )
+ RuiSetImage( Hud_GetRui( nextMapImage ), "basicImage", mapImage )
+ Hud_SetText( nextMapName, GetMapDisplayName( mapName ) )
+
+ string modeName = PrivateMatch_GetSelectedMode()
+ bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( mapName, modeName )
+ if ( !mapSupportsMode )
+ Hud_SetText( nextMapDesc, Localize( "#PRIVATE_MATCH_MAP_NO_MODE_SUPPORT", Localize( GetMapDisplayName( mapName ) ), Localize( GetGameModeDisplayName( modeName ) ) ) )
+ else
+ Hud_SetText( nextMapDesc, GetMapDisplayDesc( mapName ) )
+
+ // Update window scrolling if we highlight a map not in view
+ int minScrollState = int( clamp( buttonID - (MAP_LIST_VISIBLE_ROWS - 1), 0, file.numMapButtonsOffScreen ) )
+ int maxScrollState = int( clamp( buttonID, 0, file.numMapButtonsOffScreen ) )
+
+ if ( file.mapListScrollState < minScrollState )
+ file.mapListScrollState = minScrollState
+ if ( file.mapListScrollState > maxScrollState )
+ file.mapListScrollState = maxScrollState
+
+ UpdateMapListScroll()
+}
+
+void function MapButton_LostFocus( var button )
+{
+ HandleLockedCustomMenuItem( file.menu, button, [], true )
+}
+
+void function MapButton_Activate( var button )
+{
+ if ( Hud_IsLocked( button ) )
+ {
+ return
+ }
+
+ if ( !AmIPartyLeader() && GetPartySize() > 1 )
+ return
+
+ array<string> mapsArray = GetPrivateMatchMaps()
+ int mapID = int( Hud_GetScriptID( button ) )
+ string mapName = mapsArray[mapID]
+
+ printt( mapName, mapID )
+
+ ClientCommand( "SetCustomMap " + mapName )
+ CloseActiveMenu()
+}
+
+
+void function OnMapListScrollUp_Activate( var button )
+{
+ file.mapListScrollState--
+ if ( file.mapListScrollState < 0 )
+ file.mapListScrollState = 0
+
+ UpdateMapListScroll()
+}
+
+void function OnMapListScrollDown_Activate( var button )
+{
+ file.mapListScrollState++
+ if ( file.mapListScrollState > file.numMapButtonsOffScreen )
+ file.mapListScrollState = file.numMapButtonsOffScreen
+
+ UpdateMapListScroll()
+}
+
+function UpdateMapListScroll()
+{
+ array<var> buttons = file.buttons
+ local basePos = buttons[0].GetBasePos()
+ local offset = buttons[0].GetHeight() * file.mapListScrollState
+
+ buttons[0].SetPos( basePos[0], basePos[1] - offset )
+}
+
+void function CycleModesBack( var button )
+{}
+
+void function CycleModesForward( var button )
+{}
diff --git a/bobthebob.testing/scripts/vscripts/ui/menu_mode_select.nut b/bobthebob.testing/scripts/vscripts/ui/menu_mode_select.nut
new file mode 100644
index 00000000..4e0ecef5
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/ui/menu_mode_select.nut
@@ -0,0 +1,138 @@
+global function InitModesMenu
+
+struct {
+ int currentModePage
+
+} file
+
+const int MODES_PER_PAGE = 15
+
+void function InitModesMenu()
+{
+ var menu = GetMenu( "ModesMenu" )
+
+ AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenModesMenu )
+
+ AddEventHandlerToButtonClass( menu, "ModeButton", UIE_GET_FOCUS, ModeButton_GetFocus )
+ AddEventHandlerToButtonClass( menu, "ModeButton", UIE_CLICK, ModeButton_Click )
+
+ AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" )
+ AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
+
+ AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack, IsNorthstarServer )
+ AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward, IsNorthstarServer )
+}
+
+void function OnOpenModesMenu()
+{
+ UpdateVisibleModes()
+
+ if ( level.ui.privatematch_mode == 0 ) // set to the first mode if there's no mode focused
+ Hud_SetFocused( GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" )[ 0 ] )
+}
+
+void function UpdateVisibleModes()
+{
+ // ensures that we only ever show enough buttons for the number of modes we have
+ array<var> buttons = GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" )
+ foreach ( var button in buttons )
+ {
+ Hud_SetEnabled( button, false )
+ Hud_SetVisible( button, false )
+ }
+
+ array<string> modesArray = GetPrivateMatchModes()
+ for ( int i = 0; i < MODES_PER_PAGE; i++ )
+ {
+ if ( i + ( file.currentModePage * MODES_PER_PAGE ) >= modesArray.len() )
+ break
+
+ int modeIndex = i + ( file.currentModePage * MODES_PER_PAGE )
+ SetButtonRuiText( buttons[ i ], GetGameModeDisplayName( modesArray[ modeIndex ] ) )
+ Hud_SetEnabled( buttons[ i ], true )
+ Hud_SetVisible( buttons[ i ], true )
+ Hud_SetLocked( buttons[ i ], false )
+
+ if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeIndex ] ) && !IsNorthstarServer() )
+ {
+ Hud_SetLocked( buttons[ i ], true )
+ SetButtonRuiText( buttons[ i ], Localize( "#PRIVATE_MATCH_UNAVAILABLE", Localize( GetGameModeDisplayName( modesArray[ modeIndex ] ) ) ) )
+ }
+ }
+}
+
+void function ModeButton_GetFocus( var button )
+{
+ int modeId = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE )
+
+ var menu = GetMenu( "ModesMenu" )
+ var nextModeImage = Hud_GetChild( menu, "NextModeImage" )
+ var nextModeIcon = Hud_GetChild( menu, "ModeIconImage" )
+ var nextModeName = Hud_GetChild( menu, "NextModeName" )
+ var nextModeDesc = Hud_GetChild( menu, "NextModeDesc" )
+
+ array<string> modesArray = GetPrivateMatchModes()
+
+ if ( modeId > modesArray.len() )
+ return
+
+ string modeName = modesArray[modeId]
+
+ asset playlistImage = GetPlaylistImage( modeName )
+ RuiSetImage( Hud_GetRui( nextModeImage ), "basicImage", playlistImage )
+ RuiSetImage( Hud_GetRui( nextModeIcon ), "basicImage", GetPlaylistThumbnailImage( modeName ) )
+ Hud_SetText( nextModeName, GetGameModeDisplayName( modeName ) )
+
+ string mapName = PrivateMatch_GetSelectedMap()
+ bool mapSupportsMode = PrivateMatch_IsValidMapModeCombo( mapName, modeName )
+ if ( !mapSupportsMode && !IsNorthstarServer() )
+ Hud_SetText( nextModeDesc, Localize( "#PRIVATE_MATCH_MODE_NO_MAP_SUPPORT", Localize( GetGameModeDisplayName( modeName ) ), Localize( GetMapDisplayName( mapName ) ) ) )
+ else if ( IsFDMode( modeName ) ) // HACK!
+ Hud_SetText( nextModeDesc, Localize( "#FD_PLAYERS_DESC", Localize( GetGameModeDisplayHint( modeName ) ) ) )
+ else
+ Hud_SetText( nextModeDesc, GetGameModeDisplayHint( modeName ) )
+}
+
+void function ModeButton_Click( var button )
+{
+ // this never activates on custom servers, but keeping it for parity with official
+ if ( !AmIPartyLeader() && GetPartySize() > 1 )
+ return
+
+ if ( Hud_IsLocked( button ) )
+ return
+
+ int mapID = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE )
+
+ var menu = GetMenu( "MapsMenu" )
+
+ array<string> modesArray = GetPrivateMatchModes()
+ string modeName = modesArray[mapID]
+
+ // on modded servers set us to the first map for that mode automatically
+ // need this for coliseum mainly which is literally impossible to select without this
+ if ( IsNorthstarServer() && !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ mapID ] ) )
+ ClientCommand( "SetCustomMap " + GetPrivateMatchMapsForMode( modeName )[ 0 ] )
+
+ // set it
+ ClientCommand( "PrivateMatchSetMode " + modeName )
+ CloseActiveMenu()
+}
+
+void function CycleModesBack( var button )
+{
+ if ( file.currentModePage == 0 )
+ return
+
+ file.currentModePage--
+ UpdateVisibleModes()
+}
+
+void function CycleModesForward( var button )
+{
+ if ( ( file.currentModePage + 1 ) * MODES_PER_PAGE >= GetPrivateMatchModes().len() )
+ return
+
+ file.currentModePage++
+ UpdateVisibleModes()
+} \ No newline at end of file
diff --git a/bobthebob.testing/scripts/vscripts/ui/menu_team_titan_select.nut b/bobthebob.testing/scripts/vscripts/ui/menu_team_titan_select.nut
new file mode 100644
index 00000000..92bb849e
--- /dev/null
+++ b/bobthebob.testing/scripts/vscripts/ui/menu_team_titan_select.nut
@@ -0,0 +1,722 @@
+global function InitTeamTitanSelectMenu
+global function TeamTitanSelectMenuIsOpen
+global function ServerCallback_OpenTeamTitanMenu
+global function ServerCallback_CloseTeamTitanMenu
+global function ServerCallback_UpdateTeamTitanMenuTime
+global function ServerCallback_RegisterTeamTitanMenuButtons
+global function TTSUpdateDoubleXP
+global function TTSUpdateDoubleXPStatus
+global function TTSMenuModeFD
+global function TTSMenuModeDefault
+global function TTSMenu_UpdateGameMode
+global function EnableDoubleXP
+
+const float SELECT_DELAY = 0.2
+
+enum eTTSMenuMode
+{
+ DEFAULT,
+ FD
+}
+
+struct
+{
+ var menu
+ bool allowManualClose = false
+ bool isReady = false
+ bool menuOpened = false
+ bool allowSelection = false
+
+ array<var> titanButtons
+ array<var> titanUpgradeButtons
+ var editButton
+ var readyPanel
+ var cover
+ var doubleXPButton
+ var chatBox
+
+ bool buttonsRegistered = false
+
+ int menuMode
+
+ float nextAllowSoundTime = 0.0
+} file
+
+void function InitTeamTitanSelectMenu()
+{
+ file.menu = GetMenu( "TeamTitanSelectMenu" )
+
+ AddMenuEventHandler( file.menu, eUIEvent.MENU_NAVIGATE_BACK, OnTeamTitanSelectMenu_NavigateBack )
+ AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnTeamTitanSelectMenu_Open )
+ AddMenuEventHandler( file.menu, eUIEvent.MENU_SHOW, OnTeamTitanSelectMenu_Open )
+ AddMenuEventHandler( file.menu, eUIEvent.MENU_HIDE, OnTeamTitanSelectMenu_Hide )
+ AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnTeamTitanSelectMenu_Close )
+
+ RegisterSignal( "TTSMenuClosed" )
+ RegisterSignal( "Delayed_RequestTitanLoadout" )
+
+ float margin = 10.0
+ float totalWidth = 0.0
+ for ( int i=0; i<NUM_PERSISTENT_TITAN_LOADOUTS; i++ )
+ {
+ var button = Hud_GetChild( file.menu, "TitanButton" + i )
+ file.titanButtons.append( button )
+ float xPos = totalWidth * -1
+ totalWidth += Hud_GetWidth( button ) + margin
+ Hud_SetPos( button, xPos, Hud_GetY( button ) )
+ }
+
+ var bg = Hud_GetChild( file.menu, "BG" )
+ totalWidth -= margin
+ float bgWidth = float( Hud_GetWidth( bg ) )
+ float startPos = (bgWidth*0.5 - totalWidth*0.5) * -1
+ for ( int i=0; i<NUM_PERSISTENT_TITAN_LOADOUTS; i++ )
+ {
+ var button = file.titanButtons[i]
+ Hud_SetPos( button, startPos + Hud_GetX( button ), Hud_GetY( button ) )
+
+ Hud_AddEventHandler( button, UIE_CLICK, TitanButton_OnClick )
+ Hud_AddEventHandler( button, UIE_GET_FOCUS, TitanButton_OnFocused )
+ }
+
+ for ( int i=0; i<7; i++ )
+ {
+ var button = Hud_GetChild( file.menu, "BtnSub" + i )
+
+ Hud_AddEventHandler( button, UIE_LOSE_FOCUS, TitanUpgradeButton_OnLoseFocus )
+ Hud_AddEventHandler( button, UIE_GET_FOCUS, TitanUpgradeButton_OnFocused )
+ }
+
+ SetNavLeftRight( file.titanButtons, true )
+
+ //file.editButton = Hud_GetChild( file.menu, "EditTitanButton" )
+ //Hud_AddEventHandler( file.editButton, UIE_CLICK, EditTitanButton_OnClick )
+ file.readyPanel = Hud_GetChild( file.menu, "ReadyRui" )
+ file.cover = Hud_GetChild( file.menu, "Cover" )
+
+ #if PC_PROG
+ file.chatBox = Hud_GetChild( file.menu, "LobbyChatBox" )
+ #endif // PC_PROG
+
+ file.doubleXPButton = Hud_GetChild( file.menu, "DoubleXP" )
+
+ AddMenuFooterOption( file.menu, BUTTON_A, "#A_BUTTON_SELECT", "", null, TeamTitanSelect_IsNotReady )
+ AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" )
+ AddMenuFooterOption( file.menu, BUTTON_X, "#MENU_X_BUTTON_EDIT_TITAN", "#MENU_EDIT_TITAN", EditTitanButton_OnClick, TeamTitanSelect_IsReady )
+ AddMenuFooterOption( file.menu, BUTTON_Y, "#MENU_Y_BUTTON_EDIT_PILOT", "#MENU_EDIT_PILOT", EditPilotButton_OnClick, CoverIsOff )
+}
+
+void function TTSUpdateDoubleXP( int count, bool avialable, float status )
+{
+ var rui = Hud_GetRui( file.doubleXPButton )
+ RuiSetInt( rui, "doubleXPCount", count )
+ RuiSetBool( rui, "doubleXPAvailable", avialable )
+ RuiSetFloat( rui, "doubleXPStatus", status )
+}
+
+void function TTSUpdateDoubleXPStatus( int status )
+{
+ var rui = Hud_GetRui( file.doubleXPButton )
+ RuiSetFloat( rui, "doubleXPStatus", float( status ) )
+}
+
+void function ServerCallback_UpdateTeamTitanMenuTime( float endTime )
+{
+ Signal( uiGlobal.signalDummy, "TTSMenuClosed" )
+
+ file.allowSelection = true
+
+ if ( file.nextAllowSoundTime < Time() )
+ {
+ EmitUISound( "ui_ctf_1p_playerscore" )
+ file.nextAllowSoundTime = Time() + 5.0
+ }
+
+ Hud_SetEnabled( file.cover, false )
+ Hud_Hide( file.cover )
+ Hud_SetAlpha( file.cover, 0 )
+
+ if ( endTime > 5 )
+ file.allowSelection = true
+
+ thread UpdateSubText( Time() + endTime )
+}
+
+void function ServerCallback_OpenTeamTitanMenu( float endTime )
+{
+ if ( TeamTitanSelectMenuIsOpen() )
+ return
+
+ if ( uiGlobal.activeMenu != null )
+ CloseAllMenus()
+
+ RunClientScript( "PlayTTSMusic" )
+
+ file.allowManualClose = false
+ file.allowSelection = true
+ file.isReady = true // set to true so selection mode kicks in
+ thread MenuFadeIn()
+ BeginSelectionMode()
+ AdvanceMenu( file.menu )
+ thread UpdateSubText( Time() + endTime )
+}
+
+void function MenuFadeIn()
+{
+ Hud_SetEnabled( file.cover, true )
+ Hud_SetAlpha( file.cover, 255 )
+ Hud_Show( file.cover )
+ wait 1.0
+ Hud_FadeOverTime( file.cover, 0, 1.0 )
+ wait 1.0
+ Hud_Hide( file.cover )
+ Hud_SetEnabled( file.cover, false )
+}
+
+void function UpdateSubText( float endTime )
+{
+ EndSignal( uiGlobal.signalDummy, "TTSMenuClosed" )
+
+ var subText = Hud_GetChild( file.menu, "MenuSubTitle" )
+ var rui = Hud_GetRui( file.readyPanel )
+ RuiSetBool( rui, "isReady", true )
+
+ thread Countdown( endTime )
+ while ( Time() < endTime )
+ {
+ int countdownTime = int( ceil( endTime - Time() ) )
+ Hud_SetText( subText, Localize( "#MENU_STARTS_IN", countdownTime ) )
+ RuiSetInt( rui, "timer", countdownTime )
+ WaitFrame()
+ }
+
+ Hud_SetText( subText, Localize( "#MENU_STARTS_IN", 0 ) )
+ RuiSetInt( rui, "timer", 0 )
+}
+
+void function Countdown( float endTime )
+{
+ EndSignal( uiGlobal.signalDummy, "TTSMenuClosed" )
+
+ float countdownTime = 5.0
+ float startCountdownTime = endTime - countdownTime
+
+ if ( Time() > startCountdownTime )
+ return
+
+ wait startCountdownTime - Time()
+
+ while ( Time() < endTime )
+ {
+ EmitUISound( "UI_InGame_MarkedForDeath_CountdownToMarked" )
+ wait 1.0
+ }
+
+ file.allowSelection = false
+ BeginEditMode(null)
+
+ Hud_SetAlpha( file.cover, 0 )
+ Hud_SetEnabled( file.cover, true )
+ Hud_Show( file.cover )
+ Hud_FadeOverTime( file.cover, 255, 1.0 )
+
+ float soundTime = DoPrematchWarpSound() ? PICK_LOADOUT_SOUND_TIME : 1.5
+ wait soundTime
+
+ thread ServerCallback_CloseTeamTitanMenu()
+}
+
+void function ServerCallback_CloseTeamTitanMenu()
+{
+ if ( TeamTitanSelectMenuIsOpen() )
+ {
+ file.allowManualClose = true
+ UI_SetPresentationType( ePresentationType.INACTIVE )
+ CloseAllMenus()
+ OnTeamTitanSelectMenu_Close()
+ }
+}
+
+void function OnTeamTitanSelectMenu_NavigateBack()
+{
+ if ( file.allowManualClose )
+ {
+ CloseActiveMenu()
+ return
+ }
+
+ if ( file.isReady && file.allowSelection )
+ {
+ BeginSelectionMode()
+ return
+ }
+
+ LeaveDialog()
+ return
+}
+
+void function TTSMenu_UpdateGameMode( string modeName )
+{
+ var title = Hud_GetChild( file.menu, "MenuTitle" )
+ Hud_SetText( title, Localize( modeName ) )
+}
+
+void function ServerCallback_RegisterTeamTitanMenuButtons()
+{
+ RegisterButtonCallbacks()
+}
+
+void function RegisterButtonCallbacks()
+{
+ if ( file.buttonsRegistered )
+ return
+
+ file.buttonsRegistered = true
+ RegisterButtonPressedCallback( BUTTON_BACK, EnableDoubleXP )
+ RegisterButtonPressedCallback( KEY_RSHIFT, EnableDoubleXP )
+}
+
+void function OnTeamTitanSelectMenu_Open()
+{
+ file.menuOpened = true
+
+ var dataTable = GetDataTable( $"datatable/titan_properties.rpak" )
+ int loadoutIconCol = GetDataTableColumnByName( dataTable, "loadoutIconFD" )
+ int titanCol = GetDataTableColumnByName( dataTable, "titanRef" )
+
+ entity player = GetUIPlayer()
+
+ var nextMapImage = Hud_GetChild( file.menu, "NextMapImage" )
+ string mapName = GetActiveLevel()
+ asset mapImage = GetMapImageForMapName( mapName )
+
+ RefreshCreditsAvailable()
+
+ RuiSetImage( Hud_GetRui( nextMapImage ), "basicImage", mapImage )
+ Hud_Show( nextMapImage )
+ Hud_SetText( Hud_GetChild( file.menu, "NextMapName" ), GetMapDisplayName( mapName ) )
+ Hud_Show( Hud_GetChild( file.menu, "NextMapName" ) )
+
+ var buttonToFocus
+
+ for ( int i=0; i<NUM_PERSISTENT_TITAN_LOADOUTS; i++ )
+ {
+ var button = file.titanButtons[i]
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( i )
+ int row = GetDataTableRowMatchingStringValue( dataTable, titanCol, loadout.titanClass )
+
+ asset icon = GetDataTableAsset( dataTable, row, loadoutIconCol )
+ var rui = Hud_GetRui( button )
+
+ RuiSetImage( rui, "buttonImage", icon )
+
+ if ( !IsTitanLoadoutAvailable( player, loadout.titanClass ) )
+ {
+ Hud_SetLocked( button, true )
+ if ( !IsItemLocked( player, loadout.titanClass ) )
+ RefreshButtonCost( button, loadout.titanClass, "", 0, 0 )
+ }
+ else
+ {
+ Hud_SetLocked( button, IsItemLocked( player, loadout.titanClass ) )
+ RefreshButtonCost( button, loadout.titanClass )
+
+ if ( uiGlobal.titanSpawnLoadoutIndex == i )
+ {
+ buttonToFocus = button
+ }
+ }
+ }
+
+ if ( buttonToFocus == null )
+ buttonToFocus = FindValidTitanButton()
+ thread HACK_DelayedSetFocus_BecauseWhy( buttonToFocus )
+
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.titanSpawnLoadoutIndex )
+
+ for ( int i=0; i<7; i++ )
+ {
+ var button = Hud_GetChild( file.menu, "BtnSub"+i )
+ file.titanUpgradeButtons.append( button )
+
+ if ( file.menuMode == eTTSMenuMode.FD )
+ {
+ Hud_Show( button )
+ }
+ else
+ {
+ Hud_Hide( button )
+ }
+ }
+ SetNavLeftRight( file.titanUpgradeButtons, true )
+
+ SetBlurEnabled( false )
+ var title = Hud_GetChild( file.menu, "MenuTitle" )
+ string name = expect string( GetCurrentPlaylistVar( "name" ) )
+ Hud_SetText( title, Localize( name ) )
+ RunMenuClientFunction( "ShowTTSPanel" )
+
+ if ( file.isReady )
+ UI_SetPresentationType( ePresentationType.TITAN_CENTER_SELECTED )
+ else
+ UI_SetPresentationType( ePresentationType.TITAN_CENTER )
+
+
+ RunClientScript( "TTS_UpdateLocalPlayerTitan", loadout.setFile, loadout.primary, loadout.passive1, loadout.passive2 )
+}
+
+void function EnableDoubleXP( var button )
+{
+ #if PC_PROG
+ if ( Hud_IsFocused( file.chatBox ) )
+ return
+ #endif // PC_PROG
+
+ if ( CanRunClientScript() )
+ {
+ EmitUISound( "Menu_Email_Sent" )
+ RunClientScript( "UseDoubleXP" )
+ }
+}
+
+void function OnTeamTitanSelectMenu_Hide()
+{
+ RunMenuClientFunction( "HideTTSPanel" )
+
+ DeregisterButtonCallbacks()
+}
+
+void function DeregisterButtonCallbacks()
+{
+ if ( !file.buttonsRegistered )
+ return
+
+ file.buttonsRegistered = false
+
+ DeregisterButtonPressedCallback( BUTTON_BACK, EnableDoubleXP )
+ DeregisterButtonPressedCallback( KEY_RSHIFT, EnableDoubleXP )
+}
+
+void function OnTeamTitanSelectMenu_Close()
+{
+ RunMenuClientFunction( "ClearAllPilotPreview" )
+ Signal( uiGlobal.signalDummy, "TTSMenuClosed" )
+ file.menuOpened = false
+ UI_SetPresentationType( ePresentationType.INACTIVE )
+
+ DeregisterButtonCallbacks()
+}
+
+void function TitanButton_OnClick( var button )
+{
+ int scriptID = int( Hud_GetScriptID( button ) )
+ if ( Hud_IsLocked( button ) )
+ {
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( scriptID )
+ if ( !IsTitanLoadoutAvailable( GetUIPlayer(), loadout.titanClass ) )
+ return
+
+ OpenBuyItemDialog( file.titanButtons, button, GetItemName( loadout.titanClass ), loadout.titanClass )
+ return
+ }
+
+ if ( file.isReady )
+ {
+ BeginSelectionMode()
+ return
+ }
+
+ uiGlobal.titanSpawnLoadoutIndex = scriptID
+ Signal( uiGlobal.signalDummy, "Delayed_RequestTitanLoadout" )
+ ClientCommand( "RequestTitanLoadout " + uiGlobal.titanSpawnLoadoutIndex )
+ BeginEditMode( button )
+}
+
+void function TitanButton_OnFocused( var button )
+{
+ int scriptID = int( Hud_GetScriptID( button ) )
+
+ var rui = Hud_GetRui( Hud_GetChild( file.menu, "TitanName" ) )
+
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( scriptID )
+
+ RuiSetString( rui, "titanName", GetTitanLoadoutName( loadout ) )
+ RuiSetString( rui, "titanLevelString", "" )
+ RuiSetString( rui, "titanRole", "" )
+
+ entity player = GetUIPlayer()
+
+ var dataTable = GetDataTable( $"datatable/titan_properties.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "titanRef" ), loadout.titanClass )
+ string role = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "fdRole" ) )
+ int titanLevel = FD_TitanGetLevelForXP( loadout.titanClass, FD_TitanGetXP( GetUIPlayer(), loadout.titanClass ) )
+ array<ItemDisplayData> titanUpgrades = FD_GetUpgradesForTitanClass( loadout.titanClass )
+
+ if ( file.menuMode == eTTSMenuMode.FD )
+ {
+ RuiSetString( rui, "titanLevelString", Localize( "#FD_TITAN_LEVEL", titanLevel ) )
+ RuiSetString( rui, "titanRole", Localize( "#FD_ROLE", Localize(role) ) )
+
+ foreach ( index, item in titanUpgrades )
+ {
+ var button = file.titanUpgradeButtons[index]
+ var upgradeRui = Hud_GetRui( button )
+
+ bool locked = IsSubItemLocked( GetUIPlayer(), item.ref, item.parentRef )
+
+ if ( locked )
+ RuiSetImage( upgradeRui, "buttonImage", expect asset( item.i.lockedImage ) )
+ else
+ RuiSetImage( upgradeRui, "buttonImage", item.image )
+
+ Hud_SetLocked( button, locked )
+ }
+ }
+
+ if ( !Hud_IsLocked( button ) )
+ {
+ uiGlobal.titanSpawnLoadoutIndex = scriptID
+ thread Delayed_RequestTitanLoadout( uiGlobal.titanSpawnLoadoutIndex )
+ SetLabelRuiText( Hud_GetChild( file.menu, "TitanSelectTitle" ), "#MENU_TITAN_SELECT" )
+ }
+ else
+ {
+ RuiSetString( rui, "titanLevelString", GetItemUnlockReqText( loadout.titanClass ) )
+ }
+
+ SetLabelRuiText( Hud_GetChild( file.menu, "TitanSelectTitle" ), GetTitanAvailableText( player, loadout.titanClass) )
+
+ RunMenuClientFunction( "UpdateTitanModel", scriptID )
+ RunClientScript( "TTS_UpdateLocalPlayerTitan", loadout.setFile, loadout.primary, loadout.passive1, loadout.passive2 )
+}
+
+string function GetTitanAvailableText( entity player, string titanClass )
+{
+ int titanAvailableState = GetTitanLoadAvailableState( player, titanClass )
+
+ if ( titanAvailableState == TITAN_CLASS_LOCK_STATE_AVAILABLE )
+ return "#MENU_TITAN_SELECT_HINT"
+
+ if ( titanAvailableState == TITAN_CLASS_LOCK_STATE_LEVELREQUIRED || titanAvailableState == TITAN_CLASS_LOCK_STATE_LEVELRECOMMENDED )
+ {
+ int difficultyLevel = GetCurrentPlaylistVarInt( "fd_difficulty", 0 )
+ int requiredTitanLevel = 0
+ switch ( difficultyLevel )
+ {
+ case eFDDifficultyLevel.EASY:
+ if ( GetItemUnlockType( "fd_easy" ) == eUnlockType.STAT )
+ requiredTitanLevel = int( GetStatUnlockStatVal( "fd_easy" ) )
+ break
+ case eFDDifficultyLevel.NORMAL:
+ if ( GetItemUnlockType( "fd_normal" ) == eUnlockType.STAT )
+ requiredTitanLevel = int( GetStatUnlockStatVal( "fd_normal" ) )
+ break
+ case eFDDifficultyLevel.HARD:
+ if ( GetItemUnlockType( "fd_hard" ) == eUnlockType.STAT )
+ requiredTitanLevel = int( GetStatUnlockStatVal( "fd_hard" ) )
+ break
+ case eFDDifficultyLevel.MASTER:
+ if ( GetItemUnlockType( "fd_master" ) == eUnlockType.STAT )
+ requiredTitanLevel = int( GetStatUnlockStatVal( "fd_master" ) )
+ break
+ case eFDDifficultyLevel.INSANE:
+ if ( GetItemUnlockType( "fd_insane" ) == eUnlockType.STAT )
+ requiredTitanLevel = int( GetStatUnlockStatVal( "fd_insane" ) )
+ break
+ }
+
+ if ( titanAvailableState == TITAN_CLASS_LOCK_STATE_LEVELREQUIRED )
+ return Localize( "#MENU_TITAN_SELECT_LEVELREQUIRED", requiredTitanLevel )
+ else
+ return Localize( "#MENU_TITAN_SELECT_LEVELRECOMMENDED", requiredTitanLevel )
+ }
+
+ if ( titanAvailableState == TITAN_CLASS_LOCK_STATE_INUSE )
+ return "#MENU_TITAN_SELECT_INUSE"
+
+ if ( titanAvailableState == TITAN_CLASS_LOCK_STATE_LOCKED )
+ return "#MENU_TITAN_SELECT_LOCKED"
+
+ return "#MENU_TITAN_SELECT_HINT"
+}
+
+void function Delayed_RequestTitanLoadout( int index )
+{
+ Signal( uiGlobal.signalDummy, "Delayed_RequestTitanLoadout" )
+ EndSignal( uiGlobal.signalDummy, "Delayed_RequestTitanLoadout" )
+ wait 0.5
+ ClientCommand( "RequestTitanLoadout " + uiGlobal.titanSpawnLoadoutIndex )
+}
+
+void function TitanUpgradeButton_OnFocused( var button )
+{
+ if ( file.menuMode == eTTSMenuMode.DEFAULT )
+ return
+
+ int scriptID = int( Hud_GetScriptID( button ) )
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.titanSpawnLoadoutIndex )
+ array<ItemDisplayData> titanUpgrades = FD_GetUpgradesForTitanClass( loadout.titanClass )
+
+ ItemDisplayData item = titanUpgrades[ scriptID ]
+ var panel = Hud_GetChild( file.menu, "UpgradeName" )
+ Hud_Show( panel )
+ var rui = Hud_GetRui( panel )
+ RuiSetString( rui, "upgradeName", item.name )
+ RuiSetString( rui, "upgradeDesc", item.desc )
+ RuiSetBool( rui, "isLocked", IsSubItemLocked( GetUIPlayer(), item.ref, item.parentRef ) )
+}
+
+void function TitanUpgradeButton_OnLoseFocus( var button )
+{
+ Hud_Hide( Hud_GetChild( file.menu, "UpgradeName" ) )
+}
+
+void function BeginEditMode( var button )
+{
+ if ( file.isReady )
+ return
+
+ file.isReady = true
+
+ EmitUISound( "UI_InGame_FD_TitanSelected" )
+ SetLabelRuiText( Hud_GetChild( file.menu, "TitanSelectTitle" ), "#MENU_TITAN_SELECTED" )
+ Hud_Hide( Hud_GetChild( file.menu, "TitanSelectTitle" ) )
+ Hud_Show( file.readyPanel )
+ var rui = Hud_GetRui( file.readyPanel )
+ RuiSetBool( rui, "isReady", true )
+
+ foreach ( b in file.titanButtons )
+ {
+ Hud_Hide( b )
+ }
+
+ //Hud_Show( file.editButton )
+ //Hud_SetFocused( file.editButton )
+ Hud_SetFocused( file.titanUpgradeButtons[0] )
+
+ TitanLoadoutDef loadout = GetCachedTitanLoadout( uiGlobal.titanSpawnLoadoutIndex )
+ string primeTitanString = ""
+
+ if ( loadout.isPrime == "titan_is_prime" )
+ primeTitanString = "_prime"
+
+ string modifiedAlias = "diag_gs_titan" + loadout.titanClass + primeTitanString + "_embark"
+ EmitUISound( modifiedAlias )
+
+ if ( uiGlobal.activeMenu == file.menu )
+ UI_SetPresentationType( ePresentationType.TITAN_CENTER_SELECTED )
+
+ Signal( uiGlobal.signalDummy, "Delayed_RequestTitanLoadout" )
+ ClientCommand( "RequestTitanLoadout " + uiGlobal.titanSpawnLoadoutIndex )
+ RunMenuClientFunction( "UpdateTitanModel", uiGlobal.titanSpawnLoadoutIndex )
+
+ var subText = Hud_GetChild( file.menu, "MenuSubTitle" )
+ // Hud_Hide( subText )
+}
+
+void function BeginSelectionMode()
+{
+ if ( !file.isReady )
+ return
+
+ file.isReady = false
+ //Hud_Hide( file.editButton )
+
+ SetLabelRuiText( Hud_GetChild( file.menu, "TitanSelectTitle" ), "#MENU_TITAN_SELECT_HINT" )
+ Hud_Show( Hud_GetChild( file.menu, "TitanSelectTitle" ) )
+ Hud_Hide( file.readyPanel )
+ var rui = Hud_GetRui( file.readyPanel )
+ RuiSetBool( rui, "isReady", false )
+
+ Hud_SetFocused( FindValidTitanButton() )
+
+ for ( int i=0; i<file.titanButtons.len(); i++ )
+ {
+ var b = file.titanButtons[i]
+ Hud_Show( b )
+ if ( i == uiGlobal.titanSpawnLoadoutIndex && !Hud_IsLocked( b ) )
+ {
+ Hud_SetFocused( b )
+ }
+ }
+
+ Hud_Hide( Hud_GetChild( file.menu, "UpgradeName" ) )
+
+ UI_SetPresentationType( ePresentationType.TITAN_CENTER )
+ RunMenuClientFunction( "UpdateTitanModel", uiGlobal.titanSpawnLoadoutIndex )
+
+ var subText = Hud_GetChild( file.menu, "MenuSubTitle" )
+ // Hud_Show( subText )
+}
+
+void function EditPilotButton_OnClick( var button )
+{
+ // SetEditLoadout( "pilot", uiGlobal.pilotSpawnLoadoutIndex )
+ // RunMenuClientFunction( "SetEditingPilotLoadoutIndex", uiGlobal.pilotSpawnLoadoutIndex )
+ AdvanceMenu( GetMenu( "EditPilotLoadoutsMenu" ) )
+ RunMenuClientFunction( "HideTTSPanel" )
+}
+
+void function EditTitanButton_OnClick( var button )
+{
+ SetEditLoadout( "titan", uiGlobal.titanSpawnLoadoutIndex )
+ RunMenuClientFunction( "SetEditingTitanLoadoutIndex", uiGlobal.titanSpawnLoadoutIndex )
+ AdvanceMenu( GetMenu( "EditTitanLoadoutMenu" ) )
+ RunMenuClientFunction( "HideTTSPanel" )
+}
+
+bool function CoverIsOff()
+{
+ return !Hud_IsEnabled( file.cover )
+}
+
+bool function TeamTitanSelectMenuIsOpen()
+{
+ return file.menuOpened
+}
+
+bool function TeamTitanSelect_IsReady()
+{
+ return file.isReady
+}
+
+bool function TeamTitanSelect_IsNotReady()
+{
+ return !file.isReady
+}
+
+void function TTSMenuModeFD()
+{
+ file.menuMode = eTTSMenuMode.FD
+
+ foreach ( button in file.titanUpgradeButtons )
+ {
+ Hud_Show( button )
+ }
+}
+
+void function TTSMenuModeDefault()
+{
+ file.menuMode = eTTSMenuMode.DEFAULT
+
+ foreach ( button in file.titanUpgradeButtons )
+ {
+ Hud_Hide( button )
+ }
+
+ var panel = Hud_GetChild( file.menu, "UpgradeName" )
+ Hud_Hide( panel )
+}
+
+var function FindValidTitanButton()
+{
+ foreach ( button in file.titanButtons )
+ {
+ if ( Hud_IsLocked( button ) )
+ continue
+
+ return button
+ }
+
+ return file.titanButtons[0]
+} \ No newline at end of file