aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Northstar.Client/mod/resource/ui/menus/server_browser.menu2
-rw-r--r--Northstar.Client/mod/scripts/vscripts/client/cl_codecallbacks.gnut316
-rw-r--r--Northstar.Client/mod/scripts/vscripts/client/cl_flyout.gnut255
-rw-r--r--Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut2906
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut9
-rw-r--r--Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut22
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut7
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut4
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut3
-rw-r--r--Northstar.Custom/mod/scripts/vscripts/sh_bleedout_damage.gnut16
-rw-r--r--Northstar.CustomServers/mod.json8
-rw-r--r--Northstar.CustomServers/mod/cfg/autoexec_ns_server.cfg2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut14
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut1
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut16
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut11
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_changemap.nut3
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut5
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut2
20 files changed, 3579 insertions, 47 deletions
diff --git a/Northstar.Client/mod/resource/ui/menus/server_browser.menu b/Northstar.Client/mod/resource/ui/menus/server_browser.menu
index 90785e46..213f46e9 100644
--- a/Northstar.Client/mod/resource/ui/menus/server_browser.menu
+++ b/Northstar.Client/mod/resource/ui/menus/server_browser.menu
@@ -249,7 +249,7 @@ resource/ui/menus/mods_browse.menu
LabelDetails
{
ControlName RuiPanel
- xpos 900
+ xpos 675
ypos 160
tall 800
wide 950
diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_codecallbacks.gnut b/Northstar.Client/mod/scripts/vscripts/client/cl_codecallbacks.gnut
new file mode 100644
index 00000000..486689d3
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/client/cl_codecallbacks.gnut
@@ -0,0 +1,316 @@
+
+global function ClDroppedWeaponFlyout_Init
+
+global function ClientCodeCallback_BodyGroupChanged
+
+global function ClientCodeCallback_UseEntGainedFocus
+global function ClientCodeCallback_UseEntLostFocus
+
+global function AddCallback_OnPetTitanChanged
+global function ClientCodeCallback_OnPetTitanModeChanged
+global function AddCallback_OnPetTitanModeChanged
+global function ClientCodeCallback_OnPetTitanChanged
+
+global function DestroyPickupFlyout
+global function HidePickupFlyout
+global function ShowPickupFlyout
+global function IsCurrentlyFocusedWeapon
+global function IsPickupFlyoutValid
+
+#if HAS_WEAPON_PICKUP_HIGHLIGHT
+global function ServerCallback_RefreshWeaponHighlights
+#endif
+
+enum eFlyoutType
+{
+ STANDARD_WEAPON
+ BT_LOADOUT_PICKUP
+}
+
+struct
+{
+ var flyoutRUI
+ var lastWeaponRuiSet
+ int flyoutType
+ entity focusedEnt
+ table<string, asset> modImages
+} file
+
+void function ClDroppedWeaponFlyout_Init()
+{
+ RegisterSignal( "PetTitanChanged" )
+ RegisterSignal( "PetTitanModeChanged" )
+
+ var dataTable = GetDataTable( $"datatable/pilot_weapon_mods_common.rpak" )
+ int numRows = GetDatatableRowCount( dataTable )
+
+ for ( int i = 0; i < numRows; i++ )
+ {
+ string modRef = GetDataTableString( dataTable, i, PILOT_WEAPON_MOD_COMMON_COLUMN )
+ asset modImage = GetDataTableAsset( dataTable, i, PILOT_WEAPON_MOD_COMMON_IMAGE_COLUMN )
+ file.modImages[ modRef ] <- modImage
+ }
+
+ AddCinematicEventFlagChangedCallback( CE_FLAG_HIDE_MAIN_HUD, WeaponPickupFlyout_UpdateVisibility )
+
+ #if HAS_WEAPON_PICKUP_HIGHLIGHT
+ AddCreateCallback( "weaponx", ClWeaponCreationCallback )
+ #endif
+}
+
+void function ClientCodeCallback_BodyGroupChanged( entity ent, int bodyGroupIndex, int oldState, int newState )
+{
+// PrintFunc( "entity " + ent + " index " + bodyGroupIndex + "newstate " + newState )
+
+ if ( IsSpectre( ent ) || IsStalker( ent ) )
+ {
+ if ( bodyGroupIndex == ent.FindBodyGroup( "removableHead" ) )
+ {
+ ModelFX_DisableGroup( ent, "foe_lights" )
+ ModelFX_DisableGroup( ent, "friend_lights" )
+ }
+ }
+}
+
+void function ClientCodeCallback_UseEntGainedFocus( entity ent )
+{
+ foreach ( callbackFunc in clGlobal.onUseEntGainFocusCallbacks )
+ {
+ callbackFunc( ent )
+ }
+
+ DestroyPickupFlyout()
+
+ int neededType = eFlyoutType.STANDARD_WEAPON
+
+ if ( ent.GetClassName() == "weaponx" )
+ {
+ #if SP
+ int loadoutIndex = GetSPTitanLoadoutIndexForWeapon( ent.GetWeaponClassName() )
+ neededType = (loadoutIndex >= 0) ? eFlyoutType.BT_LOADOUT_PICKUP : eFlyoutType.STANDARD_WEAPON
+ #endif
+
+ if ( neededType == eFlyoutType.STANDARD_WEAPON )
+ {
+ if ( (file.flyoutRUI == null) || file.flyoutType != neededType )
+ {
+ DestroyPickupFlyout()
+ file.flyoutRUI = RuiCreate( $"ui/dropped_weapon_flyout.rpak", clGlobal.topoFullScreen, RUI_DRAW_HUD, 0 )
+ file.flyoutType = neededType
+ }
+
+ int modNum = 1
+ array<string> weaponMods = ent.GetMods()
+ foreach ( mod in weaponMods )
+ {
+ if ( modNum >= 5 ) // setting mod5 in the rui crashes client
+ break
+
+ if ( mod in file.modImages )
+ RuiSetImage( file.flyoutRUI, "mod" + modNum++, file.modImages[ mod ] )
+ }
+
+ RuiSetGameTime( file.flyoutRUI, "startTime", Time() )
+ RuiTrackFloat3( file.flyoutRUI, "pos", ent, RUI_TRACK_ABSORIGIN_FOLLOW )
+ RuiSetString( file.flyoutRUI, "titleText", expect string( ent.GetWeaponInfoFileKeyField( "shortprintname" ) ) )
+ RuiSetString( file.flyoutRUI, "descriptionText", expect string( ent.GetWeaponInfoFileKeyField( "description" ) ) )
+
+ RuiSetBool( file.flyoutRUI, "isOffhandWeapon", ent.IsWeaponOffhand() )
+ RuiSetImage( file.flyoutRUI, "icon", ent.GetWeaponInfoFileKeyFieldAsset( "hud_icon" ) )
+ RuiSetFloat( file.flyoutRUI, "worldOffsetY", GetLocalViewPlayer().IsTitan() ? 98.0 : 32.0 )
+ RuiSetResolutionToScreenSize( file.flyoutRUI )
+
+ if ( ent.GetWeaponSettingBool( eWeaponVar.is_burn_mod ) )
+ RuiSetFloat3( file.flyoutRUI, "color", BURN_CARD_WEAPON_HUD_COLOR_VECTOR )
+
+ var rui = ClWeaponStatus_GetWeaponHudRui( GetLocalViewPlayer(), ent )
+ if ( rui != null )
+ {
+ RuiSetBool( rui, "isHighlighted", true )
+ file.lastWeaponRuiSet = rui
+ }
+ }
+ // #if SP
+ // else if ( neededType == eFlyoutType.BT_LOADOUT_PICKUP )
+ // {
+ // // The first one is picked up automatically an dhandled by a different custom system.
+ // if ( ent.GetWeaponClassName() == SP_FIRST_TITAN_LOADOUT_KIT )
+ // return
+
+ // if ( (file.flyoutRUI == null) || file.flyoutType != neededType )
+ // {
+ // DestroyPickupFlyout()
+ // file.flyoutRUI = CreateCockpitRui( $"ui/dropped_weapon_bt_loadout_flyout.rpak", 0 )
+ // file.flyoutType = neededType
+ // }
+
+ // RuiSetGameTime( file.flyoutRUI, "startTime", Time() )
+ // RuiSetString( file.flyoutRUI, "titleText", GetSPTitanLoadoutForIndex_MenuItem( loadoutIndex ) )
+ // RuiSetImage( file.flyoutRUI, "icon", ent.GetWeaponInfoFileKeyFieldAsset( "hud_icon" ) )
+ // }
+ // #endif
+ }
+
+ file.focusedEnt = ent
+ if ( GetWeaponFlyoutAliveTime() < 0.5 && IsWeaponFlyoutVisible() )
+ {
+ HidePickupFlyout( 2.0 )
+ SetWeaponFlyoutRemainingTime( 2.0 )
+ }
+ else
+ {
+ DestroyWeaponFlyout()
+ }
+
+#if HAS_AMMO_FULL_FLYOUT
+ if ( IsAmmoFullWeapon( ent ) )
+ HideAmmoFullFlyout()
+#endif
+
+#if HAS_WEAPON_PICKUP_HIGHLIGHT
+ ManageHighlightEntity( ent )
+#endif
+
+ #if SP
+ ScriptCallback_UpdateOnscreenHint()
+ #endif
+}
+
+void function ClientCodeCallback_UseEntLostFocus( entity ent )
+{
+ foreach ( callbackFunc in clGlobal.onUseEntLoseFocusCallbacks )
+ {
+ callbackFunc( ent )
+ }
+
+ DestroyPickupFlyout()
+
+ if ( file.lastWeaponRuiSet != null )
+ {
+ RuiSetBool( file.lastWeaponRuiSet, "isHighlighted", false )
+ file.lastWeaponRuiSet = null
+ }
+
+ if ( file.focusedEnt == ent )
+ {
+ file.focusedEnt = null
+ }
+
+#if HAS_WEAPON_PICKUP_HIGHLIGHT
+ if ( IsValid( ent ) )
+ ManageHighlightEntity( ent )
+#endif
+}
+
+bool function IsPickupFlyoutValid()
+{
+ return ( file.flyoutRUI != null )
+}
+
+bool function IsCurrentlyFocusedWeapon( entity ent )
+{
+ return file.focusedEnt == ent
+}
+
+void function DestroyPickupFlyout()
+{
+ if ( file.flyoutRUI == null )
+ return
+
+ RuiDestroy( file.flyoutRUI )
+ file.flyoutRUI = null
+
+ #if SP
+ ScriptCallback_UpdateOnscreenHint()
+ #endif
+}
+
+void function HidePickupFlyout( float hideDuration )
+{
+ if ( file.flyoutRUI == null )
+ return
+
+ RuiSetFloat( file.flyoutRUI, "hideDuration", hideDuration )
+ RuiSetGameTime( file.flyoutRUI, "hideStartTime", Time() )
+}
+
+void function ShowPickupFlyout()
+{
+ if ( file.flyoutRUI == null )
+ return
+
+ RuiSetFloat( file.flyoutRUI, "hideDuration", 0.0 )
+
+ #if SP
+ ScriptCallback_UpdateOnscreenHint()
+ #endif
+}
+
+void function WeaponPickupFlyout_UpdateVisibility( entity player )
+{
+ if ( file.flyoutRUI == null )
+ return
+
+ int ceFlags = player.GetCinematicEventFlags()
+ bool hideHud = ( ceFlags & CE_FLAG_HIDE_MAIN_HUD ) > 0
+ RuiSetBool( file.flyoutRUI, "inCinematic", hideHud )
+}
+
+#if HAS_WEAPON_PICKUP_HIGHLIGHT
+void function ServerCallback_RefreshWeaponHighlights( int eHandle )
+{
+ entity weapon = GetEntityFromEncodedEHandle( eHandle )
+ if ( weapon != null )
+ ManageHighlightEntity( weapon )
+}
+
+void function ClWeaponCreationCallback( entity weapon )
+{
+
+}
+#endif
+
+
+void function AddCallback_OnPetTitanChanged( void functionref( entity ) callbackFunc )
+{
+ clGlobal.onPetTitanChangedCallbacks.append( callbackFunc )
+}
+
+void function ClientCodeCallback_OnPetTitanChanged( entity player )
+{
+ if ( !IsValid( player ) || player != GetLocalViewPlayer() )
+ return
+
+ if ( !IsMenuLevel() )
+ thread PetTitanChanged( player )
+
+ player.Signal( "PetTitanChanged" )
+
+ // Added via AddCallback_OnPetTitanModeChanged
+ foreach ( callbackFunc in clGlobal.onPetTitanChangedCallbacks )
+ {
+ callbackFunc( player )
+ }
+}
+
+void function ClientCodeCallback_OnPetTitanModeChanged( entity player )
+{
+ if ( !IsValid( player ) || player != GetLocalViewPlayer() )
+ return
+
+ if ( !IsValid( player.GetPetTitan() ) ) // should be an assert...
+ return
+
+ player.Signal( "PetTitanModeChanged" )
+
+ // Added via AddCallback_OnPetTitanModeChanged
+ foreach ( callbackFunc in clGlobal.onPetTitanModeChangedCallbacks )
+ {
+ callbackFunc( player )
+ }
+}
+
+void function AddCallback_OnPetTitanModeChanged( void functionref( entity ) callbackFunc )
+{
+ clGlobal.onPetTitanModeChangedCallbacks.append( callbackFunc )
+} \ No newline at end of file
diff --git a/Northstar.Client/mod/scripts/vscripts/client/cl_flyout.gnut b/Northstar.Client/mod/scripts/vscripts/client/cl_flyout.gnut
new file mode 100644
index 00000000..e077ab68
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/client/cl_flyout.gnut
@@ -0,0 +1,255 @@
+
+global function ClWeaponFlyout_Init
+
+global function WeaponFlyoutThink
+global function ShouldShowWeaponFlyout
+global function WeaponFlyoutRefresh
+global function IsWeaponFlyoutVisible
+global function DestroyWeaponFlyout
+global function GetWeaponFlyoutAliveTime
+global function GetWeaponFlyoutAliveTimeLeft
+global function SetWeaponFlyoutRemainingTime
+
+global function WeaponFlyout_SetLevelEnabled
+
+const float FLYOUT_DURATION = 4.0
+const float FLYOUT_DURATION_SHORT = 1.0
+const vector FLYOUT_COLOR = <0.851, 0.976, 1.0>
+
+struct
+{
+ var weaponRUI
+ string weaponClassName
+ float flyoutShowTime = -99.0
+ float lastFlyoutDuration = FLYOUT_DURATION
+
+ bool flyoutLevelEnabled = true
+
+ table<string, asset> modImages
+} file
+
+void function ClWeaponFlyout_Init()
+{
+ AddOnDeathCallback( "player", WeaponFlyout_OnDeathCallback )
+ AddCallback_OnSelectedWeaponChanged( OnSelectedWeaponChanged )
+
+ var dataTable = GetDataTable( $"datatable/pilot_weapon_mods_common.rpak" )
+ int numRows = GetDatatableRowCount( dataTable )
+
+ for ( int i = 0; i < numRows; i++ )
+ {
+ string modRef = GetDataTableString( dataTable, i, PILOT_WEAPON_MOD_COMMON_COLUMN )
+ asset modImage = GetDataTableAsset( dataTable, i, PILOT_WEAPON_MOD_COMMON_IMAGE_COLUMN )
+ file.modImages[ modRef ] <- modImage
+ }
+}
+
+void function WeaponFlyout_OnDeathCallback( entity player )
+{
+ if ( player == GetLocalViewPlayer() )
+ DestroyWeaponFlyout()
+}
+
+void function WeaponFlyoutShow( entity weapon, string weaponClassName )
+{
+ if ( IsWatchingReplay() )
+ return
+
+ file.weaponClassName = weaponClassName
+
+ entity player = GetLocalViewPlayer()
+ if ( !IsValid( player ) )
+ return
+
+ entity viewModel = player.GetViewModelEntity()
+ if ( !IsValid( viewModel ) )
+ return
+
+ if ( GetConVarInt( "hud_setting_showWeaponFlyouts" ) == 0 )
+ return
+
+ //file.weaponRUI = RuiCreate( $"ui/weapon_flyout.rpak", clGlobal.topoFullScreen, RUI_DRAW_HUD, 0 )
+ file.weaponRUI = CreateCockpitRui( $"ui/weapon_flyout.rpak" )
+ file.flyoutShowTime = Time()
+
+ float flyoutDuration = IsPickupFlyoutValid() ? FLYOUT_DURATION_SHORT : FLYOUT_DURATION
+ file.lastFlyoutDuration = flyoutDuration
+
+ RuiSetGameTime( file.weaponRUI, "startTime", file.flyoutShowTime )
+ RuiSetFloat( file.weaponRUI, "duration", file.lastFlyoutDuration )
+
+ if ( IsMultiplayer() && file.flyoutLevelEnabled )
+ WeaponFlyoutRefresh()
+
+ if ( weapon.GetWeaponSettingBool( eWeaponVar.is_burn_mod ) )
+ RuiSetFloat3( file.weaponRUI, "color", BURN_CARD_WEAPON_HUD_COLOR_VECTOR )
+
+ string weaponPrintName = Localize( expect string( weapon.GetWeaponInfoFileKeyField( "shortprintname" ) ) )
+ string weaponDescription = weapon.GetWeaponDescription() + " "
+ RuiSetString( file.weaponRUI, "titleText", weaponPrintName )
+ RuiSetString( file.weaponRUI, "descriptionText", weaponDescription )
+
+ int modNum = 1
+ array<string> weaponMods = weapon.GetMods()
+ foreach ( mod in weaponMods )
+ {
+ if ( modNum >= 5 ) // setting mod5 in the rui crashes client
+ break
+
+ if ( mod in file.modImages )
+ RuiSetImage( file.weaponRUI, "mod" + modNum++, file.modImages[ mod ] )
+ }
+
+ RuiSetFloat( file.weaponRUI, "underlineHeight", 4.0 )
+ RuiSetFloat( file.weaponRUI, "underlineWidth", 4.0 )
+
+ int attachment = viewModel.LookupAttachment( "flyout" )
+ if ( attachment <= 0 )
+ attachment = viewModel.LookupAttachment( "shell" )
+
+ RuiTrackFloat3( file.weaponRUI, "pos", viewModel, RUI_TRACK_POINT_FOLLOW, attachment )
+
+ HidePickupFlyout( file.lastFlyoutDuration )
+
+ #if SP
+ ScriptCallback_UpdateOnscreenHint()
+ #endif
+}
+
+void function WeaponFlyoutRefresh()
+{
+ entity player = GetLocalViewPlayer()
+ if ( !IsValid( player ) )
+ return
+
+ if ( file.weaponRUI == null )
+ return
+
+ if ( file.flyoutShowTime + ( file.lastFlyoutDuration - 0.2 ) <= Time() )
+ return
+
+#if MP
+ if ( !ShouldTrackXPForWeapon( file.weaponClassName ) )
+ return
+
+ string persistenceVar = GetItemPersistenceStruct( file.weaponClassName ) + ".weaponXP"
+ int currentXP = player.GetPersistentVarAsInt( persistenceVar )
+
+ RuiSetInt( file.weaponRUI, "numPips", WeaponGetNumPipsForXP( file.weaponClassName, currentXP ) )
+ RuiSetInt( file.weaponRUI, "numFilledPips", WeaponGetFilledPipsForXP( file.weaponClassName, currentXP ) )
+ RuiSetString( file.weaponRUI, "currentLevel", WeaponGetDisplayGenAndLevelForXP( file.weaponClassName, currentXP ) )
+ RuiSetBool( file.weaponRUI, "showWeaponXP", true )
+#endif
+}
+
+void function WeaponFlyoutThink( entity player )
+{
+ if ( !WEAPON_FLYOUTS_ENABLED )
+ return
+
+ entity currentWeapon = player.GetActiveWeapon()
+
+ if ( !IsValid( currentWeapon ) )
+ return
+
+ string weaponClassName = currentWeapon.GetWeaponClassName()
+
+ if ( currentWeapon == player.p.previousWeapon )
+ return
+
+ if ( !ShouldShowWeaponFlyout( player, currentWeapon, weaponClassName ) )
+ return
+
+ player.p.previousWeapon = currentWeapon
+
+ WeaponFlyoutShow( currentWeapon, weaponClassName )
+}
+
+bool function ShouldShowWeaponFlyout( entity player, entity weapon, string weaponClassName )
+{
+ // Allow time for weapons to be disabled at level start
+ if ( Time() < 2.0 )
+ return false
+
+ // No weapon
+ if ( !IsValid( weapon ) )
+ return false
+
+ // MP can be dead with new weapon
+ if ( !IsAlive( player ) )
+ return false
+
+ if ( weapon.IsWeaponOffhand() )
+ return false
+
+ if ( GetWeaponInfoFileKeyField_Global( weaponClassName, "flyoutEnabled" ) == 0 )
+ return false
+
+ if ( player.IsWeaponDisabled() )
+ return false
+
+ if ( player.IsInThirdPersonReplay() )
+ return false
+
+ if ( GetGameState() < eGameState.Playing )
+ return false
+
+ if ( player.IsTitan() && GameRules_GetGameMode() == FD )
+ return false
+
+ if( !player.GetPlayerNetBool( "shouldShowWeaponFlyout" ) )
+ return false
+
+ return true
+}
+
+void function OnSelectedWeaponChanged( entity selectedWeapon )
+{
+ DestroyWeaponFlyout()
+}
+
+void function DestroyWeaponFlyout()
+{
+ if ( file.weaponRUI != null )
+ {
+ RuiDestroyIfAlive( file.weaponRUI )
+ file.weaponRUI = null
+ file.flyoutShowTime = -99.0
+ }
+
+ #if SP
+ ScriptCallback_UpdateOnscreenHint()
+ #endif
+}
+
+float function GetWeaponFlyoutAliveTime()
+{
+ return Time() - file.flyoutShowTime
+}
+
+float function GetWeaponFlyoutAliveTimeLeft()
+{
+ return file.flyoutShowTime + file.lastFlyoutDuration - Time()
+}
+
+bool function IsWeaponFlyoutVisible()
+{
+ return ( file.weaponRUI != null && ( file.flyoutShowTime + file.lastFlyoutDuration > Time() ) )
+}
+
+void function WeaponFlyout_SetLevelEnabled( bool state )
+{
+ file.flyoutLevelEnabled = state
+}
+
+void function SetWeaponFlyoutRemainingTime( float time )
+{
+ if ( file.weaponRUI == null )
+ return
+
+ file.flyoutShowTime = Time()
+ file.lastFlyoutDuration = time
+
+ RuiSetGameTime( file.weaponRUI, "startTime", file.flyoutShowTime )
+ RuiSetFloat( file.weaponRUI, "duration", file.lastFlyoutDuration )
+} \ No newline at end of file
diff --git a/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut b/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut
new file mode 100644
index 00000000..58850e6a
--- /dev/null
+++ b/Northstar.Client/mod/scripts/vscripts/sh_menu_models.gnut
@@ -0,0 +1,2906 @@
+// TODO:
+// Model tracking and save/Clear functions are temp. We already update the client knowledge of loadouts. Derive from that.
+// Move the struct off the player?
+
+#if CLIENT && MP
+ untyped
+#endif //client && MP
+
+#if CLIENT
+ const float CARD_TAG_SCALE = 0.0 // update to match same const in hud_defs.rui
+
+ const DEFAULT_FOV = 50.0
+ const DEFAULT_DOF_NEAR_START = 7.5
+ const DEFAULT_DOF_NEAR_END = 7.7
+ const DEFAULT_DOF_FAR_START = 200.0
+ const DEFAULT_DOF_FAR_END = 300.0
+ const TRANSITION_DURATION = 0.25
+
+ const DEFAULT_MAX_TURN_SPEED = 270.0
+ const PILOT_MAX_TURN_SPEED = 270.0
+ const TITAN_MAX_TURN_SPEED = 100.0
+
+ const MENU_COLOR_CORRECTION = "materials/correction/menu.raw"
+ const MENU_TEST_EFFECT = $"P_menu_motes"
+
+ const vector WEAPON_DLIGHT_COLOR = <0.65, 0.75, 1.0>
+
+ global struct MenuCharacterDef
+ {
+ asset bodyModel = $""
+ int camoIndex = -1
+ int skinIndex = 0
+ int decalIndex = -1
+ int loadoutIndex = 0
+ string idleAnim
+
+ string weapon
+ array<string> mods
+ asset weaponModel = $""
+ int weaponCamoIndex = -1
+ int weaponSkinIndex = -1
+
+ int showArmBadge = 0
+ asset armBadgeModel = $""
+ int armBadgeBodyGroupIndex = 0
+ bool isPrime = false
+ }
+
+ struct CharacterData
+ {
+ entity mover
+ entity body
+ entity weapon
+ entity prop
+ entity armBadge
+ string attachName
+ string bodyAnim
+ float[2] rotationDelta
+ float fovScale = 1.0
+ float maxTurnSpeed = DEFAULT_MAX_TURN_SPEED
+ }
+
+ struct PresentationDef
+ {
+ CharacterData ornull characterData = null
+ float maxTurnDegrees = 360.0
+ float maxPitchDegrees = 0.0
+ bool useRollAxis = true
+ string sceneAnim
+
+ float fov = DEFAULT_FOV
+ float dofNearStart = DEFAULT_DOF_NEAR_START
+ float dofNearEnd = DEFAULT_DOF_NEAR_END
+ float dofFarStart = DEFAULT_DOF_FAR_START
+ float dofFarEnd = DEFAULT_DOF_FAR_END
+
+ float csmTexelScale1 = 1.0
+ float csmTexelScale2 = 1.0
+ float csmStartDistance = 0.0
+
+ string pilotAnimType
+ string titanAnimType
+
+ bool showCallsign = false
+ bool showStoreBG = false
+ bool showStorePrimeBG = false
+ bool showMiscModel = false
+ bool showWeaponModel = false
+ bool showTitanModel = true // false would be a better default, but the hiding/showing of this stuff needs be done in a more general/flexible way, so leaving this for now
+
+ void functionref() activateFunc
+ }
+
+ struct
+ {
+ entity sceneRef
+ entity cameraTarget
+ float[2] mouseRotateDelta
+
+ CharacterData menuPilot
+ CharacterData menuTitan
+ CharacterData menuFaction
+ CharacterData menuMiscModel
+ CharacterData menuWeaponModel
+ CharacterData ornull activeCharacter = null
+ var menuCallsignRui
+ var menuCallsignTopo
+ var menuStoreBackground
+ var menuStorePrimeBg
+ var menuStorePrimeBgRui
+ var menuStorePrimeBgCreated
+
+ entity weaponDLight
+
+ float lastZoomTime
+
+ int presentationType = ePresentationType.INACTIVE
+ bool presentationTypeInitialized = false
+ PresentationDef[ePresentationType.COUNT] presentationData
+
+ table< string, table<string, table<int,string> > > pilotAnims
+ table< string, table<string, string> > titanAnims
+
+ int menuColorCorrection = -1
+ } file
+
+ global function MenuModels_Init
+ global function MenuMapEntitiesExist
+#endif //CLIENT
+
+#if CLIENT && MP
+ global function SetPresentationType
+
+ global function UpdatePilotModel
+ global function UpdateTitanModel
+ global function UpdateFactionModel
+ global function UpdateBoostModel
+ global function UpdateStoreBackground
+ global function UpdateStorePrimeBg
+ global function UpdateCallsignCard
+ global function UpdateCallsignIcon
+ global function UpdateCallsign
+
+ global function SetEditingPilotLoadoutIndex
+ global function ClearEditingPilotLoadoutIndex
+
+ global function SetHeldPilotWeaponType
+
+ global function SetEditingTitanLoadoutIndex
+ global function ClearEditingTitanLoadoutIndex
+
+ global function PreviewPilotCharacter
+ global function SavePilotCharacterPreview
+ global function PreviewPilotWeapon
+ global function SavePilotWeaponPreview
+ global function PreviewPilotWeaponCamoChange
+ global function PreviewPilotWeaponSkinChange
+ global function ClearAllPilotPreview
+
+ global function PreviewPilotWeaponMod
+ global function SavePilotWeaponModPreview
+
+ global function PreviewPilotCamoChange
+ //global function SavePilotCamoPreview
+
+ global function PreviewTitanCamoChange
+ global function SaveTitanCamoPreview
+ global function ClearTitanCamoPreview
+
+ global function PreviewTitanSkinChange
+ global function SaveTitanSkinPreview
+ global function ClearTitanSkinPreview
+
+ global function PreviewTitanDecalChange
+ global function SaveTitanDecalPreview
+ global function ClearTitanDecalPreview
+
+ global function PreviewTitanCombinedChange
+ global function SaveTitanCombinedPreview
+ global function ClearTitanCombinedPreview
+
+ global function PreviewTitanWeaponCamoChange
+ global function ClearAllTitanPreview
+
+ global function SetMenuOpenState
+
+ // Only these 2 functions are run from the server and they may not be needed. Remove server updates if possible.
+ global function ServerCallback_UpdatePilotModel
+ global function ServerCallback_UpdateTitanModel
+
+ global function GetMenuPilotBody
+ global function GetCallsignTopo
+
+ global function GetFactionModel
+ global function GetFactionModelSkin
+
+ global function UpdateStoreWeaponModelSkin
+ global function UpdateStoreWeaponModelZoom
+
+ global function UpdateMouseRotateDelta
+
+ global function GetMenuMiscModel // TODO: Remove when done testing
+
+ global function UpdateMenuToHarvester
+
+ global function GetDLightEntity
+#endif // CLIENT && MP
+
+#if UI
+ const MOUSE_ROTATE_MULTIPLIER = 25.0
+
+ global function UpdateUIMapSupportsMenuModels
+ global function RunMenuClientFunction
+ global function UI_SetPresentationType
+
+ global function UICodeCallback_MouseMovementCapture
+#endif // UI
+
+ global const STORE_BG_DEFAULT = 0
+ global const STORE_BG_BUNDLE1 = 1
+ global const STORE_BG_BUNDLE2 = 2
+ global const STORE_BG_BUNDLE3 = 3
+ global const STORE_BG_BUNDLE4 = 4
+ global const STORE_BG_BUNDLE5 = 5
+ global const STORE_BG_BUNDLE6 = 6
+
+#if CLIENT
+
+ var function GetCallsignTopo()
+ {
+ return file.menuCallsignTopo
+ }
+
+ entity function GetMenuPilotBody()
+ {
+ return file.menuPilot.body
+ }
+
+ void function MenuModels_Init()
+ {
+ if ( IsMultiplayer() && MenuMapEntitiesExist() )
+ clGlobal.mapSupportsMenuModels = true
+
+ RunUIScript( "UpdateUIMapSupportsMenuModels", clGlobal.mapSupportsMenuModels )
+
+ if ( !clGlobal.mapSupportsMenuModels )
+ return
+
+ #if MP
+ PrecacheParticleSystem( MENU_TEST_EFFECT )
+ file.menuColorCorrection = ColorCorrection_Register( MENU_COLOR_CORRECTION )
+
+ InitPresentationData()
+ InitMenuModelAnims()
+ thread InitMenuEntities( GetLocalClientPlayer() )
+ thread ModelRotationThread()
+ AddCallback_OnClientScriptInit( OnClientScriptInit )
+ #endif // MP
+
+ RegisterSignal( "UpdateCallsign" )
+ }
+
+ bool function MenuMapEntitiesExist()
+ {
+ array<string> entNames =
+ [
+ "menu_scene_ref",
+ "menu_camera_target"
+ ]
+
+ foreach ( name in entNames )
+ {
+ if ( GetEntArrayByScriptName( name ).len() != 1 )
+ return false
+ }
+
+ return true
+ }
+#endif // CLIENT
+
+#if UI
+ void function UpdateUIMapSupportsMenuModels( bool value )
+ {
+ uiGlobal.mapSupportsMenuModels = value
+ uiGlobal.mapSupportsMenuModelsUpdated = true
+
+ printt( Time(), "uiGlobal.mapSupportsMenuModelsUpdated set to: true" )
+ }
+#endif // UI
+
+#if CLIENT && MP
+ void function InitPresentationData()
+ {
+ // TODO: Rework so scenes can be defined in a more flexible way (what entities get created, shown, hidden, animated)
+ // TODO: Need anims happening a bit differently for transition support
+ // Interruptable function that plays intro anim and then idle if intro completes uninterrupted
+ // Outro anims should work the same
+
+ int presentationType = ePresentationType.INACTIVE
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_main_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+
+ presentationType = ePresentationType.DEFAULT
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_main_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Show spawn models
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+ file.presentationData[ presentationType ].showCallsign = true
+
+ presentationType = ePresentationType.STORE_CAMO_PACKS
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_main_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Show spawn models
+ file.presentationData[ presentationType ].dofFarStart = 200.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.STORE_FRONT
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_settings_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 2300.0
+ file.presentationData[ presentationType ].dofFarEnd = 3000.0
+ file.presentationData[ presentationType ].showStoreBG = true
+
+ presentationType = ePresentationType.STORE_PRIME_TITANS
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 4000.0
+ file.presentationData[ presentationType ].dofFarEnd = 5000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+ file.presentationData[ presentationType ].showStorePrimeBG = true
+
+ presentationType = ePresentationType.STORE_WEAPON_SKINS
+ file.presentationData[ presentationType ].characterData = file.menuWeaponModel
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_weapon_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].maxPitchDegrees = 90
+ file.presentationData[ presentationType ].dofFarStart = 4000.0
+ file.presentationData[ presentationType ].dofFarEnd = 5000.0
+ file.presentationData[ presentationType ].showWeaponModel = true
+ file.presentationData[ presentationType ].showTitanModel = false
+ //file.presentationData[ presentationType ].useRollAxis = true
+
+ presentationType = ePresentationType.SEARCH
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_main_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Show spawn models
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV + 10
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+ file.presentationData[ presentationType ].showCallsign = true
+
+ presentationType = ePresentationType.CALLSIGN
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_main_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Show spawn models
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.KNOWLEDGEBASE_MAIN
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "weapon_inspect_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV - 25
+ file.presentationData[ presentationType ].dofFarStart = 30.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.KNOWLEDGEBASE_SUB
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "weapon_inspect_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV - 28
+ file.presentationData[ presentationType ].dofFarStart = 30.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.PVE_MAIN
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "weapon_inspect_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV - 25
+ file.presentationData[ presentationType ].dofFarStart = 30.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.PILOT
+ file.presentationData[ presentationType ].characterData = file.menuPilot
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "focused_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 200.0
+ file.presentationData[ presentationType ].dofFarEnd = 300.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.4
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.PILOT_LOADOUT_EDIT
+ file.presentationData[ presentationType ].characterData = file.menuPilot
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "focused_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].dofFarStart = 200.0
+ file.presentationData[ presentationType ].dofFarEnd = 300.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.4
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.PILOT_CHARACTER
+ file.presentationData[ presentationType ].characterData = file.menuPilot
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "focused_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 200.0
+ file.presentationData[ presentationType ].dofFarEnd = 300.0
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.4
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.PILOT_WEAPON
+ file.presentationData[ presentationType ].characterData = file.menuPilot
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_loadout_edit_idle_01"
+ file.presentationData[ presentationType ].pilotAnimType = "weapon_inspect_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.22
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 40.0
+
+ presentationType = ePresentationType.TITAN
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_LOADOUT_EDIT
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_edit"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "editing_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_SKIN_EDIT
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_edit"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "editing_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_ARMBADGE
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_edit"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "editing_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_WEAPON
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "editing_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_NOSE_ART
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_noseart_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "nose_art_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Titan animation change
+ file.presentationData[ presentationType ].maxTurnDegrees = 100.0
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.NO_MODELS
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_settings_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+
+ presentationType = ePresentationType.FACTIONS
+ file.presentationData[ presentationType ].characterData = file.menuFaction
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_faction_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].csmTexelScale1 = 0.4
+ file.presentationData[ presentationType ].csmTexelScale2 = 0.55
+ file.presentationData[ presentationType ].csmStartDistance = 70.0
+
+ presentationType = ePresentationType.BOOSTS
+ file.presentationData[ presentationType ].characterData = file.menuMiscModel
+ file.presentationData[ presentationType ].sceneAnim = "camera_menu_burncard_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "main_idle"
+ file.presentationData[ presentationType ].titanAnimType = "background_idle"
+ file.presentationData[ presentationType ].showMiscModel = true
+
+ presentationType = ePresentationType.TITAN_CENTER
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_frontierdefense_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_CENTER_SELECTED
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_frontierdefense_idle_selected"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "editing_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV - 10
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_LEFT
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_left_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.TITAN_RIGHT
+ file.presentationData[ presentationType ].characterData = file.menuTitan
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_right_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+
+ presentationType = ePresentationType.FD_MAIN
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_frontierdefense_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "hidden_from_main"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+ file.presentationData[ presentationType ].showCallsign = true
+ file.presentationData[ presentationType ].showMiscModel = true
+
+ presentationType = ePresentationType.FD_SEARCH
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_frontierdefense_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "hidden_from_main"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV + 10
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+ file.presentationData[ presentationType ].showCallsign = true
+ file.presentationData[ presentationType ].showMiscModel = true
+
+ presentationType = ePresentationType.FD_FIND_GAME
+ file.presentationData[ presentationType ].sceneAnim = "camera_titan_menu_loadout_idle"
+ file.presentationData[ presentationType ].pilotAnimType = "background_idle"
+ file.presentationData[ presentationType ].titanAnimType = "focused_idle"
+ file.presentationData[ presentationType ].activateFunc = UpdateBothModels // Animation change
+ file.presentationData[ presentationType ].fov = DEFAULT_FOV + 10
+ file.presentationData[ presentationType ].dofFarStart = 500.0
+ file.presentationData[ presentationType ].dofFarEnd = 1000.0
+ file.presentationData[ presentationType ].csmStartDistance = 200.0
+ file.presentationData[ presentationType ].showCallsign = true
+ file.presentationData[ presentationType ].showMiscModel = true
+ }
+
+ void function UpdateBothModels()
+ {
+ entity player = GetLocalClientPlayer()
+
+ int loadoutIndex
+ if ( clGlobal.editingPilotLoadoutIndex != -1 )
+ loadoutIndex = clGlobal.editingPilotLoadoutIndex
+ else
+ loadoutIndex = GetPersistentSpawnLoadoutIndex( player, "pilot" )
+ UpdatePilotModel( player, loadoutIndex )
+
+ if ( clGlobal.editingTitanLoadoutIndex != -1 )
+ loadoutIndex = clGlobal.editingTitanLoadoutIndex
+ else
+ loadoutIndex = GetPersistentSpawnLoadoutIndex( player, "titan" )
+ UpdateTitanModel( player, loadoutIndex )
+ }
+
+ void function OnClientScriptInit( entity player )
+ {
+ UpdateCallsign( player )
+ }
+
+ void function InitMenuModelAnims()
+ {
+ string animType = "main_idle"
+ file.pilotAnims[ animType ] <- {}
+
+ string bodyType = "light"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "medium"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "heavy"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "nomad"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "stalker"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "geist"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ bodyType = "grapple"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_main_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_main_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_main_idle_01"
+
+ animType = "background_idle"
+ file.pilotAnims[ animType ] <- {}
+
+ bodyType = "light"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "medium"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "heavy"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "nomad"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "stalker"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "geist"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "grapple"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ animType = "focused_idle"
+ file.pilotAnims[ animType ] <- {}
+
+ bodyType = "light"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "medium"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "heavy"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "nomad"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "stalker"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "geist"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ bodyType = "grapple"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_idle_01"
+
+ animType = "weapon_inspect_idle"
+ file.pilotAnims[ animType ] <- {}
+
+ bodyType = "light"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "medium"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "heavy"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "nomad"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "stalker"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "geist"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ bodyType = "grapple"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_menu_loadout_edit_idle_02"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_menu_loadout_edit_idle_01"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_menu_loadout_edit_idle_03"
+
+ animType = "hidden_from_main"
+ file.pilotAnims[ animType ] <- {}
+
+ bodyType = "light"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "medium"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "heavy"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "nomad"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "stalker"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "geist"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ bodyType = "grapple"
+ file.pilotAnims[ animType ][ bodyType ] <- {}
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.SMALL ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.MEDIUM ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.LARGE ] <- "pt_titan_menu_loadout_idle"
+ file.pilotAnims[ animType ][ bodyType ][ eMenuAnimClass.CUSTOM ] <- "pt_titan_menu_loadout_idle"
+
+ animType = "background_idle"
+ file.titanAnims[ animType ] <- {}
+ file.titanAnims[ animType ][ "titan_stryder_arc" ] <- "titan_light_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_stryder_leadwall" ] <- "titan_light_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_stryder_sniper" ] <- "titan_light_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_stryder_northstar_prime" ] <- "titan_light_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_stryder_ronin_prime" ] <- "titan_light_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_atlas_tracker" ] <- "titan_medium_menu_main_idle_01_TONE"
+ file.titanAnims[ animType ][ "titan_atlas_vanguard" ] <- "titan_medium_menu_main_idle_01_MONARCH"
+ file.titanAnims[ animType ][ "titan_atlas_stickybomb" ] <- "titan_medium_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_atlas_ion_prime" ] <- "titan_medium_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_atlas_tone_prime" ] <- "titan_medium_menu_main_idle_01_TONE"
+ file.titanAnims[ animType ][ "titan_ogre_meteor" ] <- "titan_heavy_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_ogre_scorch_prime" ] <- "titan_heavy_menu_main_idle_01"
+ file.titanAnims[ animType ][ "titan_ogre_minigun" ] <- "titan_heavy_menu_main_idle_01_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_legion_prime" ] <- "titan_heavy_menu_main_idle_01_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_fighter" ] <- "titan_heavy_menu_main_idle_01"
+
+ animType = "focused_idle"
+ file.titanAnims[ animType ] <- {}
+ file.titanAnims[ animType ][ "titan_stryder_arc" ] <- "titan_light_menu_loadout_idle"
+ file.titanAnims[ animType ][ "titan_stryder_leadwall" ] <- "titan_light_menu_loadout_idle"
+ file.titanAnims[ animType ][ "titan_stryder_sniper" ] <- "titan_light_menu_loadout_idle_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_northstar_prime" ] <- "titan_light_menu_loadout_idle_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_ronin_prime" ] <- "titan_light_menu_loadout_idle"
+ file.titanAnims[ animType ][ "titan_atlas_tracker" ] <- "titan_medium_menu_loadout_idle"
+ file.titanAnims[ animType ][ "titan_atlas_vanguard" ] <- "titan_medium_menu_loadout_idle_MONARCH"
+ file.titanAnims[ animType ][ "titan_atlas_stickybomb" ] <- "titan_medium_menu_loadout_idle_ION"
+ file.titanAnims[ animType ][ "titan_atlas_ion_prime" ] <- "titan_medium_menu_loadout_idle_ION"
+ file.titanAnims[ animType ][ "titan_atlas_tone_prime" ] <- "titan_medium_menu_loadout_idle"
+ file.titanAnims[ animType ][ "titan_ogre_meteor" ] <- "titan_heavy_menu_loadout_idle_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_scorch_prime" ] <- "titan_heavy_menu_loadout_idle_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_minigun" ] <- "titan_heavy_menu_loadout_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_legion_prime" ] <- "titan_heavy_menu_loadout_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_fighter" ] <- "titan_heavy_menu_loadout_idle"
+
+ animType = "editing_idle"
+ file.titanAnims[ animType ] <- {}
+ file.titanAnims[ animType ][ "titan_stryder_arc" ] <- "titan_light_menu_loadout_idle_edit_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_leadwall" ] <- "titan_light_menu_loadout_idle_edit_RONIN"
+ file.titanAnims[ animType ][ "titan_stryder_sniper" ] <- "titan_light_menu_loadout_idle_edit_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_northstar_prime" ] <- "titan_light_menu_loadout_idle_edit_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_ronin_prime" ] <- "titan_light_menu_loadout_idle_edit_RONIN"
+ file.titanAnims[ animType ][ "titan_atlas_tracker" ] <- "titan_medium_menu_loadout_idle_edit_TONE"
+ file.titanAnims[ animType ][ "titan_atlas_vanguard" ] <- "titan_medium_menu_loadout_idle_edit_MONARCH"
+ file.titanAnims[ animType ][ "titan_atlas_stickybomb" ] <- "titan_medium_menu_loadout_idle_edit_ION"
+ file.titanAnims[ animType ][ "titan_atlas_ion_prime" ] <- "titan_medium_menu_loadout_idle_edit_ION"
+ file.titanAnims[ animType ][ "titan_atlas_tone_prime" ] <- "titan_medium_menu_loadout_idle_edit_TONE"
+ file.titanAnims[ animType ][ "titan_ogre_meteor" ] <- "titan_heavy_menu_loadout_idle_edit_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_scorch_prime" ] <- "titan_heavy_menu_loadout_idle_edit_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_minigun" ] <- "titan_heavy_menu_loadout_idle_edit_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_legion_prime" ] <- "titan_heavy_menu_loadout_idle_edit_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_fighter" ] <- "titan_heavy_menu_loadout_idle_edit_LEGION"
+
+ animType = "nose_art_idle"
+ file.titanAnims[ animType ] <- {}
+ file.titanAnims[ animType ][ "titan_stryder_arc" ] <- "titan_light_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_stryder_leadwall" ] <- "titan_light_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_stryder_sniper" ] <- "titan_light_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_stryder_northstar_prime" ] <- "titan_light_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_stryder_ronin_prime" ] <- "titan_light_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_atlas_tracker" ] <- "titan_medium_menu_noseart_idle_TONE"
+ file.titanAnims[ animType ][ "titan_atlas_vanguard" ] <- "titan_medium_menu_noseart_idle_MONARCH"
+ file.titanAnims[ animType ][ "titan_atlas_stickybomb" ] <- "titan_medium_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_atlas_ion_prime" ] <- "titan_medium_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_atlas_tone_prime" ] <- "titan_medium_menu_noseart_idle_TONE"
+ file.titanAnims[ animType ][ "titan_ogre_meteor" ] <- "titan_heavy_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_ogre_scorch_prime" ] <- "titan_heavy_menu_noseart_idle"
+ file.titanAnims[ animType ][ "titan_ogre_minigun" ] <- "titan_heavy_menu_noseart_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_legion_prime" ] <- "titan_heavy_menu_noseart_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_fighter" ] <- "titan_heavy_menu_noseart_idle"
+
+ animType = "fd_idle"
+ file.titanAnims[ animType ] <- {}
+ file.titanAnims[ animType ][ "titan_stryder_leadwall" ] <- "titan_light_menu_FD_idle_RONIN"
+ file.titanAnims[ animType ][ "titan_stryder_sniper" ] <- "titan_light_menu_FD_idle_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_northstar_prime" ] <- "titan_light_menu_FD_idle_NSTAR"
+ file.titanAnims[ animType ][ "titan_stryder_ronin_prime" ] <- "titan_light_menu_FD_idle_RONIN"
+ file.titanAnims[ animType ][ "titan_atlas_tracker" ] <- "titan_medium_menu_FD_idle_TONE"
+ file.titanAnims[ animType ][ "titan_atlas_vanguard" ] <- "titan_medium_menu_FD_idle_MONARCH"
+ file.titanAnims[ animType ][ "titan_atlas_stickybomb" ] <- "titan_medium_menu_FD_idle_ION"
+ file.titanAnims[ animType ][ "titan_atlas_ion_prime" ] <- "titan_medium_menu_FD_idle_ION"
+ file.titanAnims[ animType ][ "titan_atlas_tone_prime" ] <- "titan_medium_menu_FD_idle_TONE"
+ file.titanAnims[ animType ][ "titan_ogre_meteor" ] <- "titan_heavy_menu_FD_idle_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_scorch_prime" ] <- "titan_heavy_menu_FD_idle_SCORCH"
+ file.titanAnims[ animType ][ "titan_ogre_minigun" ] <- "titan_heavy_menu_FD_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_ogre_legion_prime" ] <- "titan_heavy_menu_FD_idle_LEGION"
+ file.titanAnims[ animType ][ "titan_stryder_arc" ] <- "titan_light_menu_FD_idle_RONIN"
+ file.titanAnims[ animType ][ "titan_ogre_fighter" ] <- "titan_heavy_menu_FD_idle_SCORCH"
+ }
+
+ string function GetPilotAnimType()
+ {
+ return file.presentationData[ file.presentationType ].pilotAnimType
+ }
+
+ string function GetTitanAnimType()
+ {
+ return file.presentationData[ file.presentationType ].titanAnimType
+ }
+
+ string function GetMenuPilotAnim( string animType, string bodyType, int menuAnimClass )
+ {
+ Assert( animType in file.pilotAnims )
+ Assert( bodyType in file.pilotAnims[ animType ] )
+ Assert( menuAnimClass in file.pilotAnims[ animType ][ bodyType ] )
+
+ return file.pilotAnims[ animType ][ bodyType ][ menuAnimClass ]
+ }
+
+ string function GetMenuTitanAnim( string anim, string setFile )
+ {
+ Assert( anim in file.titanAnims )
+ Assert( setFile in file.titanAnims[ anim ] )
+
+ return file.titanAnims[ anim ][ setFile ]
+ }
+
+ void function InitMenuEntities( entity player )
+ {
+ file.sceneRef = GetEntByScriptName( "menu_scene_ref" )
+ vector refOrigin = file.sceneRef.GetOrigin()
+ vector refAngles = file.sceneRef.GetAngles()
+
+ entity environmentModel = CreateClientSidePropDynamic( refOrigin, refAngles, DEFAULT_MENU_ENVIRONMENT_MODEL )
+ environmentModel.kv.solid = 0
+ environmentModel.kv.disableshadows = 1
+ environmentModel.MakeSafeForUIScriptHack()
+
+ #if DEV
+ if ( BuildingCubeMaps() )
+ return
+ #endif
+
+ file.cameraTarget = GetEntByScriptName( "menu_camera_target" )
+ clGlobal.menuCamera = CreateClientSidePointCamera( <0, 0, 0>, <0, 0, 0>, DEFAULT_FOV )
+
+ CreateMenuFX( environmentModel )
+
+
+ // Create scene model
+ clGlobal.menuSceneModel = CreateClientSidePropDynamic( refOrigin, refAngles, GetSetFileModel( DEFAULT_PILOT_SETTINGS ) )
+ clGlobal.menuSceneModel.Hide()
+ clGlobal.menuSceneModel.MakeSafeForUIScriptHack()
+ file.cameraTarget.SetParent( clGlobal.menuSceneModel, "VDU", false, 0.0 )
+
+ // Create movers
+ CreateMover( file.menuPilot, "ORIGIN", PILOT_MAX_TURN_SPEED )
+ CreateMover( file.menuTitan, "PROPGUN", TITAN_MAX_TURN_SPEED )
+ CreateMover( file.menuFaction, "CHESTFOCUS" )
+ CreateMover( file.menuMiscModel, "HEADFOCUS" )
+ CreateMover( file.menuWeaponModel, "HEADFOCUS" )
+ /*{
+ vector origin = clGlobal.menuSceneModel.GetAttachmentOrigin( clGlobal.menuSceneModel.LookupAttachment( "HEADFOCUS" ) )
+ file.menuWeaponModel.mover.ClearParent()
+ file.menuWeaponModel.mover.SetOrigin( origin + <16, -3, 4> )
+ file.menuWeaponModel.mover.SetParent( clGlobal.menuSceneModel, "HEADFOCUS", true, 0.0 )
+
+ file.weaponDLight = CreateClientSideDynamicLight( origin, <0,0,0>, <0, 0, 0>, 512.0 )
+ }*/
+
+ //thread DrawTag( clGlobal.menuSceneModel, "ORIGIN" )
+ //thread DrawTag( clGlobal.menuSceneModel, "PROPGUN" )
+ //thread DrawTag( clGlobal.menuSceneModel, "CHESTFOCUS" )
+ //thread DrawTag( clGlobal.menuSceneModel, "HEADFOCUS" )
+
+ //thread DrawOrg( file.menuPilot.mover )
+ //thread DrawOrg( file.menuTitan.mover )
+ //thread DrawOrg( file.menuFaction.mover )
+ //thread DrawOrg( file.menuMiscModel.mover )
+ //thread DrawOrg( file.menuWeaponModel.mover )
+
+ WaitSignal( level, "CachedLoadoutsReady" )
+
+ CreatePilotModel( player, file.menuPilot.mover )
+ CreateTitanModel( player, file.menuTitan.mover )
+ CreateFactionModel( player, file.menuFaction.mover )
+ CreateMiscModel( player, file.menuMiscModel.mover )
+ file.menuWeaponModel.body = CreateModelForMover( player, file.menuWeaponModel.mover )
+
+ #if HAS_WORLD_CALLSIGN
+ CreateCallsign( player, clGlobal.menuSceneModel )
+ #endif
+ CreateStoreBackground( player )
+
+ clGlobal.initializedMenuModels = true
+ UpdateCallsign( player )
+ }
+
+ entity function GetDLightEntity()
+ {
+// return file.weaponDLight
+ return file.menuWeaponModel.body
+ }
+
+ void function CreateMover( CharacterData character, string attachName, float maxTurnSpeed = DEFAULT_MAX_TURN_SPEED )
+ {
+ character.mover = CreateClientsideScriptMover( $"models/dev/empty_model.mdl", <0, 0, 0>, <0, 0, 0> )
+ character.mover.SetParent( clGlobal.menuSceneModel, attachName, false, 0.0 )
+ character.attachName = attachName
+ character.maxTurnSpeed = maxTurnSpeed
+ }
+
+ void function CreatePilotModel( entity player, entity mover )
+ {
+ int team = player.GetTeam()
+ int loadoutIndex = GetPersistentSpawnLoadoutIndex( player, "pilot" )
+ string suit = GetPilotLoadoutSuit( loadoutIndex )
+ string genderRace = GetPilotLoadoutGenderRace( loadoutIndex )
+ string setFile = GetSuitAndGenderBasedSetFile( suit, genderRace )
+ asset bodyModel = GetSetFileModel( setFile )
+
+ vector refOrigin = mover.GetOrigin()
+ vector refAngles = mover.GetAngles()
+
+ if ( DREW_MODE == 1 ) // TEMPHACK
+ {
+ refOrigin = refOrigin + <0, 0, -1000>
+ }
+ else if ( DREW_MODE == 2 )
+ {
+ entity greenScreenEnt = CreateClientSidePropDynamic( <0, 0, 0>, <0, 0, 0>, GREEN_SCREEN_MODEL )
+ greenScreenEnt.MakeSafeForUIScriptHack()
+ greenScreenEnt.kv.disableshadows = 1
+ }
+
+ entity bodyEnt = CreateClientSidePropDynamic( refOrigin, refAngles, bodyModel )
+ bodyEnt.SetParent( mover )
+ bodyEnt.SetAlive( true )
+ bodyEnt.SetVisibleForLocalPlayer( 0 )
+ bodyEnt.MakeSafeForUIScriptHack()
+ SetTeam( bodyEnt, team )
+
+ file.menuPilot.body = bodyEnt
+
+ string attachName = "PROPGUN"
+ int attachIndex = bodyEnt.LookupAttachment( attachName )
+ vector origin = bodyEnt.GetAttachmentOrigin( attachIndex )
+ vector angles = bodyEnt.GetAttachmentAngles( attachIndex )
+ string weapon = GetPilotLoadoutWeapon( loadoutIndex, clGlobal.heldPilotWeaponType )
+ entity weaponEnt = CreateWeaponModel( weapon, origin, angles )
+
+ weaponEnt.SetParent( bodyEnt, attachName, false, 0.0 )
+
+ bodyEnt.SetIKWeapon( weaponEnt )
+ file.menuPilot.weapon = weaponEnt
+ }
+
+ var function CreateCallsignTopology( vector org, vector ang, float width, float height )
+ {
+ // adjust so the RUI is drawn with the org as its center point
+ org += ( (AnglesToRight( ang )*-1) * (width*0.5) )
+ org += ( AnglesToUp( ang ) * (height*0.5) )
+
+ // right and down vectors that get added to base org to create the display size
+ vector right = ( AnglesToRight( ang ) * width )
+ vector down = ( (AnglesToUp( ang )*-1) * height )
+
+ return RuiTopology_CreatePlane( org, right, down, true )
+ }
+
+ void function CreateCallsign( entity player, entity mover )
+ {
+ //var topo = CreateCallsignTopology( GetMenuPilotBody().GetOrigin() + <110, 32, 100>, < 0, 45, 6 >, 32 * 1.25, 17 * 1.25 )
+ //var topo = CreateCallsignTopology( GetMenuPilotBody().GetOrigin() + <98, 16, 92>, < 0, 45, 6 >, 32 * 1.15, 17 * 1.15 )
+ var topo = CreateCallsignTopology( < -32, 50, 67 >, <0, 165, 6>, 28, 15 + (28 * CARD_TAG_SCALE) )
+ RuiTopology_SetParent( topo, mover, "ORIGIN" )
+ var rui = RuiCreate( $"ui/callsign_basic.rpak", topo, RUI_DRAW_WORLD, 0 )
+ file.menuCallsignRui = rui
+ file.menuCallsignTopo = topo
+
+ UpdateCallsign( player )
+ }
+
+ void function CreateStoreBackground( entity player )
+ {
+ file.menuStoreBackground = CreateClientSidePropDynamic( <68.1134, 377.554, -21.029>, <0.0, 225.0, 0.0>, $"models/test/brad/store_card.mdl" )
+ }
+
+ void function UpdateStoreBackground( entity player, int storeBgIndex )
+ {
+ switch ( storeBgIndex )
+ {
+ case STORE_BG_DEFAULT:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_card.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE1:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_card_angel_city.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE2:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_card_colony.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE3:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_card_relic.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE4:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_card_prime_bundle.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE5:
+ file.menuStoreBackground.SetModel( $"models/test/brad/store_weapon_warpaint_bundle.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ case STORE_BG_BUNDLE6:
+ file.menuStoreBackground.SetModel( $"models/test/brad/jump_start.mdl" )
+ file.menuStoreBackground.SetOrigin( <68.1134, 377.554, -18.25> )
+ break
+ }
+ }
+
+ void function UpdateStorePrimeBg( entity player, int loadoutIndex )
+ {
+ switch ( loadoutIndex )
+ {
+ case 0:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_ion_bg" )
+ break
+ case 1:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_scorch_bg" )
+ break
+ case 2:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_northstar_bg" )
+ break
+ case 3:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_ronin_bg" )
+ break
+ case 4:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_tone_bg" )
+ break
+ case 5:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_legion_bg" )
+ break
+ case 6:
+ RuiSetImage( file.menuStorePrimeBgRui, "bgImage", $"rui/menu/store/prime_vanguard_bg" )
+ break
+ }
+ }
+
+ void function UpdateCallsign( entity player )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ #if HAS_WORLD_CALLSIGN
+ CallingCard callingCard = PlayerCallingCard_GetActive( player )
+ CallsignIcon callsignIcon = PlayerCallsignIcon_GetActive( player )
+
+ RuiSetImage( file.menuCallsignRui, "cardImage", callingCard.image )
+ RuiSetInt( file.menuCallsignRui, "layoutType", callingCard.layoutType )
+ RuiSetImage( file.menuCallsignRui, "iconImage", callsignIcon.image )
+ RuiSetString( file.menuCallsignRui, "playerLevel", PlayerXPDisplayGenAndLevel( player.GetGen(), player.GetLevel() ) )
+ RuiSetString( file.menuCallsignRui, "playerName", player.GetPlayerName() )
+ RuiSetImage( file.menuCallsignRui, "cardGenImage", PlayerXPGetGenIcon( player ) ) //Commented Out Temporarily to Fix Blocker Bug: 220132
+ RuiSetBool( file.menuCallsignRui, "isLobbyCard", true )
+
+ thread KeepCallsignUpToDate( player )
+ #endif
+ }
+
+ void function KeepCallsignUpToDate( entity player )
+ {
+ #if HAS_WORLD_CALLSIGN
+ player.Signal( "UpdateCallsign" )
+ player.EndSignal( "UpdateCallsign" )
+
+ while ( IsValid( player ) )
+ {
+ CallingCard callingCard = PlayerCallingCard_GetActive( player )
+ CallsignIcon callsignIcon = PlayerCallsignIcon_GetActive( player )
+ RuiSetString( file.menuCallsignRui, "playerName", player.GetPlayerName() )
+ RuiSetString( file.menuCallsignRui, "playerLevel", PlayerXPDisplayGenAndLevel( player.GetGen(), player.GetLevel() ) )
+ RuiSetImage( file.menuCallsignRui, "cardImage", callingCard.image )
+ RuiSetImage( file.menuCallsignRui, "iconImage", callsignIcon.image )
+ RuiSetImage( file.menuCallsignRui, "cardGenImage", PlayerXPGetGenIcon( player ) ) //Commented Out Temporarily to Fix Blocker Bug: 220132
+ RuiSetInt( file.menuCallsignRui, "layoutType", callingCard.layoutType )
+ wait 0.5
+ }
+ #endif
+ }
+
+ entity function CreateWeaponModel( string weapon, vector origin, vector angles )
+ {
+ entity weaponEnt = CreateClientSidePropDynamic( origin, angles, GetWeaponModel( weapon ) )
+ weaponEnt.MakeSafeForUIScriptHack()
+
+ return weaponEnt
+ }
+
+ void function CreateTitanModel( entity player, entity mover )
+ {
+ int team = player.GetTeam()
+ int loadoutIndex = GetPersistentSpawnLoadoutIndex( player, "titan" )
+ string setFile = GetTitanLoadoutSetFile( loadoutIndex )
+ asset chassisModel = GetSetFileModel( setFile )
+
+ vector refOrigin = mover.GetOrigin()
+ vector refAngles = mover.GetAngles()
+
+ if ( DREW_MODE == 1 ) // TEMPHACK
+ refOrigin = refOrigin + < 0, 0, -1000 >
+
+ entity chassisEnt = CreateClientSidePropDynamic( refOrigin, refAngles, chassisModel )
+ chassisEnt.SetParent( mover )
+ chassisEnt.SetAlive( true )
+ chassisEnt.SetVisibleForLocalPlayer( 0 )
+ chassisEnt.MakeSafeForUIScriptHack()
+ SetTeam( chassisEnt, team )
+
+ file.menuTitan.body = chassisEnt
+
+ int attachIndex = chassisEnt.LookupAttachment( "PROPGUN" )
+ vector origin = chassisEnt.GetAttachmentOrigin( attachIndex )
+ vector angles = chassisEnt.GetAttachmentAngles( attachIndex )
+
+ string weapon = GetTitanLoadoutPrimary( loadoutIndex )
+ asset weaponModel = GetWeaponModel( weapon )
+
+ entity weaponEnt = CreateClientSidePropDynamic( origin, angles, weaponModel )
+ weaponEnt.SetParent( chassisEnt, "PROPGUN", false, 0.0 )
+ weaponEnt.MakeSafeForUIScriptHack()
+ file.menuTitan.weapon = weaponEnt
+ }
+
+ void function CreateFactionModel( entity player, entity mover )
+ {
+ int team = player.GetTeam()
+ string ref = GetFactionChoice( player )
+ asset bodyModel = GetFactionModel( ref )
+ int skin = GetFactionModelSkin( ref )
+
+ vector refOrigin = mover.GetOrigin()
+ vector refAngles = mover.GetAngles()
+
+ entity bodyEnt = CreateClientSidePropDynamic( refOrigin, refAngles, bodyModel )
+ bodyEnt.SetParent( mover )
+ bodyEnt.SetAlive( true )
+ bodyEnt.SetVisibleForLocalPlayer( 0 )
+ bodyEnt.MakeSafeForUIScriptHack()
+ bodyEnt.SetSkin( skin )
+ SetTeam( bodyEnt, team )
+
+ file.menuFaction.body = bodyEnt
+
+ entity propEnt = CreateFactionPropModel( bodyEnt, ref )
+ if ( IsValid( file.menuFaction.weapon ) )
+ file.menuFaction.weapon.Destroy()
+
+ file.menuFaction.weapon = propEnt
+ }
+
+ entity function CreateFactionPropModel( entity baseEnt, string ref )
+ {
+ string attachName = GetFactionPropAttachment( ref )
+ if ( attachName == "" )
+ return null
+
+ int attachIndex = baseEnt.LookupAttachment( attachName )
+ vector origin = baseEnt.GetAttachmentOrigin( attachIndex )
+ vector angles = baseEnt.GetAttachmentAngles( attachIndex )
+ asset propModel = GetFactionPropModel( ref )
+
+ entity propEnt = CreateClientSidePropDynamic( origin, angles, propModel )
+ propEnt.SetParent( baseEnt, attachName, false, 0.0 )
+ propEnt.MakeSafeForUIScriptHack()
+
+ return propEnt
+ }
+
+ void function CreateMiscModel( entity player, entity mover )
+ {
+ entity modelEnt = CreateClientSidePropDynamic( mover.GetOrigin(), mover.GetAngles(), $"models/dev/empty_model.mdl" )
+ modelEnt.SetParent( mover )
+ modelEnt.SetVisibleForLocalPlayer( 0 )
+ modelEnt.MakeSafeForUIScriptHack()
+
+ file.menuMiscModel.body = modelEnt
+ }
+
+
+ entity function CreateModelForMover( entity player, entity mover )
+ {
+ entity modelEnt = CreateClientSidePropDynamic( mover.GetOrigin(), mover.GetAngles(), $"models/dev/empty_model.mdl" )
+ modelEnt.SetParent( mover )
+ modelEnt.SetVisibleForLocalPlayer( 0 )
+ modelEnt.MakeSafeForUIScriptHack()
+
+ return modelEnt
+ }
+
+ entity function CreateAttachedModel( entity baseEnt, asset model, string attachName )
+ {
+ int attachIndex = baseEnt.LookupAttachment( attachName )
+ vector origin = baseEnt.GetAttachmentOrigin( attachIndex )
+ vector angles = baseEnt.GetAttachmentAngles( attachIndex )
+
+ entity propEnt = CreateClientSidePropDynamic( origin, angles, model )
+ propEnt.SetParent( baseEnt, attachName, false, 0.0 )
+ propEnt.MakeSafeForUIScriptHack()
+
+ return propEnt
+ }
+
+ void function CreateMenuFX( entity model )
+ {
+ int index = GetParticleSystemIndex( MENU_TEST_EFFECT )
+ int attachID = model.LookupAttachment( "ORIGIN" )
+
+ printt( index )
+ printt( model )
+ printt( attachID )
+ int fxID = StartParticleEffectOnEntity( model, index, FX_PATTACH_POINT_FOLLOW, attachID )
+ EffectSetDontKillForReplay( fxID )
+ }
+
+ void function ServerCallback_UpdatePilotModel( int loadoutIndex )
+ {
+ if ( !clGlobal.mapSupportsMenuModels )
+ return
+
+ entity player = GetLocalClientPlayer()
+
+ UpdatePilotModel( player, loadoutIndex )
+ }
+
+ void function UpdatePilotModel( entity player, int loadoutIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ string genderRace = GetPilotLoadoutGenderRace( loadoutIndex )
+ string suit = GetPilotLoadoutSuit( loadoutIndex )
+ string setFile = GetSuitAndGenderBasedSetFile( suit, genderRace )
+ string weapon = GetPilotLoadoutWeapon( loadoutIndex, clGlobal.heldPilotWeaponType )
+ array<string> mods = GetPilotLoadoutWeaponMods( loadoutIndex, clGlobal.heldPilotWeaponType )
+ mods.removebyvalue( "" )
+ mods.removebyvalue( "none" )
+
+ asset bodyModel = GetSetFileModel( setFile )
+ asset weaponModel = GetWeaponModel( weapon )
+ string idleAnim = GetMenuPilotAnim( GetPilotAnimType(), suit, GetItemMenuAnimClass( weapon ) )
+ int camoIndex = GetPilotCamoIndex( loadoutIndex )
+ int weaponSkinIndex = GetPilotLoadoutWeaponSkinIndex( loadoutIndex, clGlobal.heldPilotWeaponType )
+ int weaponCamoIndex = GetPilotLoadoutWeaponCamoIndex( loadoutIndex, clGlobal.heldPilotWeaponType )
+
+ clGlobal.currentMenuPilotModels.loadoutIndex = loadoutIndex
+ clGlobal.currentMenuPilotModels.bodyModel = bodyModel
+ clGlobal.currentMenuPilotModels.camoIndex = camoIndex
+ clGlobal.currentMenuPilotModels.idleAnim = idleAnim
+
+ clGlobal.currentMenuPilotModels.weapon = weapon
+ clGlobal.currentMenuPilotModels.weaponModel = weaponModel
+ clGlobal.currentMenuPilotModels.weaponSkinIndex = weaponSkinIndex
+ clGlobal.currentMenuPilotModels.weaponCamoIndex = weaponCamoIndex
+ clGlobal.currentMenuPilotModels.mods = mods
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function ServerCallback_UpdateTitanModel( int loadoutIndex, int flags = 0 )
+ {
+ if ( !clGlobal.mapSupportsMenuModels )
+ return
+
+ entity player = GetLocalClientPlayer()
+
+ UpdateTitanModel( player, loadoutIndex, flags )
+ }
+
+ void function UpdateTitanModel( entity player, int loadoutIndex, int flags = 0 )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ if ( loadoutIndex == -1 )
+ {
+ file.menuTitan.body.Hide()
+ file.menuTitan.weapon.Hide()
+
+ return
+ }
+
+ file.menuTitan.body.Show()
+ file.menuTitan.weapon.Show()
+
+ TitanLoadoutDef cachedLoadout = GetCachedTitanLoadout( loadoutIndex )
+ string setFile
+ if ( flags & TITANMENU_FORCE_NON_PRIME )
+ setFile = GetSetFileForTitanClassAndPrimeStatus( cachedLoadout.titanClass, false )
+ else if ( flags & TITANMENU_FORCE_PRIME )
+ setFile = GetSetFileForTitanClassAndPrimeStatus( cachedLoadout.titanClass, true )
+ else
+ setFile = GetTitanLoadoutSetFile( loadoutIndex )
+
+ string weapon = GetTitanLoadoutPrimary( loadoutIndex )
+ asset chassisModel = GetSetFileModel( setFile )
+ asset weaponModel = GetWeaponModel( weapon )
+ string idleAnim = GetMenuTitanAnim( GetTitanAnimType(), setFile )
+ int camoIndex
+ int skinIndex
+ int decalIndex
+ int weaponCamoIndex
+ int showArmBadge
+
+ if ( !( flags & TITANMENU_NO_CUSTOMIZATION ) )
+ {
+ camoIndex = GetTitanCamoIndex( loadoutIndex )
+ skinIndex = GetTitanSkinIndex( loadoutIndex )
+ decalIndex = GetTitanDecalIndex( loadoutIndex )
+ weaponCamoIndex = cachedLoadout.primaryCamoIndex
+ showArmBadge = GetTitanLoadoutArmBadgeState( loadoutIndex )
+ }
+
+ clGlobal.currentMenuTitanModels.isPrime = Dev_GetPlayerSettingByKeyField_Global( setFile, "isPrime" ) == 1
+ clGlobal.currentMenuTitanModels.loadoutIndex = loadoutIndex
+ clGlobal.currentMenuTitanModels.bodyModel = chassisModel
+ clGlobal.currentMenuTitanModels.camoIndex = camoIndex
+ clGlobal.currentMenuTitanModels.skinIndex = skinIndex
+ clGlobal.currentMenuTitanModels.decalIndex = decalIndex
+ clGlobal.currentMenuTitanModels.idleAnim = idleAnim
+
+ clGlobal.currentMenuTitanModels.weaponModel = weaponModel
+ clGlobal.currentMenuTitanModels.weaponCamoIndex = weaponCamoIndex
+
+ asset armBadgeModel = GetTitanLoadoutArmBadge( loadoutIndex )
+ clGlobal.currentMenuTitanModels.armBadgeModel = armBadgeModel
+ clGlobal.currentMenuTitanModels.armBadgeBodyGroupIndex = armBadgeModel != $"" ? 0 : 0
+ clGlobal.currentMenuTitanModels.showArmBadge = showArmBadge
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function UpdatePilotModelDisplay( entity player )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ asset bodyModel = clGlobal.previewMenuPilotModels.bodyModel
+ if ( bodyModel == $"" )
+ bodyModel = clGlobal.currentMenuPilotModels.bodyModel
+
+ string idleAnim = clGlobal.previewMenuPilotModels.idleAnim
+ if ( idleAnim == "" )
+ idleAnim = clGlobal.currentMenuPilotModels.idleAnim
+
+ bool playIdle = false
+ if ( file.menuPilot.body.GetModelName() != bodyModel || idleAnim != file.menuPilot.bodyAnim ) // Model has changed or anim has changed
+ playIdle = true
+
+ file.menuPilot.body.SetModel( bodyModel )
+
+ int camoIndex = clGlobal.previewMenuPilotModels.camoIndex
+ if ( camoIndex == -1 )
+ camoIndex = clGlobal.currentMenuPilotModels.camoIndex
+
+ if ( camoIndex > 0 )
+ {
+ file.menuPilot.body.SetSkin( PILOT_SKIN_INDEX_CAMO )
+ file.menuPilot.body.SetCamo( camoIndex )
+ }
+ else
+ {
+ file.menuPilot.body.SetSkin( 0 )
+ file.menuPilot.body.SetCamo( -1 )
+ }
+
+ if ( playIdle )
+ {
+ PlayMenuAnim( file.menuPilot.body, idleAnim )
+ file.menuPilot.bodyAnim = idleAnim
+ }
+
+ string weapon = clGlobal.previewMenuPilotModels.weapon
+ if ( weapon == "" )
+ weapon = clGlobal.currentMenuPilotModels.weapon
+
+ asset weaponModel = clGlobal.previewMenuPilotModels.weaponModel
+ if ( weaponModel == $"" )
+ weaponModel = clGlobal.currentMenuPilotModels.weaponModel
+
+ file.menuPilot.weapon.SetSkin( WEAPON_SKIN_INDEX_DEFAULT ) // Lame that we need this, but this avoids invalid skin errors when the model changes and the currently shown skin index doesn't exist for the new model
+ file.menuPilot.weapon.SetModel( weaponModel )
+
+ bool isPreviewingWeaponNotMatchingCurrent = clGlobal.previewMenuPilotModels.weaponModel != $"" && clGlobal.previewMenuPilotModels.weaponModel != clGlobal.currentMenuPilotModels.weaponModel
+
+ array<string> mods = clGlobal.previewMenuPilotModels.mods
+ if ( mods.len() == 0 )
+ {
+ // Don't show mods if previewing a weapon that isn't already equipped
+ if ( isPreviewingWeaponNotMatchingCurrent )
+ mods = []
+ else
+ mods = clGlobal.currentMenuPilotModels.mods
+ }
+ SetBodyGroupsForWeaponConfig( file.menuPilot.weapon, weapon, mods )
+
+ int weaponCamoIndex
+ int weaponSkinIndex
+ if ( isPreviewingWeaponNotMatchingCurrent )
+ {
+ weaponCamoIndex = 0
+ weaponSkinIndex = 0
+ }
+ else
+ {
+ // Skin or camo preview is active so use preview values for both
+ if ( clGlobal.previewMenuPilotModels.weaponSkinIndex != -1 || clGlobal.previewMenuPilotModels.weaponCamoIndex != -1 )
+ {
+ weaponSkinIndex = clGlobal.previewMenuPilotModels.weaponSkinIndex
+ weaponCamoIndex = clGlobal.previewMenuPilotModels.weaponCamoIndex
+ }
+ else // no preview active, show current for both
+ {
+ weaponSkinIndex = clGlobal.currentMenuPilotModels.weaponSkinIndex
+ weaponCamoIndex = clGlobal.currentMenuPilotModels.weaponCamoIndex
+ }
+ }
+
+
+ if ( weaponCamoIndex > 0 )
+ weaponSkinIndex = WEAPON_SKIN_INDEX_CAMO
+ else
+ weaponCamoIndex = -1
+
+ file.menuPilot.weapon.SetSkin( weaponSkinIndex )
+ //printt( "Set pilot weapon skin to:", weaponSkinIndex )
+ file.menuPilot.weapon.SetCamo( weaponCamoIndex )
+ //printt( "Set pilot weapon camo to:", weaponCamoIndex )
+ }
+
+ void function UpdateTitanModelDisplay( entity player )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ asset bodyModel = clGlobal.previewMenuTitanModels.bodyModel
+ if ( bodyModel == $"" )
+ bodyModel = clGlobal.currentMenuTitanModels.bodyModel
+
+ string idleAnim = clGlobal.previewMenuTitanModels.idleAnim
+ if ( idleAnim == "" )
+ idleAnim = clGlobal.currentMenuTitanModels.idleAnim
+
+ bool playIdle = false
+ if ( file.menuTitan.body.GetModelName() != bodyModel || idleAnim != file.menuTitan.bodyAnim ) // Model has changed or anim has changed
+ playIdle = true
+
+ if ( file.menuTitan.body.GetModelName() != bodyModel )
+ {
+ file.menuTitan.body.SetSkin( 0 ) //First reset skin and decal to default to avoid code error message when changing models, if the new models don't have the same skins supported
+ file.menuTitan.body.SetCamo( -1 )
+ file.menuTitan.body.SetModel( bodyModel )
+ }
+
+ int camoIndex = clGlobal.previewMenuTitanModels.camoIndex
+ int skinIndex = clGlobal.previewMenuTitanModels.skinIndex
+
+ bool usedCurrentValues = false
+ if ( camoIndex == -1 && skinIndex == 0 )
+ {
+ camoIndex = clGlobal.currentMenuTitanModels.camoIndex
+ skinIndex = clGlobal.currentMenuTitanModels.skinIndex
+ usedCurrentValues = true
+ }
+ else
+ {
+ camoIndex = clGlobal.previewMenuTitanModels.camoIndex
+ skinIndex = clGlobal.previewMenuTitanModels.skinIndex
+ }
+
+ if ( camoIndex > 0 )
+ {
+ skinIndex = TITAN_SKIN_INDEX_CAMO
+ }
+ else
+ {
+ camoIndex = -1
+ }
+
+ file.menuTitan.body.SetSkin( skinIndex )
+ file.menuTitan.body.SetCamo( camoIndex )
+
+ int decalIndex = clGlobal.previewMenuTitanModels.decalIndex
+ if ( decalIndex == -1 )
+ decalIndex = clGlobal.currentMenuTitanModels.decalIndex
+
+ file.menuTitan.body.SetDecal( decalIndex )
+ //printt( "Set titan decal to:", decalIndex )
+
+ if ( playIdle )
+ {
+ PlayMenuAnim( file.menuTitan.body, idleAnim )
+ file.menuTitan.bodyAnim = idleAnim
+ }
+
+ asset weaponModel = clGlobal.previewMenuTitanModels.weaponModel
+ if ( weaponModel == $"" )
+ weaponModel = clGlobal.currentMenuTitanModels.weaponModel
+
+ file.menuTitan.weapon.SetModel( weaponModel )
+
+ int weaponCamoIndex = clGlobal.previewMenuTitanModels.weaponCamoIndex
+ if ( weaponCamoIndex == -1 )
+ weaponCamoIndex = clGlobal.currentMenuTitanModels.weaponCamoIndex
+
+ //printt( "clGlobal.previewMenuTitanModels.weaponCamoIndex:", clGlobal.previewMenuTitanModels.weaponCamoIndex )
+ //printt( "clGlobal.currentMenuTitanModels.weaponCamoIndex:", clGlobal.currentMenuTitanModels.weaponCamoIndex )
+ //printt( "weaponCamoIndex:", weaponCamoIndex )
+ if ( weaponCamoIndex > 0 )
+ {
+ file.menuTitan.weapon.SetSkin( WEAPON_SKIN_INDEX_CAMO )
+ //printt( "Set titan weapon skin to:", WEAPON_SKIN_INDEX_CAMO )
+ file.menuTitan.weapon.SetCamo( weaponCamoIndex )
+ //printt( "Set titan weapon camo to:", weaponCamoIndex )
+ }
+ else
+ {
+ file.menuTitan.weapon.SetSkin( 0 )
+ //printt( "Set titan weapon skin to:", 0 )
+ file.menuTitan.weapon.SetCamo( -1 )
+ //printt( "Set titan weapon camo to:", -1 )
+ }
+
+ if ( IsValid( file.menuTitan.prop ) )
+ file.menuTitan.prop.Destroy()
+
+ if ( bodyModel == $"models/titans/light/titan_light_locust.mdl" )
+ file.menuTitan.prop = CreateAttachedModel( file.menuTitan.body, $"models/weapons/titan_sword/w_titan_sword.mdl", "SIDEARM_HOLSTER" )
+ else if ( bodyModel == $"models/titans/light/titan_light_ronin_prime.mdl" )
+ file.menuTitan.prop = CreateAttachedModel( file.menuTitan.body, $"models/weapons/titan_sword/w_titan_sword_prime.mdl", "SIDEARM_HOLSTER" )
+
+ if ( IsValid( file.menuTitan.armBadge ) )
+ file.menuTitan.armBadge.Destroy()
+
+ UpdatePreviewTitanArmBadge( player, skinIndex, camoIndex, clGlobal.currentMenuTitanModels.loadoutIndex )
+ asset armBadgeModel = clGlobal.previewMenuTitanModels.armBadgeModel
+ int armBadgeBodyGroupIndex = clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex
+ if ( usedCurrentValues )
+ {
+ UpdateMenuTitanArmBadge( player, skinIndex, camoIndex, clGlobal.currentMenuTitanModels.loadoutIndex )
+ armBadgeModel = clGlobal.currentMenuTitanModels.armBadgeModel
+ armBadgeBodyGroupIndex = clGlobal.currentMenuTitanModels.armBadgeBodyGroupIndex
+ }
+
+ if ( armBadgeBodyGroupIndex != -1 && armBadgeModel != $"" )
+ {
+ file.menuTitan.armBadge = CreateAttachedModel( file.menuTitan.body, armBadgeModel, TITAN_ARM_BADGE_ATTACHMENT )
+ file.menuTitan.armBadge.SetBodygroup( 0, armBadgeBodyGroupIndex )
+ }
+ }
+
+ void function SetEditingPilotLoadoutIndex( entity player, int loadoutIndex )
+ {
+ clGlobal.editingPilotLoadoutIndex = loadoutIndex
+ }
+
+ void function ClearEditingPilotLoadoutIndex( entity player )
+ {
+ clGlobal.editingPilotLoadoutIndex = -1
+ }
+
+ void function SetHeldPilotWeaponType( entity player, int itemType )
+ {
+ clGlobal.heldPilotWeaponType = itemType
+ }
+
+ void function SetEditingTitanLoadoutIndex( entity player, int loadoutIndex )
+ {
+ clGlobal.editingTitanLoadoutIndex = loadoutIndex
+ }
+
+ void function ClearEditingTitanLoadoutIndex( entity player )
+ {
+ clGlobal.editingTitanLoadoutIndex = -1
+ }
+
+
+ void function PreviewPilotCharacter( entity player, int itemIndex )
+ {
+ Assert( clGlobal.editingPilotLoadoutIndex != -1 )
+
+ array<ItemDisplayData> items = GetVisibleItemsOfType( eItemTypes.PILOT_SUIT )
+ string animType = "focused_idle"
+ string suit = items[ itemIndex ].ref
+ string weapon = GetPilotLoadoutWeapon( clGlobal.editingPilotLoadoutIndex, clGlobal.heldPilotWeaponType )
+ string idleAnim = GetMenuPilotAnim( animType, suit, GetItemMenuAnimClass( weapon ) )
+ string genderRace = GetPilotLoadoutGenderRace( clGlobal.editingPilotLoadoutIndex )
+ string setFile = GetSuitAndGenderBasedSetFile( suit, genderRace )
+ asset bodyModel = GetSetFileModel( setFile )
+
+ clGlobal.previewMenuPilotModels.bodyModel = bodyModel
+ clGlobal.previewMenuPilotModels.idleAnim = idleAnim
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PreviewPilotWeapon( entity player, int itemType, int itemIndex, int weaponCategory )
+ {
+ Assert( itemType == eItemTypes.PILOT_PRIMARY || itemType == eItemTypes.PILOT_SECONDARY )
+ Assert( clGlobal.editingPilotLoadoutIndex != -1 )
+
+ array<ItemDisplayData> items
+ if ( weaponCategory != -1 )
+ items = GetVisibleItemsOfTypeForCategory( itemType, weaponCategory )
+ else
+ items = GetVisibleItemsOfType( itemType )
+
+ string weapon = items[ itemIndex ].ref
+ asset weaponModel = GetWeaponModel( weapon )
+ string animType = "weapon_inspect_idle"
+ string suit = GetPilotLoadoutSuit( clGlobal.editingPilotLoadoutIndex )
+ string idleAnim = GetMenuPilotAnim( animType, suit, GetItemMenuAnimClass( weapon ) )
+ int weaponSkinIndex = GetPilotLoadoutWeaponSkinIndex( clGlobal.editingPilotLoadoutIndex, itemType )
+ int weaponCamoIndex = GetPilotLoadoutWeaponCamoIndex( clGlobal.editingPilotLoadoutIndex, itemType )
+
+ clGlobal.previewMenuPilotModels.idleAnim = idleAnim
+ clGlobal.previewMenuPilotModels.weapon = weapon
+ clGlobal.previewMenuPilotModels.weaponModel = weaponModel
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = weaponSkinIndex
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = weaponCamoIndex
+ clGlobal.previewMenuPilotModels.mods = []
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PreviewPilotWeaponMod( entity player, int modIndex, string modRef )
+ {
+ Assert( clGlobal.editingPilotLoadoutIndex != -1 )
+
+ array<string> mods = GetPilotLoadoutWeaponMods( clGlobal.editingPilotLoadoutIndex, clGlobal.heldPilotWeaponType )
+ mods[ modIndex ] = modRef
+ mods.removebyvalue( "" )
+ mods.removebyvalue( "none" )
+
+ clGlobal.previewMenuPilotModels.mods = mods
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PreviewPilotCamoChange( entity player, int camoIndex )
+ {
+ clGlobal.previewMenuPilotModels.camoIndex = camoIndex
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PreviewPilotWeaponCamoChange( entity player, int camoIndex )
+ {
+ if ( camoIndex == 0 ) // Special case for factory issue. Should make factory issue work as any other weapon skin item in the future.
+ {
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = WEAPON_SKIN_INDEX_DEFAULT
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = -1
+ }
+ else
+ {
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = WEAPON_SKIN_INDEX_CAMO
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = camoIndex
+ }
+
+ printt( "PreviewPilotWeaponCamoChange", clGlobal.previewMenuPilotModels.weaponSkinIndex, clGlobal.previewMenuPilotModels.weaponCamoIndex )
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PrintWeaponModelData()
+ {
+ printt( "clGlobal.previewMenuPilotModels.weaponSkinIndex:", clGlobal.previewMenuPilotModels.weaponSkinIndex, "clGlobal.currentMenuPilotModels.weaponSkinIndex:", clGlobal.currentMenuPilotModels.weaponSkinIndex )
+ printt( "clGlobal.previewMenuPilotModels.weaponCamoIndex:", clGlobal.previewMenuPilotModels.weaponCamoIndex, "clGlobal.currentMenuPilotModels.weaponCamoIndex:", clGlobal.currentMenuPilotModels.weaponCamoIndex )
+ }
+
+ void function PreviewPilotWeaponSkinChange( entity player, int skinIndex )
+ {
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = skinIndex
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = -1
+ printt( "PreviewPilotWeaponSkinChange", clGlobal.previewMenuPilotModels.weaponSkinIndex, clGlobal.previewMenuPilotModels.weaponCamoIndex )
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function PreviewTitanDecalChange( entity player, int decalIndex )
+ {
+ clGlobal.previewMenuTitanModels.decalIndex = decalIndex
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function PreviewTitanCamoChange( entity player, int camoIndex )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = camoIndex
+ clGlobal.previewMenuTitanModels.skinIndex = camoIndex > 0 ? TITAN_SKIN_INDEX_CAMO : 0
+ // clGlobal.previewMenuTitanModels.armBadgeModel = $""
+ // clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex = 0
+
+ printt( "PreviewTitanCamoChange", clGlobal.previewMenuTitanModels.skinIndex, clGlobal.previewMenuTitanModels.camoIndex )
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function PreviewTitanSkinChange( entity player, int skinIndex )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+ clGlobal.previewMenuTitanModels.skinIndex = skinIndex
+ printt( "PreviewTitanSkinChange", clGlobal.previewMenuTitanModels.skinIndex, clGlobal.previewMenuTitanModels.camoIndex )
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function PreviewTitanCombinedChange( entity player, int skinIndex, int camoIndex, int loadoutIndex )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = camoIndex
+ clGlobal.previewMenuTitanModels.skinIndex = skinIndex
+ clGlobal.previewMenuTitanModels.loadoutIndex = loadoutIndex
+ UpdatePreviewTitanArmBadge( player, skinIndex, camoIndex, loadoutIndex )
+ printt( "PreviewTitanCombinedChange", clGlobal.previewMenuTitanModels.skinIndex, clGlobal.previewMenuTitanModels.camoIndex )
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function UpdatePreviewTitanArmBadge( entity player, int skinIndex, int camoIndex, int loadoutIndex )
+ {
+ UpdateMenuDefArmBadge( clGlobal.previewMenuTitanModels, player, skinIndex, camoIndex, loadoutIndex )
+ }
+
+ void function UpdateMenuTitanArmBadge( entity player, int skinIndex, int camoIndex, int loadoutIndex )
+ {
+ UpdateMenuDefArmBadge( clGlobal.currentMenuTitanModels, player, skinIndex, camoIndex, loadoutIndex )
+ }
+
+ void function UpdateMenuDefArmBadge( MenuCharacterDef charDef, entity player, int skinIndex, int camoIndex, int loadoutIndex )
+ {
+ if ( !IsConnected() ) //Defensive fix for persistence not being loaded when disconnecting or connecting into a match.
+ return
+
+ TitanLoadoutDef loadout = clone GetCachedTitanLoadout( loadoutIndex )
+
+ asset armBadgeModel = GetTitanArmBadgeFromLoadoutAndSkinIndex( loadout, skinIndex )
+
+ int armBadgeBodyGroupIndex = -1
+ if ( armBadgeModel != $"" )
+ {
+ int difficulty = FD_GetHighestDifficultyForTitan( player, loadout.titanClass )
+ switch ( difficulty )
+ {
+ case eFDDifficultyLevel.HARD:
+ armBadgeBodyGroupIndex = 1
+ break
+ case eFDDifficultyLevel.MASTER:
+ armBadgeBodyGroupIndex = 2
+ break
+ case eFDDifficultyLevel.INSANE:
+ armBadgeBodyGroupIndex = 3
+ break
+ default:
+ armBadgeBodyGroupIndex = 0
+ break
+ }
+ }
+ charDef.armBadgeModel = armBadgeModel
+ charDef.armBadgeBodyGroupIndex = armBadgeBodyGroupIndex
+ }
+
+ void function PreviewTitanWeaponCamoChange( entity player, int camoIndex )
+ {
+ clGlobal.previewMenuTitanModels.weaponCamoIndex = camoIndex
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function UpdateFactionModel( entity player, int itemIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ array<ItemDisplayData> items = GetVisibleItemsOfType( eItemTypes.FACTION )
+ string ref = items[ itemIndex ].ref
+ asset model = GetFactionModel( ref )
+ int skinIndex = GetFactionModelSkin( ref )
+ asset propModel = GetFactionPropModel( ref )
+ string idleAnim = GetFactionIdleAnim( ref )
+
+ //bool playIdle = false
+ //if ( file.menuFaction.body.GetModelName() != model || idleAnim != file.menuFaction.bodyAnim ) // Model has changed or anim has changed
+ // playIdle = true
+
+ file.menuFaction.body.SetSkin( 0 )
+ file.menuFaction.body.SetModel( model )
+ file.menuFaction.body.SetSkin( skinIndex )
+
+ entity propEnt = CreateFactionPropModel( file.menuFaction.body, ref )
+ if ( IsValid( file.menuFaction.weapon ) )
+ file.menuFaction.weapon.Destroy()
+
+ file.menuFaction.weapon = propEnt
+
+ //if ( playIdle )
+ //{
+ PlayMenuAnim( file.menuFaction.body, idleAnim )
+ file.menuFaction.bodyAnim = idleAnim
+ //}
+ }
+
+ void function UpdateMenuToHarvester()
+ {
+ thread SpawnHarvester()
+ }
+
+ void function SpawnHarvester()
+ {
+ EndSignal( level, "EndSetPresentationType" )
+
+ while ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ WaitFrame()
+
+ vector originOffset = < 450, -700, 0 >
+ vector angleOffset = <0, 0, 0>
+
+ file.menuMiscModel.body.SetLocalOrigin( originOffset )
+ file.menuMiscModel.body.SetLocalAngles( angleOffset )
+ bool success = file.menuMiscModel.body.SetModel( MODEL_HARVESTER_TOWER )
+
+ if ( !success )
+ return
+
+ entity harvester = file.menuMiscModel.body
+ int attachID = harvester.LookupAttachment( "ref" )
+ vector attachOrg = harvester.GetAttachmentOrigin( attachID )
+ vector attachAng = harvester.GetAttachmentAngles( attachID )
+ entity ringEnt = CreateClientSidePropDynamic( attachOrg, attachAng, MODEL_HARVESTER_TOWER_RINGS )
+ ringEnt.SetParent( harvester )
+ ringEnt.Anim_Play( "generator_cycle_fast" )
+ int harvesterBeamFX = StartParticleEffectOnEntity( harvester, GetParticleSystemIndex( FX_HARVESTER_BEAM ), FX_PATTACH_ABSORIGIN_FOLLOW, -1 )
+ EffectSetControlPointVector( harvesterBeamFX, 1, < 126.0, 188.0, 236.0 > )
+
+ OnThreadEnd(
+ function() : ( ringEnt, harvesterBeamFX )
+ {
+ ringEnt.Destroy()
+ EffectStop( harvesterBeamFX, true, true )
+ }
+ )
+
+ WaitForever()
+ }
+
+ void function UpdateBoostModel( entity player, int itemIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ array<ItemDisplayData> items = GetVisibleItemsOfType( eItemTypes.BURN_METER_REWARD )
+ string ref = items[ itemIndex ].ref
+ asset model = GetBoostModel( ref )
+ int skinIndex = GetBoostSkin( ref )
+
+ vector originOffset = <0, 0, 0>
+ vector angleOffset = <0, 0, 90>
+
+ file.menuMiscModel.body.SetLocalOrigin( originOffset )
+ file.menuMiscModel.body.SetLocalAngles( angleOffset )
+ file.menuMiscModel.body.SetModel( model )
+ file.menuMiscModel.body.SetSkin( skinIndex )
+ }
+
+ vector function GetWeaponModelOffset( string weaponRef )
+ {
+ vector vec = <0, 0, 0>
+
+ switch ( weaponRef )
+ {
+ case "mp_weapon_sniper":
+ vec = <27.5, -2.55, 1.2>
+ break
+ }
+
+ return vec
+ }
+
+ void function UpdateStoreWeaponModelSkin( entity player, string weaponRef, int skinIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ printt( "skinIndex:", skinIndex )
+
+ vector moverOffset = GetWeaponModelOffset( weaponRef )
+ file.menuWeaponModel.mover.SetLocalOrigin( moverOffset )
+
+ asset model = GetWeaponViewmodel( weaponRef )
+ file.menuWeaponModel.body.SetSkin( 0 ) // Lame, but without this the game can complain that the skin is invalid when the model or skin is changed, regardless of which happens first
+ file.menuWeaponModel.body.SetModel( model )
+ file.menuWeaponModel.body.SetSkin( skinIndex )
+
+ vector angleOffset = <0, 60, 0>
+
+ string attachmentName = "MENU_ROTATE"
+ vector originOffset = GetAttachmentOriginOffset( file.menuWeaponModel.body, attachmentName, angleOffset )
+
+ file.menuWeaponModel.body.SetLocalOrigin( originOffset )
+ file.menuWeaponModel.body.SetLocalAngles( angleOffset )
+ file.menuWeaponModel.body.Anim_SetPaused( true )
+ }
+
+ void function UpdateStoreWeaponModelZoom( entity player, float zoomFrac )
+ {
+ if ( file.activeCharacter == null )
+ return
+
+ if ( Time() - file.lastZoomTime < 0.1 )
+ return
+
+ CharacterData character = expect CharacterData( file.activeCharacter )
+ if ( zoomFrac == 0 )
+ character.fovScale = character.fovScale < 1.0 ? 1.0 : 0.0
+ else if ( zoomFrac > 0 )
+ character.fovScale = 1.0
+ else
+ character.fovScale = 0.0
+
+ file.lastZoomTime = Time()
+ }
+
+ vector function GetAttachmentOriginOffset( entity ent, string attachName, vector angles )
+ {
+ int attachIndex = ent.LookupAttachment( attachName )
+ ent.SetAngles( angles )
+ vector worldOrigin = ent.GetAttachmentOrigin( attachIndex )
+ vector localOffset = ent.GetOrigin() - worldOrigin
+
+ return localOffset
+ }
+
+ vector function GetWorldSpaceCenterOffset( entity ent, vector angles )
+ {
+ ent.SetAngles( angles )
+ vector worldOrigin = ent.GetWorldSpaceCenter()
+ vector localOffset = ent.GetOrigin() - worldOrigin
+
+ return localOffset
+ }
+
+ entity function GetMenuMiscModel()
+ {
+ return file.menuMiscModel.body
+ }
+
+ void function UpdateCallsignCard( entity player, int itemIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ #if HAS_WORLD_CALLSIGN
+ CallingCard callsignCard = CallingCard_GetByIndex( itemIndex )
+ RuiSetImage( file.menuCallsignRui, "cardImage", callsignCard.image )
+ RuiSetInt( file.menuCallsignRui, "layoutType", callsignCard.layoutType )
+ RuiSetImage( file.menuCallsignRui, "cardGenImage", PlayerXPGetGenIcon( player ) )
+ #endif
+ }
+
+ void function UpdateCallsignIcon( entity player, int itemIndex )
+ {
+ if ( !clGlobal.initializedMenuModels ) // Handle early calls that UI script can trigger before client is ready
+ return
+
+ #if HAS_WORLD_CALLSIGN
+ CallsignIcon callsignIcon = CallsignIcon_GetByIndex( itemIndex )
+ RuiSetImage( file.menuCallsignRui, "iconImage", callsignIcon.image )
+ #endif
+ }
+
+ // TODO: Do we need to account for model strings sometimes having a skin specified by appending ":0", ":1", etc?
+ asset function GetSetFileModel( string setFile )
+ {
+ return GetPlayerSettingsAssetForClassName( setFile, "bodymodel" )
+ }
+
+ string function GetPilotLoadoutGenderRace( int loadoutIndex )
+ {
+ return GetCachedPilotLoadout( loadoutIndex ).race
+ }
+
+ string function GetPilotLoadoutSuit( int loadoutIndex )
+ {
+ return GetCachedPilotLoadout( loadoutIndex ).suit
+ }
+
+ int function GetPilotCamoIndex( int loadoutIndex )
+ {
+ return GetCachedPilotLoadout( loadoutIndex ).camoIndex
+ }
+
+ string function GetPilotLoadoutWeapon( int loadoutIndex, int weaponItemType )
+ {
+ string ref
+
+ if ( weaponItemType == eItemTypes.PILOT_PRIMARY )
+ ref = GetCachedPilotLoadout( loadoutIndex ).primary
+ else if ( weaponItemType == eItemTypes.PILOT_SECONDARY )
+ ref = GetCachedPilotLoadout( loadoutIndex ).secondary
+ else if ( weaponItemType == eItemTypes.PILOT_WEAPON3 )
+ ref = GetCachedPilotLoadout( loadoutIndex ).weapon3
+ else
+ Assert( false )
+
+ return ref
+ }
+
+ array<string> function GetPilotLoadoutWeaponMods( int loadoutIndex, int weaponItemType )
+ {
+ array<string> mods
+
+ if ( weaponItemType == eItemTypes.PILOT_PRIMARY )
+ {
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).primaryMod1 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).primaryMod2 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).primaryMod3 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).primaryAttachment )
+ }
+ else if ( weaponItemType == eItemTypes.PILOT_SECONDARY )
+ {
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).secondaryMod1 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).secondaryMod2 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).secondaryMod3 )
+ }
+ else if ( weaponItemType == eItemTypes.PILOT_WEAPON3 )
+ {
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).weapon3Mod1 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).weapon3Mod2 )
+ mods.append( GetCachedPilotLoadout( loadoutIndex ).weapon3Mod3 )
+ }
+ else
+ {
+ Assert( false )
+ }
+
+ return mods
+ }
+
+ int function GetPilotLoadoutWeaponCamoIndex( int loadoutIndex, int weaponItemType )
+ {
+ int camoIndex = -1
+
+ if ( weaponItemType == eItemTypes.PILOT_PRIMARY )
+ camoIndex = GetCachedPilotLoadout( loadoutIndex ).primaryCamoIndex
+ else if ( weaponItemType == eItemTypes.PILOT_SECONDARY )
+ camoIndex = GetCachedPilotLoadout( loadoutIndex ).secondaryCamoIndex
+ else if ( weaponItemType == eItemTypes.PILOT_WEAPON3 )
+ camoIndex = GetCachedPilotLoadout( loadoutIndex ).weapon3CamoIndex
+ else
+ Assert( false )
+
+ return camoIndex
+ }
+
+ int function GetPilotLoadoutWeaponSkinIndex( int loadoutIndex, int weaponItemType )
+ {
+ int skinIndex = 0
+
+ if ( weaponItemType == eItemTypes.PILOT_PRIMARY )
+ skinIndex = GetCachedPilotLoadout( loadoutIndex ).primarySkinIndex
+ else if ( weaponItemType == eItemTypes.PILOT_SECONDARY )
+ skinIndex = GetCachedPilotLoadout( loadoutIndex ).secondarySkinIndex
+ else if ( weaponItemType == eItemTypes.PILOT_WEAPON3 )
+ skinIndex = GetCachedPilotLoadout( loadoutIndex ).weapon3SkinIndex
+ else
+ Assert( false )
+
+ return skinIndex
+ }
+
+ string function GetTitanLoadoutSetFile( int loadoutIndex )
+ {
+ return GetCachedTitanLoadout( loadoutIndex ).setFile
+ }
+
+ string function GetTitanLoadoutPrimary( int loadoutIndex )
+ {
+ return GetCachedTitanLoadout( loadoutIndex ).primary
+ }
+
+ int function GetTitanCamoIndex( int loadoutIndex )
+ {
+ return GetCachedTitanLoadoutCamoIndex( loadoutIndex )
+ }
+
+ int function GetTitanSkinIndex( int loadoutIndex )
+ {
+ return GetCachedTitanLoadoutSkinIndex( loadoutIndex )
+ }
+
+ int function GetTitanDecalIndex( int loadoutIndex )
+ {
+ return GetCachedTitanLoadoutDecalIndex( loadoutIndex )
+ }
+
+ asset function GetTitanLoadoutArmBadge( int loadoutIndex )
+ {
+ return GetCachedTitanLoadoutArmBadge( loadoutIndex )
+ }
+
+ int function GetTitanLoadoutArmBadgeState( int loadoutIndex )
+ {
+ return GetCachedTitanArmBadgeState( loadoutIndex )
+ }
+
+ asset function GetFactionModel( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/faction_leaders.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "persistenceRef" ), ref )
+ asset model = GetDataTableAsset( dataTable, row, GetDataTableColumnByName( dataTable, "modelName" ) )
+
+ return model
+ }
+
+ int function GetFactionModelSkin( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/faction_leaders.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "persistenceRef" ), ref )
+ int skin = GetDataTableInt( dataTable, row, GetDataTableColumnByName( dataTable, "skinIndex" ) )
+
+ return skin
+ }
+
+ string function GetFactionPropAttachment( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/faction_leaders.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "persistenceRef" ), ref )
+ string attachment = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "propAttachment" ) )
+
+ return attachment
+ }
+
+ asset function GetFactionPropModel( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/faction_leaders.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "persistenceRef" ), ref )
+ asset model = GetDataTableAsset( dataTable, row, GetDataTableColumnByName( dataTable, "propModelName" ) )
+
+ return model
+ }
+
+ string function GetFactionIdleAnim( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/faction_leaders.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "persistenceRef" ), ref )
+ string anim = GetDataTableString( dataTable, row, GetDataTableColumnByName( dataTable, "menuIdleAnim" ) )
+
+ return anim
+ }
+
+ asset function GetBoostModel( string ref )
+ {
+ var dataTable = GetDataTable( $"datatable/burn_meter_rewards.rpak" )
+ int row = GetDataTableRowMatchingStringValue( dataTable, GetDataTableColumnByName( dataTable, "itemRef" ), ref )
+ asset model = GetDataTableAsset( dataTable, row, GetDataTableColumnByName( dataTable, "model" ) )
+
+ return model
+ }
+
+ void function SavePilotCharacterPreview( entity player )
+ {
+ clGlobal.currentMenuPilotModels.bodyModel = clGlobal.previewMenuPilotModels.bodyModel
+ clGlobal.previewMenuPilotModels.bodyModel = $""
+
+ clGlobal.previewMenuPilotModels.idleAnim = ""
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function SavePilotWeaponPreview( entity player )
+ {
+ clGlobal.currentMenuPilotModels.idleAnim = clGlobal.previewMenuPilotModels.idleAnim
+ clGlobal.previewMenuPilotModels.idleAnim = ""
+
+ clGlobal.currentMenuPilotModels.weapon = clGlobal.previewMenuPilotModels.weapon
+ clGlobal.previewMenuPilotModels.weapon = ""
+
+ clGlobal.currentMenuPilotModels.weaponModel = clGlobal.previewMenuPilotModels.weaponModel
+ clGlobal.previewMenuPilotModels.weaponModel = $""
+
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = -1
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = -1
+
+ clGlobal.currentMenuPilotModels.mods = []
+
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function SavePilotWeaponModPreview( entity player )
+ {
+ clGlobal.currentMenuPilotModels.mods = clGlobal.previewMenuPilotModels.mods
+ clGlobal.previewMenuPilotModels.mods = []
+ UpdatePilotModelDisplay( player )
+ }
+
+ //void function SavePilotCamoPreview( entity player )
+ //{
+ // clGlobal.currentMenuPilotModels.camoIndex = clGlobal.previewMenuPilotModels.camoIndex
+ // clGlobal.previewMenuPilotModels.camoIndex = -1
+ // UpdatePilotModelDisplay( player )
+ //}
+
+ void function ClearAllPilotPreview( entity player )
+ {
+ clGlobal.previewMenuPilotModels.bodyModel = $""
+ clGlobal.previewMenuPilotModels.camoIndex = -1
+ clGlobal.previewMenuPilotModels.weapon = ""
+ clGlobal.previewMenuPilotModels.weaponModel = $""
+ clGlobal.previewMenuPilotModels.weaponCamoIndex = -1
+ clGlobal.previewMenuPilotModels.weaponSkinIndex = -1
+ clGlobal.previewMenuPilotModels.mods = []
+ clGlobal.previewMenuPilotModels.idleAnim = ""
+ UpdatePilotModelDisplay( player )
+ }
+
+ void function SaveTitanDecalPreview( entity player )
+ {
+ clGlobal.currentMenuTitanModels.decalIndex = clGlobal.previewMenuTitanModels.decalIndex
+ clGlobal.previewMenuTitanModels.decalIndex = -1
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function ClearTitanDecalPreview( entity player )
+ {
+ clGlobal.previewMenuTitanModels.decalIndex = -1
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function SaveTitanCamoPreview( entity player )
+ {
+ clGlobal.currentMenuTitanModels.camoIndex = clGlobal.previewMenuTitanModels.camoIndex
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+
+ clGlobal.currentMenuTitanModels.skinIndex = clGlobal.previewMenuTitanModels.skinIndex
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function ClearTitanCamoPreview( entity player )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function ClearTitanCombinedPreview( entity player )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+
+ clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex = -1
+ clGlobal.previewMenuTitanModels.armBadgeModel = $""
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function SaveTitanSkinPreview( entity player )
+ {
+ clGlobal.currentMenuTitanModels.skinIndex = clGlobal.previewMenuTitanModels.skinIndex
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+
+ clGlobal.currentMenuTitanModels.camoIndex = clGlobal.previewMenuTitanModels.camoIndex
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function SaveTitanCombinedPreview( entity player )
+ {
+ clGlobal.currentMenuTitanModels.skinIndex = clGlobal.previewMenuTitanModels.skinIndex
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+
+ clGlobal.currentMenuTitanModels.camoIndex = clGlobal.previewMenuTitanModels.camoIndex
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+
+ clGlobal.currentMenuTitanModels.armBadgeModel = clGlobal.previewMenuTitanModels.armBadgeModel
+ clGlobal.previewMenuTitanModels.armBadgeModel = $""
+
+ clGlobal.currentMenuTitanModels.armBadgeBodyGroupIndex = clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex
+ clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex = -1
+
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function ClearTitanSkinPreview( entity player )
+ {
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function ClearAllTitanPreview( entity player )
+ {
+ clGlobal.previewMenuTitanModels.bodyModel = $""
+ clGlobal.previewMenuTitanModels.camoIndex = -1
+ clGlobal.previewMenuTitanModels.skinIndex = 0
+ clGlobal.previewMenuTitanModels.decalIndex = -1
+ //clGlobal.previewMenuTitanModels.armBadgeModel = $"" // Not sure why these aren't in here. These should be uncommented when we're sure it's safe to.
+ //clGlobal.previewMenuTitanModels.armBadgeBodyGroupIndex = -1
+ clGlobal.previewMenuTitanModels.weaponModel = $""
+ clGlobal.previewMenuTitanModels.weaponCamoIndex = -1
+ clGlobal.previewMenuTitanModels.idleAnim = ""
+ UpdateTitanModelDisplay( player )
+ }
+
+ void function PlayMenuAnim( entity model, string anim )
+ {
+ float animCycle = model.GetCycle()
+
+ //printt( "PlayMenuAnim(", model, ",", anim, ")" )
+
+ model.Anim_NonScriptedPlay( anim )
+ model.SetCycle( animCycle )
+ }
+
+ void function SetPresentationType( entity player, int presentationType, bool interpolate )
+ {
+ thread SetPresentationTypeThread( player, presentationType, interpolate )
+ }
+
+ void function SetPresentationTypeThread( entity player, int presentationType, bool interpolate )
+ {
+ Signal( level, "EndSetPresentationType" )
+ EndSignal( level, "EndSetPresentationType" )
+
+ while ( !clGlobal.initializedMenuModels )
+ WaitFrame()
+
+ // setting menu camera while our viewentity isn't player will crash
+ // unfortunately no way to close menu if we get our viewentity set while menu is open atm
+ while ( GetViewEntity().GetClassName() == "class C_BaseEntity" )
+ WaitFrame()
+
+ if ( file.presentationTypeInitialized && presentationType == file.presentationType )
+ return
+
+ file.presentationType = presentationType
+
+ if ( !file.presentationTypeInitialized )
+ file.presentationTypeInitialized = true
+
+ if ( file.presentationData[ presentationType ].activateFunc != null )
+ file.presentationData[ presentationType ].activateFunc()
+
+ if ( IsValid( player ) )
+ SetMenuCamera( player, presentationType, interpolate )
+
+ CharacterData ornull lastActiveCharacter = file.activeCharacter
+ file.activeCharacter = file.presentationData[ presentationType ].characterData
+
+ #if HAS_WORLD_CALLSIGN
+ if ( !file.presentationData[ presentationType ].showCallsign )
+ {
+ RuiSetFloat( file.menuCallsignRui, "cardAlpha", 0.0 )
+ }
+ else
+ {
+ RuiSetFloat( file.menuCallsignRui, "cardAlpha", 1.0 )
+ }
+ #endif
+
+ if ( !file.presentationData[ presentationType ].showStoreBG )
+ file.menuStoreBackground.Hide()
+ else
+ file.menuStoreBackground.Show()
+
+ if ( !file.presentationData[ presentationType ].showStorePrimeBG )
+ {
+ if ( file.menuStorePrimeBgCreated )
+ {
+ file.menuStorePrimeBgCreated = false
+ RuiTopology_Destroy( file.menuStorePrimeBg )
+ RuiDestroy( file.menuStorePrimeBgRui )
+ }
+ }
+ else
+ {
+ file.menuStorePrimeBgCreated = true
+ file.menuStorePrimeBg = RuiTopology_CreatePlane( < -91.6658, 453.079, 463.765>, <399.802, -12.5803, 0.000155184>, <3.28334, 104.34, -386.138>, false )
+ file.menuStorePrimeBgRui = RuiCreate( $"ui/prime_titan_bg.rpak", file.menuStorePrimeBg, RUI_DRAW_WORLD, 0 )
+ }
+
+ if ( file.presentationData[ presentationType ].showMiscModel )
+ file.menuMiscModel.body.Show()
+ else
+ file.menuMiscModel.body.Hide()
+
+ if ( file.presentationData[ presentationType ].showWeaponModel )
+ {
+ //file.weaponDLight.SetLightColor( WEAPON_DLIGHT_COLOR )
+ file.menuWeaponModel.body.Show()
+ }
+ else
+ {
+ //file.weaponDLight.SetLightColor( <0, 0, 0> )
+ file.menuWeaponModel.body.Hide()
+ }
+
+ if ( file.presentationData[ presentationType ].showTitanModel )
+ {
+ file.menuTitan.body.Show()
+ file.menuTitan.weapon.Show()
+ if ( IsValid( file.menuTitan.prop ) )
+ file.menuTitan.prop.Show()
+ if ( IsValid( file.menuTitan.armBadge ) )
+ file.menuTitan.armBadge.Show()
+ }
+ else
+ {
+ file.menuTitan.body.Hide()
+ file.menuTitan.weapon.Hide()
+ if ( IsValid( file.menuTitan.prop ) )
+ file.menuTitan.prop.Hide()
+ if ( IsValid( file.menuTitan.armBadge ) )
+ file.menuTitan.armBadge.Hide()
+ }
+
+ if ( lastActiveCharacter != null )
+ ResetCharacterRotation( expect CharacterData( lastActiveCharacter ) )
+ }
+
+ void function SetMenuCamera( entity player, int presentationType, bool interpolate )
+ {
+ string sceneAnim = file.presentationData[ presentationType ].sceneAnim
+ clGlobal.menuSceneModel.Anim_PlayWithRefPoint( sceneAnim, file.sceneRef.GetOrigin(), file.sceneRef.GetAngles() + <0, -90, 0>, 0 )
+ if ( !interpolate )
+ clGlobal.menuSceneModel.Anim_SetStartTime( 1.0 )
+
+ if ( presentationType == ePresentationType.INACTIVE )
+ {
+ SetMapSetting_CsmTexelScale( 1.0, 1.0 )
+ SetMapSetting_CsmStartDistance( 0.0 )
+
+ player.ClearMenuCameraEntity()
+ printt( "Clearing menu camera" )
+ player.SetScriptMenuOff()
+ return
+ }
+
+ player.SetScriptMenuOn()
+
+ float fov = file.presentationData[ presentationType ].fov
+ player.SetMenuCameraEntity( clGlobal.menuCamera )
+ clGlobal.menuCamera.SetTarget( file.cameraTarget, fov, interpolate, EASING_CUBIC_INOUT, TRANSITION_DURATION )
+
+ //EASING_LINEAR
+ //EASING_SINE_IN
+ //EASING_SINE_OUT
+ //EASING_SINE_INOUT
+ //EASING_CIRC_IN
+ //EASING_CIRC_OUT
+ //EASING_CIRC_INOUT
+ //EASING_CUBIC_IN
+ //EASING_CUBIC_OUT
+ //EASING_CUBIC_INOUT
+ //EASING_BACK_IN
+ //EASING_BACK_OUT
+ //EASING_BACK_INOUT
+
+ float dofNearStart = file.presentationData[ presentationType ].dofNearStart
+ float dofNearEnd = file.presentationData[ presentationType ].dofNearEnd
+ float dofFarStart = file.presentationData[ presentationType ].dofFarStart
+ float dofFarEnd = file.presentationData[ presentationType ].dofFarEnd
+
+ if ( interpolate )
+ printt( "Interpolating menu camera to:", Dev_GetEnumString( ePresentationType, presentationType ) )
+ else
+ printt( "Snapping menu camera to:", Dev_GetEnumString( ePresentationType, presentationType ) )
+
+ if ( interpolate )
+ {
+ DoF_LerpNearDepth( dofNearStart, dofNearEnd, TRANSITION_DURATION )
+ DoF_LerpFarDepth( dofFarStart, dofFarEnd, TRANSITION_DURATION )
+ }
+ else
+ {
+ DoF_SetNearDepth( dofNearStart, dofNearEnd )
+ DoF_SetFarDepth( dofFarStart, dofFarEnd )
+ }
+
+ DoFSetDilateInfocus( true ) // We want to reduce DoF aliasing around bright edges in the menus.
+
+#if CONSOLE_PROG
+ const float texelNorm = 2.0
+#else
+ const float texelNorm = 1.0
+#endif
+
+ float csmTexelScale1 = file.presentationData[ presentationType ].csmTexelScale1 * texelNorm
+ float csmTexelScale2 = file.presentationData[ presentationType ].csmTexelScale2 * texelNorm
+ float csmStartDistance = file.presentationData[ presentationType ].csmStartDistance
+
+ // Tweaks in order to maximize the shadow space usage for the pilot and/or the titan.
+ // Used the convar csm_debug_2d to find the best values on PC.
+ SetMapSetting_CsmTexelScale( csmTexelScale1, csmTexelScale2 )
+ SetMapSetting_CsmStartDistance( csmStartDistance )
+ }
+
+ void function ModelRotationThread()
+ {
+ for ( ;; )
+ {
+ WaitFrame()
+
+ if ( file.activeCharacter == null )
+ continue
+
+ CharacterData character = expect CharacterData( file.activeCharacter )
+ float[2] rotationDelta
+
+ if ( IsControllerModeActive() )
+ {
+ const float STICK_DEADZONE = 0.05
+ float stickXRaw = clamp( InputGetAxis( ANALOG_RIGHT_X ), -1.0, 1.0 )
+ float stickXRemappedAbs = (fabs( stickXRaw ) < STICK_DEADZONE) ? 0.0 : ((fabs( stickXRaw ) - STICK_DEADZONE) / (1.0 - STICK_DEADZONE))
+ float stickX = EaseIn( stickXRemappedAbs ) * (stickXRaw < 0.0 ? -1.0 : 1.0)
+
+ rotationDelta[0] = ((character.rotationDelta[0] + stickX * character.maxTurnSpeed * FrameTime()) % 360.0)
+
+ float stickYRaw = clamp( InputGetAxis( ANALOG_RIGHT_Y ), -1.0, 1.0 )
+ float stickYRemappedAbs = (fabs( stickYRaw ) < STICK_DEADZONE) ? 0.0 : ((fabs( stickYRaw ) - STICK_DEADZONE) / (1.0 - STICK_DEADZONE))
+ float stickY = EaseIn( stickYRemappedAbs ) * (stickYRaw < 0.0 ? -1.0 : 1.0)
+
+ rotationDelta[1] = ((character.rotationDelta[1] + stickY * character.maxTurnSpeed * FrameTime()) % 360.0)
+ }
+ else
+ {
+ rotationDelta[0] = ((character.rotationDelta[0] + file.mouseRotateDelta[0] * FrameTime()) % 360.0)
+ file.mouseRotateDelta[0] = 0 // clear because otherwise it would keep spinning
+
+ rotationDelta[1] = ((character.rotationDelta[1] + file.mouseRotateDelta[1] * FrameTime()) % 360.0)
+ file.mouseRotateDelta[1] = 0 // clear because otherwise it would keep spinning
+ }
+
+ float maxTurnDegrees = file.presentationData[ file.presentationType ].maxTurnDegrees
+ if ( maxTurnDegrees < 360.0 )
+ {
+ float minRotationDelta = 0 - (maxTurnDegrees / 2)
+ float maxRotationDelta = maxTurnDegrees / 2
+ rotationDelta[0] = clamp( rotationDelta[0], minRotationDelta, maxRotationDelta )
+ }
+
+ float maxPitchDegrees = file.presentationData[ file.presentationType ].maxPitchDegrees
+ if ( maxPitchDegrees < 360.0 )
+ {
+ float minRotationDelta = 0 - (maxPitchDegrees / 2)
+ float maxRotationDelta = maxPitchDegrees / 2
+ rotationDelta[1] = clamp( rotationDelta[1], minRotationDelta, maxRotationDelta )
+ }
+
+ character.rotationDelta[0] = rotationDelta[0]
+ character.rotationDelta[1] = rotationDelta[1]
+
+ vector defaultAngles = clGlobal.menuSceneModel.GetAttachmentAngles( clGlobal.menuSceneModel.LookupAttachment( character.attachName ) )
+ vector newAng
+
+ /*
+ if ( file.presentationData[ file.presentationType ].useRollAxis )
+ newAng = <defaultAngles.x, defaultAngles.y + character.rotationDelta[0], defaultAngles.z + character.rotationDelta[1]>
+ else
+ newAng = <defaultAngles.x + character.rotationDelta[1], defaultAngles.y + character.rotationDelta[0], defaultAngles.z>
+ */
+
+ vector pitchTowardCamera = < -rotationDelta[1], 0, 0> //AnglesCompose( <0, -90, 0>, AnglesCompose( <rotationDelta[1], 0, 0>, <0, 90, 0> ) )
+
+// newAng = <defaultAngles.x, defaultAngles.y + character.rotationDelta[0], defaultAngles.z>
+ newAng = AnglesCompose( defaultAngles, pitchTowardCamera )
+ newAng = AnglesCompose( newAng, <0, character.rotationDelta[0], 0> )
+
+ float fov = file.presentationData[ file.presentationType ].fov
+ float finalFOV = GraphCapped( character.fovScale, 0.0, 1.0, fov * 0.6, fov )
+ clGlobal.menuCamera.SetTarget( file.cameraTarget, finalFOV, true, EASING_CUBIC_INOUT, 0.05 )
+
+ character.mover.SetAngles( newAng )
+ }
+ }
+
+ void function ResetCharacterRotation( CharacterData character )
+ {
+ entity mover = character.mover
+ vector defaultAngles = clGlobal.menuSceneModel.GetAttachmentAngles( clGlobal.menuSceneModel.LookupAttachment( character.attachName ) )
+ vector currentAngles = mover.GetAngles()
+ character.rotationDelta[0] = 0.0
+ character.rotationDelta[1] = 0.0
+ character.fovScale = 1.0
+
+ if ( currentAngles == defaultAngles )
+ return
+
+ // Get the reset time for the degrees we need to turn to get back to defaultAngles based on a maxDuration time for the worst case which is 180 degrees
+ float absNormDeg = fabs( currentAngles.y - defaultAngles.y % 360.0 )
+ float diffDeg = min( 360.0 - absNormDeg, absNormDeg )
+ float maxDuration = 0.5
+ float duration = diffDeg * (maxDuration / 180)
+ float easeTime = duration / 3
+
+ if ( duration > 0 )
+ mover.NonPhysicsRotateTo( defaultAngles, duration, easeTime, easeTime )
+ else
+ mover.SetAngles( defaultAngles )
+ }
+
+ void function SetMenuOpenState( entity player, int state )
+ {
+ bool wasSoloDialogMenuOpen = clGlobal.isSoloDialogMenuOpen
+
+ clGlobal.isMenuOpen = (state == 1)
+ clGlobal.isSoloDialogMenuOpen = (state == 2);
+ if ( clGlobal.isSoloDialogMenuOpen != wasSoloDialogMenuOpen )
+ UpdateMainHudVisibility( player )
+
+ if ( clGlobal.mapSupportsMenuModels && IsMultiplayer() && !IsLobby() )
+ {
+ if ( clGlobal.isMenuOpen )
+ {
+ ColorCorrection_SetExclusive( file.menuColorCorrection, true )
+ ColorCorrection_SetWeight( file.menuColorCorrection, 1.0 )
+
+ SetMapSetting_FogEnabled( false )
+ }
+ else
+ {
+ DoF_SetNearDepthToDefault()
+ DoF_SetFarDepthToDefault()
+ DoFSetDilateInfocus( false );
+
+ ColorCorrection_SetWeight( file.menuColorCorrection, 0.0 )
+ ColorCorrection_SetExclusive( file.menuColorCorrection, false )
+
+ SetMapSetting_FogEnabled( true )
+ }
+ }
+ }
+
+ void function UpdateMouseRotateDelta( entity player, float deltaX, float deltaY )
+ {
+ file.mouseRotateDelta[0] = deltaX
+ file.mouseRotateDelta[1] = deltaY
+ }
+#endif // CLIENT
+
+#if UI
+ void function RunMenuClientFunction( string func, var arg1 = null, var arg2 = null, var arg3 = null )
+ {
+ if ( !CanRunClientScript() || !uiGlobal.mapSupportsMenuModels )
+ return
+
+ if ( arg1 == null )
+ RunClientScript( func, GetLocalClientPlayer() )
+ else if ( arg2 == null )
+ RunClientScript( func, GetLocalClientPlayer(), arg1 )
+ else if ( arg3 == null )
+ RunClientScript( func, GetLocalClientPlayer(), arg1, arg2 )
+ else
+ RunClientScript( func, GetLocalClientPlayer(), arg1, arg2, arg3 )
+ }
+
+ void function UI_SetPresentationType( int newPresentationType )
+ {
+ if ( IsFullyConnected() && uiGlobal.mapSupportsMenuModels )
+ {
+ if ( uiGlobal.activePresentationType == ePresentationType.NO_MODELS || newPresentationType == ePresentationType.NO_MODELS ||
+ uiGlobal.activePresentationType == ePresentationType.FACTIONS || newPresentationType == ePresentationType.FACTIONS ||
+ uiGlobal.activePresentationType == ePresentationType.BOOSTS || newPresentationType == ePresentationType.BOOSTS ||
+ uiGlobal.activePresentationType == ePresentationType.STORE_FRONT || newPresentationType == ePresentationType.STORE_FRONT ||
+ uiGlobal.activePresentationType == ePresentationType.PVE_MAIN || newPresentationType == ePresentationType.PVE_MAIN ||
+ uiGlobal.activePresentationType == ePresentationType.DEFAULT && newPresentationType == ePresentationType.STORE_WEAPON_SKINS ||
+ uiGlobal.activePresentationType == ePresentationType.STORE_WEAPON_SKINS && newPresentationType == ePresentationType.DEFAULT ||
+ uiGlobal.activePresentationType == ePresentationType.PILOT_WEAPON && newPresentationType == ePresentationType.STORE_WEAPON_SKINS ||
+ uiGlobal.activePresentationType == ePresentationType.STORE_WEAPON_SKINS && newPresentationType == ePresentationType.PILOT_WEAPON ||
+ uiGlobal.activePresentationType == ePresentationType.INACTIVE )
+ {
+ uiGlobal.interpolateCameraMoves = false
+ }
+ else
+ {
+ uiGlobal.interpolateCameraMoves = true
+ }
+
+ // When loading the lobby we don't want any interpolation
+ if ( uiGlobal.lobbyFromLoadingScreen )
+ {
+ uiGlobal.interpolateCameraMoves = false
+ uiGlobal.lobbyFromLoadingScreen = false
+ }
+
+ RunClientScript( "SetPresentationType", GetLocalClientPlayer(), newPresentationType, uiGlobal.interpolateCameraMoves )
+
+ uiGlobal.activePresentationType = newPresentationType
+
+ if ( newPresentationType == ePresentationType.FD_MAIN ||
+ newPresentationType == ePresentationType.FD_FIND_GAME
+ )
+ RunClientScript( "UpdateMenuToHarvester" )
+ }
+ }
+
+ void function UICodeCallback_MouseMovementCapture( var capturePanel, int deltaX, int deltaY )
+ {
+ float screenScaleXModifier = 1920.0 / GetScreenSize()[0] // 1920 is base screen width
+ float mouseXRotateDelta = deltaX * screenScaleXModifier * MOUSE_ROTATE_MULTIPLIER
+ //printt( "deltaX:", deltaX, "screenScaleModifier:", screenScaleModifier, "mouseRotateDelta:", mouseRotateDelta )
+
+ float screenScaleYModifier = 1080.0 / GetScreenSize()[1] // 1920 is base screen width
+ float mouseYRotationDelta = deltaY * screenScaleYModifier * MOUSE_ROTATE_MULTIPLIER
+
+ RunMenuClientFunction( "UpdateMouseRotateDelta", mouseXRotateDelta, mouseYRotationDelta )
+ }
+#endif // UI
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
index 03009764..19a544cc 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_ns_serverbrowser.nut
@@ -6,6 +6,7 @@ const int BUTTONS_PER_PAGE = 15
struct {
int page = 0
int lastSelectedServer = 0
+ bool serverListRequestFailed = false
} file
void function AddNorthstarServerBrowserMenu()
@@ -52,6 +53,7 @@ void function RefreshServers( var button )
return
file.page = 0
+ file.serverListRequestFailed = false
NSClearRecievedServerList()
NSRequestServerList()
@@ -101,7 +103,8 @@ void function WaitForServerListRequest()
while ( NSIsRequestingServerList() )
WaitFrame()
- if ( !NSMasterServerConnectionSuccessful() )
+ file.serverListRequestFailed = !NSMasterServerConnectionSuccessful()
+ if ( file.serverListRequestFailed )
SetButtonRuiText( serverButtons[ 0 ], "#NS_SERVERBROWSER_CONNECTIONFAILED" )
else
UpdateShownPage()
@@ -152,7 +155,7 @@ void function UpdateShownPage()
void function OnServerFocused( var button )
{
- if ( NSIsRequestingServerList() || !NSMasterServerConnectionSuccessful() || NSGetServerCount() == 0 )
+ if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed )
return
var menu = GetMenu( "ServerBrowserMenu" )
@@ -201,7 +204,7 @@ string function FormatServerDescription( int server )
void function OnServerSelected( var button )
{
- if ( NSIsRequestingServerList() || !NSMasterServerConnectionSuccessful() || NSGetServerCount() == 0 )
+ if ( NSIsRequestingServerList() || NSGetServerCount() == 0 || file.serverListRequestFailed )
return
int serverIndex = file.page * BUTTONS_PER_PAGE + int ( Hud_GetScriptID( button ) )
diff --git a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
index 7c81149c..25097c6f 100644
--- a/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
+++ b/Northstar.Client/mod/scripts/vscripts/ui/panel_mainmenu.nut
@@ -278,12 +278,6 @@ void function UpdatePlayButton( var button )
message = "#CONTACTING_RESPAWN_SERVERS"
file.mpButtonActivateFunc = null
}
-
- bool hasNonVanillaMods = false
- if ( hasNonVanillaMods )
- {
- // todo: make this disable non-vanilla mods
- }
else
file.mpButtonActivateFunc = LaunchMP
@@ -422,7 +416,21 @@ void function UpdatePlayButton( var button )
}
else
{
- file.mpButtonActivateFunc = LaunchMP
+ // restrict non-vanilla players from accessing official servers
+ bool hasNonVanillaMods = false
+ foreach ( string modName in NSGetModNames() )
+ {
+ if ( NSIsModEnabled( modName ) && NSIsModRequiredOnClient( modName ) )
+ {
+ hasNonVanillaMods = true
+ break
+ }
+ }
+
+ if ( hasNonVanillaMods )
+ file.mpButtonActivateFunc = null
+ else
+ file.mpButtonActivateFunc = LaunchMP
}
isLocked = file.mpButtonActivateFunc == null ? true : false
diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut
index b4e5ef2b..5f2e6adc 100644
--- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut
+++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_fastball_intro.gnut
@@ -127,10 +127,7 @@ void function FastballPlayer( entity player )
player.EndSignal( "OnDeath" )
- // do this here so it's in OnThreadEnd
- var oldVisibility = player.kv.VisibilityFlags
-
- OnThreadEnd( function() : ( player, oldVisibility )
+ OnThreadEnd( function() : ( player )
{
if ( IsValid( player ) )
{
@@ -140,7 +137,7 @@ void function FastballPlayer( entity player )
player.DeployWeapon()
player.PlayerCone_Disable()
player.ClearInvulnerable()
- player.kv.VisibilityFlags = oldVisibility // restore visibility
+ player.kv.VisibilityFlags = ENTITY_VISIBLE_TO_EVERYONE // restore visibility
}
})
diff --git a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut
index ed245152..4fb45a74 100644
--- a/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut
+++ b/Northstar.Custom/mod/scripts/vscripts/gamemodes/_gamemode_hs.gnut
@@ -184,8 +184,8 @@ void function PlayHintSoundsForHider( entity player )
while ( true )
{
- wait 1.0
- EmitSoundOnEntity( player, "weapon_chargerifle_fire_3p" )
+ wait 60.0
+ EmitSoundOnEntityToTeamExceptPlayer( player, "weapon_chargerifle_fire_3p", HIDEANDSEEK_TEAM_SEEKER, null )
}
}
diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut
index 3d7e65aa..abfd269a 100644
--- a/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut
+++ b/Northstar.Custom/mod/scripts/vscripts/sh_3psequence_to_1p_hacks.gnut
@@ -148,7 +148,8 @@ void function CleanupForced1PSequenceAfterAnimDone( FirstPersonSequenceStruct se
OnThreadEnd( function() : ( cleanupData )
{
- CleanupForced1PSequence( cleanupData )
+ if ( IsValid( cleanupData.player ) )
+ CleanupForced1PSequence( cleanupData )
})
FirstPersonSequence( sequence, player, other )
diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_bleedout_damage.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_bleedout_damage.gnut
index 3306d1bd..a0f27227 100644
--- a/Northstar.Custom/mod/scripts/vscripts/sh_bleedout_damage.gnut
+++ b/Northstar.Custom/mod/scripts/vscripts/sh_bleedout_damage.gnut
@@ -12,6 +12,12 @@ struct {
void function BleedoutDamage_PreInit()
{
AddCallback_OnRegisteringCustomNetworkVars( Bleedout_RegisterRemoteFunctions )
+
+ #if CLIENT
+ // because playlist var overrides fucking suck, they aren't actually updated by this point
+ // client bleedout can be inited late enough that we can just init it on local player spawn
+ AddCallback_LocalClientPlayerSpawned( InitClientBleedoutForLocalPlayer )
+ #endif
}
void function Bleedout_RegisterRemoteFunctions()
@@ -43,9 +49,9 @@ void function BleedoutDamage_Init()
AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_BLEEDOUT", "player_bleedout_aiBleedingPlayerMissChance", DEFAULT_AI_BLEEDING_PLAYER_MISS_CHANCE.tostring() )
#if CLIENT
- // because playlist var overrides fucking suck, they aren't actually updated by this point
- // client bleedout can be inited late enough that we can just init it on local player spawn
- AddCallback_LocalClientPlayerSpawned( InitClientBleedoutForLocalPlayer )
+ // manually register signals here: defensive fix so we don't crash
+ RegisterSignal( "Bleedout_OnRevive" )
+ RegisterSignal( "Bleedout_StopFirstAid" )
#elseif SERVER
// sh_riff_settings should set this correctly on server
if ( !Riff_PlayerBleedout() )
@@ -114,7 +120,7 @@ void function HandleDamageForBleedout( entity player, var damageInfo )
void function OnPlayerBleedoutBegin( entity player )
{
file.bleedingPlayers.append( player )
- EmitSoundOnEntity( player, "Player_Death_Begin" )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "Player_Death_Begin" )
thread PlayerBleedoutGracePeriod( player )
@@ -134,7 +140,7 @@ void function PlayerBleedoutGracePeriod( entity player )
})
player.SetInvulnerable()
- wait 2.5
+ wait 0.25
}
void function TrackPlayerBleedout( entity player )
diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json
index 99826241..40e64cf6 100644
--- a/Northstar.CustomServers/mod.json
+++ b/Northstar.CustomServers/mod.json
@@ -42,9 +42,13 @@
},
{
- // default 0 because broken
+ "Name": "ns_private_match_countdown_length",
+ "DefaultValue": "15"
+ },
+
+ {
"Name": "ns_private_match_override_maxplayers",
- "DefaultValue": "0"
+ "DefaultValue": "1"
},
{
diff --git a/Northstar.CustomServers/mod/cfg/autoexec_ns_server.cfg b/Northstar.CustomServers/mod/cfg/autoexec_ns_server.cfg
index cfd0ffe8..d92ca3ec 100644
--- a/Northstar.CustomServers/mod/cfg/autoexec_ns_server.cfg
+++ b/Northstar.CustomServers/mod/cfg/autoexec_ns_server.cfg
@@ -16,7 +16,7 @@ ns_should_return_to_lobby 1 // whether the server should return to private match
net_chan_limit_mode 2 // kick clients that go over the limit
net_chan_limit_msec_per_sec 100 // number of milliseconds of server netchan processing time clients can use per second before getting kicked
-sv_querylimit_per_sec 10 // number of connectionless packets clients can send to this server per second without getting blocked
+sv_querylimit_per_sec 15 // number of connectionless packets clients can send to this server per second without getting blocked
base_tickinterval_mp 0.016666667 // default tickrate: 60 tick
sv_updaterate_mp 20 // default updaterate: 20 tick
sv_minupdaterate 20 // unsure if this actually works, but if it does, should set minimum client updaterate
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
index ac5b8129..a4f23b85 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
@@ -192,8 +192,10 @@ void function Evac( int evacTeam, float initialWait, float arrivalTime, float wa
dropship.SetValueForModelKey( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
DispatchSpawn( dropship )
dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
+ AddEntityCallback_OnKilled( dropship, EvacDropshipKilled )
dropship.s.evacSlots <- [ null, null, null, null, null, null, null, null ]
+ file.evacDropship = dropship
dropship.EndSignal( "OnDestroy" )
OnThreadEnd( function() : ( evacTeam, completionCallback, dropship )
@@ -372,4 +374,16 @@ bool function PlayerInDropship( entity player, entity dropship )
return true
return false
+}
+
+void function EvacDropshipKilled( entity dropship, var damageInfo )
+{
+ foreach ( entity player in dropship.s.evacSlots )
+ {
+ if ( IsValid( player ) )
+ {
+ player.ClearParent()
+ player.Die( DamageInfo_GetAttacker( damageInfo ), DamageInfo_GetWeapon( damageInfo ), { damageSourceId = eDamageSourceId.evac_dropship_explosion, scriptType = DF_GIB } )
+ }
+ }
} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
index a7dc00de..9e5d95ba 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
@@ -11,6 +11,7 @@ void function GamemodeTTDM_Init()
SetLoadoutGracePeriodEnabled( false )
ClassicMP_SetCustomIntro( TTDMIntroSetup, TTDMIntroLength )
+ ClassicMP_ForceDisableEpilogue( true )
AddCallback_OnPlayerKilled( AddTeamScoreForPlayerKilled ) // dont have to track autotitan kills since you cant leave your titan in this mode
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
index b5c6ea32..08cc9d0b 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
@@ -39,10 +39,6 @@ bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<str
{
if ( file.startState == ePrivateMatchStartState.STARTING )
{
- if ( GetConVarBool( "ns_private_match_only_host_can_start" ) )
- if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
- return true
-
// cancel start if we're already mid-countdown
file.startState = ePrivateMatchStartState.READY
SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.READY )
@@ -50,6 +46,10 @@ bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<str
}
else
{
+ if ( GetConVarBool( "ns_private_match_only_host_can_start" ) )
+ if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
+ return true
+
// start match
file.startState = ePrivateMatchStartState.STARTING
thread StartMatch()
@@ -123,8 +123,8 @@ void function StartMatch()
SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.STARTING )
// start countdown
- SetUIVar( level, "gameStartTime", Time() + 15 )
- float countdownEndTime = Time() + 15.0
+ SetUIVar( level, "gameStartTime", Time() + GetConVarFloat( "ns_private_match_countdown_length" ) )
+ float countdownEndTime = Time() + GetConVarFloat( "ns_private_match_countdown_length" )
// can't use start here because we need to check stuff
while ( Time() < countdownEndTime )
@@ -159,7 +159,7 @@ void function StartMatch()
SetConVarString( "ns_private_match_last_map", file.map )
SetConVarString( "ns_private_match_last_mode", file.mode )
- SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp?
+ //SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp?
string mode = file.mode
if ( !( mode in GAMETYPE_TEXT ) )
@@ -206,7 +206,7 @@ bool function ClientCommandCallback_PrivateMatchSetPlaylistVarOverride( entity p
if ( GetConVarInt( "ns_private_match_only_host_can_change_settings" ) >= 1 )
if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
return true
-
+
bool found = false
foreach ( string category in GetPrivateMatchSettingCategories() )
{
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
index 6945fb96..62f7d459 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
@@ -42,6 +42,7 @@ void function BaseGametype_Init_MPSP()
AddPostDamageCallback( "npc_titan", AddToTitanDamageStat )
RegisterSignal( "PlayerRespawnStarted" )
+ RegisterSignal( "KillCamOver" )
}
void function SetIntermissionCamera( entity camera )
@@ -316,8 +317,10 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
player.SetObserverTarget( null )
}
+ // hack: double check if killcams are enabled and valid here in case gamestate has changed this
+ shouldDoReplay = shouldDoReplay && Replay_IsEnabled() && KillcamsEnabled() && IsValid( attacker )
// quick note: in cases where player.Die() is called: e.g. for round ends, player == attacker
- if ( shouldDoReplay && Replay_IsEnabled() && KillcamsEnabled() && IsValid( attacker ) ) // hack: double check if killcams are enabled and valid here in case gamestate has changed this
+ if ( shouldDoReplay )
{
player.watchingKillreplayEndTime = Time() + replayLength
float beforeTime = GetKillReplayBeforeTime( player, methodOfDeath )
@@ -355,7 +358,12 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
RespawnAsPilot( player )
}
else if ( GamePlayingOrSuddenDeath() || GetGameState() == eGameState.Epilogue )
+ {
+ if ( shouldDoReplay && player.IsWatchingKillReplay() )
+ player.WaitSignal( "KillCamOver" )
+
thread PlayerBecomesSpectator( player )
+ }
}
void function PlayerWatchesKillReplayWrapper( entity player, entity attacker, float timeSinceAttackerSpawned, float timeOfDeath, float beforeTime, table replayTracker )
@@ -373,6 +381,7 @@ void function PlayerWatchesKillReplayWrapper( entity player, entity attacker, fl
// don't clear if we're in a roundwinningkillreplay
if ( IsValid( player ) && !( ( GetGameState() == eGameState.SwitchingSides || GetGameState() == eGameState.WinnerDetermined ) && IsRoundWinningKillReplayEnabled() ) )
{
+ player.Signal( "KillCamOver" )
player.ClearReplayDelay()
player.ClearViewEntity()
player.SetPredictionEnabled( true )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_changemap.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_changemap.nut
index 470fa6a4..16a3ce92 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_changemap.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_changemap.nut
@@ -34,7 +34,10 @@ void function CodeCallback_MatchIsOver()
for ( int j = 0; j < GetCurrentPlaylistGamemodeByIndexMapsCount( i ); j++ )
{
if ( changeOnNextIteration )
+ {
GameRules_ChangeMap( GetCurrentPlaylistGamemodeByIndexMapByIndex( i, j ), GetCurrentPlaylistGamemodeByIndex( i ) )
+ return
+ }
if ( GetCurrentPlaylistGamemodeByIndexMapByIndex( i, j ) == GetMapName() )
changeOnNextIteration = true // change to next map/mode we iterate over
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
index fdcc468c..4f6a1291 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
@@ -146,7 +146,7 @@ void function SpawnPlayerIntoDropship( entity player )
int playerDropshipIndex = -1
foreach ( IntroDropship dropship in teamDropships )
for ( int i = 0; i < dropship.players.len(); i++ )
- if ( dropship.players[ i ] == player )
+ if ( dropship.players[ i ] == null )
{
playerDropship = dropship
playerDropshipIndex = i
@@ -203,6 +203,9 @@ void function SpawnPlayerIntoDropship( entity player )
void function PlayerJumpsFromDropship( entity player )
{
+ player.EndSignal( "OnDeath" )
+ player.EndSignal( "OnDestroy" )
+
OnThreadEnd( function() : ( player )
{
if ( IsValid( player ) )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
index 562f65e5..2f16379e 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
@@ -451,6 +451,7 @@ void function GameStateEnter_SwitchingSides_Threaded()
void function PlayerWatchesSwitchingSidesKillReplay( entity player, bool doReplay, float replayLength )
{
+ player.EndSignal( "OnDestroy" )
player.FreezeControlsOnServer()
ScreenFadeToBlackForever( player, SWITCHING_SIDES_DELAY_REPLAY ) // automatically cleared
@@ -717,18 +718,21 @@ void function SetWinner( int team, string winningReason = "", string losingReaso
else
file.announceRoundWinnerLosingSubstr = GetStringID( losingReason )
- if ( IsRoundBased() )
- {
- if ( team != TEAM_UNASSIGNED )
- {
- GameRules_SetTeamScore( team, GameRules_GetTeamScore( team ) + 1 )
- GameRules_SetTeamScore2( team, GameRules_GetTeamScore2( team ) + 1 )
+ if ( GamePlayingOrSuddenDeath() )
+ {
+ if ( IsRoundBased() )
+ {
+ if ( team != TEAM_UNASSIGNED )
+ {
+ GameRules_SetTeamScore( team, GameRules_GetTeamScore( team ) + 1 )
+ GameRules_SetTeamScore2( team, GameRules_GetTeamScore2( team ) + 1 )
+ }
+
+ SetGameState( eGameState.WinnerDetermined )
}
-
- SetGameState( eGameState.WinnerDetermined )
+ else
+ SetGameState( eGameState.WinnerDetermined )
}
- else
- SetGameState( eGameState.WinnerDetermined )
}
void function AddTeamScore( int team, int amount )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
index 58a4be02..92307f3c 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
@@ -191,6 +191,7 @@ void function PlayerWatchesWargamesIntro( entity player )
player.ClearParent()
player.UnforceStand()
player.MovementEnable()
+ player.ClearInvulnerable()
Remote_CallFunction_NonReplay( player, "ServerCallback_ClearFactionLeaderIntro" )
}
})
@@ -224,6 +225,7 @@ void function PlayerWatchesWargamesIntro( entity player )
TrainingPod_ViewConeLock_PodClosed( player )
player.DisableWeaponViewModel()
player.MovementDisable()
+ player.SetInvulnerable()
// spawn faction leader
// no clue why client subtracts 4.5 from the time we give this, so just add it here instead