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.

1566 lines
46 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "hudelement.h"
  10. #include "c_tf_player.h"
  11. #include "iclientmode.h"
  12. #include "ienginevgui.h"
  13. #include <vgui/ILocalize.h>
  14. #include <vgui/ISurface.h>
  15. #include <vgui/IVGui.h>
  16. #include <vgui_controls/Label.h>
  17. #include <vgui_controls/EditablePanel.h>
  18. #include "tf_imagepanel.h"
  19. #include "tf_gamerules.h"
  20. #include "c_tf_team.h"
  21. #include "vgui/tf_controls.h"
  22. #include <vgui_controls/TextEntry.h>
  23. #include "vgui_controls/AnimationController.h"
  24. #include "hud_basechat.h"
  25. #include "clientmode_shared.h"
  26. #include "c_playerresource.h"
  27. #include "c_tf_playerresource.h"
  28. #include "tf_hud_objectivestatus.h"
  29. #include "c_team_objectiveresource.h"
  30. #include "c_tf_team.h"
  31. #include "tf_clientscoreboard.h"
  32. #include "tf_playerpanel.h"
  33. #include "tf_hud_tournament.h"
  34. #include "c_tf_objective_resource.h"
  35. #include "tf_time_panel.h"
  36. #include "tf_hud_match_status.h"
  37. #include "tf_gc_client.h"
  38. #include "tf_lobby_server.h"
  39. #include "inputsystem/iinputsystem.h"
  40. // memdbgon must be the last include file in a .cpp file!!!
  41. #include "tier0/memdbgon.h"
  42. void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
  43. using namespace vgui;
  44. #define TOURNAMENT_PANEL_UPDATE_INTERVAL 0.25f
  45. extern ConVar mp_timelimit;
  46. extern ConVar mp_winlimit;
  47. extern ConVar mp_maxrounds;
  48. extern ConVar mp_tournament;
  49. class CHudChat;
  50. DECLARE_HUDELEMENT( CHudTournament );
  51. static const wchar_t* GetSCGlyph( const char* action )
  52. {
  53. auto origin = g_pInputSystem->GetSteamControllerActionOrigin( action, GAME_ACTION_SET_FPSCONTROLS );
  54. return g_pInputSystem->GetSteamControllerFontCharacterForActionOrigin( origin );
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose:
  58. //-----------------------------------------------------------------------------
  59. CHudTournament::CHudTournament( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudTournament" )
  60. {
  61. Panel *pParent = g_pClientMode->GetViewport();
  62. SetParent( pParent );
  63. SetHiddenBits( HIDEHUD_MISCSTATUS );
  64. vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );
  65. for ( int i = 0; i < MAX_TEAMS; i++ )
  66. {
  67. m_bTeamReady[i] = false;
  68. }
  69. m_bReadyStatusMode = false;
  70. m_bCompetitiveMode = false;
  71. m_bReadyTextBlinking = false;
  72. m_bCountDownVisible = false;
  73. m_pPlayerPanelKVs = NULL;
  74. m_bReapplyPlayerPanelKVs = false;
  75. m_pScoreboard = NULL;
  76. m_pCountdownBG = new vgui::ScalableImagePanel( this, "CountdownBG" );
  77. m_pCountdownLabel = new CExLabel( this, "CountdownLabel", L"" );
  78. m_pCountdownLabelShadow = new CExLabel( this, "CountdownLabelShadow", L"" );
  79. m_pModeImage = new vgui::ImagePanel( this, "ModeImage" );
  80. m_pHudTournamentBG = new vgui::ScalableImagePanel( this, "HudTournamentBG" );
  81. m_pTournamentConditionLabel = new CExLabel( this, "TournamentConditionLabel", L"" );
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. CHudTournament::~CHudTournament()
  87. {
  88. if ( m_pPlayerPanelKVs )
  89. {
  90. m_pPlayerPanelKVs->deleteThis();
  91. m_pPlayerPanelKVs = NULL;
  92. }
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. //-----------------------------------------------------------------------------
  97. void CHudTournament::Init( void )
  98. {
  99. // listen for events
  100. ListenForGameEvent( "tournament_stateupdate" );
  101. ListenForGameEvent( "teams_changed" );
  102. ListenForGameEvent( "localplayer_respawn" );
  103. ListenForGameEvent( "restart_timer_time" );
  104. ListenForGameEvent( "competitive_victory" );
  105. m_bShouldBeVisible = false;
  106. SetVisible( false );
  107. CHudElement::Init();
  108. m_flNextUpdate = gpGlobals->curtime;
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Purpose:
  112. //-----------------------------------------------------------------------------
  113. void CHudTournament::PlaySounds( int nTime )
  114. {
  115. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  116. if ( !pLocalPlayer )
  117. return;
  118. bool bCompetitiveMode = TFGameRules() && TFGameRules()->IsCompetitiveMode();
  119. switch( nTime )
  120. {
  121. case 60:
  122. {
  123. if ( bCompetitiveMode )
  124. {
  125. pLocalPlayer->EmitSound( "Announcer.CompGame1Begins60Seconds" );
  126. }
  127. break;
  128. }
  129. case 30:
  130. {
  131. if ( bCompetitiveMode )
  132. {
  133. pLocalPlayer->EmitSound( "Announcer.CompGame1Begins30Seconds" );
  134. }
  135. break;
  136. }
  137. case 10:
  138. {
  139. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  140. {
  141. if ( TFObjectiveResource()->GetMannVsMachineWaveCount() >= TFObjectiveResource()->GetMannVsMachineMaxWaveCount() )
  142. {
  143. pLocalPlayer->EmitSound( "Announcer.MVM_Final_Wave_Start" );
  144. }
  145. else if ( TFObjectiveResource()->GetMannVsMachineWaveCount() <= 1 )
  146. {
  147. if ( GTFGCClientSystem()->GetLobby() && IsMannUpGroup( GTFGCClientSystem()->GetLobby()->GetMatchGroup() ) )
  148. {
  149. pLocalPlayer->EmitSound( "Announcer.MVM_Manned_Up" );
  150. }
  151. else
  152. {
  153. pLocalPlayer->EmitSound( "Announcer.MVM_First_Wave_Start" );
  154. }
  155. }
  156. else
  157. {
  158. pLocalPlayer->EmitSound( "Announcer.MVM_Wave_Start" );
  159. }
  160. }
  161. else
  162. {
  163. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGame1Begins10Seconds" : "Announcer.RoundBegins10Seconds" );
  164. }
  165. break;
  166. }
  167. case 9:
  168. {
  169. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  170. {
  171. int nMaxWaves = TFObjectiveResource()->GetMannVsMachineMaxWaveCount();
  172. int nCurWave = TFObjectiveResource()->GetMannVsMachineWaveCount();
  173. bool bHasTank = false;
  174. for ( int i = 0; i < MVM_CLASS_TYPES_PER_WAVE_MAX_NEW; ++i )
  175. {
  176. // int nClassCount = TFObjectiveResource()->GetMannVsMachineWaveClassCount( i );
  177. const char *pchClassIconName = TFObjectiveResource()->GetMannVsMachineWaveClassName( i );
  178. if( V_stristr( pchClassIconName, "tank" ))
  179. {
  180. bHasTank = true;
  181. }
  182. }
  183. if( nCurWave == nMaxWaves )
  184. {
  185. pLocalPlayer->EmitSound( "music.mvm_start_last_wave" );
  186. }
  187. else if( bHasTank )
  188. {
  189. pLocalPlayer->EmitSound( "music.mvm_start_tank_wave" );
  190. }
  191. else if( nCurWave > ( nMaxWaves / 2 ) )
  192. {
  193. pLocalPlayer->EmitSound( "music.mvm_start_mid_wave" );
  194. }
  195. else
  196. {
  197. pLocalPlayer->EmitSound( "music.mvm_start_wave" );
  198. }
  199. }
  200. break;
  201. }
  202. case 5:
  203. {
  204. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGameBegins05Seconds" : "Announcer.RoundBegins5Seconds" );
  205. break;
  206. }
  207. case 4:
  208. {
  209. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGameBegins04Seconds" : "Announcer.RoundBegins4Seconds" );
  210. break;
  211. }
  212. case 3:
  213. {
  214. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGameBegins03Seconds" : "Announcer.RoundBegins3Seconds" );
  215. break;
  216. }
  217. case 2:
  218. {
  219. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGameBegins02Seconds" : "Announcer.RoundBegins2Seconds" );
  220. break;
  221. }
  222. case 1:
  223. {
  224. pLocalPlayer->EmitSound( bCompetitiveMode ? "Announcer.CompGameBegins01Seconds" : "Announcer.RoundBegins1Seconds" );
  225. break;
  226. }
  227. }
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Purpose:
  231. //-----------------------------------------------------------------------------
  232. void CHudTournament::PreparePanel( void )
  233. {
  234. if ( m_flNextUpdate > gpGlobals->curtime )
  235. return;
  236. if ( !TFGameRules() )
  237. return;
  238. bool bSteamController = ::input->IsSteamControllerActive();
  239. bool bShowReadyHintIcon = false;
  240. if ( TFGameRules()->IsInPreMatch() )
  241. {
  242. bool bCountdownVisible = false;
  243. bool bAutoReady = false;
  244. const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  245. if ( pMatchDesc )
  246. {
  247. bAutoReady = pMatchDesc->m_params.m_bAutoReady;
  248. }
  249. if ( !bAutoReady && ( TFGameRules()->IsWaitingForTeams() || TFGameRules()->GetRoundRestartTime() < 0 ) )
  250. {
  251. if ( m_bReadyStatusMode )
  252. {
  253. const char *pszLabelText;
  254. if ( TFGameRules() && TFGameRules()->PlayerReadyStatus_HaveMinPlayersToEnable() )
  255. {
  256. if ( bSteamController )
  257. {
  258. pszLabelText = "Tournament_Instructions_Ready_NoKeyHintText";
  259. bShowReadyHintIcon = true;
  260. }
  261. else
  262. {
  263. pszLabelText = "Tournament_Instructions_Ready";
  264. }
  265. }
  266. else
  267. {
  268. pszLabelText = "Tournament_Instructions_Waiting";
  269. }
  270. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( pszLabelText ) );
  271. SetDialogVariable( "tournamentstatelabel", g_pVGuiLocalize->Find( "Tournament_WaitingForTeam" ) );
  272. SetPlayerPanelsVisible( true );
  273. m_pModeImage->SetVisible( m_bCompetitiveMode );
  274. }
  275. else
  276. {
  277. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "Tournament_Instructions" ) );
  278. SetDialogVariable( "tournamentstatelabel", g_pVGuiLocalize->Find( "Tournament_WaitingForTeams" ) );
  279. SetPlayerPanelsVisible( false );
  280. m_pModeImage->SetVisible( false );
  281. }
  282. }
  283. else
  284. {
  285. float flTime = TFGameRules()->GetRoundRestartTime() - gpGlobals->curtime;
  286. int nTime = (int)( ceil( flTime ) );
  287. wchar szCountdown[64];
  288. wchar_t wzVal[16];
  289. const char *szCountDown = m_bReadyStatusMode ? "Tournament_CountDownTime" : "Tournament_Countdown";
  290. const char *szCountDownSec = m_bReadyStatusMode ? "Tournament_CountDownTime" : "Tournament_Countdown_Sec";
  291. swprintf( wzVal, ARRAYSIZE( wzVal ), L"%d", nTime );
  292. wchar_t *pFormatString = g_pVGuiLocalize->Find( szCountDown );
  293. if ( nTime == 1 )
  294. {
  295. pFormatString = g_pVGuiLocalize->Find( szCountDownSec );
  296. }
  297. if ( pFormatString )
  298. {
  299. g_pVGuiLocalize->ConstructString_safe( szCountdown, pFormatString, 1, wzVal );
  300. SetDialogVariable( "tournamentstatelabel", szCountdown );
  301. }
  302. if ( bAutoReady )
  303. {
  304. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "" ) );
  305. m_pModeImage->SetVisible( false );
  306. SetPlayerPanelsVisible( false );
  307. }
  308. else if ( nTime <= TOURNAMENT_NOCANCEL_TIME )
  309. {
  310. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "" ) );
  311. }
  312. else
  313. {
  314. if ( m_bReadyStatusMode )
  315. {
  316. if ( bSteamController )
  317. {
  318. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "Tournament_Instructions_Ready_NoKeyHintText" ) );
  319. bShowReadyHintIcon = true;
  320. }
  321. else
  322. {
  323. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "Tournament_Instructions_Ready" ) );
  324. }
  325. }
  326. else
  327. {
  328. SetDialogVariable( "readylabel", g_pVGuiLocalize->Find( "" ) );
  329. }
  330. }
  331. if ( m_bReadyStatusMode && nTime >= 0 )
  332. {
  333. bCountdownVisible = true;
  334. }
  335. }
  336. // Show the Steam Controller hint icon if need be
  337. auto pReadyHintIcon = dynamic_cast< CExLabel* >( FindChildByName( "TournamentReadyHintIcon" ) );
  338. if ( pReadyHintIcon )
  339. {
  340. if ( bShowReadyHintIcon && !bAutoReady )
  341. {
  342. pReadyHintIcon->SetText( GetSCGlyph( "toggleready" ) );
  343. pReadyHintIcon->SetVisible( true );
  344. pReadyHintIcon->SetEnabled( true );
  345. }
  346. else
  347. {
  348. pReadyHintIcon->SetVisible( false );
  349. pReadyHintIcon->SetEnabled( false );
  350. }
  351. }
  352. if ( m_bCountDownVisible != bCountdownVisible )
  353. {
  354. m_bCountDownVisible = bCountdownVisible;
  355. if ( m_bCountDownVisible )
  356. {
  357. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence(this, m_bCompetitiveMode ? "HudTournament_ShowTimerCompetitive" : "HudTournament_ShowTimerDefault", false);
  358. }
  359. else
  360. {
  361. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence(this, "HudTournament_HideTimer", false);
  362. }
  363. }
  364. }
  365. #ifdef WIN32
  366. #define STRING_FMT L"%s"
  367. #else
  368. #define STRING_FMT L"%S"
  369. #endif
  370. C_TFTeam *pBlueTeam = GetGlobalTFTeam( TF_TEAM_BLUE );
  371. SetDialogVariable( "bluenamelabel", pBlueTeam ? pBlueTeam->Get_Localized_Name() : L"BLU" );
  372. C_TFTeam *pRedTeam = GetGlobalTFTeam( TF_TEAM_RED );
  373. SetDialogVariable( "rednamelabel", pRedTeam ? pRedTeam->Get_Localized_Name() : L"RED" );
  374. SetDialogVariable( "bluestate", TFGameRules()->IsTeamReady( TF_TEAM_BLUE ) ? g_pVGuiLocalize->Find( "Tournament_TeamReady" ) : g_pVGuiLocalize->Find( "Tournament_TeamNotReady" ) );
  375. SetDialogVariable( "redstate", TFGameRules()->IsTeamReady( TF_TEAM_RED ) ? g_pVGuiLocalize->Find( "Tournament_TeamReady" ) : g_pVGuiLocalize->Find( "Tournament_TeamNotReady" ) );
  376. if ( m_bTeamReady[TF_TEAM_BLUE] != TFGameRules()->IsTeamReady( TF_TEAM_BLUE ) || m_bTeamReady[TF_TEAM_RED] != TFGameRules()->IsTeamReady( TF_TEAM_RED ) )
  377. {
  378. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  379. if ( pLocalPlayer )
  380. {
  381. pLocalPlayer->EmitSound( "Hud.Hint" );
  382. }
  383. }
  384. m_bTeamReady[TF_TEAM_BLUE] = TFGameRules()->IsTeamReady( TF_TEAM_BLUE );
  385. m_bTeamReady[TF_TEAM_RED] = TFGameRules()->IsTeamReady( TF_TEAM_RED );
  386. wchar_t szWindConditions[1024];
  387. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT, g_pVGuiLocalize->Find( "Tournament_WinConditions" ) );
  388. if ( mp_timelimit.GetInt() > 0 || mp_winlimit.GetInt() > 0 || mp_maxrounds.GetInt() )
  389. {
  390. bool bPrev = false;
  391. if ( mp_timelimit.GetInt() > 0 )
  392. {
  393. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT L"%d " STRING_FMT, szWindConditions, mp_timelimit.GetInt(), mp_timelimit.GetInt() == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsMinute" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsMinutes" ) );
  394. bPrev = true;
  395. }
  396. if ( mp_winlimit.GetInt() > 0 )
  397. {
  398. if ( bPrev )
  399. {
  400. #ifdef WIN32
  401. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), L"%s, ", szWindConditions );
  402. #else
  403. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), L"%S, ", szWindConditions );
  404. #endif
  405. }
  406. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT L"%d " STRING_FMT, szWindConditions, mp_winlimit.GetInt(), mp_winlimit.GetInt() == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsWin" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsWins" ) );
  407. bPrev = true;
  408. }
  409. if ( mp_maxrounds.GetInt() > 0 )
  410. {
  411. if ( bPrev )
  412. {
  413. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT L", ", szWindConditions );
  414. }
  415. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT L"%d " STRING_FMT, szWindConditions, mp_maxrounds.GetInt(), mp_maxrounds.GetInt() == 1 ? g_pVGuiLocalize->Find( "Tournament_WinConditionsRound" ) : g_pVGuiLocalize->Find( "Tournament_WinConditionsRounds" ) );
  416. }
  417. }
  418. else
  419. {
  420. _snwprintf( szWindConditions, ARRAYSIZE( szWindConditions ), STRING_FMT STRING_FMT, szWindConditions, g_pVGuiLocalize->Find( "Tournament_WinConditionsNone" ) );
  421. }
  422. SetDialogVariable( "winconditions", szWindConditions );
  423. }
  424. //-----------------------------------------------------------------------------
  425. // Purpose:
  426. //-----------------------------------------------------------------------------
  427. void CHudTournament::FireGameEvent( IGameEvent * event )
  428. {
  429. const char *pEventName = event->GetName();
  430. CBaseHudChat *pHUDChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
  431. if ( Q_strcmp( "tournament_stateupdate", pEventName ) == 0 )
  432. {
  433. if ( !g_TF_PR )
  434. return;
  435. if ( !pHUDChat )
  436. return;
  437. wchar_t wszLocalized[100];
  438. bool bNameChange = event->GetBool( "namechange" );
  439. int iTeamState = event->GetInt( "readystate", -1 );
  440. int iIndex = event->GetInt("userid");
  441. const char *pszName = g_TF_PR->GetPlayerName( iIndex );
  442. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  443. g_pVGuiLocalize->ConvertANSIToUnicode( pszName, wszPlayerName, sizeof(wszPlayerName) );
  444. if ( bNameChange )
  445. {
  446. wchar_t wszTeam[16];
  447. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString( "newname" ), wszTeam, sizeof(wszTeam) );
  448. g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Tournament_TeamName_Change" ), 2, wszPlayerName, wszTeam );
  449. }
  450. else
  451. {
  452. g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#Tournament_ReadyState_Change" ), 2, wszPlayerName, iTeamState == 1 ? g_pVGuiLocalize->Find( "#Tournament_TeamReady" ) : g_pVGuiLocalize->Find( "#Tournament_TeamNotReady" ) );
  453. }
  454. char szLocalized[100];
  455. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  456. pHUDChat->ChatPrintf( iIndex, CHAT_FILTER_NONE, "%s ", szLocalized );
  457. }
  458. else if ( Q_strcmp( "localplayer_respawn", pEventName ) == 0 )
  459. {
  460. if ( m_bReadyStatusMode )
  461. {
  462. if ( m_bReadyTextBlinking )
  463. {
  464. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudReadyPulse" );
  465. }
  466. }
  467. }
  468. else if ( FStrEq( "restart_timer_time", pEventName ) )
  469. {
  470. PlaySounds( event->GetInt( "time" ) );
  471. if ( TFGameRules()->GetRoundsPlayed() == 0 && m_bCompetitiveMode )
  472. {
  473. if ( event->GetInt( "time" ) == 10 )
  474. {
  475. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudTournament_MoveTimerDown", false );
  476. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudTournament_MoveChatWindow", false );
  477. }
  478. }
  479. }
  480. else if ( FStrEq( "competitive_victory", pEventName ) )
  481. {
  482. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudTournament_DoorsCloseEndRound", false );
  483. }
  484. }
  485. //-----------------------------------------------------------------------------
  486. // Purpose:
  487. // Input : -
  488. //-----------------------------------------------------------------------------
  489. void CHudTournament::OnTick( void )
  490. {
  491. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  492. if ( !pLocalPlayer )
  493. return;
  494. if ( TFGameRules() )
  495. {
  496. if ( TFGameRules()->IsInTournamentMode() )
  497. {
  498. if ( TFGameRules()->IsInWaitingForPlayers() && TFGameRules()->State_Get() != GR_STATE_GAME_OVER )
  499. {
  500. m_bShouldBeVisible = true;
  501. PreparePanel();
  502. if ( !TFGameRules()->IsInArenaMode() )
  503. {
  504. if ( !pLocalPlayer->IsAlive() )
  505. {
  506. m_bShouldBeVisible = false;
  507. }
  508. }
  509. }
  510. else
  511. {
  512. m_bShouldBeVisible = false;
  513. }
  514. if ( TFGameRules()->UsePlayerReadyStatusMode() )
  515. {
  516. if ( !m_bReadyStatusMode )
  517. {
  518. m_bReadyStatusMode = true;
  519. InvalidateLayout( false, true );
  520. }
  521. }
  522. else if ( m_bReadyStatusMode )
  523. {
  524. m_bReadyStatusMode = false;
  525. InvalidateLayout( false, true );
  526. }
  527. if ( TFGameRules()->IsCompetitiveMode() )
  528. {
  529. if ( !m_bCompetitiveMode )
  530. {
  531. m_bCompetitiveMode = true;
  532. InvalidateLayout( false, true );
  533. }
  534. }
  535. else if ( m_bCompetitiveMode )
  536. {
  537. m_bCompetitiveMode = false;
  538. InvalidateLayout( false, true );
  539. }
  540. }
  541. else
  542. {
  543. m_bShouldBeVisible = false;
  544. }
  545. if ( m_bReadyStatusMode )
  546. {
  547. const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  548. if ( !pMatchDesc || !pMatchDesc->m_params.m_bAutoReady )
  549. {
  550. RecalculatePlayerPanels();
  551. // Ready text animation
  552. if ( !TFGameRules()->IsPlayerReady( GetLocalPlayerIndex() ) && !m_bReadyTextBlinking )
  553. {
  554. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudReadyPulse" );
  555. m_bReadyTextBlinking = true;
  556. }
  557. else if ( TFGameRules()->IsPlayerReady( GetLocalPlayerIndex() ) && m_bReadyTextBlinking )
  558. {
  559. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudReadyPulseEnd" );
  560. m_bReadyTextBlinking = false;
  561. }
  562. }
  563. if ( !m_pScoreboard.Get() && gViewPortInterface )
  564. {
  565. m_pScoreboard = (CTFClientScoreBoardDialog *)( gViewPortInterface->FindPanelByName( PANEL_SCOREBOARD ) );
  566. }
  567. if ( m_pScoreboard.Get() && m_pScoreboard->IsVisible() )
  568. {
  569. m_bShouldBeVisible = false;
  570. }
  571. }
  572. }
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Purpose:
  576. //-----------------------------------------------------------------------------
  577. void CHudTournament::LevelInit( void )
  578. {
  579. m_bShouldBeVisible = false;
  580. SetVisible( false );
  581. Init();
  582. }
  583. //-----------------------------------------------------------------------------
  584. // Purpose:
  585. //-----------------------------------------------------------------------------
  586. void CHudTournament::SetVisible( bool state )
  587. {
  588. // we can only turn on tournament mode if we're in prematch
  589. if ( state )
  590. {
  591. if ( m_bReadyStatusMode )
  592. {
  593. if ( m_bReadyTextBlinking )
  594. {
  595. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudReadyPulse" );
  596. }
  597. }
  598. if ( TeamplayRoundBasedRules() && !TeamplayRoundBasedRules()->IsInPreMatch() )
  599. return;
  600. }
  601. BaseClass::SetVisible( state );
  602. }
  603. //-----------------------------------------------------------------------------
  604. // Purpose:
  605. //-----------------------------------------------------------------------------
  606. void CHudTournament::ApplySchemeSettings( IScheme *pScheme )
  607. {
  608. BaseClass::ApplySchemeSettings( pScheme );
  609. m_bReapplyPlayerPanelKVs = true;
  610. KeyValues *pConditions = NULL;
  611. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  612. {
  613. pConditions = new KeyValues( "conditions" );
  614. AddSubKeyNamed( pConditions, "if_mvm" );
  615. }
  616. else if ( m_bCompetitiveMode )
  617. {
  618. pConditions = new KeyValues( "conditions" );
  619. AddSubKeyNamed( pConditions, "if_competitive" );
  620. }
  621. else if ( m_bReadyStatusMode )
  622. {
  623. pConditions = new KeyValues( "conditions" );
  624. AddSubKeyNamed( pConditions, "if_readymode" );
  625. }
  626. // load control settings...
  627. LoadControlSettings( "resource/UI/HudTournament.res", NULL, NULL, pConditions );
  628. if ( pConditions )
  629. {
  630. pConditions->deleteThis();
  631. }
  632. }
  633. //-----------------------------------------------------------------------------
  634. // Purpose:
  635. //-----------------------------------------------------------------------------
  636. void CHudTournament::ApplySettings( KeyValues *inResourceData )
  637. {
  638. BaseClass::ApplySettings( inResourceData );
  639. KeyValues *pItemKV = inResourceData->FindKey( "playerpanels_kv" );
  640. if ( pItemKV )
  641. {
  642. if ( m_pPlayerPanelKVs )
  643. {
  644. m_pPlayerPanelKVs->deleteThis();
  645. }
  646. m_pPlayerPanelKVs = new KeyValues("playerpanels_kv");
  647. pItemKV->CopySubkeys( m_pPlayerPanelKVs );
  648. }
  649. }
  650. //-----------------------------------------------------------------------------
  651. // Purpose:
  652. //-----------------------------------------------------------------------------
  653. void CHudTournament::PerformLayout( void )
  654. {
  655. BaseClass::PerformLayout();
  656. if ( m_bReapplyPlayerPanelKVs )
  657. {
  658. m_bReapplyPlayerPanelKVs = false;
  659. if ( m_pPlayerPanelKVs )
  660. {
  661. for ( int i = 0; i < m_PlayerPanels.Count(); i++ )
  662. {
  663. m_PlayerPanels[i]->ApplySettings( m_pPlayerPanelKVs );
  664. m_PlayerPanels[i]->InvalidateLayout( false, true );
  665. }
  666. }
  667. }
  668. bool bShowTournamentConditions = !m_bCompetitiveMode && TFGameRules() && !TFGameRules()->IsMannVsMachineMode();
  669. // Hide some elements when in competitive mode
  670. if ( m_pTournamentConditionLabel )
  671. {
  672. m_pTournamentConditionLabel->SetVisible( bShowTournamentConditions );
  673. }
  674. Panel* pTournamentBG = FindChildByName( "HudTournamentBG" );
  675. if ( pTournamentBG )
  676. {
  677. pTournamentBG->SetVisible( bShowTournamentConditions );
  678. }
  679. UpdatePlayerPanels();
  680. }
  681. //-----------------------------------------------------------------------------
  682. // Purpose:
  683. //-----------------------------------------------------------------------------
  684. void CHudTournament::SetPlayerPanelsVisible( bool bVisible )
  685. {
  686. for ( int i = 0; i < m_PlayerPanels.Count(); i++ )
  687. {
  688. if ( m_PlayerPanels[i] )
  689. {
  690. if ( m_PlayerPanels[i]->IsVisible() != bVisible )
  691. {
  692. m_PlayerPanels[i]->SetVisible( bVisible );
  693. }
  694. }
  695. }
  696. }
  697. //-----------------------------------------------------------------------------
  698. // Purpose: Create a new panel if necessary
  699. //-----------------------------------------------------------------------------
  700. CTFPlayerPanel *CHudTournament::GetOrAddPanel( int iPanelIndex )
  701. {
  702. if ( iPanelIndex < m_PlayerPanels.Count() )
  703. {
  704. return m_PlayerPanels[ iPanelIndex ];
  705. }
  706. Assert( iPanelIndex == m_PlayerPanels.Count() );
  707. CTFPlayerPanel *pPanel = new CTFPlayerPanel( this, VarArgs("playerpanel%d", iPanelIndex) );
  708. if ( m_pPlayerPanelKVs )
  709. {
  710. pPanel->ApplySettings( m_pPlayerPanelKVs );
  711. pPanel->InvalidateLayout( false, true );
  712. }
  713. m_PlayerPanels.AddToTail( pPanel );
  714. return pPanel;
  715. }
  716. //-----------------------------------------------------------------------------
  717. // Purpose: Decide which players we will show
  718. //-----------------------------------------------------------------------------
  719. void CHudTournament::RecalculatePlayerPanels( void )
  720. {
  721. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  722. if ( !pPlayer || !g_TF_PR )
  723. return;
  724. int iLocalTeam = g_TF_PR->GetTeam( pPlayer->entindex() );
  725. int iPanel = 0;
  726. for ( int i = 1; i <= MAX_PLAYERS; i++ )
  727. {
  728. if ( !g_TF_PR->IsConnected( i ) )
  729. continue;
  730. int iTeam = g_TF_PR->GetTeam( i );
  731. if ( iTeam == TEAM_UNASSIGNED && !m_bReadyStatusMode )
  732. continue;
  733. // Spectators see all players, team members only see their team.
  734. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && iTeam != iLocalTeam && iLocalTeam != TEAM_SPECTATOR )
  735. continue;
  736. if ( iTeam != TF_TEAM_RED && iTeam != TF_TEAM_BLUE )
  737. continue;
  738. // Add an entry for him
  739. CTFPlayerPanel *pPanel = GetOrAddPanel( iPanel );
  740. pPanel->SetPlayerIndex( i );
  741. ++iPanel;
  742. }
  743. // Check if we have a lobby, then add in players that have a reservation in the lobby,
  744. // but aren't in the game yet
  745. // XXX(JohnS): Once eric's change to mirror the match info to playerresource is in, we should just trust that and
  746. // not look at the lobby on our end. Eventually client lobbies shouldn't even have other members in
  747. // them.
  748. CTFGSLobby *pLobby = GTFGCClientSystem()->GetLobby();
  749. if ( pLobby )
  750. {
  751. for ( int i = 0; i < pLobby->GetNumMembers(); ++i )
  752. {
  753. CSteamID steamID = pLobby->GetMember( i );
  754. // Already have a panel for him?
  755. bool bFound = false;
  756. for ( int j = 0; j < iPanel; ++j )
  757. {
  758. if ( m_PlayerPanels[j]->GetSteamID() == steamID )
  759. {
  760. bFound = true;
  761. break;
  762. }
  763. }
  764. if ( !bFound )
  765. {
  766. CTFPlayerPanel *pPanel = GetOrAddPanel( iPanel );
  767. pPanel->Setup( 0, steamID, pLobby->GetMemberDetails( i )->name().c_str(), pLobby->GetMemberDetails( steamID )->team() );
  768. ++iPanel;
  769. }
  770. }
  771. }
  772. // Clear out any extra panels
  773. for ( int i = iPanel; i < m_PlayerPanels.Count(); i++ )
  774. {
  775. m_PlayerPanels[i]->SetPlayerIndex( 0 );
  776. }
  777. UpdatePlayerPanels();
  778. }
  779. //-----------------------------------------------------------------------------
  780. // Purpose:
  781. //-----------------------------------------------------------------------------
  782. void CHudTournament::UpdatePlayerPanels( void )
  783. {
  784. if ( !g_TF_PR )
  785. return;
  786. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  787. if ( !pPlayer )
  788. return;
  789. if ( !TFGameRules() )
  790. return;
  791. // Hide panels for players when they're no longer able to stop the countdown
  792. if ( TFGameRules()->GetRoundRestartTime() >= 0.f && TFGameRules()->GetRoundRestartTime() - gpGlobals->curtime <= TOURNAMENT_NOCANCEL_TIME )
  793. {
  794. SetPlayerPanelsVisible( false );
  795. m_pModeImage->SetVisible( false );
  796. return;
  797. }
  798. bool bNeedsPlayerLayout = false;
  799. for ( int i = 0; i < m_PlayerPanels.Count(); i++ )
  800. {
  801. if ( m_PlayerPanels[i]->Update() )
  802. {
  803. bNeedsPlayerLayout = true;
  804. }
  805. }
  806. if ( !bNeedsPlayerLayout || !TFGameRules() )
  807. return;
  808. // Try and always put the local player's team on team1, if he's in a team
  809. int iTeam1 = TF_TEAM_BLUE;
  810. int iTeam2 = TF_TEAM_RED;
  811. int iLocalTeam = g_TF_PR->GetTeam( pPlayer->entindex() );
  812. if ( ( iLocalTeam == TF_TEAM_RED || iLocalTeam == TF_TEAM_BLUE ) && !TFGameRules()->IsCompetitiveMode() ) // Blue always on left in comp
  813. {
  814. iTeam1 = iLocalTeam;
  815. iTeam2 = ( iTeam1 == TF_TEAM_BLUE ) ? TF_TEAM_RED : TF_TEAM_BLUE;
  816. }
  817. int iTeam1Count = g_TF_PR->GetNumPlayersForTeam( iTeam1, false );
  818. if ( GTFGCClientSystem()->GetLobby() )
  819. {
  820. // Everyone's on the same team in MvM, and any other lobby-based game is assumed to be two teams.
  821. iTeam1Count = TFGameRules()->IsMannVsMachineMode() ?
  822. GTFGCClientSystem()->GetLobby()->GetNumMembers() :
  823. GTFGCClientSystem()->GetLobby()->GetNumMembers()>>1;
  824. }
  825. int iTeam1Processed = 0;
  826. int iTeam2Processed = 0;
  827. int iCenter = GetWide() * 0.5;
  828. for ( int i = 0; i < m_PlayerPanels.Count(); i++ )
  829. {
  830. int iTeam = m_PlayerPanels[i]->GetTeam();
  831. if ( !m_PlayerPanels[i]->GetPlayerIndex() && iTeam == TEAM_INVALID )
  832. continue;
  833. int iXPos = ( m_bCompetitiveMode ) ? -XRES( 30 ) : 0; // Hack to make space for the season image
  834. int iYPos = ( m_iTeam1PlayerBaseY + m_iTeam1PlayerDeltaY );
  835. int nOffset = ( m_bCompetitiveMode ) ? m_iTeamsPlayerDeltaXComp : m_iTeam2PlayerDeltaX;
  836. if ( iTeam == iTeam1 )
  837. {
  838. // Two teams. First team left of center.
  839. if ( m_bReadyStatusMode && !TFGameRules()->IsMannVsMachineMode() )
  840. {
  841. int iTeam1LeftCorner = iCenter - ( iTeam1Count * nOffset );
  842. iXPos += ( iTeam1LeftCorner + ( iTeam1Processed * nOffset ) );
  843. }
  844. // One team. Centered.
  845. else
  846. {
  847. int iTeam1LeftCorner = ( iCenter - ( iTeam1Count * nOffset ) * 0.5 );
  848. iXPos += ( iTeam1LeftCorner + ( iTeam1Processed * nOffset ) );
  849. }
  850. m_PlayerPanels[i]->SetSpecIndex( 6 - iTeam1Processed );
  851. ++iTeam1Processed;
  852. }
  853. else if ( iTeam == iTeam2 )
  854. {
  855. // Two teams. Second team right of center.
  856. iXPos = ( iCenter + ( iTeam2Processed * nOffset ) );
  857. iXPos += ( m_bCompetitiveMode ) ? XRES( 30 ) : 0; // Hack to make space for the season image
  858. m_PlayerPanels[i]->SetSpecIndex( 7 + iTeam2Processed );
  859. ++iTeam2Processed;
  860. }
  861. m_PlayerPanels[i]->SetPos( iXPos, iYPos );
  862. }
  863. }
  864. DECLARE_HUDELEMENT( CHudTournamentSetup );
  865. bool TournamentHudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  866. {
  867. CHudTournamentSetup *pTournamentPanel = ( CHudTournamentSetup * )GET_HUDELEMENT( CHudTournamentSetup );
  868. if ( pTournamentPanel && down == 1 )
  869. {
  870. return pTournamentPanel->ToggleState( keynum );
  871. }
  872. return false;
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Purpose:
  876. //-----------------------------------------------------------------------------
  877. CHudTournamentSetup::CHudTournamentSetup( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudTournamentSetup" )
  878. {
  879. Panel *pParent = g_pClientMode->GetViewport();
  880. SetParent( pParent );
  881. SetHiddenBits( HIDEHUD_MISCSTATUS );
  882. vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
  883. m_pNameEntry = new TextEntry(this, "TournamentNameEdit" );
  884. m_pEntryBG = new CTFImagePanel(this, "HudTournamentNameBG" );
  885. m_pReadyButton = new CExButton(this, "TournamentReadyButton", "" );
  886. m_pNotReadyButton = new CExButton(this, "TournamentNotReadyButton", "" );
  887. m_pTeamNameLabel = NULL;
  888. m_flNextThink = gpGlobals->curtime;
  889. }
  890. //-----------------------------------------------------------------------------
  891. // Purpose:
  892. //-----------------------------------------------------------------------------
  893. void CHudTournamentSetup::Init( void )
  894. {
  895. SetVisible( false );
  896. CHudElement::Init();
  897. DisableInput();
  898. m_pNameEntry->SetText( g_pVGuiLocalize->Find( "Tournament_TeamNameNotSet" ) );
  899. m_flNextThink = gpGlobals->curtime;
  900. }
  901. //-----------------------------------------------------------------------------
  902. // Purpose:
  903. //-----------------------------------------------------------------------------
  904. void CHudTournamentSetup::OnCommand( const char *command )
  905. {
  906. if ( !Q_strcmp( command, "teamready" ) )
  907. {
  908. char szText[64];
  909. m_pNameEntry->GetText( szText, sizeof( szText ) );
  910. char szTeamName[64];
  911. Q_snprintf ( szTeamName, sizeof( szTeamName ), "tournament_teamname %s", szText );
  912. engine->ClientCmd_Unrestricted( szTeamName );
  913. engine->ClientCmd_Unrestricted( "tournament_readystate 1" );
  914. DisableInput();
  915. }
  916. else if ( !Q_strcmp( command, "teamnotready" ) )
  917. {
  918. engine->ClientCmd_Unrestricted( "tournament_readystate 0" );
  919. DisableInput();
  920. }
  921. }
  922. //-----------------------------------------------------------------------------
  923. // Purpose:
  924. //-----------------------------------------------------------------------------
  925. bool CHudTournamentSetup::ToggleState( ButtonCode_t code )
  926. {
  927. if ( !IsVisible() )
  928. return false;
  929. if ( !g_TF_PR )
  930. return false;
  931. if ( code == KEY_F4 || code == STEAMCONTROLLER_F4 )
  932. {
  933. if ( TFGameRules() && TFGameRules()->UsePlayerReadyStatusMode() )
  934. {
  935. int nReady = ( TFGameRules()->IsPlayerReady( GetLocalPlayerIndex() ) ) ? 0 : 1;
  936. char szCommand[64];
  937. Q_snprintf( szCommand, sizeof( szCommand ), "tournament_player_readystate %d", nReady );
  938. engine->ClientCmd_Unrestricted( szCommand );
  939. }
  940. else
  941. {
  942. if ( IsMouseInputEnabled() )
  943. {
  944. DisableInput();
  945. return true;
  946. }
  947. else
  948. {
  949. EnableInput();
  950. return true;
  951. }
  952. }
  953. }
  954. if ( IsMouseInputEnabled() )
  955. {
  956. if ( code == KEY_ESCAPE || code == KEY_ENTER )
  957. {
  958. if ( code == KEY_ENTER )
  959. {
  960. char szText[64];
  961. m_pNameEntry->GetText( szText, sizeof( szText ) );
  962. char szTeamName[64];
  963. Q_snprintf ( szTeamName, sizeof( szTeamName ), "tournament_teamname %s", szText );
  964. engine->ClientCmd_Unrestricted( szTeamName );
  965. m_flNextThink = gpGlobals->curtime + TOURNAMENT_PANEL_UPDATE_INTERVAL;
  966. }
  967. DisableInput();
  968. return true;
  969. }
  970. }
  971. return false;
  972. }
  973. //-----------------------------------------------------------------------------
  974. // Purpose:
  975. //-----------------------------------------------------------------------------
  976. void CHudTournamentSetup::FireGameEvent( IGameEvent * event )
  977. {
  978. const char *pEventName = event->GetName();
  979. if ( Q_strcmp( "tournament_stateupdate", pEventName ) == 0 )
  980. {
  981. if ( TFGameRules()->IsInTournamentMode() && TFGameRules()->IsInWaitingForPlayers() )
  982. {
  983. m_flNextThink = gpGlobals->curtime;
  984. }
  985. }
  986. }
  987. //-----------------------------------------------------------------------------
  988. // Purpose:
  989. // Input : -
  990. //-----------------------------------------------------------------------------
  991. void CHudTournamentSetup::OnTick( void )
  992. {
  993. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  994. if ( !pLocalPlayer )
  995. return;
  996. if ( !g_TF_PR )
  997. return;
  998. int iLocalTeam = g_TF_PR->GetTeam( pLocalPlayer->entindex() );
  999. if ( iLocalTeam <= LAST_SHARED_TEAM || TFGameRules()->State_Get() == GR_STATE_GAME_OVER )
  1000. {
  1001. SetVisible( false );
  1002. return;
  1003. }
  1004. if ( TFGameRules() )
  1005. {
  1006. if ( TFGameRules()->UsePlayerReadyStatusMode() )
  1007. {
  1008. if ( TFGameRules()->IsInTournamentMode() && TFGameRules()->IsInWaitingForPlayers() )
  1009. {
  1010. if ( !IsVisible() )
  1011. {
  1012. SetVisible( true );
  1013. }
  1014. SetPos( 0, YRES( -100 ) ); // make sure the panel is WAY off the screen for MvM mode
  1015. }
  1016. else
  1017. {
  1018. if ( IsVisible() )
  1019. {
  1020. SetVisible( false );
  1021. }
  1022. }
  1023. }
  1024. else if ( TFGameRules()->IsInTournamentMode() && TFGameRules()->IsInWaitingForPlayers() )
  1025. {
  1026. if ( !IsVisible() )
  1027. {
  1028. SetVisible( true );
  1029. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudTournamentSetupPanelClose" );
  1030. }
  1031. }
  1032. else
  1033. {
  1034. if ( IsVisible() )
  1035. {
  1036. SetVisible( false );
  1037. }
  1038. }
  1039. }
  1040. if ( m_flNextThink <= gpGlobals->curtime )
  1041. {
  1042. if ( !IsMouseInputEnabled() )
  1043. {
  1044. m_pNameEntry->SetText( ( iLocalTeam == TF_TEAM_BLUE ) ? mp_tournament_blueteamname.GetString() : mp_tournament_redteamname.GetString() );
  1045. }
  1046. SetDialogVariable( "tournamentstatelabel", TFGameRules()->IsTeamReady( iLocalTeam ) ? g_pVGuiLocalize->Find( "Tournament_TeamSetupReady" ) : g_pVGuiLocalize->Find( "Tournament_TeamSetupNotReady" ) );
  1047. m_flNextThink = gpGlobals->curtime + TOURNAMENT_PANEL_UPDATE_INTERVAL;
  1048. }
  1049. }
  1050. //-----------------------------------------------------------------------------
  1051. // Purpose:
  1052. //-----------------------------------------------------------------------------
  1053. void CHudTournamentSetup::EnableInput( void )
  1054. {
  1055. SetVisible( true );
  1056. vgui::SETUP_PANEL( this );
  1057. SetKeyBoardInputEnabled( true );
  1058. SetMouseInputEnabled( true );
  1059. m_pNameEntry->SetVisible( true );
  1060. vgui::surface()->CalculateMouseVisible();
  1061. m_pNameEntry->RequestFocus();
  1062. m_pNameEntry->SetPaintBorderEnabled( true );
  1063. m_pNameEntry->SetMouseInputEnabled( true );
  1064. m_pNameEntry->SetKeyBoardInputEnabled( true );
  1065. MakePopup();
  1066. m_pEntryBG->SetVisible( true );
  1067. m_pReadyButton->SetVisible( true );
  1068. m_pReadyButton->SetMouseInputEnabled( true );
  1069. m_pNotReadyButton->SetVisible( true );
  1070. m_pNotReadyButton->SetMouseInputEnabled( true );
  1071. m_pTeamNameLabel->SetVisible( true );
  1072. engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" );
  1073. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudTournamentSetupPanelOpen" );
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. // Purpose:
  1077. //-----------------------------------------------------------------------------
  1078. void CHudTournamentSetup::DisableInput( void )
  1079. {
  1080. SetKeyBoardInputEnabled( false );
  1081. SetMouseInputEnabled( false );
  1082. m_pNameEntry->SetMouseInputEnabled( false );
  1083. m_pNameEntry->SetKeyBoardInputEnabled( false );
  1084. engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
  1085. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudTournamentSetupPanelClose" );
  1086. }
  1087. //-----------------------------------------------------------------------------
  1088. // Purpose:
  1089. //-----------------------------------------------------------------------------
  1090. void CHudTournamentSetup::LevelInit( void )
  1091. {
  1092. SetVisible( false );
  1093. Init();
  1094. }
  1095. //-----------------------------------------------------------------------------
  1096. // Purpose:
  1097. //-----------------------------------------------------------------------------
  1098. bool CHudTournamentSetup::ShouldDraw( void )
  1099. {
  1100. return ( IsVisible() );
  1101. }
  1102. //-----------------------------------------------------------------------------
  1103. // Purpose:
  1104. //-----------------------------------------------------------------------------
  1105. void CHudTournamentSetup::ApplySchemeSettings( IScheme *pScheme )
  1106. {
  1107. // load control settings...
  1108. LoadControlSettings( "resource/UI/HudTournamentSetup.res" );
  1109. BaseClass::ApplySchemeSettings( pScheme );
  1110. m_pNameEntry->SetFont( pScheme->GetFont( "HudFontSmallest", IsProportional() ) );
  1111. m_pTeamNameLabel = dynamic_cast<Label *>( FindChildByName( "TournamentTeamNameLabel" ) );
  1112. }
  1113. DECLARE_HUDELEMENT( CHudStopWatch );
  1114. //-----------------------------------------------------------------------------
  1115. // Purpose:
  1116. //-----------------------------------------------------------------------------
  1117. CHudStopWatch::CHudStopWatch( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudStopWatch" )
  1118. {
  1119. Panel *pParent = g_pClientMode->GetViewport();
  1120. SetParent( pParent );
  1121. SetHiddenBits( HIDEHUD_MISCSTATUS );
  1122. m_bShouldBeVisible = false;
  1123. vgui::ivgui()->AddTickSignal( GetVPanel(), 100 );
  1124. m_pTimePanel = new CTFHudTimeStatus( this, "ObjectiveStatusTimePanel" );
  1125. m_pStopWatchLabel = new CExLabel( this, "StopWatchLabel", "" );
  1126. m_pStopWatchScore = new CExLabel( this, "StopWatchScoreToBeat", "" );
  1127. m_pStopWatchPointsLabel = new CExLabel( this, "StopWatchPointsLabel", "" );
  1128. m_pStopWatchImage = new ImagePanel( this, "StopWatchImageCaptureTime" );
  1129. m_pStopWatchDescriptionLabel = new CExLabel( this, "StopWatchDescriptionLabel", "" );
  1130. ListenForGameEvent( "competitive_state_changed" );
  1131. }
  1132. //-----------------------------------------------------------------------------
  1133. // Purpose:
  1134. //-----------------------------------------------------------------------------
  1135. bool CHudStopWatch::ShouldDraw( void )
  1136. {
  1137. bool bRetVal = m_bShouldBeVisible;
  1138. if ( bRetVal )
  1139. {
  1140. // give the HUD a chance to turn us off when we should be hidden
  1141. bRetVal = CHudElement::ShouldDraw();
  1142. }
  1143. return bRetVal;
  1144. }
  1145. //-----------------------------------------------------------------------------
  1146. // Purpose:
  1147. //-----------------------------------------------------------------------------
  1148. void CHudStopWatch::LevelInit( void )
  1149. {
  1150. m_bShouldBeVisible = true;
  1151. if ( m_pTimePanel )
  1152. {
  1153. m_pTimePanel->SetVisible( true );
  1154. m_pTimePanel->Reset();
  1155. }
  1156. m_pStopWatchLabel->SetVisible( false );
  1157. }
  1158. //-----------------------------------------------------------------------------
  1159. // Purpose:
  1160. //-----------------------------------------------------------------------------
  1161. void CHudStopWatch::ApplySchemeSettings( IScheme *pScheme )
  1162. {
  1163. KeyValues *pConditions = NULL;
  1164. if ( ShouldUseMatchHUD() )
  1165. {
  1166. pConditions = new KeyValues( "conditions" );
  1167. AddSubKeyNamed( pConditions, "if_comp" );
  1168. }
  1169. // load control settings...
  1170. LoadControlSettings( "resource/UI/HudStopWatch.res", NULL, NULL, pConditions );
  1171. BaseClass::ApplySchemeSettings( pScheme );
  1172. m_pStopWatchDescriptionBG = FindChildByName( "HudStopWatchDescriptionBG" );
  1173. if ( pConditions )
  1174. {
  1175. pConditions->deleteThis();
  1176. }
  1177. }
  1178. //-----------------------------------------------------------------------------
  1179. // Purpose:
  1180. //-----------------------------------------------------------------------------
  1181. void CHudStopWatch::OnTick( void )
  1182. {
  1183. BaseClass::OnTick();
  1184. if ( !TFGameRules() )
  1185. return;
  1186. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  1187. if ( !pPlayer )
  1188. return;
  1189. bool bInFreezeCam = ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM );
  1190. bool bProperMatch = TFGameRules()->IsInTournamentMode() || TFGameRules()->IsCompetitiveMode();
  1191. if ( !bProperMatch || TFGameRules()->IsInPreMatch() || !TFGameRules()->IsInStopWatch() || bInFreezeCam || TFGameRules()->State_Get() == GR_STATE_GAME_OVER )
  1192. {
  1193. m_bShouldBeVisible = false;
  1194. return;
  1195. }
  1196. else
  1197. {
  1198. m_bShouldBeVisible = true;
  1199. }
  1200. if ( m_pTimePanel && ObjectiveResource() )
  1201. {
  1202. int iActiveTimer = ObjectiveResource()->GetStopWatchTimer();
  1203. m_pTimePanel->SetTimerIndex( iActiveTimer );
  1204. C_TFTeam *pAttacker = NULL;
  1205. C_TFTeam *pDefender = NULL;
  1206. for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ )
  1207. {
  1208. C_TFTeam *pTeam = GetGlobalTFTeam( i );
  1209. if ( pTeam )
  1210. {
  1211. if ( pTeam->GetRole() == TEAM_ROLE_DEFENDERS )
  1212. {
  1213. pDefender = pTeam;
  1214. }
  1215. if ( pTeam->GetRole() == TEAM_ROLE_ATTACKERS )
  1216. {
  1217. pAttacker = pTeam;
  1218. }
  1219. }
  1220. }
  1221. if ( !pAttacker || !pDefender )
  1222. return;
  1223. if ( TFGameRules()->GetStopWatchState() == STOPWATCH_CAPTURE_TIME_NOT_SET )
  1224. {
  1225. m_pTimePanel->SetVisible( false );
  1226. m_pStopWatchLabel->SetVisible( true );
  1227. m_pStopWatchScore->SetVisible( false );
  1228. m_pStopWatchPointsLabel->SetVisible( false );
  1229. m_pStopWatchDescriptionBG->SetVisible( false );
  1230. m_pStopWatchDescriptionLabel->SetVisible( false );
  1231. m_pStopWatchImage->SetImage( "../hud/ico_time_none" );
  1232. SetDialogVariable( "stopwatchlabel", g_pVGuiLocalize->Find( "Tournament_StopWatchNoCap" ) );
  1233. }
  1234. else if ( TFGameRules()->GetStopWatchState() == STOPWATCH_RUNNING )
  1235. {
  1236. m_pTimePanel->SetVisible( true );
  1237. m_pStopWatchLabel->SetVisible( false );
  1238. m_pStopWatchScore->SetVisible( true );
  1239. m_pStopWatchPointsLabel->SetVisible( true );
  1240. m_pStopWatchImage->SetImage( "../hud/ico_time_10" );
  1241. CTeamRoundTimer *pTimer = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iActiveTimer ) );
  1242. int iPoints = 0;
  1243. if ( pTimer )
  1244. {
  1245. if ( pTimer->IsWatchingTimeStamps() )
  1246. {
  1247. iPoints = pAttacker->Get_Score();
  1248. }
  1249. else
  1250. {
  1251. iPoints = pDefender->Get_Score() - pAttacker->Get_Score();
  1252. }
  1253. }
  1254. wchar_t wzScoreVal[128];
  1255. static wchar_t wzScore[128];
  1256. wchar_t *pszPoints = NULL;
  1257. _snwprintf( wzScoreVal, ARRAYSIZE( wzScoreVal ), L"%i", iPoints );
  1258. if ( 1 == iPoints )
  1259. {
  1260. pszPoints = g_pVGuiLocalize->Find( "#Tournament_StopWatch_Point" );
  1261. }
  1262. else
  1263. {
  1264. pszPoints = g_pVGuiLocalize->Find( "#Tournament_StopWatch_Points" );
  1265. }
  1266. SetDialogVariable( "pointslabel", pszPoints );
  1267. SetDialogVariable( "scoretobeat", wzScoreVal );
  1268. wchar_t wzHelp[128];
  1269. if ( pPlayer->GetTeam() == pAttacker )
  1270. {
  1271. g_pVGuiLocalize->ConstructString_safe( wzHelp, g_pVGuiLocalize->Find( "Tournament_StopWatch_TimeVictory" ), 1, pDefender->Get_Localized_Name() );
  1272. }
  1273. else
  1274. {
  1275. g_pVGuiLocalize->ConstructString_safe( wzHelp, g_pVGuiLocalize->Find( "Tournament_StopWatch_TimeVictoryDefender" ), 1, pDefender->Get_Localized_Name() );
  1276. }
  1277. SetDialogVariable( "descriptionlabel", wzHelp );
  1278. if ( pTimer && !pTimer->IsWatchingTimeStamps() )
  1279. {
  1280. m_pStopWatchDescriptionBG->SetVisible( true );
  1281. m_pStopWatchDescriptionLabel->SetVisible( true );
  1282. }
  1283. else
  1284. {
  1285. m_pStopWatchDescriptionBG->SetVisible( false );
  1286. m_pStopWatchDescriptionLabel->SetVisible( false );
  1287. }
  1288. }
  1289. else if ( TFGameRules()->GetStopWatchState() == STOPWATCH_OVERTIME )
  1290. {
  1291. m_pTimePanel->SetVisible( false );
  1292. m_pStopWatchLabel->SetVisible( true );
  1293. m_pStopWatchScore->SetVisible( false );
  1294. m_pStopWatchPointsLabel->SetVisible( false );
  1295. m_pStopWatchDescriptionBG->SetVisible( false );
  1296. m_pStopWatchDescriptionLabel->SetVisible( false );
  1297. SetDialogVariable( "descriptionlabel", g_pVGuiLocalize->Find( "#Tournament_StopWatch_CapVictory" ) );
  1298. m_pStopWatchImage->SetImage( "../hud/ico_time_60" );
  1299. wchar_t wzScoreVal[128];
  1300. int iPoints = (pDefender->Get_Score() - pAttacker->Get_Score()) + 1;
  1301. wchar_t wzVal[16];
  1302. swprintf( wzVal, ARRAYSIZE( wzVal ), L"%x", iPoints );
  1303. if ( pPlayer->GetTeam() == pAttacker )
  1304. {
  1305. g_pVGuiLocalize->ConstructString_safe( wzScoreVal, g_pVGuiLocalize->Find( "Tournament_StopWatchPointCaptureAttacker" ), 2, wzVal, iPoints == 1 ? g_pVGuiLocalize->Find( "#Tournament_StopWatch_Point" ) : g_pVGuiLocalize->Find( "#Tournament_StopWatch_Points" ) );
  1306. }
  1307. else if ( pPlayer->GetTeam() == pDefender )
  1308. {
  1309. g_pVGuiLocalize->ConstructString_safe( wzScoreVal, g_pVGuiLocalize->Find( "Tournament_StopWatchPointCaptureDefender" ), 2, wzVal, iPoints == 1 ? g_pVGuiLocalize->Find( "#Tournament_StopWatch_Point" ) : g_pVGuiLocalize->Find( "#Tournament_StopWatch_Points" ) );
  1310. }
  1311. else
  1312. {
  1313. g_pVGuiLocalize->ConstructString_safe( wzScoreVal, g_pVGuiLocalize->Find( "Tournament_StopWatchPointCaptureSpectator" ), 2, wzVal, iPoints == 1 ? g_pVGuiLocalize->Find( "#Tournament_StopWatch_Point" ) : g_pVGuiLocalize->Find( "#Tournament_StopWatch_Points" ) );
  1314. }
  1315. SetDialogVariable( "stopwatchlabel", wzScoreVal );
  1316. }
  1317. }
  1318. }
  1319. void CHudStopWatch::FireGameEvent( IGameEvent * event )
  1320. {
  1321. if ( FStrEq( event->GetName(), "competitive_state_changed" ) )
  1322. {
  1323. InvalidateLayout( false, true );
  1324. return;
  1325. }
  1326. CHudElement::FireGameEvent( event );
  1327. }
  1328. //-----------------------------------------------------------------------------
  1329. // Purpose:
  1330. //-----------------------------------------------------------------------------
  1331. CON_COMMAND( player_ready_toggle, "Toggle player ready state" )
  1332. {
  1333. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  1334. if ( pPlayer )
  1335. {
  1336. CHudTournamentSetup *pTournamentPanel = dynamic_cast< CHudTournamentSetup* >( GET_HUDELEMENT( CHudTournamentSetup ) );
  1337. if ( pTournamentPanel )
  1338. {
  1339. pTournamentPanel->ToggleState( KEY_F4 );
  1340. }
  1341. }
  1342. }