Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

901 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include <vgui_controls/Label.h>
  9. #include <vgui_controls/Button.h>
  10. #include <vgui_controls/ImagePanel.h>
  11. #include <vgui_controls/RichText.h>
  12. #include <vgui_controls/Frame.h>
  13. #include <vgui/IScheme.h>
  14. #include <game/client/iviewport.h>
  15. #include <vgui/IVGui.h>
  16. #include <KeyValues.h>
  17. #include <filesystem.h>
  18. #include <vgui_controls/AnimationController.h>
  19. #include "iclientmode.h"
  20. #include "clientmode_shared.h"
  21. #include "inputsystem/iinputsystem.h"
  22. #include "vguicenterprint.h"
  23. #include "tf_controls.h"
  24. #include "basemodelpanel.h"
  25. #include "tf_teammenu.h"
  26. #include <convar.h>
  27. #include "IGameUIFuncs.h" // for key bindings
  28. #include "hud.h" // for gEngfuncs
  29. #include "c_tf_player.h"
  30. #include "tf_gamerules.h"
  31. #include "c_team.h"
  32. #include "tf_hud_notification_panel.h"
  33. #include "iinput.h"
  34. //-----------------------------------------------------------------------------
  35. // Purpose: Constructor
  36. //-----------------------------------------------------------------------------
  37. CTFTeamButton::CTFTeamButton( vgui::Panel *parent, const char *panelName ) : CExButton( parent, panelName, "" )
  38. {
  39. m_szModelPanel[0] = '\0';
  40. m_iTeam = TEAM_UNASSIGNED;
  41. m_flHoverTimeToWait = -1;
  42. m_flHoverTime = -1;
  43. m_bMouseEntered = false;
  44. m_bTeamDisabled = false;
  45. vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose:
  49. //-----------------------------------------------------------------------------
  50. void CTFTeamButton::ApplySettings( KeyValues *inResourceData )
  51. {
  52. BaseClass::ApplySettings( inResourceData );
  53. Q_strncpy( m_szModelPanel, inResourceData->GetString( "associated_model", "" ), sizeof( m_szModelPanel ) );
  54. m_iTeam = inResourceData->GetInt( "team", TEAM_UNASSIGNED );
  55. m_flHoverTimeToWait = inResourceData->GetFloat( "hover", -1 );
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose:
  59. //-----------------------------------------------------------------------------
  60. void CTFTeamButton::ApplySchemeSettings( vgui::IScheme *pScheme )
  61. {
  62. BaseClass::ApplySchemeSettings( pScheme );
  63. SetDefaultColor( GetFgColor(), Color( 0, 0, 0, 0 ) );
  64. SetArmedColor( GetButtonFgColor(), Color( 0, 0, 0, 0 ) );
  65. SetDepressedColor( GetButtonFgColor(), Color( 0, 0, 0, 0 ) );
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose:
  69. //-----------------------------------------------------------------------------
  70. void CTFTeamButton::SendAnimation( const char *pszAnimation )
  71. {
  72. Panel *pParent = GetParent();
  73. if ( pParent )
  74. {
  75. CModelPanel *pModel = dynamic_cast< CModelPanel* >( pParent->FindChildByName( m_szModelPanel ) );
  76. if ( pModel )
  77. {
  78. KeyValues *kvParms = new KeyValues( "SetAnimation" );
  79. if ( kvParms )
  80. {
  81. kvParms->SetString( "animation", pszAnimation );
  82. PostMessage( pModel, kvParms );
  83. }
  84. }
  85. }
  86. }
  87. //-----------------------------------------------------------------------------
  88. // Purpose:
  89. //-----------------------------------------------------------------------------
  90. void CTFTeamButton::SetDefaultAnimation( const char *pszName )
  91. {
  92. Panel *pParent = GetParent();
  93. if ( pParent )
  94. {
  95. CModelPanel *pModel = dynamic_cast< CModelPanel* >( pParent->FindChildByName( m_szModelPanel ) );
  96. if ( pModel )
  97. {
  98. pModel->SetDefaultAnimation( pszName );
  99. }
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. //-----------------------------------------------------------------------------
  105. bool CTFTeamButton::IsTeamFull()
  106. {
  107. if ( TFGameRules() && TFGameRules()->IsInArenaMode() == true && tf_arena_use_queue.GetBool() == true )
  108. return false;
  109. bool bRetVal = false;
  110. if ( ( m_iTeam > TEAM_UNASSIGNED ) && GetParent() )
  111. {
  112. CTFTeamMenu *pTeamMenu = dynamic_cast< CTFTeamMenu* >( GetParent() );
  113. if ( pTeamMenu )
  114. {
  115. bRetVal = ( m_iTeam == TF_TEAM_BLUE ) ? pTeamMenu->IsBlueTeamDisabled() : pTeamMenu->IsRedTeamDisabled();
  116. }
  117. }
  118. return bRetVal;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. //-----------------------------------------------------------------------------
  123. void CTFTeamButton::OnCursorEntered()
  124. {
  125. BaseClass::OnCursorEntered();
  126. SetMouseEnteredState( true );
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose:
  130. //-----------------------------------------------------------------------------
  131. void CTFTeamButton::OnCursorExited()
  132. {
  133. BaseClass::OnCursorExited();
  134. SetMouseEnteredState( false );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. //-----------------------------------------------------------------------------
  139. void CTFTeamButton::SetMouseEnteredState( bool state )
  140. {
  141. if ( state )
  142. {
  143. m_bMouseEntered = true;
  144. if ( m_flHoverTimeToWait > 0 )
  145. {
  146. m_flHoverTime = gpGlobals->curtime + m_flHoverTimeToWait;
  147. }
  148. else
  149. {
  150. m_flHoverTime = -1;
  151. }
  152. if ( m_bTeamDisabled )
  153. {
  154. SendAnimation( "enter_disabled" );
  155. }
  156. else
  157. {
  158. SendAnimation( "enter_enabled" );
  159. }
  160. }
  161. else
  162. {
  163. m_bMouseEntered = false;
  164. m_flHoverTime = -1;
  165. if ( m_bTeamDisabled )
  166. {
  167. SendAnimation( "exit_disabled" );
  168. }
  169. else
  170. {
  171. SendAnimation( "exit_enabled" );
  172. }
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose:
  177. //-----------------------------------------------------------------------------
  178. void CTFTeamButton::OnTick()
  179. {
  180. if ( GetParent() && !GetParent()->IsVisible() )
  181. return;
  182. // check to see if our state has changed
  183. bool bDisabled = IsTeamFull();
  184. if ( bDisabled != m_bTeamDisabled )
  185. {
  186. m_bTeamDisabled = bDisabled;
  187. if ( m_bMouseEntered )
  188. {
  189. // something has changed, so reset our state
  190. SetMouseEnteredState( true );
  191. }
  192. else
  193. {
  194. // the mouse isn't currently over the button, but we should update the status
  195. if ( m_bTeamDisabled )
  196. {
  197. SendAnimation( "idle_disabled" );
  198. }
  199. else
  200. {
  201. SendAnimation( "idle_enabled" );
  202. }
  203. }
  204. }
  205. if ( ( m_flHoverTime > 0 ) && ( m_flHoverTime < gpGlobals->curtime ) )
  206. {
  207. m_flHoverTime = -1;
  208. if ( m_bTeamDisabled )
  209. {
  210. SendAnimation( "hover_disabled" );
  211. }
  212. else
  213. {
  214. SendAnimation( "hover_enabled" );
  215. }
  216. }
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Purpose: Constructor
  220. //-----------------------------------------------------------------------------
  221. CTFTeamMenu::CTFTeamMenu( IViewPort *pViewPort ) : CTeamMenu( pViewPort )
  222. {
  223. SetMinimizeButtonVisible( false );
  224. SetMaximizeButtonVisible( false );
  225. SetCloseButtonVisible( false );
  226. SetVisible( false );
  227. SetKeyBoardInputEnabled( true );
  228. m_iTeamMenuKey = BUTTON_CODE_INVALID;
  229. m_pBlueTeamButton = new CTFTeamButton( this, "teambutton0" );
  230. m_pRedTeamButton = new CTFTeamButton( this, "teambutton1" );
  231. m_pAutoTeamButton = new CTFTeamButton( this, "teambutton2" );
  232. m_pSpecTeamButton = new CTFTeamButton( this, "teambutton3" );
  233. m_pSpecLabel = new CExLabel( this, "TeamMenuSpectate", "" );
  234. #ifdef _X360
  235. m_pFooter = new CTFFooter( this, "Footer" );
  236. #else
  237. m_pCancelButton = new CExButton( this, "CancelButton", "#TF_Cancel" );
  238. m_pHighlanderLabel = new CExLabel( this, "HighlanderLabel", "" );
  239. m_pHighlanderLabelShadow = new CExLabel( this, "HighlanderLabelShadow", "" );
  240. m_pTeamsFullLabel = new CExLabel( this, "TeamsFullLabel", "" );
  241. m_pTeamsFullLabelShadow = new CExLabel( this, "TeamsFullLabelShadow", "" );
  242. m_pTeamsFullArrow = new CTFImagePanel( this, "TeamsFullArrow" );
  243. #endif
  244. vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
  245. m_bRedDisabled = false;
  246. m_bBlueDisabled = false;
  247. if ( g_pInputSystem && ::input->IsSteamControllerActive() )
  248. {
  249. LoadControlSettings( "Resource/UI/Teammenu_SC.res" );
  250. SetMouseInputEnabled( false );
  251. }
  252. else
  253. {
  254. LoadControlSettings( "Resource/UI/Teammenu.res" );
  255. SetMouseInputEnabled( true );
  256. }
  257. ListenForGameEvent( "server_spawn" );
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose: Destructor
  261. //-----------------------------------------------------------------------------
  262. CTFTeamMenu::~CTFTeamMenu()
  263. {
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose: Destructor
  267. //-----------------------------------------------------------------------------
  268. void CTFTeamMenu::ApplySchemeSettings( IScheme *pScheme )
  269. {
  270. BaseClass::ApplySchemeSettings( pScheme );
  271. if ( ::input->IsSteamControllerActive() )
  272. {
  273. LoadControlSettings( "Resource/UI/Teammenu_SC.res" );
  274. m_pCancelHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "CancelHintIcon" ) );
  275. m_pJoinAutoHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinAutoHintIcon" ) );
  276. m_pJoinBluHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinBluHintIcon" ) );
  277. m_pJoinRedHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinRedHintIcon" ) );
  278. m_pJoinSpectatorsHintIcon = dynamic_cast< CSCHintIcon* >( FindChildByName( "JoinSpectatorsHintIcon" ) );
  279. SetMouseInputEnabled( false );
  280. }
  281. else
  282. {
  283. LoadControlSettings( "Resource/UI/Teammenu.res" );
  284. m_pCancelHintIcon = nullptr;
  285. m_pJoinAutoHintIcon = m_pJoinRedHintIcon = m_pJoinBluHintIcon = m_pJoinSpectatorsHintIcon = nullptr;
  286. SetMouseInputEnabled( true );
  287. }
  288. Update();
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Purpose:
  292. //-----------------------------------------------------------------------------
  293. void CTFTeamMenu::ShowPanel( bool bShow )
  294. {
  295. if ( BaseClass::IsVisible() == bShow )
  296. return;
  297. if ( !gameuifuncs || !gViewPortInterface || !engine )
  298. return;
  299. if ( bShow )
  300. {
  301. if ( !C_TFPlayer::GetLocalTFPlayer() )
  302. return;
  303. bool bDisallowChange = false;
  304. if ( C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() >= FIRST_GAME_TEAM )
  305. {
  306. const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  307. if ( pMatchDesc && !pMatchDesc->m_params.m_bAllowTeamChange )
  308. {
  309. bDisallowChange = true;
  310. }
  311. }
  312. if ( ( TFGameRules()->State_Get() == GR_STATE_TEAM_WIN
  313. && C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TFGameRules()->GetWinningTeam()
  314. && C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TEAM_SPECTATOR
  315. && C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() != TEAM_UNASSIGNED )
  316. || TFGameRules()->State_Get() == GR_STATE_GAME_OVER
  317. // [msmith] Don't allow the player to switch teams when in training.
  318. || TFGameRules()->IsInTraining()
  319. // or if they are coaching
  320. || C_TFPlayer::GetLocalTFPlayer()->m_bIsCoaching
  321. || bDisallowChange
  322. )
  323. {
  324. SetVisible( false );
  325. CHudNotificationPanel *pNotifyPanel = GET_HUDELEMENT( CHudNotificationPanel );
  326. if ( pNotifyPanel )
  327. {
  328. pNotifyPanel->SetupNotifyCustom( "#TF_CantChangeTeamNow", "ico_notify_flag_moving", C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() );
  329. }
  330. return;
  331. }
  332. extern void Coaching_CheckIfEligibleForCoaching();
  333. Coaching_CheckIfEligibleForCoaching();
  334. gViewPortInterface->ShowPanel( PANEL_CLASS_RED, false );
  335. gViewPortInterface->ShowPanel( PANEL_CLASS_BLUE, false );
  336. engine->CheckPoint( "TeamMenu" );
  337. // Force us to reload our scheme, in case Steam Controller stuff has changed.
  338. InvalidateLayout( true, true );
  339. Activate();
  340. // get key bindings if shown
  341. m_iTeamMenuKey = gameuifuncs->GetButtonCodeForBind( "changeteam" );
  342. m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
  343. switch ( C_TFPlayer::GetLocalTFPlayer()->GetTeamNumber() )
  344. {
  345. case TF_TEAM_BLUE:
  346. if ( ::input->EnableJoystickMode() )
  347. {
  348. m_pBlueTeamButton->OnCursorEntered();
  349. m_pBlueTeamButton->SetDefaultAnimation( "enter_enabled" );
  350. }
  351. GetFocusNavGroup().SetCurrentFocus( m_pBlueTeamButton->GetVPanel(), m_pBlueTeamButton->GetVPanel() );
  352. break;
  353. case TF_TEAM_RED:
  354. if ( ::input->EnableJoystickMode() )
  355. {
  356. m_pRedTeamButton->OnCursorEntered();
  357. m_pRedTeamButton->SetDefaultAnimation( "enter_enabled" );
  358. }
  359. GetFocusNavGroup().SetCurrentFocus( m_pRedTeamButton->GetVPanel(), m_pRedTeamButton->GetVPanel() );
  360. break;
  361. default:
  362. if ( ::input->EnableJoystickMode() )
  363. {
  364. m_pAutoTeamButton->OnCursorEntered();
  365. m_pAutoTeamButton->SetDefaultAnimation( "enter_enabled" );
  366. }
  367. GetFocusNavGroup().SetCurrentFocus( m_pAutoTeamButton->GetVPanel(), m_pAutoTeamButton->GetVPanel() );
  368. break;
  369. }
  370. ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
  371. }
  372. else
  373. {
  374. SetVisible( false );
  375. SetHighlanderTeamsFullPanels( false, true );
  376. if ( ::input->EnableJoystickMode() )
  377. {
  378. // Close the door behind us
  379. CTFTeamButton *pButton = dynamic_cast< CTFTeamButton *> ( GetFocusNavGroup().GetCurrentFocus() );
  380. if ( pButton )
  381. {
  382. pButton->OnCursorExited();
  383. }
  384. }
  385. }
  386. }
  387. //-----------------------------------------------------------------------------
  388. // Purpose: called to update the menu with new information
  389. //-----------------------------------------------------------------------------
  390. void CTFTeamMenu::Update( void )
  391. {
  392. BaseClass::Update();
  393. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  394. if ( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() != TEAM_UNASSIGNED ) )
  395. {
  396. #ifdef _X360
  397. if ( m_pFooter )
  398. {
  399. m_pFooter->ShowButtonLabel( "cancel", true );
  400. }
  401. #else
  402. if ( m_pCancelButton )
  403. {
  404. m_pCancelButton->SetVisible( true );
  405. if ( m_pCancelHintIcon )
  406. {
  407. m_pCancelHintIcon->SetVisible( true );
  408. }
  409. }
  410. #endif
  411. }
  412. else
  413. {
  414. #ifdef _X360
  415. if ( m_pFooter )
  416. {
  417. m_pFooter->ShowButtonLabel( "cancel", false );
  418. }
  419. #else
  420. if ( m_pCancelButton && m_pCancelButton->IsVisible() )
  421. {
  422. m_pCancelButton->SetVisible( false );
  423. if ( m_pCancelHintIcon )
  424. {
  425. m_pCancelHintIcon->SetVisible( false );
  426. }
  427. }
  428. #endif
  429. }
  430. }
  431. #ifdef _X360
  432. //-----------------------------------------------------------------------------
  433. // Purpose:
  434. //-----------------------------------------------------------------------------
  435. void CTFTeamMenu::Join_Team( const CCommand &args )
  436. {
  437. if ( args.ArgC() > 1 )
  438. {
  439. char cmd[256];
  440. Q_snprintf( cmd, sizeof( cmd ), "jointeam_nomenus %s", args.Arg( 1 ) );
  441. OnCommand( cmd );
  442. }
  443. }
  444. #endif
  445. //-----------------------------------------------------------------------------
  446. // Purpose: chooses and loads the text page to display that describes mapName map
  447. //-----------------------------------------------------------------------------
  448. void CTFTeamMenu::LoadMapPage( const char *mapName )
  449. {
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Purpose:
  453. //-----------------------------------------------------------------------------
  454. void CTFTeamMenu::OnKeyCodePressed( KeyCode code )
  455. {
  456. if ( ( m_iTeamMenuKey != BUTTON_CODE_INVALID && m_iTeamMenuKey == code ) ||
  457. code == KEY_XBUTTON_BACK ||
  458. code == KEY_XBUTTON_B ||
  459. code == STEAMCONTROLLER_B )
  460. {
  461. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  462. if ( pLocalPlayer && ( pLocalPlayer->GetTeamNumber() != TEAM_UNASSIGNED ) )
  463. {
  464. ShowPanel( false );
  465. }
  466. }
  467. else if( code == KEY_SPACE || code == STEAMCONTROLLER_Y )
  468. {
  469. engine->ClientCmd( "jointeam auto" );
  470. ShowPanel( false );
  471. OnClose();
  472. }
  473. else if( code == KEY_XBUTTON_A || code == KEY_XBUTTON_RTRIGGER || code == STEAMCONTROLLER_A )
  474. {
  475. // select the active focus
  476. if ( GetFocusNavGroup().GetCurrentFocus() )
  477. {
  478. ipanel()->SendMessage( GetFocusNavGroup().GetCurrentFocus()->GetVPanel(), new KeyValues( "PressButton" ), GetVPanel() );
  479. }
  480. }
  481. else if( code == KEY_XBUTTON_RIGHT || code == KEY_XSTICK1_RIGHT || code == STEAMCONTROLLER_DPAD_RIGHT )
  482. {
  483. CTFTeamButton *pButton;
  484. pButton = dynamic_cast< CTFTeamButton *> ( GetFocusNavGroup().GetCurrentFocus() );
  485. if ( pButton )
  486. {
  487. pButton->OnCursorExited();
  488. GetFocusNavGroup().RequestFocusNext( pButton->GetVPanel() );
  489. }
  490. else
  491. {
  492. GetFocusNavGroup().RequestFocusNext( NULL );
  493. }
  494. pButton = dynamic_cast< CTFTeamButton * > ( GetFocusNavGroup().GetCurrentFocus() );
  495. if ( pButton )
  496. {
  497. pButton->OnCursorEntered();
  498. }
  499. ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
  500. }
  501. else if( code == KEY_XBUTTON_LEFT || code == KEY_XSTICK1_LEFT || code == STEAMCONTROLLER_DPAD_LEFT )
  502. {
  503. CTFTeamButton *pButton;
  504. pButton = dynamic_cast< CTFTeamButton *> ( GetFocusNavGroup().GetCurrentFocus() );
  505. if ( pButton )
  506. {
  507. pButton->OnCursorExited();
  508. GetFocusNavGroup().RequestFocusPrev( pButton->GetVPanel() );
  509. }
  510. else
  511. {
  512. GetFocusNavGroup().RequestFocusPrev( NULL );
  513. }
  514. pButton = dynamic_cast< CTFTeamButton * > ( GetFocusNavGroup().GetCurrentFocus() );
  515. if ( pButton )
  516. {
  517. pButton->OnCursorEntered();
  518. }
  519. ActivateSelectIconHint( GetFocusNavGroup().GetCurrentFocus() ? GetFocusNavGroup().GetCurrentFocus()->GetTabPosition() : -1 );
  520. }
  521. else if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
  522. {
  523. gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
  524. gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
  525. }
  526. else
  527. {
  528. BaseClass::OnKeyCodePressed( code );
  529. }
  530. }
  531. //-----------------------------------------------------------------------------
  532. // Purpose: Called when the user picks a team
  533. //-----------------------------------------------------------------------------
  534. void CTFTeamMenu::OnCommand( const char *command )
  535. {
  536. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  537. if ( Q_stricmp( command, "vguicancel" ) )
  538. {
  539. // we're selecting a team, so make sure it's not the team we're already on before sending to the server
  540. if ( pLocalPlayer && ( Q_strstr( command, "jointeam " ) ) )
  541. {
  542. const char *pTeam = command + Q_strlen( "jointeam " );
  543. int iTeam = TEAM_INVALID;
  544. if ( Q_stricmp( pTeam, "spectate" ) == 0 )
  545. {
  546. iTeam = TEAM_SPECTATOR;
  547. }
  548. else if ( Q_stricmp( pTeam, "red" ) == 0 )
  549. {
  550. iTeam = TF_TEAM_RED;
  551. }
  552. else if ( Q_stricmp( pTeam, "blue" ) == 0 )
  553. {
  554. iTeam = TF_TEAM_BLUE;
  555. }
  556. if ( iTeam == TF_TEAM_RED && m_bRedDisabled )
  557. {
  558. return;
  559. }
  560. if ( iTeam == TF_TEAM_BLUE && m_bBlueDisabled )
  561. {
  562. return;
  563. }
  564. // are we selecting the team we're already on?
  565. if ( pLocalPlayer->GetTeamNumber() != iTeam )
  566. {
  567. engine->ClientCmd( command );
  568. }
  569. }
  570. else if ( pLocalPlayer && ( Q_strstr( command, "jointeam_nomenus " ) ) )
  571. {
  572. engine->ClientCmd( command );
  573. }
  574. }
  575. BaseClass::OnCommand( command );
  576. ShowPanel( false );
  577. OnClose();
  578. }
  579. void CTFTeamMenu::OnClose()
  580. {
  581. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  582. if ( pLocalPlayer )
  583. {
  584. // Clear the HIDEHUD_HEALTH bit we hackily added. Turns out prediction
  585. // was restoring these bits every frame. Unfortunately, prediction
  586. // is off for karts which means the spell hud item would disappear if you
  587. // brought up this menu and returned.
  588. pLocalPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_HEALTH;
  589. }
  590. BaseClass::OnClose();
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Purpose: Activate the right selection hint icon, depending on the focus group number selected
  594. //-----------------------------------------------------------------------------
  595. void CTFTeamMenu::ActivateSelectIconHint( int focus_group_number )
  596. {
  597. if ( m_pJoinAutoHintIcon ) m_pJoinAutoHintIcon->SetVisible( false );
  598. if ( m_pJoinBluHintIcon ) m_pJoinBluHintIcon->SetVisible( false );
  599. if ( m_pJoinRedHintIcon ) m_pJoinRedHintIcon->SetVisible( false );
  600. if ( m_pJoinSpectatorsHintIcon ) m_pJoinSpectatorsHintIcon->SetVisible( false );
  601. CSCHintIcon* icon = nullptr;
  602. switch ( focus_group_number )
  603. {
  604. case 1: icon = m_pJoinAutoHintIcon; break;
  605. case 2: icon = m_pJoinSpectatorsHintIcon; break;
  606. case 3: icon = m_pJoinBluHintIcon; break;
  607. case 4: icon = m_pJoinRedHintIcon; break;
  608. }
  609. if ( icon )
  610. {
  611. icon->SetVisible( true );
  612. }
  613. }
  614. //-----------------------------------------------------------------------------
  615. // Purpose:
  616. //-----------------------------------------------------------------------------
  617. void CTFTeamMenu::SetHighlanderTeamsFullPanels( bool bTeamsFull, bool bForce /* = false */ )
  618. {
  619. if ( m_pTeamsFullLabel )
  620. {
  621. if ( bForce || ( m_pTeamsFullLabel->IsVisible() != bTeamsFull ) )
  622. {
  623. m_pTeamsFullLabel->SetVisible( bTeamsFull );
  624. }
  625. }
  626. if ( m_pTeamsFullLabelShadow )
  627. {
  628. if ( bForce || ( m_pTeamsFullLabelShadow->IsVisible() != bTeamsFull ) )
  629. {
  630. m_pTeamsFullLabelShadow->SetVisible( bTeamsFull );
  631. }
  632. }
  633. if ( !mp_allowspectators.GetBool() )
  634. {
  635. // don't show the arrow if the server doesn't allow spectators
  636. bTeamsFull = false;
  637. }
  638. if ( m_pTeamsFullArrow )
  639. {
  640. if ( bForce || ( m_pTeamsFullArrow->IsVisible() != bTeamsFull ) )
  641. {
  642. m_pTeamsFullArrow->SetVisible( bTeamsFull );
  643. if ( bTeamsFull )
  644. {
  645. // turn on animation
  646. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TeamsFullArrowAnimate" );
  647. }
  648. else
  649. {
  650. // turn off animation
  651. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TeamsFullArrowAnimateEnd" );
  652. }
  653. }
  654. }
  655. }
  656. //-----------------------------------------------------------------------------
  657. // Frame-based update
  658. //-----------------------------------------------------------------------------
  659. void CTFTeamMenu::OnTick()
  660. {
  661. // update the number of players on each team
  662. // enable or disable buttons based on team limit
  663. if ( !IsVisible() )
  664. return;
  665. C_Team *pRed = GetGlobalTeam( TF_TEAM_RED );
  666. C_Team *pBlue = GetGlobalTeam( TF_TEAM_BLUE );
  667. if ( !pRed || !pBlue )
  668. return;
  669. // set our team counts
  670. SetDialogVariable( "bluecount", pBlue->Get_Number_Players() );
  671. SetDialogVariable( "redcount", pRed->Get_Number_Players() );
  672. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  673. if ( !pLocalPlayer )
  674. return;
  675. CTFGameRules *pRules = TFGameRules();
  676. if ( !pRules )
  677. return;
  678. bool bHighlander = pRules->IsInHighlanderMode();
  679. if ( m_pHighlanderLabel )
  680. {
  681. if ( m_pHighlanderLabel->IsVisible() != bHighlander )
  682. {
  683. m_pHighlanderLabel->SetVisible( bHighlander );
  684. }
  685. }
  686. if ( m_pHighlanderLabelShadow )
  687. {
  688. if ( m_pHighlanderLabelShadow->IsVisible() != bHighlander )
  689. {
  690. m_pHighlanderLabelShadow->SetVisible( bHighlander );
  691. }
  692. }
  693. // check if teams are unbalanced
  694. m_bRedDisabled = m_bBlueDisabled = false;
  695. int iHeavyTeam, iLightTeam;
  696. bool bUnbalanced = pRules->AreTeamsUnbalanced( iHeavyTeam, iLightTeam );
  697. int iCurrentTeam = pLocalPlayer->GetTeamNumber();
  698. if ( ( bUnbalanced && iHeavyTeam == TF_TEAM_RED ) ||
  699. ( pRules->WouldChangeUnbalanceTeams( TF_TEAM_RED, iCurrentTeam ) ) ||
  700. ( bHighlander && GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() >= TF_LAST_NORMAL_CLASS - 1 ) ||
  701. ( pRules->IsMannVsMachineMode() && ( GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() >= kMVM_DefendersTeamSize ) ) )
  702. {
  703. m_bRedDisabled = true;
  704. }
  705. if ( ( bUnbalanced && iHeavyTeam == TF_TEAM_BLUE ) ||
  706. ( pRules->WouldChangeUnbalanceTeams( TF_TEAM_BLUE, iCurrentTeam ) ) ||
  707. ( bHighlander && GetGlobalTeam( TF_TEAM_BLUE )->GetNumPlayers() >= TF_LAST_NORMAL_CLASS - 1 ) ||
  708. ( pRules->IsMannVsMachineMode() ) )
  709. {
  710. m_bBlueDisabled = true;
  711. }
  712. bool bTeamsFull = m_bRedDisabled && m_bBlueDisabled;
  713. SetHighlanderTeamsFullPanels( bHighlander && bTeamsFull );
  714. if ( m_pSpecTeamButton && m_pSpecLabel && m_pAutoTeamButton )
  715. {
  716. {
  717. if ( mp_allowspectators.GetBool() )
  718. {
  719. if ( !m_pSpecTeamButton->IsVisible() )
  720. {
  721. m_pSpecTeamButton->SetVisible( true );
  722. m_pSpecLabel->SetVisible( true );
  723. }
  724. if ( !m_pAutoTeamButton->IsVisible() )
  725. {
  726. m_pAutoTeamButton->SetVisible( true );
  727. }
  728. }
  729. else
  730. {
  731. if ( m_pSpecTeamButton->IsVisible() )
  732. {
  733. m_pSpecTeamButton->SetVisible( false );
  734. m_pSpecLabel->SetVisible( false );
  735. }
  736. if ( bHighlander )
  737. {
  738. if ( bTeamsFull )
  739. {
  740. if ( m_pAutoTeamButton->IsVisible() )
  741. {
  742. m_pAutoTeamButton->SetVisible( false );
  743. }
  744. }
  745. else
  746. {
  747. if ( !m_pAutoTeamButton->IsVisible() )
  748. {
  749. m_pAutoTeamButton->SetVisible( true );
  750. }
  751. }
  752. }
  753. }
  754. }
  755. }
  756. }
  757. void CTFTeamMenu::OnThink()
  758. {
  759. //Always hide the health... this needs to be done every frame because a message from the server keeps resetting this.
  760. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  761. if ( pLocalPlayer )
  762. {
  763. pLocalPlayer->m_Local.m_iHideHUD |= HIDEHUD_HEALTH;
  764. }
  765. BaseClass::OnThink();
  766. }
  767. //-----------------------------------------------------------------------------
  768. // Purpose:
  769. //-----------------------------------------------------------------------------
  770. void CTFTeamMenu::FireGameEvent( IGameEvent *event )
  771. {
  772. // when we are changing levels
  773. if ( FStrEq( event->GetName(), "server_spawn" ) )
  774. {
  775. SetHighlanderTeamsFullPanels( false, true );
  776. }
  777. }