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.

1834 lines
58 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //===========================================================================//
  4. #include "cbase.h"
  5. #include "inputsystem/iinputsystem.h"
  6. #include "input.h"
  7. #include "hud.h"
  8. #include "hudelement.h"
  9. #include "hud_macros.h"
  10. #include "hud_numericdisplay.h"
  11. #include "iclientmode.h"
  12. #include "clientmode_shared.h"
  13. #include "VGuiMatSurface/IMatSystemSurface.h"
  14. #include "materialsystem/imaterial.h"
  15. #include "materialsystem/imesh.h"
  16. #include "materialsystem/imaterialvar.h"
  17. #include "con_nprint.h"
  18. #include "hud_vote.h"
  19. #include "menu.h"
  20. #include <vgui/IScheme.h>
  21. #include <vgui/ISurface.h>
  22. #include <vgui/ILocalize.h>
  23. #include <KeyValues.h>
  24. #include <vgui_controls/AnimationController.h>
  25. #include <vgui_controls/EditablePanel.h>
  26. #include <vgui_controls/Label.h>
  27. #include <vgui_controls/ComboBox.h>
  28. #include <vgui_controls/ImageList.h>
  29. #include "vgui_avatarimage.h"
  30. #ifdef TF_CLIENT_DLL
  31. #include "ienginevgui.h"
  32. #include "tf_gcmessages.h"
  33. #include "c_tf_player.h"
  34. #include "econ_notifications.h"
  35. #include "confirm_dialog.h"
  36. #include "gc_clientsystem.h"
  37. #include "tf_gamerules.h"
  38. #include "c_playerresource.h"
  39. #include "c_tf_objective_resource.h"
  40. #endif
  41. // memdbgon must be the last include file in a .cpp file!!!
  42. #include "tier0/memdbgon.h"
  43. ConVar cl_vote_ui_active_after_voting( "cl_vote_ui_active_after_voting", "0" );
  44. ConVar cl_vote_ui_show_notification( "cl_vote_ui_show_notification", "0" );
  45. #ifdef TF_CLIENT_DLL
  46. //-----------------------------------------------------------------------------
  47. // Purpose:
  48. //-----------------------------------------------------------------------------
  49. class CTFVoteNotification : public CEconNotification
  50. {
  51. public:
  52. CTFVoteNotification( const char *pPlayerName ) : CEconNotification()
  53. {
  54. g_pVGuiLocalize->ConvertANSIToUnicode( pPlayerName, m_wszPlayerName, sizeof(m_wszPlayerName) );
  55. SetLifetime( 7 );
  56. SetText( "#GameUI_Vote_Notification_Text" );
  57. AddStringToken( "initiator", m_wszPlayerName );
  58. }
  59. virtual EType NotificationType() { return eType_AcceptDecline; }
  60. virtual void Trigger()
  61. {
  62. CTFGenericConfirmDialog *pDialog = ShowConfirmDialog( "#GameUI_Vote_Notification_Title",
  63. "#GameUI_Vote_Notification_Text",
  64. "#GameUI_Vote_Notification_View",
  65. "#cancel", &ConfirmShowVoteSetup );
  66. pDialog->SetContext( this );
  67. pDialog->AddStringToken( "initiator", m_wszPlayerName );
  68. // so we aren't deleted
  69. SetIsInUse( true );
  70. }
  71. virtual void Accept()
  72. {
  73. ConfirmShowVoteSetup( true, this );
  74. }
  75. virtual void Decline()
  76. {
  77. ConfirmShowVoteSetup( false, this );
  78. }
  79. static void ConfirmShowVoteSetup( bool bConfirmed, void *pContext )
  80. {
  81. CTFVoteNotification *pNotification = (CTFVoteNotification*)pContext;
  82. if ( bConfirmed )
  83. {
  84. // Show vote
  85. CHudVote *pHudVote = GET_HUDELEMENT( CHudVote );
  86. if ( pHudVote )
  87. {
  88. pHudVote->ShowVoteUI( true );
  89. }
  90. }
  91. pNotification->SetIsInUse( false );
  92. pNotification->MarkForDeletion();
  93. }
  94. public:
  95. wchar_t m_wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  96. };
  97. #endif // TF_CLIENT_DLL
  98. //-----------------------------------------------------------------------------
  99. // Purpose:
  100. //-----------------------------------------------------------------------------
  101. VoteBarPanel::VoteBarPanel( vgui::Panel *parent, const char *panelName ) : vgui::Panel( parent, panelName )
  102. {
  103. for( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
  104. {
  105. m_nVoteOptionCount[index] = 0;
  106. }
  107. m_nPotentialVotes = 0;
  108. ListenForGameEvent( "vote_changed" );
  109. }
  110. void VoteBarPanel::Paint( void )
  111. {
  112. int wide, tall;
  113. GetSize( wide, tall );
  114. int x = 0;
  115. // driller: this shouldn't ship - temp UI solution for playtesting
  116. for ( int i = 0; i < 2; i++ )
  117. {
  118. // Draw an outlined box
  119. vgui::surface()->DrawSetColor( 128, 128, 128, 128 );
  120. vgui::surface()->DrawFilledRect( x, 0, x + m_iBoxSize, m_iBoxSize );
  121. vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
  122. vgui::surface()->DrawFilledRect( x + m_iBoxInset, m_iBoxInset, x + m_iBoxSize - m_iBoxInset, m_iBoxSize - m_iBoxInset );
  123. vgui::surface()->DrawSetColor( Color(255, 255, 255, 255) );
  124. x += ( m_iBoxSize + 64 );
  125. }
  126. x = 0;
  127. int iImageInset = 2 * m_iBoxInset;
  128. // Yes image
  129. vgui::surface()->DrawSetTexture( m_nYesTextureId );
  130. vgui::surface()->DrawTexturedRect( x + iImageInset, iImageInset, x + m_iBoxSize - iImageInset, m_iBoxSize - iImageInset );
  131. x += ( m_iBoxSize + 64 );
  132. // No image
  133. vgui::surface()->DrawSetTexture( m_nNoTextureId );
  134. vgui::surface()->DrawTexturedRect( x + iImageInset, iImageInset, x + m_iBoxSize - iImageInset, m_iBoxSize - iImageInset );
  135. }
  136. void VoteBarPanel::FireGameEvent( IGameEvent *event )
  137. {
  138. const char *eventName = event->GetName();
  139. if ( !eventName )
  140. return;
  141. if( FStrEq( eventName, "vote_changed" ) )
  142. {
  143. for ( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
  144. {
  145. char szOption[2];
  146. Q_snprintf( szOption, sizeof( szOption ), "%i", index + 1 );
  147. char szVoteOption[13] = "vote_option";
  148. Q_strncat( szVoteOption, szOption, sizeof( szVoteOption ), COPY_ALL_CHARACTERS );
  149. m_nVoteOptionCount[index] = event->GetInt( szVoteOption );
  150. }
  151. m_nPotentialVotes = event->GetInt( "potentialVotes" );
  152. }
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose: Constructor
  156. //-----------------------------------------------------------------------------
  157. CVoteSetupDialog::CVoteSetupDialog( vgui::Panel *parent ) : BaseClass( parent, "VoteSetupDialog" )
  158. {
  159. SetMoveable( false );
  160. SetSizeable( false );
  161. m_pVoteSetupList = new SectionedListPanel( this, "VoteSetupList" );
  162. m_pVoteParameterList = new SectionedListPanel( this, "VoteParameterList" );
  163. m_pCallVoteButton = new Button( this, "CallVoteButton", "CallVote", this, "CallVote" );
  164. m_pComboBox = new ComboBox( this, "ComboBox", 5, false );
  165. m_pImageList = NULL;
  166. #ifdef TF_CLIENT_DLL
  167. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  168. SetScheme(scheme);
  169. #else
  170. SetScheme( "ClientScheme" );
  171. #endif
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose: Destructor
  175. //-----------------------------------------------------------------------------
  176. CVoteSetupDialog::~CVoteSetupDialog()
  177. {
  178. if ( m_pImageList )
  179. {
  180. delete m_pImageList;
  181. m_pImageList = NULL;
  182. }
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Purpose:
  186. //-----------------------------------------------------------------------------
  187. void CVoteSetupDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
  188. {
  189. BaseClass::ApplySchemeSettings( pScheme );
  190. SetProportional( true );
  191. LoadControlSettings( "Resource/UI/VoteHud.res" );
  192. m_pComboBox->GetComboButton()->SetFgColor( Color( 117,107,94,255 ) );
  193. m_pComboBox->GetComboButton()->SetDefaultColor( Color( 117,107,94,255), Color( 0,0,0,0) );
  194. m_pComboBox->GetComboButton()->SetArmedColor( Color( 117,107,94,255), Color( 0,0,0,0) );
  195. m_pComboBox->GetComboButton()->SetDepressedColor( Color( 117,107,94,255), Color( 0,0,0,0) );
  196. if ( m_pImageList )
  197. {
  198. delete m_pImageList;
  199. }
  200. m_pImageList = new ImageList( false );
  201. }
  202. //-----------------------------------------------------------------------------
  203. // Purpose: Does dialog-specific customization after applying scheme settings.
  204. //-----------------------------------------------------------------------------
  205. void CVoteSetupDialog::PostApplySchemeSettings( vgui::IScheme *pScheme )
  206. {
  207. // resize the images to our resolution
  208. for ( int i = 0; i < m_pImageList->GetImageCount(); i++ )
  209. {
  210. int wide, tall;
  211. m_pImageList->GetImage( i )->GetSize( wide, tall );
  212. m_pImageList->GetImage( i )->SetSize(scheme()->GetProportionalScaledValueEx( GetScheme(), wide ), scheme()->GetProportionalScaledValueEx( GetScheme(), tall ) );
  213. }
  214. m_pVoteParameterList->SetImageList( m_pImageList, false );
  215. m_pVoteParameterList->SetVisible( true );
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose:
  219. //-----------------------------------------------------------------------------
  220. void CVoteSetupDialog::ApplySettings(KeyValues *inResourceData)
  221. {
  222. BaseClass::ApplySettings( inResourceData );
  223. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  224. m_hIssueFont = INVALID_FONT;
  225. const char *pszFont = inResourceData->GetString( "issue_font", NULL );
  226. if ( pszFont && pszFont[0] )
  227. {
  228. m_hIssueFont = pScheme->GetFont( pszFont, true );
  229. }
  230. m_hHeaderFont = INVALID_FONT;
  231. pszFont = inResourceData->GetString( "header_font", NULL );
  232. if ( pszFont && pszFont[0] )
  233. {
  234. m_hHeaderFont = pScheme->GetFont( pszFont, true );
  235. }
  236. const char *pszColor = inResourceData->GetString( "issue_fgcolor", "Label.TextColor" );
  237. m_IssueFGColor = pScheme->GetColor( pszColor, Color( 255, 255, 255, 255 ) );
  238. pszColor = inResourceData->GetString( "issue_fgcolor_disabled", "Label.TextColor" );
  239. m_IssueFGColorDisabled = pScheme->GetColor( pszColor, Color( 255, 255, 255, 255 ) );
  240. pszColor = inResourceData->GetString( "header_fgcolor", "Label.TextColor" );
  241. m_HeaderFGColor = pScheme->GetColor( pszColor, Color( 255, 255, 255, 255 ) );
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose:
  245. //-----------------------------------------------------------------------------
  246. void CVoteSetupDialog::InitializeIssueList( void )
  247. {
  248. m_pComboBox->RemoveAll();
  249. m_pComboBox->SetVisible( false );
  250. SetDialogVariable( "combo_label", "" );
  251. for ( int index = 0; index < m_VoteIssues.Count(); index++ )
  252. {
  253. if ( !m_VoteIssues[index].szName || !m_VoteIssues[index].szName[0] )
  254. continue;
  255. bool bActive = m_VoteIssues[index].bIsActive;
  256. char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 };
  257. g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( m_VoteIssues[index].szNameString ), szIssueLocalized, sizeof( szIssueLocalized ) );
  258. if ( !bActive )
  259. {
  260. char szDisabled[k_MAX_VOTE_NAME_LENGTH] = { 0 };
  261. g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_Disabled" ), szDisabled, sizeof( szDisabled ) );
  262. V_strcat_safe( szIssueLocalized, szDisabled );
  263. }
  264. KeyValues *pKeyValues = new KeyValues( "Issue" );
  265. pKeyValues->SetString( "Issue", szIssueLocalized );
  266. pKeyValues->SetString( "IssueRaw", m_VoteIssues[index].szName );
  267. pKeyValues->SetBool( "Active", m_VoteIssues[index].bIsActive );
  268. int iId = m_pVoteSetupList->AddItem( 0, pKeyValues );
  269. pKeyValues->deleteThis();
  270. // Setup the list entry style
  271. if ( m_hIssueFont != INVALID_FONT )
  272. {
  273. m_pVoteSetupList->SetItemFont( iId, m_hIssueFont );
  274. Color colFG = bActive ? m_IssueFGColor : m_IssueFGColorDisabled;
  275. m_pVoteSetupList->SetItemFgColor( iId, colFG );
  276. }
  277. }
  278. // Select the first item by default
  279. if ( m_pVoteSetupList->GetItemCount() > 0 )
  280. {
  281. m_pVoteSetupList->SetSelectedItem( 0 );
  282. }
  283. else
  284. {
  285. // No active issues
  286. char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 };
  287. g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_System_Disabled" ), szIssueLocalized, sizeof( szIssueLocalized ) );
  288. KeyValues *pKeyValues = new KeyValues( "Issue" );
  289. pKeyValues->SetString( "Issue", szIssueLocalized );
  290. pKeyValues->SetString( "IssueRaw", "Disabled" );
  291. pKeyValues->SetBool( "Active", false );
  292. int iId = m_pVoteSetupList->AddItem( 0, pKeyValues );
  293. pKeyValues->deleteThis();
  294. if ( m_hIssueFont != INVALID_FONT )
  295. {
  296. m_pVoteSetupList->SetItemFont( iId, m_hIssueFont );
  297. m_pVoteSetupList->SetItemFgColor( iId, m_IssueFGColor );
  298. }
  299. }
  300. UpdateCurrentMap();
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Keep track of the current map
  304. //-----------------------------------------------------------------------------
  305. void CVoteSetupDialog::UpdateCurrentMap( void )
  306. {
  307. Q_FileBase( engine->GetLevelName(), m_szCurrentMap, sizeof(m_szCurrentMap) );
  308. Q_strlower( m_szCurrentMap );
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose: Feeds Issues from the server to this Dialog
  312. //-----------------------------------------------------------------------------
  313. void CVoteSetupDialog::AddVoteIssues( CUtlVector< VoteIssue_t > &m_VoteSetupIssues )
  314. {
  315. m_VoteIssues.RemoveAll();
  316. for ( int index = 0; index < m_VoteSetupIssues.Count(); index++ )
  317. {
  318. m_VoteIssues.AddToTail( m_VoteSetupIssues[index] );
  319. }
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose: Feeds the server's MapCycle to the parameters dialog
  323. //-----------------------------------------------------------------------------
  324. void CVoteSetupDialog::AddVoteIssueParams_MapCycle( CUtlStringList &m_VoteSetupMapCycle )
  325. {
  326. m_VoteIssuesMapCycle.RemoveAll();
  327. for ( int index = 0; index < m_VoteSetupMapCycle.Count(); index++ )
  328. {
  329. m_VoteIssuesMapCycle.AddToTail( m_VoteSetupMapCycle[index] );
  330. }
  331. }
  332. #ifdef TF_CLIENT_DLL
  333. //-----------------------------------------------------------------------------
  334. // Purpose: Feeds the server's PopFiles to the parameters dialog
  335. //-----------------------------------------------------------------------------
  336. void CVoteSetupDialog::AddVoteIssueParams_PopFiles( CUtlStringList &m_VoteSetupPopFiles )
  337. {
  338. m_VoteIssuesPopFiles.RemoveAll();
  339. for ( int index = 0; index < m_VoteSetupPopFiles.Count(); index++ )
  340. {
  341. m_VoteIssuesPopFiles.AddToTail( m_VoteSetupPopFiles[index] );
  342. }
  343. }
  344. #endif // TF_CLIENT_DLL
  345. //-----------------------------------------------------------------------------
  346. // Purpose:
  347. //-----------------------------------------------------------------------------
  348. void CVoteSetupDialog::Activate()
  349. {
  350. InvalidateLayout( true, true );
  351. BaseClass::Activate();
  352. ResetData();
  353. m_pVoteSetupList->SetVerticalScrollbar( true );
  354. m_pVoteSetupList->RemoveAll();
  355. m_pVoteSetupList->RemoveAllSections();
  356. m_pVoteSetupList->AddSection( 0, "Issue" );
  357. m_pVoteSetupList->SetSectionAlwaysVisible( 0, true );
  358. m_pVoteSetupList->SetSectionFgColor( 0, Color( 255, 255, 255, 255 ) );
  359. m_pVoteSetupList->SetBgColor( Color( 0, 0, 0, 0 ) );
  360. m_pVoteSetupList->SetBorder( NULL );
  361. m_pVoteSetupList->AddColumnToSection( 0, "Issue", "#TF_Vote_Column_Issue", SectionedListPanel::COLUMN_CENTER, m_iIssueWidth );
  362. if ( m_hHeaderFont != INVALID_FONT )
  363. {
  364. m_pVoteSetupList->SetFontSection( 0, m_hHeaderFont );
  365. m_pVoteSetupList->SetSectionFgColor( 0, m_HeaderFGColor );
  366. }
  367. m_pVoteParameterList->SetVerticalScrollbar( true );
  368. m_pVoteParameterList->RemoveAll();
  369. m_pVoteParameterList->RemoveAllSections();
  370. m_pVoteParameterList->AddSection( 0, "Name" );
  371. m_pVoteParameterList->SetSectionAlwaysVisible( 0, true );
  372. m_pVoteParameterList->SetSectionFgColor( 0, Color( 255, 255, 255, 255 ) );
  373. m_pVoteParameterList->SetBgColor( Color( 0, 0, 0, 0 ) );
  374. m_pVoteParameterList->SetBorder( NULL );
  375. m_pVoteParameterList->AddColumnToSection( 0, "Avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, 55 );
  376. m_pVoteParameterList->AddColumnToSection( 0, "", "", 0, 10 ); // Spacer
  377. m_pVoteParameterList->AddColumnToSection( 0, "Name", "#TF_Vote_Column_Name", 0, m_iParameterWidth * 0.6 );
  378. m_pVoteParameterList->AddColumnToSection( 0, "Properties", "#TF_Vote_Column_Properties", SectionedListPanel::COLUMN_CENTER, m_iParameterWidth * 0.3 );
  379. if ( m_hHeaderFont != INVALID_FONT )
  380. {
  381. m_pVoteParameterList->SetFontSection( 0, m_hHeaderFont );
  382. m_pVoteParameterList->SetSectionFgColor( 0, m_HeaderFGColor );
  383. m_pVoteParameterList->SetFontSection( 1, m_hHeaderFont );
  384. m_pVoteParameterList->SetSectionFgColor( 1, m_HeaderFGColor );
  385. }
  386. InitializeIssueList();
  387. }
  388. //-----------------------------------------------------------------------------
  389. // Purpose:
  390. //-----------------------------------------------------------------------------
  391. void CVoteSetupDialog::OnClose()
  392. {
  393. ResetData();
  394. BaseClass::OnClose();
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose:
  398. //-----------------------------------------------------------------------------
  399. void CVoteSetupDialog::OnCommand(const char *command)
  400. {
  401. // We should have enough data to issue a CallVote command
  402. if ( !V_stricmp( command, "CallVote" ) )
  403. {
  404. int iSelectedItem = m_pVoteSetupList->GetSelectedItem();
  405. if ( iSelectedItem >= 0 )
  406. {
  407. char szVoteCommand[k_MAX_VOTE_NAME_LENGTH];
  408. KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem );
  409. const char *szIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
  410. if ( !V_stricmp( "ChangeLevel", szIssueRaw ) || !V_stricmp( "NextLevel", szIssueRaw ) )
  411. {
  412. int nSelectedParam = m_pVoteParameterList->GetSelectedItem();
  413. if ( nSelectedParam >= 0 )
  414. {
  415. // Get selected Map
  416. int iSelectedParam = m_pVoteParameterList->GetSelectedItem();
  417. if ( iSelectedParam >= 0 )
  418. {
  419. KeyValues *pParameterKeyValues = m_pVoteParameterList->GetItemData( iSelectedParam );
  420. if ( pParameterKeyValues )
  421. {
  422. // Which Map?
  423. const char *szMapName = pParameterKeyValues->GetString( "Name" );
  424. Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szMapName );
  425. engine->ClientCmd( szVoteCommand );
  426. }
  427. }
  428. }
  429. }
  430. else if ( !V_stricmp( "Kick", szIssueRaw ) )
  431. {
  432. // Get selected Player
  433. int iSelectedParam = m_pVoteParameterList->GetSelectedItem();
  434. if ( iSelectedParam >= 0 )
  435. {
  436. KeyValues *pKeyValues = m_pVoteParameterList->GetItemData( iSelectedParam );
  437. if ( pKeyValues )
  438. {
  439. // Is Player valid?
  440. int playerIndex = pKeyValues->GetInt( "index" );
  441. const char *pReasonString = m_pComboBox->GetActiveItemUserData() ? m_pComboBox->GetActiveItemUserData()->GetName() : "other";
  442. player_info_t playerInfo;
  443. if ( engine->GetPlayerInfo( playerIndex, &playerInfo ) )
  444. {
  445. CBasePlayer *pPlayer = UTIL_PlayerByIndex( playerIndex );
  446. Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s \"%d %s\"\n;", szIssueRaw, pPlayer->GetUserID(), pReasonString );
  447. engine->ClientCmd( szVoteCommand );
  448. #ifdef TF_CLIENT_DLL
  449. CSteamID steamID;
  450. CTFPlayer* pSubject = ToTFPlayer( pPlayer );
  451. if ( pSubject && pSubject->GetSteamID( &steamID ) && steamID.GetAccountID() != 0 )
  452. {
  453. GCSDK::CProtoBufMsg<CMsgTFVoteKickBanPlayer> msg( k_EMsgGCVoteKickBanPlayer );
  454. uint32 reason = GetKickBanPlayerReason( pReasonString );
  455. msg.Body().set_account_id_subject( steamID.GetAccountID() );
  456. msg.Body().set_kick_reason( reason );
  457. GCClientSystem()->BSendMessage( msg );
  458. }
  459. #endif
  460. }
  461. }
  462. }
  463. }
  464. #ifdef TF_CLIENT_DLL
  465. else if ( !V_stricmp( "ChangeMission", szIssueRaw ) )
  466. {
  467. int nSelectedParam = m_pVoteParameterList->GetSelectedItem();
  468. if ( nSelectedParam >= 0 )
  469. {
  470. // Get selected Challenge
  471. int iSelectedParam = m_pVoteParameterList->GetSelectedItem();
  472. if ( iSelectedParam >= 0 )
  473. {
  474. KeyValues *pParameterKeyValues = m_pVoteParameterList->GetItemData( iSelectedParam );
  475. if ( pParameterKeyValues )
  476. {
  477. // Which Pop File?
  478. const char *szPopFile = pParameterKeyValues->GetString( "Name" );
  479. Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szPopFile );
  480. engine->ClientCmd( szVoteCommand );
  481. }
  482. }
  483. }
  484. }
  485. #endif // TF_CLIENT_DLL
  486. else
  487. {
  488. // Non-parameter vote. i.e. callvote scrambleteams
  489. Q_snprintf( szVoteCommand, sizeof(szVoteCommand), "callvote %s\n;", szIssueRaw );
  490. engine->ClientCmd( szVoteCommand );
  491. }
  492. Close();
  493. }
  494. }
  495. else
  496. {
  497. BaseClass::OnCommand( command );
  498. }
  499. }
  500. //-----------------------------------------------------------------------------
  501. // Purpose:
  502. //-----------------------------------------------------------------------------
  503. void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel )
  504. {
  505. if ( panel == m_pVoteSetupList )
  506. {
  507. m_pComboBox->RemoveAll();
  508. m_pComboBox->SetVisible( false );
  509. SetDialogVariable( "combo_label", "" );
  510. // Which Issue did we select?
  511. int iSelectedItem = m_pVoteSetupList->GetSelectedItem();
  512. if ( iSelectedItem >= 0 )
  513. {
  514. KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem );
  515. if ( !pIssueKeyValues )
  516. return;
  517. CHudVote *pHudVote = GET_HUDELEMENT( CHudVote );
  518. if ( !pHudVote )
  519. return;
  520. // We're rebuilding, so clear state
  521. m_bVoteButtonEnabled = false;
  522. m_pVoteParameterList->ClearSelection();
  523. m_pVoteParameterList->RemoveAll();
  524. const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
  525. bool bActive = pIssueKeyValues->GetBool( "Active" );
  526. if ( !pHudVote->IsVoteSystemActive() || !bActive )
  527. {
  528. m_bVoteButtonEnabled = false;
  529. }
  530. // CHANGELEVEL / NEXTLEVEL
  531. else if ( !V_stricmp( "ChangeLevel", pszIssueRaw ) || !V_stricmp( "NextLevel", pszIssueRaw ) )
  532. {
  533. // Feed the mapcycle to the parameters list
  534. for ( int index = 0; index < m_VoteIssuesMapCycle.Count(); index++ )
  535. {
  536. // Don't show the current map
  537. if ( V_strncmp( m_VoteIssuesMapCycle[index], m_szCurrentMap, ( V_strlen( m_VoteIssuesMapCycle[index] ) - 1 ) ) == 0 )
  538. continue;
  539. KeyValues *pKeyValues = new KeyValues( "Name" );
  540. pKeyValues->SetString( "Name", m_VoteIssuesMapCycle[index] );
  541. pKeyValues->SetInt( "index", index );
  542. int iId = m_pVoteParameterList->AddItem( 0, pKeyValues );
  543. pKeyValues->deleteThis();
  544. if ( m_hIssueFont != INVALID_FONT )
  545. {
  546. m_pVoteParameterList->SetItemFont( iId, m_hIssueFont );
  547. m_pVoteParameterList->SetItemFgColor( iId, m_IssueFGColor );
  548. }
  549. }
  550. if ( m_pVoteParameterList->GetItemCount() == 0 )
  551. {
  552. KeyValues *pKeyValues = new KeyValues( "Name" );
  553. pKeyValues->SetString( "Name", "#TF_vote_no_maps" );
  554. pKeyValues->SetInt( "index", 1 );
  555. m_pVoteParameterList->AddItem( 0, pKeyValues );
  556. pKeyValues->deleteThis();
  557. }
  558. }
  559. // KICK
  560. else if ( !V_stricmp( "Kick", pszIssueRaw ) )
  561. {
  562. // Feed the player list to the parameters list
  563. int nMaxClients = engine->GetMaxClients();
  564. for ( int playerIndex = 1; playerIndex <= nMaxClients; playerIndex++ )
  565. {
  566. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( playerIndex );
  567. if ( !pPlayer )
  568. continue;
  569. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  570. if ( !pLocalPlayer )
  571. continue;
  572. if ( pPlayer == pLocalPlayer )
  573. continue;
  574. bool bAllowKickUnassigned = false;
  575. #ifdef TF_CLIENT_DLL
  576. // Allow kicking team unassigned in MvM
  577. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && g_PR->IsConnected( playerIndex ) && pPlayer->GetTeamNumber() == TEAM_UNASSIGNED )
  578. {
  579. bAllowKickUnassigned = true;
  580. }
  581. #endif // TF_CLIENT_DLL
  582. // Can't kick people on the other team, so don't list them
  583. if ( pPlayer->GetTeam() != pLocalPlayer->GetTeam() && !bAllowKickUnassigned )
  584. continue;
  585. char szPlayerIndex[32];
  586. Q_snprintf( szPlayerIndex, sizeof( szPlayerIndex ), "%d", playerIndex );
  587. KeyValues *pKeyValues = new KeyValues( szPlayerIndex );
  588. pKeyValues->SetString( "Name", pPlayer->GetPlayerName() );
  589. pKeyValues->SetInt( "index", playerIndex );
  590. int iId = m_pVoteParameterList->AddItem( 0, pKeyValues );
  591. pKeyValues->deleteThis();
  592. if ( m_hIssueFont != INVALID_FONT )
  593. {
  594. m_pVoteParameterList->SetItemFont( iId, m_hIssueFont );
  595. m_pVoteParameterList->SetItemFgColor( iId, m_IssueFGColor );
  596. }
  597. }
  598. #ifdef TF_CLIENT_DLL
  599. SetDialogVariable( "combo_label", g_pVGuiLocalize->Find( "#TF_VoteKickReason" ) );
  600. m_pComboBox->AddItem( g_pVGuiLocalize->Find( "TF_VoteKickReason_Other" ), new KeyValues( "other" ) );
  601. m_pComboBox->AddItem( g_pVGuiLocalize->Find( "TF_VoteKickReason_Cheating" ), new KeyValues( "cheating" ) );
  602. m_pComboBox->AddItem( g_pVGuiLocalize->Find( "TF_VoteKickReason_Idle" ), new KeyValues( "idle" ) );
  603. m_pComboBox->AddItem( g_pVGuiLocalize->Find( "TF_VoteKickReason_Scamming" ), new KeyValues( "scamming" ) );
  604. m_pComboBox->SilentActivateItemByRow( 0 );
  605. m_pComboBox->SetVisible( true );
  606. #endif
  607. }
  608. #ifdef TF_CLIENT_DLL
  609. // CHANGE POP FILE
  610. else if ( !V_stricmp( "ChangeMission", pszIssueRaw ) )
  611. {
  612. // Feed the popfiles to the parameters list
  613. for ( int index = 0; index < m_VoteIssuesPopFiles.Count(); index++ )
  614. {
  615. // Don't show the current pop file
  616. const char *pszPopFileName = TFObjectiveResource()->GetMvMPopFileName();
  617. if ( !pszPopFileName || !pszPopFileName[0] )
  618. {
  619. // Use the map name
  620. char szShortMapName[ MAX_MAP_NAME ];
  621. V_strncpy( szShortMapName, engine->GetLevelName(), sizeof( szShortMapName ) );
  622. V_StripExtension( szShortMapName, szShortMapName, sizeof( szShortMapName ) );
  623. if ( V_strncmp( m_VoteIssuesPopFiles[index], V_GetFileName( szShortMapName ), ( V_strlen( m_VoteIssuesPopFiles[index] ) - 1 ) ) == 0 )
  624. continue;
  625. }
  626. else
  627. {
  628. // Use the specified pop file
  629. if ( V_strncmp( m_VoteIssuesPopFiles[index], TFObjectiveResource()->GetMvMPopFileName(), ( V_strlen( m_VoteIssuesPopFiles[index] ) - 1 ) ) == 0 )
  630. continue;
  631. }
  632. KeyValues *pKeyValues = new KeyValues( "Name" );
  633. pKeyValues->SetString( "Name", m_VoteIssuesPopFiles[index] );
  634. pKeyValues->SetInt( "index", index );
  635. int iId = m_pVoteParameterList->AddItem( 0, pKeyValues );
  636. pKeyValues->deleteThis();
  637. if ( m_hIssueFont != INVALID_FONT )
  638. {
  639. m_pVoteParameterList->SetItemFont( iId, m_hIssueFont );
  640. m_pVoteParameterList->SetItemFgColor( iId, m_IssueFGColor );
  641. }
  642. }
  643. if ( m_pVoteParameterList->GetItemCount() == 0 )
  644. {
  645. KeyValues *pKeyValues = new KeyValues( "Name" );
  646. pKeyValues->SetString( "Name", "#TF_vote_no_challenges" );
  647. pKeyValues->SetInt( "index", 1 );
  648. m_pVoteParameterList->AddItem( 0, pKeyValues );
  649. pKeyValues->deleteThis();
  650. }
  651. }
  652. #endif // TF_CLIENT_DLL
  653. else
  654. {
  655. // User selected an issue that doesn't require a parameter - Scrambleteams, Restartgame, etc
  656. m_bVoteButtonEnabled = true;
  657. }
  658. }
  659. }
  660. else if ( panel == m_pVoteParameterList )
  661. {
  662. // If this issue requires a parameter, make sure we have one selected before enabling the CallVote button
  663. int iSelectedParam = m_pVoteParameterList->GetSelectedItem();
  664. if ( iSelectedParam >= 0 )
  665. {
  666. KeyValues *pParameterKeyValues = m_pVoteParameterList->GetItemData( iSelectedParam );
  667. if ( pParameterKeyValues )
  668. {
  669. const char *szParameterName = pParameterKeyValues->GetString( "Name" );
  670. if ( szParameterName )
  671. {
  672. m_bVoteButtonEnabled = true;
  673. }
  674. }
  675. }
  676. }
  677. m_pCallVoteButton->SetEnabled( m_bVoteButtonEnabled );
  678. RefreshIssueParameters();
  679. }
  680. //-----------------------------------------------------------------------------
  681. // Purpose: Updates any additional data/info on Vote issue parameters
  682. //-----------------------------------------------------------------------------
  683. void CVoteSetupDialog::RefreshIssueParameters()
  684. {
  685. // In the case of the KICK issue, we list players and show additional properties (Bot, Disconnected)
  686. int iSelectedItem = m_pVoteSetupList->GetSelectedItem();
  687. if ( iSelectedItem >= 0 )
  688. {
  689. KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem );
  690. const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" );
  691. if ( !V_stricmp( "Kick", pszIssueRaw ) )
  692. {
  693. if ( m_pVoteParameterList->GetItemCount() > 0 )
  694. {
  695. for ( int index = 0; index < m_pVoteParameterList->GetItemCount(); index++ )
  696. {
  697. KeyValues *pKeyValues = m_pVoteParameterList->GetItemData( index );
  698. if ( !pKeyValues )
  699. continue;
  700. int playerIndex = pKeyValues->GetInt( "index" );
  701. player_info_t playerInfo;
  702. if ( !engine->GetPlayerInfo( playerIndex, &playerInfo ) )
  703. {
  704. pKeyValues->SetString( "Properties", "Offline" );
  705. continue;
  706. }
  707. pKeyValues->SetString( "Name", playerInfo.name );
  708. if ( playerInfo.fakeplayer )
  709. {
  710. pKeyValues->SetString( "Properties", "Bot" );
  711. }
  712. else
  713. {
  714. pKeyValues->SetString( "Properties", "" );
  715. }
  716. CSteamID steamID;
  717. C_BasePlayer* pPlayer = UTIL_PlayerByIndex( playerIndex );
  718. if ( pPlayer && pPlayer->GetSteamID( &steamID ) && steamID.GetAccountID() != 0 )
  719. {
  720. CAvatarImage *pAvatar = new CAvatarImage();
  721. pAvatar->SetAvatarSteamID( steamID );
  722. pAvatar->SetAvatarSize( 32, 32 );
  723. int iImageIndex = m_pImageList->AddImage( pAvatar );
  724. pKeyValues->SetInt( "Avatar", iImageIndex );
  725. }
  726. m_pVoteParameterList->InvalidateItem( index );
  727. }
  728. }
  729. }
  730. m_pVoteParameterList->SetImageList( m_pImageList, false );
  731. }
  732. }
  733. //-----------------------------------------------------------------------------
  734. // Purpose:
  735. //-----------------------------------------------------------------------------
  736. void CVoteSetupDialog::ResetData()
  737. {
  738. m_bVoteButtonEnabled = false;
  739. m_pVoteSetupList->RemoveAll();
  740. m_pVoteParameterList->RemoveAll();
  741. m_pComboBox->RemoveAll();
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose:
  745. //-----------------------------------------------------------------------------
  746. DECLARE_HUDELEMENT( CHudVote );
  747. DECLARE_HUD_MESSAGE( CHudVote, CallVoteFailed );
  748. DECLARE_HUD_MESSAGE( CHudVote, VoteStart );
  749. DECLARE_HUD_MESSAGE( CHudVote, VotePass );
  750. DECLARE_HUD_MESSAGE( CHudVote, VoteFailed );
  751. DECLARE_HUD_MESSAGE( CHudVote, VoteSetup );
  752. //-----------------------------------------------------------------------------
  753. // Purpose: Handles all UI for Voting
  754. //-----------------------------------------------------------------------------
  755. CHudVote::CHudVote( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "CHudVote" )
  756. {
  757. vgui::Panel *pParent = g_pClientMode->GetViewport();
  758. SetParent( pParent );
  759. #ifdef TF_CLIENT_DLL
  760. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  761. SetScheme(scheme);
  762. #endif
  763. SetHiddenBits( 0 );
  764. for( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
  765. {
  766. m_nVoteOptionCount[index] = 0;
  767. }
  768. m_pVoteActive = new EditablePanel( this, "VoteActive" );
  769. m_pVoteActiveIssueLabel = new vgui::Label( m_pVoteActive, "Issue", "" );
  770. m_pVoteActiveTargetAvatar = new CAvatarImagePanel( m_pVoteActive, "TargetAvatarImage" );
  771. m_voteBar = new VoteBarPanel( m_pVoteActive, "VoteBar" );
  772. m_pVoteFailed = new EditablePanel( this, "VoteFailed" );
  773. m_pVotePassed = new EditablePanel( this, "VotePassed" );
  774. m_pCallVoteFailed = new EditablePanel( this, "CallVoteFailed" );
  775. m_pVoteSetupDialog = new CVoteSetupDialog( pParent );
  776. RegisterForRenderGroup( "mid" );
  777. }
  778. //-----------------------------------------------------------------------------
  779. // Purpose:
  780. //-----------------------------------------------------------------------------
  781. void CHudVote::ApplySchemeSettings( vgui::IScheme *pScheme )
  782. {
  783. BaseClass::ApplySchemeSettings( pScheme );
  784. SetProportional( true );
  785. LoadControlSettings( "Resource/UI/VoteHud.res" );
  786. m_pVoteActiveIssueLabel->GetPos( m_nVoteActiveIssueLabelX, m_nVoteActiveIssueLabelY );
  787. }
  788. //-----------------------------------------------------------------------------
  789. // Purpose:
  790. //-----------------------------------------------------------------------------
  791. void CHudVote::Init( void )
  792. {
  793. ListenForGameEvent( "vote_changed" );
  794. ListenForGameEvent( "vote_options" );
  795. ListenForGameEvent( "vote_cast" );
  796. m_bVotingActive = false;
  797. m_flVoteResultCycleTime = -1;
  798. m_flHideTime = -1;
  799. m_bIsYesNoVote = true;
  800. m_bPlayerVoted = false;
  801. m_nVoteChoicesCount = 2; // Yes/No is the default
  802. m_bShowVoteActivePanel = false;
  803. m_iVoteCallerIdx = -1;
  804. m_bVoteSystemActive = false;
  805. m_nVoteTeamIndex = 0;
  806. HOOK_HUD_MESSAGE( CHudVote, CallVoteFailed );
  807. HOOK_HUD_MESSAGE( CHudVote, VoteStart );
  808. HOOK_HUD_MESSAGE( CHudVote, VotePass );
  809. HOOK_HUD_MESSAGE( CHudVote, VoteFailed );
  810. HOOK_HUD_MESSAGE( CHudVote, VoteSetup );
  811. }
  812. //-----------------------------------------------------------------------------
  813. // Purpose:
  814. //-----------------------------------------------------------------------------
  815. void CHudVote::LevelInit( void )
  816. {
  817. m_bVotingActive = false;
  818. m_flVoteResultCycleTime = -1;
  819. m_flHideTime = -1;
  820. m_flPostVotedHideTime = -1;
  821. m_bPlayerVoted = false;
  822. m_bShowVoteActivePanel = false;
  823. }
  824. //-----------------------------------------------------------------------------
  825. // Purpose:
  826. //-----------------------------------------------------------------------------
  827. int CHudVote::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  828. {
  829. if ( !IsVisible() )
  830. return 1;
  831. if ( !down )
  832. return 1;
  833. if ( !m_bVotingActive )
  834. return 1;
  835. if ( m_bPlayerVoted )
  836. return 1;
  837. if ( !m_bShowVoteActivePanel )
  838. return 1;
  839. int nSlot = 999;
  840. if ( down && keynum == KEY_F1 )
  841. {
  842. nSlot = 1;
  843. }
  844. else if ( down && keynum == KEY_F2 )
  845. {
  846. nSlot = 2;
  847. }
  848. else if ( down && keynum == KEY_F3 )
  849. {
  850. nSlot = 3;
  851. }
  852. else if ( down && keynum == KEY_F4 )
  853. {
  854. nSlot = 4;
  855. }
  856. else if ( down && keynum == KEY_F5 )
  857. {
  858. nSlot = 5;
  859. }
  860. else
  861. {
  862. return 1;
  863. }
  864. // Limit key checking to the number of options
  865. if ( nSlot > m_nVoteChoicesCount )
  866. return 1;
  867. char szNumber[2];
  868. Q_snprintf( szNumber, sizeof( szNumber ), "%i", nSlot );
  869. char szOptionName[13] = "vote option";
  870. Q_strncat( szOptionName, szNumber, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
  871. engine->ClientCmd( szOptionName );
  872. return 0;
  873. }
  874. //-----------------------------------------------------------------------------
  875. // Purpose: Sent only to the caller
  876. //-----------------------------------------------------------------------------
  877. void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg )
  878. {
  879. if ( IsPlayingDemo() )
  880. return;
  881. vote_create_failed_t nReason = (vote_create_failed_t)msg.ReadByte();
  882. int nTime = msg.ReadShort();
  883. // if we're already drawing a vote, do nothing
  884. if ( ShouldDraw() )
  885. return;
  886. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  887. if ( !pLocalPlayer )
  888. return;
  889. pLocalPlayer->EmitSound("Vote.Failed");
  890. m_pVoteActive->SetVisible( false );
  891. m_pVoteFailed->SetVisible( false );
  892. m_pVotePassed->SetVisible( false );
  893. m_pCallVoteFailed->SetVisible( true );
  894. m_pVoteSetupDialog->SetVisible( false );
  895. m_flHideTime = gpGlobals->curtime + 4.f;
  896. char szTime[k_MAX_VOTE_NAME_LENGTH];
  897. wchar_t wszTime[k_MAX_VOTE_NAME_LENGTH];
  898. bool bMinutes = ( nTime > 65 );
  899. if ( bMinutes )
  900. {
  901. nTime /= 60;
  902. }
  903. Q_snprintf( szTime, sizeof ( szTime), "%i", nTime );
  904. g_pVGuiLocalize->ConvertANSIToUnicode( szTime, wszTime, sizeof( wszTime ) );
  905. wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH];
  906. switch( nReason )
  907. {
  908. case VOTE_FAILED_GENERIC:
  909. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed" );
  910. break;
  911. case VOTE_FAILED_TRANSITIONING_PLAYERS:
  912. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_transition_vote" );
  913. break;
  914. case VOTE_FAILED_RATE_EXCEEDED:
  915. {
  916. const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_vote_spam_min" : "#GameUI_vote_failed_vote_spam_mins" ) : "#GameUI_vote_failed_vote_spam";
  917. g_pVGuiLocalize->ConstructString_safe( wszHeaderString, g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
  918. m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
  919. break;
  920. }
  921. case VOTE_FAILED_ISSUE_DISABLED:
  922. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_disabled_issue" );
  923. break;
  924. case VOTE_FAILED_MAP_NOT_FOUND:
  925. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_map_not_found" );
  926. break;
  927. case VOTE_FAILED_MAP_NOT_VALID:
  928. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_map_not_valid" );
  929. break;
  930. case VOTE_FAILED_MAP_NAME_REQUIRED:
  931. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_map_name_required" );
  932. break;
  933. case VOTE_FAILED_ON_COOLDOWN:
  934. {
  935. const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently";
  936. g_pVGuiLocalize->ConstructString_safe( wszHeaderString, g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
  937. m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
  938. break;
  939. }
  940. case VOTE_FAILED_TEAM_CANT_CALL:
  941. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_team_cant_call" );
  942. break;
  943. case VOTE_FAILED_WAITINGFORPLAYERS:
  944. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_waitingforplayers" );
  945. break;
  946. case VOTE_FAILED_CANNOT_KICK_ADMIN:
  947. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_cannot_kick_admin" );
  948. break;
  949. case VOTE_FAILED_SCRAMBLE_IN_PROGRESS:
  950. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_scramble_in_prog" );
  951. break;
  952. case VOTE_FAILED_SPECTATOR:
  953. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_spectator" );
  954. break;
  955. case VOTE_FAILED_NEXTLEVEL_SET:
  956. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_nextlevel_set" );
  957. break;
  958. case VOTE_FAILED_CANNOT_KICK_FOR_TIME:
  959. {
  960. const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_cannot_kick_min" : "#GameUI_vote_failed_cannot_kick_mins" ) : "#GameUI_vote_failed_cannot_kick";
  961. g_pVGuiLocalize->ConstructString_safe( wszHeaderString, g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime );
  962. m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString );
  963. break;
  964. }
  965. case VOTE_FAILED_CANNOT_KICK_DURING_ROUND:
  966. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_round_active" );
  967. break;
  968. case VOTE_FAILED_MODIFICATION_ALREADY_ACTIVE:
  969. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_event_already_active" );
  970. break;
  971. case VOTE_FAILED_VOTE_IN_PROGRESS:
  972. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_vote_in_progress" );
  973. break;
  974. case VOTE_FAILED_KICK_LIMIT_REACHED:
  975. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_kick_limit" );
  976. break;
  977. case VOTE_FAILED_KICK_DENIED_BY_GC:
  978. m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_kick_limit_gc" );
  979. break;
  980. }
  981. }
  982. //-----------------------------------------------------------------------------
  983. // Purpose: Sent to everyone
  984. //-----------------------------------------------------------------------------
  985. void CHudVote::MsgFunc_VoteFailed( bf_read &msg )
  986. {
  987. if ( IsPlayingDemo() )
  988. return;
  989. m_nVoteTeamIndex = msg.ReadByte();
  990. vote_create_failed_t nReason = (vote_create_failed_t)msg.ReadByte();
  991. // Visibility of this error is handled by OnThink()
  992. m_bVotingActive = false;
  993. m_bVotePassed = false;
  994. m_flVoteResultCycleTime = gpGlobals->curtime + 2.f;
  995. m_flHideTime = gpGlobals->curtime + 5.f;
  996. switch ( nReason )
  997. {
  998. case VOTE_FAILED_GENERIC:
  999. m_pVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed" );
  1000. break;
  1001. case VOTE_FAILED_YES_MUST_EXCEED_NO:
  1002. m_pVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_yesno" );
  1003. break;
  1004. case VOTE_FAILED_QUORUM_FAILURE:
  1005. m_pVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_quorum" );
  1006. break;
  1007. }
  1008. IGameEvent *event = gameeventmanager->CreateEvent( "vote_failed" );
  1009. if ( event )
  1010. {
  1011. event->SetInt( "team", m_nVoteTeamIndex );
  1012. gameeventmanager->FireEventClientSide( event );
  1013. }
  1014. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1015. if ( !pLocalPlayer )
  1016. return;
  1017. bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex );
  1018. if ( bShowToPlayer )
  1019. {
  1020. pLocalPlayer->EmitSound("Vote.Failed");
  1021. }
  1022. }
  1023. //-----------------------------------------------------------------------------
  1024. // Purpose:
  1025. //-----------------------------------------------------------------------------
  1026. void CHudVote::MsgFunc_VoteStart( bf_read &msg )
  1027. {
  1028. if ( IsPlayingDemo() )
  1029. return;
  1030. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1031. if ( !pLocalPlayer )
  1032. return;
  1033. // Is this a team-only vote?
  1034. m_nVoteTeamIndex = msg.ReadByte();
  1035. if ( m_nVoteTeamIndex >= FIRST_GAME_TEAM && m_nVoteTeamIndex != pLocalPlayer->GetTeamNumber() )
  1036. return;
  1037. // Entity calling the vote
  1038. bool bShowNotif = cl_vote_ui_show_notification.GetBool();
  1039. const char *pszCallerName = "Server";
  1040. m_iVoteCallerIdx = msg.ReadByte();
  1041. if ( m_iVoteCallerIdx != DEDICATED_SERVER )
  1042. {
  1043. C_BasePlayer *pVoteCaller = UTIL_PlayerByIndex( m_iVoteCallerIdx );
  1044. if ( pVoteCaller )
  1045. {
  1046. pszCallerName = pVoteCaller->GetPlayerName();
  1047. // Don't show a notification to the caller
  1048. if ( pVoteCaller == pLocalPlayer )
  1049. {
  1050. bShowNotif = false;
  1051. }
  1052. }
  1053. else
  1054. {
  1055. // Caller invalid for some reason
  1056. pszCallerName = "Player";
  1057. }
  1058. }
  1059. // DisplayString
  1060. char szIssue[k_MAX_VOTE_NAME_LENGTH] = { 0 };
  1061. msg.ReadString( szIssue, sizeof(szIssue) );
  1062. // DetailString
  1063. char szParam1[k_MAX_VOTE_NAME_LENGTH] = { 0 };
  1064. msg.ReadString( szParam1, sizeof(szParam1) );
  1065. m_bIsYesNoVote = msg.ReadByte();
  1066. int iTargetEntIndex = msg.ReadByte();
  1067. m_flVoteResultCycleTime = -1.f;
  1068. m_bVotingActive = true;
  1069. m_pVoteFailed->SetVisible( false );
  1070. m_pVotePassed->SetVisible( false );
  1071. m_pCallVoteFailed->SetVisible( false );
  1072. m_pVoteSetupDialog->SetVisible( false );
  1073. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" );
  1074. m_voteBar->SetVisible( m_bIsYesNoVote );
  1075. // There will always be at least two choices...
  1076. m_pVoteActive->SetControlVisible( "LabelOption1", true );
  1077. m_pVoteActive->SetControlVisible( "LabelOption2", true );
  1078. // ...sometimes more
  1079. m_pVoteActive->SetControlVisible( "LabelOption3", m_VoteSetupChoices.Count() > 2 ? true : false );
  1080. m_pVoteActive->SetControlVisible( "Option3Background_Selected", m_VoteSetupChoices.Count() > 2 ? true : false );
  1081. m_pVoteActive->SetControlVisible( "LabelOption4", m_VoteSetupChoices.Count() > 3 ? true : false );
  1082. m_pVoteActive->SetControlVisible( "Option4Background_Selected", m_VoteSetupChoices.Count() > 3 ? true : false );
  1083. m_pVoteActive->SetControlVisible( "LabelOption5", m_VoteSetupChoices.Count() > 4 ? true : false );
  1084. m_pVoteActive->SetControlVisible( "Option5Background_Selected", m_VoteSetupChoices.Count() > 4 ? true : false );
  1085. m_pVoteActive->SetControlVisible( "VoteCountLabel", m_bIsYesNoVote );
  1086. m_pVoteActive->SetControlVisible( "Option1CountLabel", m_bIsYesNoVote );
  1087. m_pVoteActive->SetControlVisible( "Option2CountLabel", m_bIsYesNoVote );
  1088. m_pVoteActive->SetControlVisible( "Divider1", m_bIsYesNoVote );
  1089. m_pVoteActive->SetControlVisible( "Divider2", m_bIsYesNoVote );
  1090. // Display vote caller's name
  1091. wchar_t wszCallerName[MAX_PLAYER_NAME_LENGTH];
  1092. wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH];
  1093. // Player
  1094. g_pVGuiLocalize->ConvertANSIToUnicode( pszCallerName, wszCallerName, sizeof( wszCallerName ) );
  1095. // String
  1096. g_pVGuiLocalize->ConstructString_safe( wszHeaderString, g_pVGuiLocalize->Find( "#GameUI_vote_header" ), 1, wszCallerName );
  1097. // Final
  1098. m_pVoteActive->SetDialogVariable( "header", wszHeaderString );
  1099. // Display the Issue
  1100. wchar_t *pwcParam;
  1101. wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH];
  1102. wchar_t *pwcIssue;
  1103. wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH];
  1104. if ( Q_strlen( szParam1 ) > 0 )
  1105. {
  1106. if ( szParam1[0] == '#' )
  1107. {
  1108. // localize it
  1109. pwcParam = g_pVGuiLocalize->Find( szParam1 );
  1110. }
  1111. else
  1112. {
  1113. // convert to wchar
  1114. g_pVGuiLocalize->ConvertANSIToUnicode( szParam1, wcParam, sizeof( wcParam ) );
  1115. pwcParam = wcParam;
  1116. }
  1117. g_pVGuiLocalize->ConstructString_safe( wcIssue, g_pVGuiLocalize->Find( szIssue ), 1, pwcParam );
  1118. pwcIssue = wcIssue;
  1119. }
  1120. else
  1121. {
  1122. // no param, just localize the issue
  1123. pwcIssue = g_pVGuiLocalize->Find( szIssue );
  1124. }
  1125. m_pVoteActive->SetDialogVariable( "voteissue", pwcIssue );
  1126. // Figure out which UI
  1127. if ( m_bIsYesNoVote )
  1128. {
  1129. // YES / NO UI
  1130. wchar_t wzFinal[k_MAX_VOTE_NAME_LENGTH] = L"";
  1131. wchar_t *pszText = g_pVGuiLocalize->Find( ::input->IsSteamControllerActive() ? "#GameUI_vote_yes_sc_instruction" : "#GameUI_vote_yes_pc_instruction" );
  1132. if ( pszText )
  1133. {
  1134. UTIL_ReplaceKeyBindings( pszText, 0, wzFinal, sizeof( wzFinal ), GAME_ACTION_SET_FPSCONTROLS );
  1135. if ( m_pVoteActive )
  1136. m_pVoteActive->SetControlString( "LabelOption1", wzFinal );
  1137. }
  1138. pszText = g_pVGuiLocalize->Find( ::input->IsSteamControllerActive() ? "#GameUI_vote_no_sc_instruction" : "#GameUI_vote_no_pc_instruction" );
  1139. if ( pszText )
  1140. {
  1141. UTIL_ReplaceKeyBindings( pszText, 0, wzFinal, sizeof( wzFinal ), GAME_ACTION_SET_FPSCONTROLS );
  1142. if ( m_pVoteActive )
  1143. m_pVoteActive->SetControlString( "LabelOption2", wzFinal );
  1144. }
  1145. }
  1146. else
  1147. {
  1148. // GENERAL UI
  1149. if ( m_VoteSetupChoices.Count() )
  1150. {
  1151. // Clear the labels to prevent previous options from being displayed,
  1152. // such as when there are fewer options this vote than the previous
  1153. for ( int iIndex = 0; iIndex < MAX_VOTE_OPTIONS; iIndex++ )
  1154. {
  1155. // Construct Label name
  1156. char szOptionNum[2];
  1157. Q_snprintf( szOptionNum, sizeof( szOptionNum ), "%i", iIndex + 1 );
  1158. char szVoteOptionCount[13] = "LabelOption";
  1159. Q_strncat( szVoteOptionCount, szOptionNum, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  1160. m_pVoteActive->SetControlString( szVoteOptionCount, "" );
  1161. }
  1162. // Set us up the vote
  1163. for ( int iIndex = 0; iIndex < m_nVoteChoicesCount; iIndex++ )
  1164. {
  1165. // Construct Option name
  1166. const char *pszChoiceName = m_VoteSetupChoices[iIndex];
  1167. char szOptionName[k_MAX_VOTE_NAME_LENGTH];
  1168. Q_snprintf( szOptionName, sizeof( szOptionName ), "F%i. ", iIndex + 1 );
  1169. Q_strncat( szOptionName, pszChoiceName, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
  1170. // Construct Label name
  1171. char szOptionNum[2];
  1172. Q_snprintf( szOptionNum, sizeof( szOptionNum ), "%i", iIndex + 1 );
  1173. char szVoteOptionCount[13] = "LabelOption";
  1174. Q_strncat( szVoteOptionCount, szOptionNum, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  1175. // Set Label string
  1176. if ( m_pVoteActive )
  1177. {
  1178. m_pVoteActive->SetControlString( szVoteOptionCount, szOptionName );
  1179. }
  1180. }
  1181. }
  1182. }
  1183. // Is the target a player?
  1184. int nTargetLabelX = m_nVoteActiveIssueLabelX;
  1185. C_BasePlayer *pTargetPlayer = NULL;
  1186. if ( iTargetEntIndex )
  1187. {
  1188. pTargetPlayer = UTIL_PlayerByIndex( iTargetEntIndex );
  1189. if ( pTargetPlayer )
  1190. {
  1191. m_pVoteActiveTargetAvatar->SetPlayer( pTargetPlayer );
  1192. m_pVoteActiveTargetAvatar->SetShouldDrawFriendIcon( false );
  1193. nTargetLabelX += ( m_pVoteActiveTargetAvatar->GetWide() + XRES( 3 ) );
  1194. }
  1195. }
  1196. m_pVoteActiveIssueLabel->SetPos( nTargetLabelX, m_nVoteActiveIssueLabelY );
  1197. m_pVoteActiveTargetAvatar->SetVisible( pTargetPlayer ? true : false );
  1198. IGameEvent *event = gameeventmanager->CreateEvent( "vote_started" );
  1199. if ( event )
  1200. {
  1201. event->SetString( "issue", szIssue );
  1202. event->SetString( "param1", szParam1 );
  1203. event->SetInt( "team", m_nVoteTeamIndex );
  1204. event->SetInt( "initiator", m_iVoteCallerIdx );
  1205. gameeventmanager->FireEventClientSide( event );
  1206. }
  1207. #ifdef TF_CLIENT_DLL
  1208. if ( bShowNotif )
  1209. {
  1210. NotificationQueue_Add( new CTFVoteNotification( pszCallerName ) );
  1211. }
  1212. else
  1213. {
  1214. m_bShowVoteActivePanel = true;
  1215. }
  1216. #else
  1217. m_bShowVoteActivePanel = true;
  1218. #endif // TF_CLIENT_DLL
  1219. }
  1220. //-----------------------------------------------------------------------------
  1221. // Purpose:
  1222. //-----------------------------------------------------------------------------
  1223. void CHudVote::MsgFunc_VotePass( bf_read &msg )
  1224. {
  1225. if ( IsPlayingDemo() )
  1226. return;
  1227. m_nVoteTeamIndex = msg.ReadByte();
  1228. // Passed string
  1229. char szResult[k_MAX_VOTE_NAME_LENGTH];
  1230. szResult[0] = 0;
  1231. msg.ReadString( szResult, sizeof(szResult) );
  1232. // Detail string
  1233. char szParam1[k_MAX_VOTE_NAME_LENGTH];
  1234. szParam1[0] = 0;
  1235. msg.ReadString( szParam1, sizeof(szParam1) );
  1236. // Localize
  1237. wchar_t *pwcParam;
  1238. wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH];
  1239. wchar_t *pwcIssue;
  1240. wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH];
  1241. if ( Q_strlen( szParam1 ) > 0 )
  1242. {
  1243. if ( szParam1[0] == '#' )
  1244. {
  1245. pwcParam = g_pVGuiLocalize->Find( szParam1 );
  1246. }
  1247. else
  1248. {
  1249. // Convert to wchar
  1250. g_pVGuiLocalize->ConvertANSIToUnicode( szParam1, wcParam, sizeof( wcParam ) );
  1251. pwcParam = wcParam;
  1252. }
  1253. g_pVGuiLocalize->ConstructString_safe( wcIssue, g_pVGuiLocalize->Find( szResult ), 1, pwcParam );
  1254. pwcIssue = wcIssue;
  1255. }
  1256. else
  1257. {
  1258. // No param, just localize the result
  1259. pwcIssue = g_pVGuiLocalize->Find( szResult );
  1260. }
  1261. m_pVotePassed->SetDialogVariable( "passedresult", pwcIssue );
  1262. m_bVotingActive = false;
  1263. m_bVotePassed = true;
  1264. m_flVoteResultCycleTime = gpGlobals->curtime + 2.f;
  1265. m_flHideTime = gpGlobals->curtime + 5.f;
  1266. // driller: this event has no listeners - will eventually hook into stats
  1267. IGameEvent *event = gameeventmanager->CreateEvent( "vote_passed" );
  1268. if ( event )
  1269. {
  1270. event->SetString( "details", szResult );
  1271. event->SetString( "param1", szParam1 );
  1272. event->SetInt( "team", m_nVoteTeamIndex );
  1273. gameeventmanager->FireEventClientSide( event );
  1274. }
  1275. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1276. if ( !pLocalPlayer )
  1277. return;
  1278. pLocalPlayer->EmitSound( "Vote.Passed" );
  1279. }
  1280. //-----------------------------------------------------------------------------
  1281. // Purpose: Creates a UI for Vote Issue selection
  1282. //-----------------------------------------------------------------------------
  1283. void CHudVote::MsgFunc_VoteSetup( bf_read &msg )
  1284. {
  1285. if ( IsPlayingDemo() )
  1286. return;
  1287. m_pVoteActive->SetVisible( false );
  1288. m_pVoteFailed->SetVisible( false );
  1289. m_pVotePassed->SetVisible( false );
  1290. m_pCallVoteFailed->SetVisible( false );
  1291. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1292. if ( !pLocalPlayer )
  1293. return;
  1294. // Load up the list of Vote Issues
  1295. m_VoteSetupIssues.RemoveAll();
  1296. int nIssueCount = msg.ReadByte();
  1297. if ( nIssueCount )
  1298. {
  1299. for ( int i = 0; i < nIssueCount; i++ )
  1300. {
  1301. char szIssue[k_MAX_VOTE_NAME_LENGTH];
  1302. char szIssueString[k_MAX_VOTE_NAME_LENGTH];
  1303. msg.ReadString( szIssue, sizeof( szIssue ) );
  1304. msg.ReadString( szIssueString, sizeof( szIssueString ) );
  1305. bool bIsActive = (bool)msg.ReadByte();
  1306. m_bVoteSystemActive |= bIsActive;
  1307. bool bAdd = true;
  1308. FOR_EACH_VEC( m_VoteSetupIssues, j )
  1309. {
  1310. if ( !V_strcmp( szIssue, m_VoteSetupIssues[j].szName ) )
  1311. {
  1312. bAdd = false;
  1313. break;
  1314. }
  1315. }
  1316. if ( bAdd )
  1317. {
  1318. // When empty, assume that we just pre-pend #Vote_ to szIssue (reduces msg size)
  1319. if ( !szIssueString[0] )
  1320. {
  1321. V_sprintf_safe( szIssueString, "#Vote_%s", szIssue );
  1322. }
  1323. VoteIssue_t issue;
  1324. V_strcpy_safe( issue.szName, szIssue );
  1325. V_strcpy_safe( issue.szNameString, szIssueString );
  1326. issue.bIsActive = bIsActive;
  1327. // Send it over to the listpanel
  1328. m_VoteSetupIssues.AddToTail( issue );
  1329. }
  1330. }
  1331. }
  1332. m_pVoteSetupDialog->AddVoteIssues( m_VoteSetupIssues );
  1333. // Load up the list of Vote Issue Parameters
  1334. m_VoteSetupMapCycle.RemoveAll();
  1335. // Use the appropriate stringtable for maps based on gamemode
  1336. bool bMvM = false;
  1337. INetworkStringTable *pStringTable = g_pStringTableServerMapCycle;
  1338. #ifdef TF_CLIENT_DLL
  1339. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  1340. {
  1341. bMvM = true;
  1342. pStringTable = g_pStringTableServerMapCycleMvM;
  1343. }
  1344. #endif // TF_CLIENT_DLL
  1345. if ( pStringTable )
  1346. {
  1347. int index = bMvM ? pStringTable->FindStringIndex( "ServerMapCycleMvM" ) : pStringTable->FindStringIndex( "ServerMapCycle" );
  1348. if ( index != ::INVALID_STRING_INDEX )
  1349. {
  1350. int nLength = 0;
  1351. const char *pszMapCycle = (const char *)pStringTable->GetStringUserData( index, &nLength );
  1352. if ( pszMapCycle && pszMapCycle[0] )
  1353. {
  1354. if ( pszMapCycle && nLength )
  1355. {
  1356. V_SplitString( pszMapCycle, "\n", m_VoteSetupMapCycle );
  1357. }
  1358. // Alphabetize
  1359. if ( m_VoteSetupMapCycle.Count() )
  1360. {
  1361. m_VoteSetupMapCycle.Sort( m_VoteSetupMapCycle.SortFunc );
  1362. }
  1363. }
  1364. }
  1365. }
  1366. #ifdef TF_CLIENT_DLL
  1367. m_VoteSetupPopFiles.RemoveAll();
  1368. if ( g_pStringTableServerPopFiles )
  1369. {
  1370. int index = g_pStringTableServerPopFiles->FindStringIndex( "ServerPopFiles" );
  1371. if ( index != ::INVALID_STRING_INDEX )
  1372. {
  1373. int nLength = 0;
  1374. const char *pszPopFiles = (const char *)g_pStringTableServerPopFiles->GetStringUserData( index, &nLength );
  1375. if ( pszPopFiles && pszPopFiles[0] )
  1376. {
  1377. if ( pszPopFiles && nLength )
  1378. {
  1379. V_SplitString( pszPopFiles, "\n", m_VoteSetupPopFiles );
  1380. }
  1381. // Alphabetize
  1382. if ( m_VoteSetupPopFiles.Count() )
  1383. {
  1384. m_VoteSetupPopFiles.Sort( m_VoteSetupPopFiles.SortFunc );
  1385. }
  1386. }
  1387. }
  1388. }
  1389. #endif // TF_CLIENT_DLL
  1390. // Now send any data we gathered over to the listpanel
  1391. PropagateOptionParameters();
  1392. m_pVoteSetupDialog->Activate();
  1393. m_pVoteSetupDialog->SetVisible( true );
  1394. }
  1395. //-----------------------------------------------------------------------------
  1396. // Purpose: Propagate vote option parameters to the Issue Parameters list
  1397. //-----------------------------------------------------------------------------
  1398. void CHudVote::PropagateOptionParameters( void )
  1399. {
  1400. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1401. if ( !pLocalPlayer )
  1402. return;
  1403. m_pVoteSetupDialog->AddVoteIssueParams_MapCycle( m_VoteSetupMapCycle );
  1404. #ifdef TF_CLIENT_DLL
  1405. m_pVoteSetupDialog->AddVoteIssueParams_PopFiles( m_VoteSetupPopFiles );
  1406. #endif // TF_CLIENT_DLL
  1407. // Insert future issue param data containers here
  1408. }
  1409. //-----------------------------------------------------------------------------
  1410. // Purpose:
  1411. //-----------------------------------------------------------------------------
  1412. void CHudVote::FireGameEvent( IGameEvent *event )
  1413. {
  1414. const char *eventName = event->GetName();
  1415. if ( !eventName )
  1416. return;
  1417. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1418. if ( !pLocalPlayer )
  1419. return;
  1420. if( FStrEq( eventName, "vote_changed" ) )
  1421. {
  1422. for ( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
  1423. {
  1424. char szOption[2];
  1425. Q_snprintf( szOption, sizeof( szOption ), "%i", index + 1 );
  1426. char szVoteOptionCount[13] = "vote_option";
  1427. Q_strncat( szVoteOptionCount, szOption, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  1428. m_nVoteOptionCount[index] = event->GetInt( szVoteOptionCount );
  1429. }
  1430. m_nPotentialVotes = event->GetInt( "potentialVotes" );
  1431. }
  1432. else if ( FStrEq( eventName, "vote_options" ) )
  1433. {
  1434. m_VoteSetupChoices.RemoveAll();
  1435. m_nVoteChoicesCount = event->GetInt( "count" );
  1436. for ( int iIndex = 0; iIndex < m_nVoteChoicesCount; iIndex++ )
  1437. {
  1438. char szNumber[2];
  1439. Q_snprintf( szNumber, sizeof( szNumber ), "%i", iIndex + 1 );
  1440. char szOptionName[8] = "option";
  1441. Q_strncat( szOptionName, szNumber, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
  1442. const char *pszOptionName = event->GetString( szOptionName );
  1443. m_VoteSetupChoices.CopyAndAddToTail( pszOptionName );
  1444. }
  1445. }
  1446. else if ( FStrEq( eventName, "vote_cast" ) )
  1447. {
  1448. int iPlayer = event->GetInt( "entityid" );
  1449. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayer );
  1450. if ( pPlayer != pLocalPlayer )
  1451. return;
  1452. int vote_option = event->GetInt( "vote_option", TEAM_UNASSIGNED );
  1453. if( vote_option == VOTE_OPTION1 )
  1454. {
  1455. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption1" );
  1456. }
  1457. else if( vote_option == VOTE_OPTION2 )
  1458. {
  1459. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption2" );
  1460. }
  1461. else if( vote_option == VOTE_OPTION3 )
  1462. {
  1463. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption3" );
  1464. }
  1465. else if( vote_option == VOTE_OPTION4 )
  1466. {
  1467. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption4" );
  1468. }
  1469. else if( vote_option == VOTE_OPTION5 )
  1470. {
  1471. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption5" );
  1472. }
  1473. m_bPlayerVoted = true;
  1474. bool bForceActive = false;
  1475. #ifdef TF_CLIENT_DLL
  1476. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  1477. {
  1478. if ( m_iVoteCallerIdx == GetLocalPlayerIndex() )
  1479. {
  1480. bForceActive = true;
  1481. }
  1482. }
  1483. #endif // TF_CLIENT_DLL
  1484. if ( !cl_vote_ui_active_after_voting.GetBool() && !bForceActive )
  1485. {
  1486. m_flPostVotedHideTime = gpGlobals->curtime + 1.5f;
  1487. }
  1488. }
  1489. }
  1490. //-----------------------------------------------------------------------------
  1491. // Purpose:
  1492. //-----------------------------------------------------------------------------
  1493. void CHudVote::OnThink()
  1494. {
  1495. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  1496. if ( pLocalPlayer )
  1497. {
  1498. bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex );
  1499. // We delay hiding the menu after we cast a vote
  1500. if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && gpGlobals->curtime > m_flPostVotedHideTime )
  1501. {
  1502. m_pVoteActive->SetVisible( false );
  1503. m_bShowVoteActivePanel = false;
  1504. m_flPostVotedHideTime = -1;
  1505. }
  1506. if ( m_flVoteResultCycleTime > 0 && gpGlobals->curtime > m_flVoteResultCycleTime )
  1507. {
  1508. m_pVoteActive->SetVisible( false );
  1509. m_pVoteFailed->SetVisible( !m_bVotePassed && bShowToPlayer );
  1510. m_pVotePassed->SetVisible( m_bVotePassed && bShowToPlayer );
  1511. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" );
  1512. m_flVoteResultCycleTime = -1;
  1513. m_bPlayerVoted = false;
  1514. m_bVotingActive = false;
  1515. m_bShowVoteActivePanel = false;
  1516. m_iVoteCallerIdx = -1;
  1517. }
  1518. if ( m_bVotingActive && m_bShowVoteActivePanel )
  1519. {
  1520. // driller: Need to rewrite this to handle all vote types (Yes/No and General)
  1521. if ( m_bIsYesNoVote && m_pVoteActive )
  1522. {
  1523. char szYesCount[k_MAX_VOTE_NAME_LENGTH] = "";
  1524. Q_snprintf( szYesCount, sizeof( szYesCount ), "%d", m_nVoteOptionCount[0] );
  1525. char szNoCount[k_MAX_VOTE_NAME_LENGTH] = "";
  1526. Q_snprintf( szNoCount, sizeof( szNoCount ), "%d", m_nVoteOptionCount[1] );
  1527. m_pVoteActive->SetControlString( "Option1CountLabel", szYesCount );
  1528. m_pVoteActive->SetControlString( "Option2CountLabel", szNoCount );
  1529. }
  1530. if ( !m_pVoteActive->IsVisible() && bShowToPlayer )
  1531. {
  1532. m_pVoteActive->SetVisible( true );
  1533. pLocalPlayer->EmitSound("Vote.Created");
  1534. }
  1535. }
  1536. }
  1537. BaseClass::OnThink();
  1538. }
  1539. //-----------------------------------------------------------------------------
  1540. // Purpose:
  1541. //-----------------------------------------------------------------------------
  1542. bool CHudVote::ShouldDraw( void )
  1543. {
  1544. return ( m_bVotingActive || gpGlobals->curtime < m_flHideTime );
  1545. }
  1546. //-----------------------------------------------------------------------------
  1547. // Purpose:
  1548. //-----------------------------------------------------------------------------
  1549. bool CHudVote::IsPlayingDemo() const
  1550. {
  1551. return engine->IsPlayingDemo();
  1552. }
  1553. //-----------------------------------------------------------------------------
  1554. // Purpose:
  1555. //-----------------------------------------------------------------------------
  1556. bool CHudVote::IsVoteUIActive( void )
  1557. {
  1558. return m_bShowVoteActivePanel;
  1559. }
  1560. bool CHudVote::IsShowingVoteSetupDialog()
  1561. {
  1562. return m_pVoteSetupDialog && m_pVoteSetupDialog->IsEnabled() && m_pVoteSetupDialog->IsVisible();
  1563. }
  1564. bool CHudVote::IsShowingVotingUI()
  1565. {
  1566. return m_pVoteActive && m_pVoteActive->IsEnabled() && m_pVoteActive->IsVisible();
  1567. }