Counter Strike : Global Offensive Source Code
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.

1206 lines
33 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #if defined( INCLUDE_SCALEFORM )
  9. #include "sfhudvotepanel.h"
  10. #include "hud_macros.h"
  11. #include "sfhudcallvotepanel.h"
  12. #include "sfhudfreezepanel.h"
  13. #include "vgui/ILocalize.h"
  14. #include "c_cs_playerresource.h"
  15. #include "cs_hud_chat.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. #define SAFECALL( handle, func ) \
  19. if ( handle ) \
  20. { \
  21. func \
  22. }
  23. ConVar cl_vote_ui_active_after_voting( "cl_vote_ui_active_after_voting", "1" );
  24. ConVar cl_vote_ui_show_notification( "cl_vote_ui_show_notification", "0" );
  25. DECLARE_HUDELEMENT( SFHudVotePanel );
  26. DECLARE_HUD_MESSAGE( SFHudVotePanel, CallVoteFailed );
  27. DECLARE_HUD_MESSAGE( SFHudVotePanel, VoteStart );
  28. DECLARE_HUD_MESSAGE( SFHudVotePanel, VotePass );
  29. DECLARE_HUD_MESSAGE( SFHudVotePanel, VoteFailed );
  30. DECLARE_HUD_MESSAGE( SFHudVotePanel, VoteSetup );
  31. SFUI_BEGIN_GAME_API_DEF
  32. //SFUI_DECL_METHOD( TimerCallback ),
  33. SFUI_DECL_METHOD( VoteYes ),
  34. SFUI_DECL_METHOD( VoteNo ),
  35. SFUI_END_GAME_API_DEF( SFHudVotePanel, VotePanel );
  36. //-----------------------------------------------------------------------------
  37. // Purpose: Constructor
  38. //-----------------------------------------------------------------------------
  39. SFHudVotePanel::SFHudVotePanel( const char *value ) : SFHudFlashInterface( value )
  40. {
  41. SetHiddenBits( HIDEHUD_MISCSTATUS );
  42. m_hVoteButtonBG = NULL;
  43. m_hVoteLocalCast = NULL;
  44. m_option1Text = NULL;
  45. m_option2Text = NULL;
  46. m_option1CountText = NULL;
  47. m_option2CountText = NULL;
  48. m_bVisible = false;
  49. m_bHasFocus = false;
  50. m_nVoteYes = 0;
  51. m_nVoteNo = 0;
  52. m_flPostVotedHideTime = -1;
  53. }
  54. void SFHudVotePanel::ProcessInput( void )
  55. {
  56. OnThink();
  57. }
  58. void SFHudVotePanel::LevelInit( void )
  59. {
  60. if ( !FlashAPIIsValid() )
  61. {
  62. SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudVotePanel, this, VotePanel );
  63. }
  64. }
  65. void SFHudVotePanel::LevelShutdown( void )
  66. {
  67. if ( FlashAPIIsValid() )
  68. {
  69. RemoveFlashElement();
  70. }
  71. }
  72. void SFHudVotePanel::FlashReady( void )
  73. {
  74. if ( !m_FlashAPI )
  75. {
  76. return;
  77. }
  78. SFVALUE root = g_pScaleformUI->Value_GetMember( m_FlashAPI, "VotePanel" );
  79. if ( !root )
  80. {
  81. return;
  82. }
  83. SFVALUE inner = g_pScaleformUI->Value_GetMember( root, "VotePanelInner" );
  84. if ( !inner )
  85. {
  86. SafeReleaseSFVALUE( root );
  87. return;
  88. }
  89. m_hVoteButtonBG = g_pScaleformUI->Value_GetMember( inner, "VoteButtonBG" );
  90. m_hVoteLocalCast = g_pScaleformUI->TextObject_MakeTextObjectFromMember( inner, "VoteConfirm" );
  91. m_option1Text = g_pScaleformUI->TextObject_MakeTextObjectFromMember( inner, "Vote1" );
  92. m_option2Text = g_pScaleformUI->TextObject_MakeTextObjectFromMember( inner, "Vote2" );
  93. m_option1CountText = g_pScaleformUI->TextObject_MakeTextObjectFromMember( inner, "Vote1Count" );
  94. m_option2CountText = g_pScaleformUI->TextObject_MakeTextObjectFromMember( inner, "Vote2Count" );
  95. SafeReleaseSFVALUE( root );
  96. SafeReleaseSFVALUE( inner );
  97. // listen for events
  98. ListenForGameEvent( "vote_changed" );
  99. ListenForGameEvent( "vote_options" );
  100. ListenForGameEvent( "vote_cast" );
  101. SetVoteActive( false );
  102. m_flVoteResultCycleTime = -1;
  103. m_flHideTime = -1;
  104. m_bIsYesNoVote = true;
  105. m_bPlayerVoted = false;
  106. m_bPlayerLocalVote = VOTE_UNCAST;
  107. m_nVoteChoicesCount = 2; // Yes/No is the default
  108. m_nVoteYes = 0;
  109. m_nVoteNo = 0;
  110. HOOK_HUD_MESSAGE( SFHudVotePanel, CallVoteFailed );
  111. HOOK_HUD_MESSAGE( SFHudVotePanel, VoteStart );
  112. HOOK_HUD_MESSAGE( SFHudVotePanel, VotePass );
  113. HOOK_HUD_MESSAGE( SFHudVotePanel, VoteFailed );
  114. HOOK_HUD_MESSAGE( SFHudVotePanel, VoteSetup );
  115. }
  116. bool SFHudVotePanel::PreUnloadFlash( void )
  117. {
  118. SafeReleaseSFVALUE( m_hVoteButtonBG );
  119. SafeReleaseSFTextObject( m_hVoteLocalCast );
  120. SafeReleaseSFTextObject( m_option1Text );
  121. SafeReleaseSFTextObject( m_option2Text );
  122. SafeReleaseSFTextObject( m_option1CountText );
  123. SafeReleaseSFTextObject( m_option2CountText );
  124. return true;
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Purpose:
  128. //-----------------------------------------------------------------------------
  129. void SFHudVotePanel::FireGameEvent( IGameEvent *event )
  130. {
  131. const char *eventName = event->GetName();
  132. if ( !eventName )
  133. return;
  134. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  135. if ( !pLocalPlayer )
  136. return;
  137. if( FStrEq( eventName, "vote_changed" ) )
  138. {
  139. for ( int index = 0; index < MAX_VOTE_OPTIONS; index++ )
  140. {
  141. char szOption[2];
  142. Q_snprintf( szOption, sizeof( szOption ), "%i", index + 1 );
  143. char szVoteOptionCount[13] = "vote_option";
  144. Q_strncat( szVoteOptionCount, szOption, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  145. m_nVoteOptionCount[index] = event->GetInt( szVoteOptionCount );
  146. }
  147. m_nPotentialVotes = event->GetInt( "potentialVotes" );
  148. }
  149. else if ( FStrEq( eventName, "vote_options" ) )
  150. {
  151. m_VoteSetupChoices.RemoveAll();
  152. m_nVoteChoicesCount = event->GetInt( "count" );
  153. for ( int iIndex = 0; iIndex < m_nVoteChoicesCount; iIndex++ )
  154. {
  155. char szNumber[2];
  156. Q_snprintf( szNumber, sizeof( szNumber ), "%i", iIndex + 1 );
  157. char szOptionName[8] = "option";
  158. Q_strncat( szOptionName, szNumber, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
  159. const char *pszOptionName = event->GetString( szOptionName );
  160. m_VoteSetupChoices.CopyAndAddToTail( pszOptionName );
  161. }
  162. }
  163. else if ( FStrEq( eventName, "vote_cast" ) )
  164. {
  165. int iPlayer = event->GetInt( "entityid" );
  166. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayer );
  167. if ( pPlayer != pLocalPlayer )
  168. return;
  169. int vote_option = event->GetInt( "vote_option", TEAM_UNASSIGNED );
  170. if( vote_option == VOTE_OPTION1 )
  171. {
  172. WITH_SLOT_LOCKED
  173. {
  174. if ( m_pScaleformUI )
  175. {
  176. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "flashYesVote", NULL, 0 );
  177. }
  178. }
  179. //ThumbBg1
  180. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption1" );
  181. }
  182. else if( vote_option == VOTE_OPTION2 )
  183. {
  184. WITH_SLOT_LOCKED
  185. {
  186. if ( m_pScaleformUI )
  187. {
  188. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "flashNoVote", NULL, 0 );
  189. }
  190. }
  191. //ThumbBg2
  192. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption2" );
  193. }
  194. else if( vote_option == VOTE_OPTION3 )
  195. {
  196. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption3" );
  197. }
  198. else if( vote_option == VOTE_OPTION4 )
  199. {
  200. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption4" );
  201. }
  202. else if( vote_option == VOTE_OPTION5 )
  203. {
  204. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "PulseOption5" );
  205. }
  206. m_bPlayerVoted = true;
  207. m_bPlayerLocalVote = vote_option;
  208. if ( !cl_vote_ui_active_after_voting.GetBool() )
  209. {
  210. m_flPostVotedHideTime = gpGlobals->curtime + 1.5f;
  211. }
  212. }
  213. }
  214. void SFHudVotePanel::Hide( void )
  215. {
  216. WITH_SLOT_LOCKED
  217. {
  218. if ( m_pScaleformUI )
  219. {
  220. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hide", NULL, 0 );
  221. }
  222. }
  223. m_bHasFocus = false;
  224. }
  225. bool SFHudVotePanel::ShouldDraw( void )
  226. {
  227. if ( IsTakingAFreezecamScreenshot() || (CSGameRules() && CSGameRules()->IsPlayingTraining()) )
  228. return false;
  229. return cl_drawhud.GetBool() && CHudElement::ShouldDraw();
  230. }
  231. // void SFHudVotePanel::TimerCallback( SCALEFORM_CALLBACK_ARGS_DECL )
  232. // {
  233. // OnThink();
  234. // }
  235. //-----------------------------------------------------------------------------
  236. // Purpose: Sent only to the caller
  237. //-----------------------------------------------------------------------------
  238. bool SFHudVotePanel::MsgFunc_CallVoteFailed( const CCSUsrMsg_CallVoteFailed &msg )
  239. {
  240. if ( !FlashAPIIsValid() )
  241. {
  242. return true;
  243. }
  244. vote_create_failed_t nReason = (vote_create_failed_t)msg.reason();
  245. int nTime = msg.time();
  246. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  247. if ( !pLocalPlayer )
  248. return true;
  249. if ( CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters() )
  250. {
  251. if ( pParams->m_bAnonymousPlayerIdentity )
  252. return true;
  253. }
  254. pLocalPlayer->EmitSound("Vote.Failed");
  255. m_flHideTime = gpGlobals->curtime + 3.0;
  256. char szTime[256];
  257. wchar_t wszTime[256];
  258. Q_snprintf( szTime, sizeof ( szTime), "%i", nTime );
  259. g_pVGuiLocalize->ConvertANSIToUnicode( szTime, wszTime, sizeof( wszTime ) );
  260. wchar_t wszFailureString[512];
  261. const char * voteFailedStrings[VOTE_FAILED_MAX] = { NULL };
  262. voteFailedStrings[VOTE_FAILED_GENERIC] = "#SFUI_vote_failed";
  263. voteFailedStrings[VOTE_FAILED_TRANSITIONING_PLAYERS] = "#SFUI_vote_failed_transition_vote";
  264. voteFailedStrings[VOTE_FAILED_RATE_EXCEEDED] = "#SFUI_vote_failed_vote_spam";
  265. voteFailedStrings[VOTE_FAILED_ISSUE_DISABLED] = "#SFUI_vote_failed_disabled_issue";
  266. voteFailedStrings[VOTE_FAILED_MAP_NOT_FOUND] = "#SFUI_vote_failed_map_not_found";
  267. voteFailedStrings[VOTE_FAILED_MAP_NAME_REQUIRED] = "#SFUI_vote_failed_map_name_required";
  268. voteFailedStrings[VOTE_FAILED_FAILED_RECENTLY] = "#SFUI_vote_failed_recently";
  269. voteFailedStrings[VOTE_FAILED_FAILED_RECENT_KICK] = "#SFUI_vote_failed_recent_kick";
  270. voteFailedStrings[VOTE_FAILED_FAILED_RECENT_CHANGEMAP] = "#SFUI_vote_failed_recent_changemap";
  271. voteFailedStrings[VOTE_FAILED_FAILED_RECENT_SWAPTEAMS] = "#SFUI_vote_failed_recent_swapteams";
  272. voteFailedStrings[VOTE_FAILED_FAILED_RECENT_SCRAMBLETEAMS] = "#SFUI_vote_failed_recent_scrambleteams";
  273. voteFailedStrings[VOTE_FAILED_FAILED_RECENT_RESTART] = "#SFUI_vote_failed_recent_restart";
  274. voteFailedStrings[VOTE_FAILED_TEAM_CANT_CALL] = "#SFUI_vote_failed_team_cant_call";
  275. voteFailedStrings[VOTE_FAILED_WAITINGFORPLAYERS] = "#SFUI_vote_failed_waitingforplayers";
  276. voteFailedStrings[VOTE_FAILED_CANNOT_KICK_ADMIN] = "#SFUI_vote_failed_cannot_kick_admin";
  277. voteFailedStrings[VOTE_FAILED_SWAP_IN_PROGRESS] = "#SFUI_vote_failed_swap_in_prog";
  278. voteFailedStrings[VOTE_FAILED_SCRAMBLE_IN_PROGRESS] = "#SFUI_vote_failed_scramble_in_prog";
  279. voteFailedStrings[VOTE_FAILED_SPECTATOR] = "#SFUI_vote_failed_spectator";
  280. voteFailedStrings[VOTE_FAILED_DISABLED] = "#SFUI_vote_failed_disabled";
  281. voteFailedStrings[VOTE_FAILED_NEXTLEVEL_SET] = "#SFUI_vote_failed_nextlevel_set";
  282. voteFailedStrings[VOTE_FAILED_TOO_EARLY_SURRENDER] = "#SFUI_vote_failed_surrender_too_early";
  283. voteFailedStrings[ VOTE_FAILED_MATCH_PAUSED ] = "#SFUI_vote_failed_paused";
  284. voteFailedStrings[ VOTE_FAILED_MATCH_NOT_PAUSED ] = "#SFUI_vote_failed_not_paused";
  285. voteFailedStrings[ VOTE_FAILED_NOT_10_PLAYERS ] = "#SFUI_vote_failed_not_10_players";
  286. voteFailedStrings[ VOTE_FAILED_NOT_IN_WARMUP ] = "#SFUI_vote_failed_not_in_warmup";
  287. voteFailedStrings[ VOTE_FAILED_CANT_ROUND_END ] = "#SFUI_vote_failed_cant_round_end";
  288. voteFailedStrings[ VOTE_FAILED_TIMEOUT_EXHAUSTED ] = "#SFUI_vote_failed_timeouts_exhausted";
  289. voteFailedStrings[ VOTE_FAILED_TIMEOUT_ACTIVE ] = "#SFUI_vote_failed_timeout_active";
  290. Assert( nReason < VOTE_FAILED_MAX );
  291. if ( nReason < VOTE_FAILED_MAX )
  292. {
  293. if ( nReason == VOTE_FAILED_RATE_EXCEEDED || nReason == VOTE_FAILED_FAILED_RECENTLY || nReason == VOTE_FAILED_FAILED_RECENT_KICK
  294. || nReason == VOTE_FAILED_FAILED_RECENT_CHANGEMAP || nReason == VOTE_FAILED_FAILED_RECENT_SWAPTEAMS
  295. || nReason == VOTE_FAILED_FAILED_RECENT_SCRAMBLETEAMS || nReason == VOTE_FAILED_FAILED_RECENT_RESTART )
  296. {
  297. g_pVGuiLocalize->ConstructString( wszFailureString, sizeof( wszFailureString ), g_pVGuiLocalize->FindSafe( voteFailedStrings[nReason] ? voteFailedStrings[nReason] : voteFailedStrings[VOTE_FAILED_GENERIC] ), 1, wszTime );
  298. }
  299. else
  300. {
  301. g_pVGuiLocalize->ConstructString( wszFailureString, sizeof( wszFailureString ), g_pVGuiLocalize->FindSafe( voteFailedStrings[nReason] ? voteFailedStrings[nReason] : voteFailedStrings[VOTE_FAILED_GENERIC] ), 0 );
  302. }
  303. WITH_SLOT_LOCKED
  304. {
  305. WITH_SFVALUEARRAY( data, 4 )
  306. {
  307. m_pScaleformUI->ValueArray_SetElement( data, 0, "#SFUI_vote_failed" );
  308. m_pScaleformUI->ValueArray_SetElement( data, 1, wszFailureString );
  309. m_pScaleformUI->ValueArray_SetElement( data, 2, false ); // did not pass
  310. m_pScaleformUI->ValueArray_SetElement( data, 3, false ); // shows the thumb results?
  311. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showResult", data, 4 );
  312. }
  313. }
  314. }
  315. return true;
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Purpose: Sent to everyone
  319. //-----------------------------------------------------------------------------
  320. bool SFHudVotePanel::MsgFunc_VoteFailed( const CCSUsrMsg_VoteFailed &msg )
  321. {
  322. if ( !FlashAPIIsValid() )
  323. {
  324. return true;
  325. }
  326. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  327. if ( !pLocalPlayer )
  328. return true;
  329. if ( CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters() )
  330. {
  331. if ( pParams->m_bAnonymousPlayerIdentity )
  332. return true;
  333. }
  334. bool bShouldShowResults = false;
  335. // Is this a team-only vote?
  336. int iTeam = msg.team();
  337. int invalidTeam = TEAM_INVALID;
  338. if ( (iTeam == invalidTeam || iTeam == pLocalPlayer->GetTeamNumber()) && (m_nVoteYes != 0 || m_nVoteNo != 0) )
  339. {
  340. bShouldShowResults = true;
  341. }
  342. bool bOtherTeam = false;
  343. if ( iTeam != invalidTeam && iTeam != pLocalPlayer->GetTeamNumber() )
  344. bOtherTeam = true;
  345. vote_create_failed_t nReason = (vote_create_failed_t)msg.reason();
  346. const char* failureString;
  347. bool bThumbsCondition = false;
  348. switch ( nReason )
  349. {
  350. case VOTE_FAILED_GENERIC:
  351. failureString = "#SFUI_vote_failed";
  352. break;
  353. case VOTE_FAILED_YES_MUST_EXCEED_NO:
  354. failureString = "#SFUI_vote_failed_yesno";
  355. bThumbsCondition = true;
  356. break;
  357. case VOTE_FAILED_QUORUM_FAILURE:
  358. failureString = "#SFUI_vote_failed_quorum";
  359. bThumbsCondition = true;
  360. break;
  361. case VOTE_FAILED_REMATCH:
  362. failureString = "#SFUI_vote_failed_rematch";
  363. bThumbsCondition = true;
  364. break;
  365. case VOTE_FAILED_CONTINUE:
  366. failureString = "#SFUI_vote_failed_continue";
  367. bThumbsCondition = true;
  368. break;
  369. default:
  370. AssertMsg( false, "Invalid vote failure reason" );
  371. failureString = "";
  372. break;
  373. }
  374. if ( bOtherTeam )
  375. {
  376. // don't do anything because you'll see the result of the vote in chat based on the action
  377. // CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
  378. // if ( pwcIssue[0] )
  379. // {
  380. // hudChat->ChatPrintfW( pLocalPlayer->entindex(), CHAT_FILTER_SERVERMSG, pwcIssue );
  381. // }
  382. }
  383. else
  384. {
  385. //This will be hidden in OnThink
  386. WITH_SFVALUEARRAY( data, 4 )
  387. {
  388. m_pScaleformUI->ValueArray_SetElement( data, 0, "#SFUI_vote_failed" );
  389. m_pScaleformUI->ValueArray_SetElement( data, 1, failureString );
  390. m_pScaleformUI->ValueArray_SetElement( data, 2, false ); // did not pass
  391. m_pScaleformUI->ValueArray_SetElement( data, 3, bThumbsCondition && bShouldShowResults ); // shows the thumb results?
  392. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showResult", data, 4 );
  393. }
  394. SetVoteActive( false );
  395. m_bVotePassed = false;
  396. m_flVoteResultCycleTime = gpGlobals->curtime + 2;
  397. m_flHideTime = gpGlobals->curtime + 3.5;
  398. pLocalPlayer->EmitSound("Vote.Failed");
  399. }
  400. return true;
  401. }
  402. //-----------------------------------------------------------------------------
  403. // Purpose:
  404. //-----------------------------------------------------------------------------
  405. bool SFHudVotePanel::MsgFunc_VoteStart( const CCSUsrMsg_VoteStart &msg )
  406. {
  407. if ( !FlashAPIIsValid() )
  408. {
  409. return true;
  410. }
  411. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  412. if ( !pLocalPlayer )
  413. return true;
  414. if ( CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters() )
  415. {
  416. if ( pParams->m_bAnonymousPlayerIdentity )
  417. return true;
  418. }
  419. // Is this a team-only vote?
  420. // first
  421. int iTeam = msg.team();
  422. int invalidTeam = TEAM_INVALID;
  423. bool bShowingOtherTeam = false;
  424. if ( iTeam != invalidTeam && iTeam != pLocalPlayer->GetTeamNumber() )
  425. {
  426. m_nVoteYes = 0;
  427. m_nVoteNo = 0;
  428. bShowingOtherTeam = true;
  429. }
  430. // Entity calling the vote
  431. bool bShowNotif = cl_vote_ui_show_notification.GetBool();
  432. const char *pszCallerName = "Server";
  433. // second
  434. int iEntityCallingVote = msg.ent_idx();
  435. if ( iEntityCallingVote != 99 )
  436. {
  437. C_BasePlayer *pVoteCaller = UTIL_PlayerByIndex( iEntityCallingVote );
  438. if ( pVoteCaller )
  439. {
  440. pszCallerName = pVoteCaller->GetPlayerName();
  441. // Don't show a notification to the caller
  442. if ( pVoteCaller == pLocalPlayer )
  443. {
  444. bShowNotif = false;
  445. m_bPlayerVoted = true;
  446. // we're assuming they did vote option 1 here because they voted for it
  447. m_bPlayerLocalVote = VOTE_OPTION1;
  448. }
  449. }
  450. else
  451. {
  452. // Caller invalid for some reason
  453. pszCallerName = "Player";
  454. }
  455. }
  456. // the vote type
  457. // third
  458. int nVoteType = msg.vote_type();
  459. // DisplayString
  460. // fourth
  461. const char *szIssue = msg.disp_str().c_str();
  462. // DetailString
  463. // fifth
  464. const char *szParam1 = msg.details_str().c_str();
  465. // OtherTeam string
  466. // sixth
  467. const char *szOtherTeam = msg.other_team_str().c_str();
  468. // seventh
  469. m_bIsYesNoVote = msg.is_yes_no_vote();
  470. // Display vote caller's name
  471. wchar_t wszCallerName[MAX_PLAYER_NAME_LENGTH];
  472. wchar_t wszCleanName[MAX_DECORATED_PLAYER_NAME_LENGTH];
  473. wchar_t wszHeaderString[512];
  474. wchar_t *pwszHeaderString;
  475. // Player
  476. g_pVGuiLocalize->ConvertANSIToUnicode( pszCallerName, wszCallerName, sizeof( wszCallerName ) );
  477. g_pScaleformUI->MakeStringSafe( wszCallerName, wszCleanName, sizeof( wszCleanName ) );
  478. TruncatePlayerName( wszCleanName, ARRAYSIZE( wszCleanName ), VOTE_PANEL_NAME_TRUNCATE_AT );
  479. // String
  480. g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#SFUI_vote_header" ), 1, wszCleanName );
  481. pwszHeaderString = wszHeaderString;
  482. // Display the Issue
  483. wchar_t *pwcParam;
  484. wchar_t wcParam[128] = {0};
  485. wchar_t *pwcIssue;
  486. wchar_t wcIssue[512] = {0};
  487. if ( Q_strlen( szParam1 ) > 0 )
  488. {
  489. const int nMaxLength = MAX_MAP_NAME+10+1;
  490. char szToken[nMaxLength];
  491. if ( nVoteType == VOTEISSUE_NEXTLEVEL || nVoteType == VOTEISSUE_CHANGELEVEL )
  492. {
  493. szParam1 = V_GetFileName( szParam1 );
  494. }
  495. if ( (nVoteType == VOTEISSUE_CHANGELEVEL || nVoteType == VOTEISSUE_NEXTLEVEL ) && CSGameRules()->GetFriendlyMapNameToken(szParam1, szToken, nMaxLength) )
  496. {
  497. pwcParam = g_pVGuiLocalize->Find( szToken );
  498. }
  499. else
  500. {
  501. if ( szParam1[0] == '#' )
  502. {
  503. pwcParam = g_pVGuiLocalize->Find( szParam1 );
  504. }
  505. else
  506. {
  507. // Convert to wchar
  508. g_pVGuiLocalize->ConvertANSIToUnicode( szParam1, wcParam, sizeof( wcParam ) );
  509. pwcParam = wcParam;
  510. }
  511. }
  512. if ( bShowingOtherTeam )
  513. g_pVGuiLocalize->ConstructString( wcIssue, sizeof(wcIssue), g_pVGuiLocalize->Find( szOtherTeam ), 1, pwcParam );
  514. else
  515. g_pVGuiLocalize->ConstructString( wcIssue, sizeof(wcIssue), g_pVGuiLocalize->Find( szIssue ), 1, pwcParam );
  516. pwcIssue = wcIssue;
  517. }
  518. else
  519. {
  520. // no param, just localize the issue
  521. if ( bShowingOtherTeam )
  522. pwcIssue = g_pVGuiLocalize->Find( szOtherTeam );
  523. else
  524. pwcIssue = g_pVGuiLocalize->Find( szIssue );
  525. if ( !pwcIssue )
  526. pwcIssue = L"VOTE";
  527. }
  528. g_pScaleformUI->MakeStringSafe( pwcIssue, wszCleanName, sizeof( wszCleanName ) );
  529. pwcIssue = wszCleanName;
  530. // if the vote is called by the other team, just show a chat message here informing this team
  531. if ( bShowingOtherTeam )
  532. {
  533. CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
  534. if ( pwcIssue[0] )
  535. {
  536. hudChat->ChatPrintfW( pLocalPlayer->entindex(), CHAT_FILTER_SERVERMSG, pwcIssue );
  537. }
  538. return true;
  539. }
  540. SetVoteActive( true );
  541. SAFECALL( m_hVoteButtonBG, m_pScaleformUI->Value_SetVisible( m_hVoteButtonBG, false ); );
  542. // Figure out which UI
  543. if ( m_bIsYesNoVote )
  544. {
  545. UpdateYesNoButtonText( bShowingOtherTeam );
  546. }
  547. #if !defined( CSTRIKE15 )
  548. else
  549. {
  550. // GENERAL UI
  551. if ( m_VoteSetupChoices.Count() )
  552. {
  553. // Clear the labels to prevent previous options from being displayed,
  554. // such as when there are fewer options this vote than the previous
  555. for ( int iIndex = 0; iIndex < MAX_VOTE_OPTIONS; iIndex++ )
  556. {
  557. // Construct Label name
  558. char szOptionNum[2];
  559. Q_snprintf( szOptionNum, sizeof( szOptionNum ), "%i", iIndex + 1 );
  560. char szVoteOptionCount[13] = "LabelOption";
  561. Q_strncat( szVoteOptionCount, szOptionNum, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  562. //Convert to Scaleform if we go to non-yes/no votes: m_pVoteActive->SetControlString( szVoteOptionCount, "" );
  563. }
  564. // Set us up the vote
  565. for ( int iIndex = 0; iIndex < m_nVoteChoicesCount; iIndex++ )
  566. {
  567. // Construct Option name
  568. const char *pszChoiceName = m_VoteSetupChoices[iIndex];
  569. char szOptionName[256];
  570. Q_snprintf( szOptionName, sizeof( szOptionName ), "F%i. ", iIndex + 1 );
  571. Q_strncat( szOptionName, pszChoiceName, sizeof( szOptionName ), COPY_ALL_CHARACTERS );
  572. // Construct Label name
  573. char szOptionNum[2];
  574. Q_snprintf( szOptionNum, sizeof( szOptionNum ), "%i", iIndex + 1 );
  575. char szVoteOptionCount[13] = "LabelOption";
  576. Q_strncat( szVoteOptionCount, szOptionNum, sizeof( szVoteOptionCount ), COPY_ALL_CHARACTERS );
  577. // Set Label string
  578. //Convert to Scaleform if we go to non-yes/no votes:
  579. /*
  580. if ( m_pVoteActive )
  581. {
  582. m_pVoteActive->SetControlString( szVoteOptionCount, szOptionName );
  583. }
  584. */
  585. }
  586. }
  587. }
  588. #endif //!defined( CSTRIKE15 )
  589. ShowVoteUI( pwszHeaderString, pwcIssue );
  590. return true;
  591. }
  592. void SFHudVotePanel::UpdateYesNoButtonText( bool bShowOtherTeam )
  593. {
  594. bool bUsingKeyboard = ( m_pScaleformUI && false == m_pScaleformUI->IsSetToControllerUI( SF_FULL_SCREEN_SLOT ) );
  595. // YES / NO UI
  596. wchar_t *pszTextVoted;
  597. wchar_t *pszTextY;
  598. wchar_t *pszTextN;
  599. if ( bShowOtherTeam )
  600. {
  601. pszTextN = L"";
  602. pszTextY = L"";
  603. pszTextVoted = L"";
  604. }
  605. else if ( !m_bPlayerVoted )
  606. {
  607. if ( bUsingKeyboard )
  608. {
  609. pszTextN = g_pVGuiLocalize->Find( "#SFUI_vote_no_pc_instruction" );
  610. pszTextY = g_pVGuiLocalize->Find( "#SFUI_vote_yes_pc_instruction" );
  611. }
  612. else
  613. {
  614. pszTextN = g_pVGuiLocalize->Find( "#SFUI_vote_no_console_instruction" );
  615. pszTextY = g_pVGuiLocalize->Find( "#SFUI_vote_yes_console_instruction" );
  616. }
  617. pszTextVoted = L"";
  618. SAFECALL( m_hVoteButtonBG, m_pScaleformUI->Value_SetVisible( m_hVoteButtonBG, true ); );
  619. }
  620. else
  621. {
  622. if( m_bPlayerLocalVote == VOTE_OPTION1 )
  623. {
  624. pszTextVoted = g_pVGuiLocalize->Find( "#SFUI_vote_yes_confirmation_pc_instruction" );
  625. }
  626. else
  627. {
  628. pszTextVoted = g_pVGuiLocalize->Find( "#SFUI_vote_no_confirmation_pc_instruction" );
  629. }
  630. pszTextN = L"";
  631. pszTextY = L"";
  632. SAFECALL( m_hVoteButtonBG, m_pScaleformUI->Value_SetVisible( m_hVoteButtonBG, true ); );
  633. }
  634. if ( pszTextY )
  635. {
  636. WITH_SLOT_LOCKED
  637. {
  638. if ( m_option1Text )
  639. {
  640. m_option1Text->SetTextHTML( m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( pszTextY ) );
  641. }
  642. }
  643. }
  644. if ( pszTextN )
  645. {
  646. WITH_SLOT_LOCKED
  647. {
  648. if ( m_option2Text )
  649. {
  650. m_option2Text->SetTextHTML( m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( pszTextN ) );
  651. }
  652. }
  653. }
  654. if ( pszTextVoted )
  655. {
  656. WITH_SLOT_LOCKED
  657. {
  658. if ( m_hVoteLocalCast )
  659. {
  660. m_hVoteLocalCast->SetTextHTML( m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( pszTextVoted ) );
  661. }
  662. }
  663. }
  664. if ( !bShowOtherTeam )
  665. {
  666. char szYesCount[512] = "";
  667. Q_snprintf( szYesCount, 512, "%d", m_nVoteYes );
  668. char szNoCount[512] = "";
  669. Q_snprintf( szNoCount, 512, "%d", m_nVoteNo );
  670. WITH_SLOT_LOCKED
  671. {
  672. if ( m_option1CountText )
  673. {
  674. m_option1CountText->SetText( szYesCount );
  675. }
  676. if ( m_option2CountText )
  677. {
  678. m_option2CountText->SetText( szNoCount );
  679. }
  680. }
  681. }
  682. }
  683. //-----------------------------------------------------------------------------
  684. // Purpose:
  685. //-----------------------------------------------------------------------------
  686. bool SFHudVotePanel::MsgFunc_VotePass( const CCSUsrMsg_VotePass &msg )
  687. {
  688. if ( !FlashAPIIsValid() )
  689. {
  690. return true;
  691. }
  692. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  693. if ( !pLocalPlayer )
  694. return true;
  695. if ( CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters() )
  696. {
  697. if ( pParams->m_bAnonymousPlayerIdentity )
  698. return true;
  699. }
  700. bool bShouldShowResults = false;
  701. // Is this a team-only vote?
  702. int iTeam = msg.team();
  703. int invalidTeam = TEAM_INVALID;
  704. if ( pLocalPlayer->GetTeamNumber() > 0 && (iTeam == invalidTeam || iTeam == pLocalPlayer->GetTeamNumber()) && (m_nVoteYes != 0 || m_nVoteNo != 0) )
  705. {
  706. bShouldShowResults = true;
  707. }
  708. bool bOtherTeam = false;
  709. if ( pLocalPlayer->GetTeamNumber() > 0 && iTeam != invalidTeam && iTeam != pLocalPlayer->GetTeamNumber() )
  710. bOtherTeam = true;
  711. int nVoteType = msg.vote_type();
  712. // Passed string
  713. const char *szResult = msg.disp_str().c_str();
  714. // Detail string
  715. const char *szParam1 = msg.details_str().c_str();
  716. // Localize
  717. wchar_t *pwcParam;
  718. wchar_t wcParam[128];
  719. const wchar_t *pwcIssue;
  720. wchar_t wcIssue[512];
  721. if ( Q_strlen( szParam1 ) > 0 )
  722. {
  723. const int nMaxLength = MAX_MAP_NAME+10+1;
  724. char szToken[nMaxLength];
  725. if ( nVoteType == VOTEISSUE_NEXTLEVEL || nVoteType == VOTEISSUE_CHANGELEVEL )
  726. {
  727. szParam1 = V_GetFileName( szParam1 );
  728. }
  729. if ( (nVoteType == VOTEISSUE_CHANGELEVEL || nVoteType == VOTEISSUE_NEXTLEVEL ) && CSGameRules()->GetFriendlyMapNameToken(szParam1, szToken, nMaxLength) )
  730. {
  731. pwcParam = g_pVGuiLocalize->Find( szToken );
  732. }
  733. else
  734. {
  735. if ( szParam1[0] == '#' )
  736. {
  737. pwcParam = g_pVGuiLocalize->Find( szParam1 );
  738. }
  739. else
  740. {
  741. // Convert to wchar
  742. g_pVGuiLocalize->ConvertANSIToUnicode( szParam1, wcParam, sizeof( wcParam ) );
  743. pwcParam = wcParam;
  744. }
  745. }
  746. g_pVGuiLocalize->ConstructString( wcIssue, sizeof(wcIssue), g_pVGuiLocalize->Find( szResult ), 1, pwcParam );
  747. pwcIssue = wcIssue;
  748. }
  749. else
  750. {
  751. // No param, just localize the result
  752. pwcIssue = g_pVGuiLocalize->FindSafe( szResult );
  753. }
  754. if ( bOtherTeam )
  755. {
  756. // don't do anything because you'll see the result of the vote in chat based on the action
  757. // CBaseHudChat *hudChat = (CBaseHudChat *)GET_HUDELEMENT( CHudChat );
  758. // if ( pwcIssue[0] )
  759. // {
  760. // hudChat->ChatPrintfW( pLocalPlayer->entindex(), CHAT_FILTER_SERVERMSG, pwcIssue );
  761. // }
  762. }
  763. else
  764. {
  765. UpdateYesNoButtonText();
  766. WITH_SFVALUEARRAY( data, 4 )
  767. {
  768. m_pScaleformUI->ValueArray_SetElement( data, 0, "#SFUI_vote_passed" );
  769. m_pScaleformUI->ValueArray_SetElement( data, 1, pwcIssue );
  770. m_pScaleformUI->ValueArray_SetElement( data, 2, true ); // passed!
  771. m_pScaleformUI->ValueArray_SetElement( data, 3, bShouldShowResults ); // shows the thumb results?
  772. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showResult", data, 4 );
  773. }
  774. pLocalPlayer->EmitSound( "Vote.Passed" );
  775. SetVoteActive( false );
  776. m_bVotePassed = true;
  777. m_flVoteResultCycleTime = gpGlobals->curtime + 2;
  778. m_flHideTime = gpGlobals->curtime + 3.5;
  779. }
  780. return true;
  781. }
  782. //-----------------------------------------------------------------------------
  783. // Purpose: Creates a UI for Vote Issue selection
  784. //-----------------------------------------------------------------------------
  785. bool SFHudVotePanel::MsgFunc_VoteSetup( const CCSUsrMsg_VoteSetup &msg )
  786. {
  787. if ( CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters() )
  788. {
  789. if ( pParams->m_bAnonymousPlayerIdentity )
  790. return true;
  791. }
  792. SFHudCallVotePanel::LoadDialog();
  793. //[tj] This stuff should be ported to the CallVote module.
  794. /*
  795. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  796. if ( !pLocalPlayer )
  797. return;
  798. // Load up the list of Vote Issues
  799. m_VoteSetupIssues.RemoveAll();
  800. int nIssueCount = msg.ReadByte();
  801. if ( nIssueCount )
  802. {
  803. for ( int index = 0; index < nIssueCount; index++ )
  804. {
  805. char szIssue[256];
  806. msg.ReadString( szIssue, sizeof(szIssue) );
  807. if ( !m_VoteSetupIssues.HasElement( szIssue ) )
  808. {
  809. // Send it over to the listpanel
  810. m_VoteSetupIssues.CopyAndAddToTail( szIssue );
  811. }
  812. }
  813. }
  814. else
  815. {
  816. m_VoteSetupIssues.CopyAndAddToTail( "Voting disabled on this Server" );
  817. }
  818. m_pVoteSetupDialog->AddVoteIssues( m_VoteSetupIssues );
  819. // Load up the list of Vote Issue Parameters
  820. m_VoteSetupMapCycle.RemoveAll();
  821. if ( g_pStringTableServerMapCycle )
  822. {
  823. int index = g_pStringTableServerMapCycle->FindStringIndex( "ServerMapCycle" );
  824. if ( index != ::INVALID_STRING_INDEX )
  825. {
  826. int nLength = 0;
  827. const char *pszMapCycle = (const char *)g_pStringTableServerMapCycle->GetStringUserData( index, &nLength );
  828. if ( pszMapCycle && pszMapCycle[0] )
  829. {
  830. if ( pszMapCycle && nLength )
  831. {
  832. V_SplitString( pszMapCycle, "\n", m_VoteSetupMapCycle );
  833. }
  834. // Alphabetize
  835. if ( m_VoteSetupMapCycle.Count() )
  836. {
  837. m_VoteSetupMapCycle.Sort( m_VoteSetupMapCycle.SortFunc );
  838. }
  839. }
  840. }
  841. }
  842. // Now send any data we gathered over to the listpanel
  843. PropagateOptionParameters();
  844. m_pVoteSetupDialog->Activate();
  845. */
  846. return true;
  847. }
  848. //[tj] This stuff should be ported to the CallVote module.
  849. /*
  850. //-----------------------------------------------------------------------------
  851. // Purpose: Propagate vote option parameters to the Issue Parameters list
  852. //-----------------------------------------------------------------------------
  853. void SFHudVotePanel::PropagateOptionParameters( void )
  854. {
  855. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  856. if ( !pLocalPlayer )
  857. return;
  858. m_pVoteSetupDialog->AddVoteIssueParams_MapCycle( m_VoteSetupMapCycle );
  859. // Insert future issue param data containers here
  860. }
  861. */
  862. void SFHudVotePanel::SetVoteActive( bool bActive )
  863. {
  864. m_bVoteActive = bActive;
  865. }
  866. //-----------------------------------------------------------------------------
  867. // Purpose:
  868. //-----------------------------------------------------------------------------
  869. void SFHudVotePanel::ShowVoteUI( wchar_t* headerText, wchar_t* voteText, bool bShowingOtherTeam )
  870. {
  871. if ( !FlashAPIIsValid() )
  872. {
  873. return;
  874. }
  875. m_bHasFocus = false;
  876. //Force a refresh before showing
  877. OnThink();
  878. WITH_SLOT_LOCKED
  879. {
  880. WITH_SFVALUEARRAY( data, 2 )
  881. {
  882. m_pScaleformUI->ValueArray_SetElement( data, 0, headerText );
  883. m_pScaleformUI->ValueArray_SetElement( data, 1, voteText );
  884. if ( bShowingOtherTeam )
  885. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showOtherTeamCastVote", data, 2 );
  886. else
  887. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showCastVote", data, 2 );
  888. }
  889. }
  890. if ( !bShowingOtherTeam )
  891. {
  892. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  893. if ( pLocalPlayer )
  894. {
  895. pLocalPlayer->EmitSound("Vote.Created");
  896. }
  897. }
  898. }
  899. //-----------------------------------------------------------------------------
  900. // Purpose:
  901. //-----------------------------------------------------------------------------
  902. void SFHudVotePanel::OnThink( void )
  903. {
  904. if ( !FlashAPIIsValid() )
  905. return;
  906. if ( !m_bVoteActive && m_flHideTime < 0 && m_flPostVotedHideTime < 0 )
  907. return;
  908. if ( m_bVoteActive && m_bHasFocus == false && GetHud().HudDisabled() == false )
  909. {
  910. // do not give focus to the vote panel until the HUD becomes visible
  911. m_bHasFocus = true;
  912. WITH_SLOT_LOCKED
  913. {
  914. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "focusCastVote", NULL, 0 );
  915. }
  916. }
  917. if ( m_bVoteActive && m_bVisible == false )
  918. {
  919. SetActive( true );
  920. }
  921. // We delay hiding the menu after we cast a vote
  922. if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && m_flPostVotedHideTime < gpGlobals->curtime )
  923. {
  924. Hide();
  925. m_flPostVotedHideTime = -1;
  926. }
  927. if ( !m_bVoteActive && m_flHideTime != -1 && m_flHideTime < gpGlobals->curtime )
  928. {
  929. Hide();
  930. m_flHideTime = -1;
  931. }
  932. if ( m_flVoteResultCycleTime > 0 && m_flVoteResultCycleTime < gpGlobals->curtime )
  933. {
  934. //[tj]Convert toScaleform animation g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" );
  935. m_flVoteResultCycleTime = -1;
  936. m_bPlayerVoted = false;
  937. m_bPlayerLocalVote = VOTE_UNCAST;
  938. m_bVoteActive = false;
  939. }
  940. if ( m_bIsYesNoVote )
  941. {
  942. if ( m_nVoteOptionCount[0] != m_nVoteYes )
  943. {
  944. m_nVoteYes = m_nVoteOptionCount[0];
  945. }
  946. if ( m_nVoteOptionCount[1] != m_nVoteNo )
  947. {
  948. m_nVoteNo = m_nVoteOptionCount[1];
  949. }
  950. UpdateYesNoButtonText();
  951. }
  952. }
  953. void SFHudVotePanel::VoteYes( SCALEFORM_CALLBACK_ARGS_DECL )
  954. {
  955. bool bEatKey = false;
  956. if ( m_bVoteActive )
  957. {
  958. if ( !m_bPlayerVoted )
  959. {
  960. engine->ClientCmd( "vote option1" );
  961. bEatKey = true;
  962. }
  963. }
  964. m_pScaleformUI->Params_SetResult( obj, bEatKey );
  965. }
  966. void SFHudVotePanel::VoteNo( SCALEFORM_CALLBACK_ARGS_DECL )
  967. {
  968. bool bEatKey = false;
  969. if ( m_bVoteActive )
  970. {
  971. if ( !m_bPlayerVoted )
  972. {
  973. engine->ClientCmd( "vote option2" );
  974. bEatKey = true;
  975. }
  976. }
  977. m_pScaleformUI->Params_SetResult( obj, bEatKey );
  978. }
  979. void SFHudVotePanel::SetActive( bool bActive )
  980. {
  981. if ( bActive != m_bVisible )
  982. {
  983. if ( FlashAPIIsValid() )
  984. {
  985. if ( bActive )
  986. {
  987. WITH_SLOT_LOCKED
  988. {
  989. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showImmediate", NULL, 0 );
  990. }
  991. }
  992. else
  993. {
  994. WITH_SLOT_LOCKED
  995. {
  996. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hideImmediate", NULL, 0 );
  997. }
  998. }
  999. }
  1000. m_bVisible = bActive;
  1001. }
  1002. CHudElement::SetActive( bActive );
  1003. }
  1004. #endif // INCLUDE_SCALEFORM