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.

738 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "sessionlobbydialog.h"
  7. #include "engine/imatchmaking.h"
  8. #include "GameUI_Interface.h"
  9. #include "EngineInterface.h"
  10. #include "vgui/ISurface.h"
  11. #include "vgui_controls/ImagePanel.h"
  12. #include "vgui/ILocalize.h"
  13. #include "BasePanel.h"
  14. #include "matchmakingbasepanel.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. CSessionLobbyDialog *g_pLobbyDialog;
  18. //--------------------------------
  19. // CSessionLobbyDialog
  20. //--------------------------------
  21. CSessionLobbyDialog::CSessionLobbyDialog( vgui::Panel *pParent ) : BaseClass( pParent, "SessionLobbyDialog" )
  22. {
  23. m_Menus[0].SetParent( this );
  24. m_Menus[0].SetName( "BluePlayers" );
  25. m_Menus[1].SetParent( this );
  26. m_Menus[1].SetName( "RedPlayers" );
  27. m_iLocalTeam = -1;
  28. m_iActiveMenu = -1;
  29. m_nHostId = 0;
  30. m_bHostLobby = false;
  31. m_bCenterOnScreen = true;
  32. m_pLobbyStateBg = new vgui::Panel( this, "LobbyStateBg" );
  33. m_pLobbyStateLabel = new CPropertyLabel( this, "LobbyStateLabel", "" );
  34. m_pLobbyStateIcon = new CPropertyLabel( this, "LobbyStateIcon", "" );
  35. m_pHostLabel = new CPropertyLabel( this, "HostLabel", "" );
  36. m_pHostOptionsPanel = new vgui::EditablePanel( this, "HostOptions" );
  37. m_pScenarioInfo = new CScenarioInfoPanel( this, "GameScenario" );
  38. m_pTeamInfos[BLUE_TEAM_LOBBY] = new CScenarioInfoPanel( this, "BlueTeamDescription" );
  39. m_pTeamInfos[RED_TEAM_LOBBY] = new CScenarioInfoPanel( this, "RedTeamDescription" );
  40. m_pDialogKeys = NULL;
  41. g_pLobbyDialog = this;
  42. m_bStartingGame = false;
  43. m_nLastPlayersNeeded = 0;
  44. m_nMinInfoHeight[BLUE_TEAM_LOBBY] = 0;
  45. m_nMinInfoHeight[RED_TEAM_LOBBY] = 0;
  46. }
  47. CSessionLobbyDialog::~CSessionLobbyDialog()
  48. {
  49. delete m_pLobbyStateBg;
  50. delete m_pLobbyStateLabel;
  51. delete m_pLobbyStateIcon;
  52. delete m_pHostLabel;
  53. delete m_pHostOptionsPanel;
  54. delete m_pScenarioInfo;
  55. for ( int i = 0; i < TOTAL_LOBBY_TEAMS; ++i )
  56. {
  57. delete m_pTeamInfos[i];
  58. }
  59. }
  60. //---------------------------------------------------------------------
  61. // Purpose: Dialog keys contain session contexts and properties
  62. //---------------------------------------------------------------------
  63. void CSessionLobbyDialog::SetDialogKeys( KeyValues *pKeys )
  64. {
  65. m_pDialogKeys = pKeys;
  66. InvalidateLayout();
  67. }
  68. //---------------------------------------------------------------------
  69. // Purpose: Helper to set label text from keyvalues
  70. //---------------------------------------------------------------------
  71. void CSessionLobbyDialog::SetTextFromKeyvalues( CPropertyLabel *pLabel )
  72. {
  73. KeyValues *pKey = m_pDialogKeys->FindKey( pLabel->m_szPropertyString );
  74. if ( pKey )
  75. {
  76. const char *pString = pKey->GetString( "displaystring", NULL );
  77. if ( pString )
  78. {
  79. pLabel->SetText( pString );
  80. }
  81. }
  82. }
  83. //---------------------------------------------------------------------
  84. // Purpose: Center the dialog on the screen
  85. //---------------------------------------------------------------------
  86. void CSessionLobbyDialog::PerformLayout()
  87. {
  88. BaseClass::PerformLayout();
  89. if ( !m_pDialogKeys )
  90. return;
  91. // Set the label strings according to the keyvalues passed in
  92. SetTextFromKeyvalues( m_pScenarioInfo->m_pTitle );
  93. SetTextFromKeyvalues( m_pScenarioInfo->m_pDescOne );
  94. SetTextFromKeyvalues( m_pScenarioInfo->m_pDescTwo );
  95. SetTextFromKeyvalues( m_pScenarioInfo->m_pDescThree );
  96. SetTextFromKeyvalues( m_pScenarioInfo->m_pValueTwo );
  97. SetTextFromKeyvalues( m_pScenarioInfo->m_pValueThree );
  98. const char *pDiskName = "unknown";
  99. KeyValues *pName = m_pDialogKeys->FindKey( "MapDiskNames" );
  100. if ( pName )
  101. {
  102. KeyValues *pScenario = m_pDialogKeys->FindKey( "CONTEXT_SCENARIO" );
  103. if ( pScenario )
  104. {
  105. pDiskName = pName->GetString( pScenario->GetString( "displaystring" ), "unknown" );
  106. }
  107. }
  108. // find the scenario type
  109. KeyValues *pType = m_pDialogKeys->FindKey( "ScenarioTypes" );
  110. if ( pType )
  111. {
  112. const char *pString = pType->GetString( pDiskName, NULL );
  113. if ( pString )
  114. {
  115. m_pScenarioInfo->m_pSubtitle->SetText( pString );
  116. }
  117. }
  118. // Set the team goals
  119. KeyValues *pGoals = m_pDialogKeys->FindKey( "TeamGoals" );
  120. if ( pGoals )
  121. {
  122. KeyValues *pTeam = pGoals->FindKey( "Blue" );
  123. if ( pTeam )
  124. {
  125. m_pTeamInfos[BLUE_TEAM_LOBBY]->m_pDescOne->SetText( pTeam->GetString( pDiskName, "" ) );
  126. }
  127. pTeam = pGoals->FindKey( "Red" );
  128. if ( pTeam )
  129. {
  130. m_pTeamInfos[RED_TEAM_LOBBY]->m_pDescOne->SetText( pTeam->GetString( pDiskName, "" ) );
  131. }
  132. }
  133. for ( int i = 0; i < TOTAL_LOBBY_TEAMS; ++i )
  134. {
  135. UpdatePlayerCountDisplay( i );
  136. }
  137. if ( m_bCenterOnScreen )
  138. {
  139. MoveToCenterOfScreen();
  140. }
  141. // Don't allow player reviews in system link games
  142. CMatchmakingBasePanel *pBase = dynamic_cast< CMatchmakingBasePanel* >( m_pParent );
  143. if ( pBase )
  144. {
  145. pBase->SetFooterButtonVisible( "#GameUI_PlayerReview", pBase->GetGameType() != GAMETYPE_SYSTEMLINK_MATCH );
  146. // hide the settings changing if we're in a ranked game
  147. if ( m_pHostOptionsPanel )
  148. {
  149. bool bVisible = pBase->GetGameType() != GAMETYPE_RANKED_MATCH;
  150. vgui::Label *pSettingsLabel = (vgui::Label *)m_pHostOptionsPanel->FindChildByName("ChangeSettingsButton",true);
  151. if ( pSettingsLabel )
  152. {
  153. pSettingsLabel->SetVisible( bVisible );
  154. }
  155. pSettingsLabel = (vgui::Label *)m_pHostOptionsPanel->FindChildByName("ChangeSettingsText",true);
  156. if ( pSettingsLabel )
  157. {
  158. pSettingsLabel->SetVisible( bVisible );
  159. }
  160. }
  161. }
  162. }
  163. //---------------------------------------------------------------------
  164. // Purpose: Parse session properties and contexts from the resource file
  165. //---------------------------------------------------------------------
  166. void CSessionLobbyDialog::ApplySettings( KeyValues *pResourceData )
  167. {
  168. BaseClass::ApplySettings( pResourceData );
  169. m_nImageBorderWidth = pResourceData->GetInt( "imageborderwidth", 15 );
  170. m_nTeamspacing = pResourceData->GetInt( "teamspacing", 0 );
  171. m_bHostLobby = pResourceData->GetInt( "hostlobby", 0 ) != 0;
  172. m_bCenterOnScreen = pResourceData->GetInt( "center", 1 ) == 1;
  173. Q_strncpy( m_szCommand, pResourceData->GetString( "commandstring", "NULL" ), sizeof( m_szCommand ) );
  174. }
  175. //---------------------------------------------------------------------
  176. // Purpose: Set up colors and other such stuff
  177. //---------------------------------------------------------------------
  178. void CSessionLobbyDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
  179. {
  180. BaseClass::ApplySchemeSettings( pScheme );
  181. Color cLabelColor = pScheme->GetColor( "MatchmakingDialogTitleColor", Color( 0, 0, 0, 255 ) );
  182. m_pLobbyStateLabel->SetFgColor( cLabelColor );
  183. m_pHostLabel->SetFgColor( cLabelColor );
  184. m_pLobbyStateBg->SetBgColor( pScheme->GetColor( "TanDarker", Color( 0, 0, 0, 255 ) ) );
  185. m_pLobbyStateBg->SetPaintBackgroundType( 2 );
  186. m_pHostOptionsPanel->SetBgColor( pScheme->GetColor( "TanDarker", Color( 0, 0, 0, 255 ) ) );
  187. m_pHostOptionsPanel->SetPaintBackgroundType( 2 );
  188. m_pScenarioInfo->SetBgColor( pScheme->GetColor( "TanDarker", Color( 0, 0, 0, 255 ) ) );
  189. m_pTeamInfos[BLUE_TEAM_LOBBY]->SetBgColor( pScheme->GetColor( "HudBlueTeam", Color( 0, 0, 0, 255 ) ) );
  190. m_pTeamInfos[RED_TEAM_LOBBY]->SetBgColor( pScheme->GetColor( "HudRedTeam", Color( 0, 0, 0, 255 ) ) );
  191. // Cache of these heights so we never go below them when resizing
  192. m_nMinInfoHeight[BLUE_TEAM_LOBBY] = m_pTeamInfos[BLUE_TEAM_LOBBY]->GetTall();
  193. m_nMinInfoHeight[RED_TEAM_LOBBY] = m_pTeamInfos[RED_TEAM_LOBBY]->GetTall();
  194. //Lets set all the labels this panel owns to be the right fgcolor. hooray vgui!
  195. int iChildren = m_pHostOptionsPanel->GetChildCount();
  196. for ( int i=0;i<iChildren;i++ )
  197. {
  198. vgui::Label *pLabel = dynamic_cast< vgui::Label * >( m_pHostOptionsPanel->GetChild(i) );
  199. if ( pLabel )
  200. {
  201. SETUP_PANEL( pLabel );
  202. pLabel->SetFgColor( cLabelColor );
  203. }
  204. }
  205. vgui::Label *pPlayerReviewLabel = (vgui::Label *)FindChildByName("PlayerReviewLabel" );
  206. if ( pPlayerReviewLabel )
  207. {
  208. SETUP_PANEL( pPlayerReviewLabel );
  209. pPlayerReviewLabel->SetFgColor( cLabelColor );
  210. }
  211. SetLobbyReadyState( m_nLastPlayersNeeded );
  212. }
  213. void CSessionLobbyDialog::PositionTeamInfos()
  214. {
  215. // Line up the team info panels and menus
  216. int x, y;
  217. int menux, menuy;
  218. m_pTeamInfos[0]->GetPos( x, y );
  219. m_Menus[0].GetPos( menux, menuy );
  220. for ( int i = 1; i < TOTAL_LOBBY_TEAMS; ++i )
  221. {
  222. y += m_pTeamInfos[i - 1]->GetTall() + m_nTeamspacing;
  223. m_pTeamInfos[i]->SetPos( x, y );
  224. m_Menus[i].SetPos( menux, y );
  225. }
  226. }
  227. void CSessionLobbyDialog::ActivateNextMenu()
  228. {
  229. int startIndex = m_iActiveMenu;
  230. m_Menus[m_iActiveMenu].SetFocus( -1 );
  231. do
  232. {
  233. m_iActiveMenu = (m_iActiveMenu + 1) % TOTAL_LOBBY_TEAMS;
  234. } while ( m_Menus[m_iActiveMenu].GetItemCount() == 0 && m_iActiveMenu != startIndex );
  235. m_Menus[m_iActiveMenu].SetFocus( 0 );
  236. }
  237. void CSessionLobbyDialog::ActivatePreviousMenu()
  238. {
  239. int startIndex = m_iActiveMenu;
  240. m_Menus[m_iActiveMenu].SetFocus( -1 );
  241. do
  242. {
  243. m_iActiveMenu = m_iActiveMenu ? m_iActiveMenu - 1 : TOTAL_LOBBY_TEAMS - 1;
  244. } while ( m_Menus[m_iActiveMenu].GetItemCount() == 0 && m_iActiveMenu != startIndex );
  245. m_Menus[m_iActiveMenu].SetFocus( m_Menus[m_iActiveMenu].GetItemCount() - 1 );
  246. }
  247. void CSessionLobbyDialog::UpdatePlayerCountDisplay( int iTeam )
  248. {
  249. int ct = m_Menus[iTeam].GetItemCount();
  250. wchar_t wszString[32];
  251. wchar_t *wzPlayersFmt = g_pVGuiLocalize->Find( ct != 1 ? "#TF_ScoreBoard_Players" : "#TF_ScoreBoard_Player" );
  252. wchar_t wzPlayerCt[8];
  253. V_snwprintf( wzPlayerCt, ARRAYSIZE( wzPlayerCt ), L"%d", ct );
  254. g_pVGuiLocalize->ConstructString( wszString, sizeof( wszString ), wzPlayersFmt, 1, wzPlayerCt );
  255. m_pTeamInfos[iTeam]->m_pSubtitle->SetText( wszString );
  256. if ( m_nMinInfoHeight[iTeam] == 0 )
  257. {
  258. m_nMinInfoHeight[iTeam] = m_pTeamInfos[iTeam]->GetTall();
  259. }
  260. int height = max( m_nMinInfoHeight[iTeam], m_Menus[iTeam].GetTall() );
  261. m_pTeamInfos[iTeam]->SetTall( height );
  262. PositionTeamInfos();
  263. }
  264. void CSessionLobbyDialog::UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int iTeam, byte cVoiceState, int nPlayersNeeded, bool bHost )
  265. {
  266. if ( m_iLocalTeam == -1 )
  267. {
  268. m_iLocalTeam = iTeam;
  269. }
  270. bool bReady = ( nPlayersNeeded == 0 );
  271. // Look for the player
  272. int iFoundTeam = -1;
  273. int iFoundItem = -1;
  274. CPlayerItem *pFound = NULL;
  275. for ( int iMenu = 0; iMenu < TOTAL_LOBBY_TEAMS && !pFound; ++iMenu )
  276. {
  277. CDialogMenu &menu = m_Menus[iMenu];
  278. if ( menu.GetItemCount() == 0 )
  279. continue;
  280. for ( int idx = 0; idx < menu.GetItemCount(); ++idx )
  281. {
  282. CPlayerItem *pPlayerItem = dynamic_cast< CPlayerItem* >( menu.GetItem( idx ) );
  283. if ( pPlayerItem && pPlayerItem->m_nId == nPlayerId )
  284. {
  285. pFound = pPlayerItem;
  286. iFoundTeam = iMenu;
  287. iFoundItem = idx;
  288. break;
  289. }
  290. }
  291. }
  292. // Update menu and item focus if the player changed teams
  293. if ( iFoundTeam != iTeam )
  294. {
  295. if ( pFound )
  296. {
  297. // Remove the player from the current team
  298. m_Menus[iFoundTeam].RemovePlayerItem( iFoundItem );
  299. UpdatePlayerCountDisplay( iFoundTeam );
  300. }
  301. if ( 0 <= iTeam && iTeam < TOTAL_LOBBY_TEAMS )
  302. {
  303. // Add the player to the new team
  304. m_Menus[iTeam].AddPlayerItem( pName, nPlayerId, cVoiceState, bReady );
  305. UpdatePlayerCountDisplay( iTeam );
  306. }
  307. // if the player joined an empty lobby, set the active team
  308. if ( m_iActiveMenu == -1 )
  309. {
  310. m_iActiveMenu = iTeam;
  311. m_Menus[m_iActiveMenu].SetFocus( 0 );
  312. }
  313. // update the highlight position
  314. if ( iFoundTeam == m_iActiveMenu )
  315. {
  316. CDialogMenu &activeMenu = m_Menus[m_iActiveMenu];
  317. int iActive = activeMenu.GetActiveItemIndex();
  318. if ( iActive == iFoundItem )
  319. {
  320. // The changed player was also the highlighted player
  321. if ( iTeam >= 0 )
  322. {
  323. // Move the highlight to the player's new position
  324. activeMenu.SetFocus( -1 );
  325. m_iActiveMenu = iTeam;
  326. m_Menus[m_iActiveMenu].SetFocus( m_Menus[m_iActiveMenu].GetItemCount() - 1 );
  327. }
  328. else
  329. {
  330. // player left the game, move the highlight to the next filled slot
  331. if ( iActive >= activeMenu.GetItemCount() )
  332. {
  333. ActivateNextMenu();
  334. }
  335. }
  336. }
  337. else if ( iActive > iFoundItem )
  338. {
  339. // Need to drop the highlighted index one slot
  340. m_Menus[m_iActiveMenu].SetFocus( iActive - 1 );
  341. }
  342. }
  343. }
  344. else
  345. {
  346. if ( pFound )
  347. {
  348. if ( pFound->m_bVoice != cVoiceState )
  349. {
  350. pFound->m_bVoice = cVoiceState;
  351. pFound->InvalidateLayout();
  352. }
  353. }
  354. }
  355. if ( bHost )
  356. {
  357. wchar_t wszString[MAX_PATH];
  358. wchar_t wszHostname[MAX_PATH];
  359. wchar_t *wzHostFmt = g_pVGuiLocalize->Find( "#TF_Lobby_Host" );
  360. g_pVGuiLocalize->ConvertANSIToUnicode( pName, wszHostname, sizeof( wszHostname ) );
  361. V_snwprintf( wszString, ARRAYSIZE(wszString), L"%s\n%s", wzHostFmt, wszHostname );
  362. m_pHostLabel->SetText( wszString );
  363. m_nHostId = nPlayerId;
  364. }
  365. int iPlayersNeeded = ( bReady ) ? 0 : nPlayersNeeded;
  366. SetLobbyReadyState( iPlayersNeeded );
  367. m_nLastPlayersNeeded = iPlayersNeeded;
  368. InvalidateLayout( true, false );
  369. }
  370. void CSessionLobbyDialog::SetLobbyReadyState( int nPlayersNeeded )
  371. {
  372. // check if the host is allowed to start the game
  373. if ( nPlayersNeeded <= 0 )
  374. {
  375. if ( m_bHostLobby )
  376. {
  377. m_pLobbyStateLabel->SetText( "#TF_PressStart" );
  378. m_pLobbyStateIcon->SetText( "#GameUI_Icons_START" );
  379. }
  380. else
  381. {
  382. m_pLobbyStateLabel->SetText( "#TF_WaitingForHost" );
  383. m_pLobbyStateIcon->SetText( "#TF_Icon_Alert" );
  384. m_bStartingGame = false; // client guesses that they can change teams
  385. }
  386. }
  387. else
  388. {
  389. wchar_t wszWaiting[64];
  390. wchar_t *wzWaitingFmt;
  391. if ( nPlayersNeeded == 1 )
  392. {
  393. wzWaitingFmt = g_pVGuiLocalize->Find( "#TF_WaitingForPlayerFmt" );
  394. }
  395. else
  396. {
  397. wzWaitingFmt = g_pVGuiLocalize->Find( "#TF_WaitingForPlayersFmt" );
  398. }
  399. wchar_t wzPlayers[8];
  400. V_snwprintf( wzPlayers, ARRAYSIZE( wzPlayers ), L"%d", nPlayersNeeded );
  401. g_pVGuiLocalize->ConstructString( wszWaiting, sizeof( wszWaiting ), wzWaitingFmt, 1, wzPlayers );
  402. m_pLobbyStateLabel->SetText( wszWaiting );
  403. m_pLobbyStateIcon->SetText( "#TF_Icon_Alert" );
  404. // If we were starting and dropped below min players, cancel
  405. SetStartGame( false );
  406. }
  407. }
  408. void CSessionLobbyDialog::UpdateCountdown( int seconds )
  409. {
  410. if ( seconds == -1 )
  411. {
  412. // countdown was canceled
  413. SetLobbyReadyState( 0 );
  414. return;
  415. }
  416. // Set the text in the countdown label
  417. wchar_t wszCountdown[MAX_PATH];
  418. wchar_t wszSeconds[MAX_PATH];
  419. wchar_t *wzCountdownFmt;
  420. if ( seconds != 1 )
  421. {
  422. wzCountdownFmt = g_pVGuiLocalize->Find( "#TF_StartingInSecs" );
  423. }
  424. else
  425. {
  426. wzCountdownFmt = g_pVGuiLocalize->Find( "#TF_StartingInSec" );
  427. }
  428. V_snwprintf( wszSeconds, ARRAYSIZE( wszSeconds ), L"%d", seconds );
  429. g_pVGuiLocalize->ConstructString( wszCountdown, sizeof( wszCountdown ), wzCountdownFmt, 1, wszSeconds );
  430. m_pLobbyStateLabel->SetText( wszCountdown );
  431. if ( !m_bHostLobby )
  432. {
  433. m_bStartingGame = true; // client guesses that they can't change teams
  434. }
  435. }
  436. //-----------------------------------------------------------------
  437. // Purpose: Send key presses to the dialog's menu
  438. //-----------------------------------------------------------------
  439. void CSessionLobbyDialog::OnKeyCodePressed( vgui::KeyCode code )
  440. {
  441. CDialogMenu *pMenu = &m_Menus[m_iActiveMenu];
  442. if ( !pMenu )
  443. return;
  444. int idx = pMenu->GetActiveItemIndex();
  445. int itemCt = pMenu->GetItemCount();
  446. CPlayerItem *pItem = dynamic_cast< CPlayerItem* >( pMenu->GetItem( idx ) );
  447. if ( !pItem )
  448. return;
  449. SetDeleteSelfOnClose( true );
  450. switch( code )
  451. {
  452. case KEY_XBUTTON_DOWN:
  453. case KEY_XSTICK1_DOWN:
  454. case STEAMCONTROLLER_DPAD_DOWN:
  455. if ( idx >= itemCt - 1 )
  456. {
  457. ActivateNextMenu();
  458. }
  459. else
  460. {
  461. pMenu->HandleKeyCode( code );
  462. }
  463. break;
  464. case KEY_XBUTTON_UP:
  465. case KEY_XSTICK1_UP:
  466. case STEAMCONTROLLER_DPAD_UP:
  467. if ( idx <= 0 )
  468. {
  469. ActivatePreviousMenu();
  470. }
  471. else
  472. {
  473. pMenu->HandleKeyCode( code );
  474. }
  475. break;
  476. case KEY_XBUTTON_A:
  477. case STEAMCONTROLLER_A:
  478. #ifdef _X360
  479. XShowGamerCardUI( XBX_GetPrimaryUserId(), pItem->m_nId );
  480. #endif
  481. break;
  482. case KEY_XBUTTON_RIGHT_SHOULDER:
  483. #ifdef _X360
  484. {
  485. // Don't allow player reviews in system link games
  486. CMatchmakingBasePanel *pBase = dynamic_cast< CMatchmakingBasePanel* >( m_pParent );
  487. if ( pBase && pBase->GetGameType() == GAMETYPE_SYSTEMLINK_MATCH )
  488. break;
  489. }
  490. XShowPlayerReviewUI( XBX_GetPrimaryUserId(), pItem->m_nId );
  491. #endif
  492. break;
  493. case KEY_XBUTTON_LEFT_SHOULDER:
  494. {
  495. // Don't kick ourselves
  496. if ( m_bHostLobby )
  497. {
  498. if ( pItem && ((CPlayerItem*)pItem)->m_nId != m_nHostId )
  499. {
  500. GameUI().ShowMessageDialog( MD_KICK_CONFIRMATION, this );
  501. }
  502. else
  503. {
  504. vgui::surface()->PlaySound( "player/suit_denydevice.wav" );
  505. }
  506. }
  507. }
  508. break;
  509. case KEY_XBUTTON_B:
  510. case STEAMCONTROLLER_B:
  511. GameUI().ShowMessageDialog( MD_EXIT_SESSION_CONFIRMATION, this );
  512. if ( m_bHostLobby )
  513. {
  514. SetStartGame( false );
  515. }
  516. break;
  517. case KEY_XBUTTON_X:
  518. case STEAMCONTROLLER_X:
  519. if ( m_bStartingGame )
  520. {
  521. // We think we're loading the game, so play deny sound
  522. vgui::surface()->PlaySound( "player/suit_denydevice.wav" );
  523. }
  524. else
  525. {
  526. matchmaking->ChangeTeam( NULL );
  527. }
  528. break;
  529. case KEY_XBUTTON_Y:
  530. case STEAMCONTROLLER_Y:
  531. if ( m_bHostLobby )
  532. {
  533. // Don't allow settings changes in ranked games
  534. CMatchmakingBasePanel *pBase = dynamic_cast< CMatchmakingBasePanel* >( m_pParent );
  535. if ( pBase && pBase->GetGameType() == GAMETYPE_RANKED_MATCH )
  536. break;
  537. SetDeleteSelfOnClose( false );
  538. OnCommand( "SessionOptions_Modify" );
  539. SetStartGame( false );
  540. }
  541. break;
  542. case KEY_XBUTTON_START:
  543. SetStartGame( !m_bStartingGame );
  544. break;
  545. default:
  546. pMenu->HandleKeyCode( code );
  547. break;
  548. }
  549. }
  550. //---------------------------------------------------------------------
  551. // Purpose: start and stop the countdown
  552. //---------------------------------------------------------------------
  553. void CSessionLobbyDialog::SetStartGame( bool bStartGame )
  554. {
  555. if ( !m_bHostLobby )
  556. return;
  557. bool bCanStart = true;
  558. if ( m_bStartingGame != bStartGame )
  559. {
  560. if ( bStartGame )
  561. {
  562. m_bStartingGame = matchmaking->StartGame();
  563. bCanStart = m_bStartingGame;
  564. }
  565. else
  566. {
  567. if ( matchmaking->CancelStartGame() )
  568. {
  569. m_bStartingGame = false;
  570. }
  571. }
  572. // If we can start the game but haven't started yet, show the "Start Game" label
  573. bool bShowStartGame = bCanStart && !m_bStartingGame;
  574. // show/hide the "start game" and countdown hint label based on state
  575. vgui::Label *pStartGame = (vgui::Label *)m_pHostOptionsPanel->FindChildByName("StartGameText" );
  576. if ( pStartGame )
  577. {
  578. pStartGame->SetVisible( m_bStartingGame == false );
  579. }
  580. vgui::Label *pCancelCountdown = (vgui::Label *)m_pHostOptionsPanel->FindChildByName("CancelGameText" );
  581. if ( pCancelCountdown )
  582. {
  583. pCancelCountdown->SetVisible( m_bStartingGame == true );
  584. }
  585. if ( bShowStartGame )
  586. {
  587. m_pLobbyStateLabel->SetText( "#TF_PressStart" );
  588. m_pLobbyStateIcon->SetText( "#GameUI_Icons_START" );
  589. }
  590. }
  591. }
  592. //---------------------------------------------------------------------
  593. // Purpose: Handle menu commands
  594. //---------------------------------------------------------------------
  595. void CSessionLobbyDialog::OnCommand( const char *pCommand )
  596. {
  597. if ( !Q_stricmp( pCommand, "ReturnToMainMenu" ) )
  598. {
  599. matchmaking->KickPlayerFromSession( 0 );
  600. }
  601. else if ( !Q_stricmp( pCommand, "KickPlayer" ) )
  602. {
  603. CDialogMenu *pMenu = &m_Menus[m_iActiveMenu];
  604. CPlayerItem *pItem = (CPlayerItem*)pMenu->GetItem( pMenu->GetActiveItemIndex() );
  605. if ( pItem )
  606. {
  607. matchmaking->KickPlayerFromSession( pItem->m_nId );
  608. }
  609. }
  610. GetParent()->OnCommand( pCommand );
  611. }
  612. static int pnum = 1;
  613. CON_COMMAND( mm_add_player, "Add a player" )
  614. {
  615. if ( args.ArgC() >= 5 )
  616. {
  617. int team = atoi( args[1] );
  618. const char *pName = args[2];
  619. uint32 id = atoi( args[3] );
  620. byte cVoiceState = atoi( args[4] ) != 0;
  621. int nPlayersNeeded = atoi( args[5] );
  622. g_pLobbyDialog->UpdatePlayerInfo( id, pName, team, cVoiceState, nPlayersNeeded, false );
  623. }
  624. else if ( args.ArgC() >= 1 )
  625. {
  626. char name[ 32 ];
  627. int team = pnum & 0x1;
  628. int id = pnum++;
  629. if ( args.ArgC() >= 2 )
  630. {
  631. team = atoi( args[ 1 ] );
  632. if ( args.ArgC() >= 3 )
  633. {
  634. id = atoi( args[2] );
  635. }
  636. }
  637. Q_snprintf( name, sizeof( name ), "Player%d", pnum );
  638. g_pLobbyDialog->UpdatePlayerInfo( id, name, team, true, 0, false );
  639. }
  640. }