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.

812 lines
19 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "basetypes.h"
  9. #include "hud.h"
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include "voice_status.h"
  13. #include "r_efx.h"
  14. #include <vgui_controls/TextImage.h>
  15. #include <vgui/MouseCode.h>
  16. #include "cdll_client_int.h"
  17. #include "hud_macros.h"
  18. #include "c_playerresource.h"
  19. #include "cliententitylist.h"
  20. #include "c_baseplayer.h"
  21. #include "materialsystem/imesh.h"
  22. #include "view.h"
  23. #include "convar.h"
  24. #include <vgui_controls/Controls.h>
  25. #include <vgui/IScheme.h>
  26. #include <vgui/ISurface.h>
  27. #include "vgui_bitmapimage.h"
  28. #include "materialsystem/imaterial.h"
  29. #include "tier0/dbg.h"
  30. #include "cdll_int.h"
  31. #include <vgui/IPanel.h>
  32. #include "con_nprint.h"
  33. #if defined(PORTAL2)
  34. #include "c_portal_gamestats.h"
  35. #endif
  36. #if defined ( CSTRIKE15 )
  37. #include "c_cs_player.h"
  38. #include "matchmaking/imatchtitle.h"
  39. #include "matchmaking/iplayer.h"
  40. #include "matchmaking/mm_helpers.h"
  41. #include "matchmaking/imatchframework.h"
  42. #endif
  43. // memdbgon must be the last include file in a .cpp file!!!
  44. #include "tier0/memdbgon.h"
  45. using namespace vgui;
  46. extern int cam_thirdperson;
  47. #define VOICE_MODEL_INTERVAL 0.3
  48. #define SQUELCHOSCILLATE_PER_SECOND 2.0f
  49. ConVar voice_modenable( "voice_modenable", "1", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Enable/disable voice in this mod." );
  50. ConVar voice_clientdebug( "voice_clientdebug", "0" );
  51. ConVar voice_head_icon_size( "voice_head_icon_size", "6", FCVAR_NONE, "Size of voice icon over player heads in inches" );
  52. ConVar voice_head_icon_height( "voice_head_icon_height", "20", FCVAR_NONE, "Voice icons are this many inches over player eye positions" );
  53. ConVar voice_local_icon( "voice_local_icon", "0", FCVAR_NONE, "Draw local player's voice icon" );
  54. ConVar voice_all_icons( "voice_all_icons", "0", FCVAR_NONE, "Draw all players' voice icons" );
  55. ConVar voice_icons_method( "voice_icons_method", "2", FCVAR_NONE, "0 = classic style, 1 = particles, 2 = integrated into target ID" );
  56. #if defined ( CSTRIKE15 )
  57. ConVar cl_mute_enemy_team( "cl_mute_enemy_team", "0", FCVAR_ARCHIVE, "Block all communication from players on the enemy team." );
  58. ConVar cl_mute_all_but_friends_and_party( "cl_mute_all_but_friends_and_party", "0", FCVAR_ARCHIVE, "Only allow communication from friends and matchmaking party members. Doesn't apply to competitive matchmaking games." );
  59. #endif
  60. // ---------------------------------------------------------------------- //
  61. // The voice manager for the client.
  62. // ---------------------------------------------------------------------- //
  63. static CVoiceStatus *g_VoiceStatus = NULL;
  64. CVoiceStatus* GetClientVoiceMgr()
  65. {
  66. if ( !g_VoiceStatus )
  67. {
  68. ClientVoiceMgr_Init();
  69. }
  70. return g_VoiceStatus;
  71. }
  72. void ClientVoiceMgr_Init()
  73. {
  74. if ( g_VoiceStatus )
  75. return;
  76. g_VoiceStatus = new CVoiceStatus();
  77. }
  78. void ClientVoiceMgr_Shutdown()
  79. {
  80. delete g_VoiceStatus;
  81. g_VoiceStatus = NULL;
  82. }
  83. void ClientVoiceMgr_LevelInit()
  84. {
  85. if ( g_VoiceStatus )
  86. {
  87. g_VoiceStatus->LevelInit();
  88. }
  89. }
  90. void ClientVoiceMgr_LevelShutdown()
  91. {
  92. if ( g_VoiceStatus )
  93. {
  94. g_VoiceStatus->LevelShutdown();
  95. }
  96. }
  97. // ---------------------------------------------------------------------- //
  98. // CVoiceStatus.
  99. // ---------------------------------------------------------------------- //
  100. static CVoiceStatus *g_pInternalVoiceStatus = NULL;
  101. bool __MsgFunc_VoiceMask(const CCSUsrMsg_VoiceMask &msg)
  102. {
  103. if(g_pInternalVoiceStatus)
  104. return g_pInternalVoiceStatus->HandleVoiceMaskMsg(msg);
  105. return true;
  106. }
  107. bool __MsgFunc_RequestState(const CCSUsrMsg_RequestState &msg)
  108. {
  109. if(g_pInternalVoiceStatus)
  110. return g_pInternalVoiceStatus->HandleReqStateMsg(msg);
  111. return true;
  112. }
  113. // ---------------------------------------------------------------------- //
  114. // CVoiceStatus.
  115. // ---------------------------------------------------------------------- //
  116. CVoiceStatus::CVoiceStatus()
  117. {
  118. m_nControlSize = 0;
  119. m_bBanMgrInitialized = false;
  120. m_LastUpdateServerState = 0;
  121. for ( int k = 0; k < MAX_SPLITSCREEN_CLIENTS; ++ k )
  122. {
  123. m_bTalking[k] = false;
  124. m_bServerAcked[k] = false;
  125. m_bAboveThreshold[k] = false;
  126. m_bAboveThresholdTimer[k].Invalidate();
  127. }
  128. m_bServerModEnable = -1;
  129. m_pHeadLabelMaterial = NULL;
  130. m_bHeadLabelsDisabled = false;
  131. }
  132. CVoiceStatus::~CVoiceStatus()
  133. {
  134. if ( m_pHeadLabelMaterial )
  135. {
  136. m_pHeadLabelMaterial->DecrementReferenceCount();
  137. }
  138. g_pInternalVoiceStatus = NULL;
  139. const char *pGameDir = engine->GetGameDirectory();
  140. if( pGameDir )
  141. {
  142. if(m_bBanMgrInitialized)
  143. {
  144. m_BanMgr.SaveState( pGameDir );
  145. }
  146. }
  147. }
  148. int CVoiceStatus::Init(
  149. IVoiceStatusHelper *pHelper,
  150. VPANEL pParentPanel)
  151. {
  152. const char *pGameDir = engine->GetGameDirectory();
  153. if( pGameDir )
  154. {
  155. m_BanMgr.Init( pGameDir );
  156. m_bBanMgrInitialized = true;
  157. }
  158. Assert(!g_pInternalVoiceStatus);
  159. g_pInternalVoiceStatus = this;
  160. m_pHeadLabelMaterial = materials->FindMaterial( "voice/icntlk_pl", TEXTURE_GROUP_VGUI );
  161. m_pHeadLabelMaterial->IncrementReferenceCount();
  162. m_bInSquelchMode = false;
  163. m_pHelper = pHelper;
  164. m_pParentPanel = pParentPanel;
  165. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  166. {
  167. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  168. HOOK_MESSAGE(VoiceMask);
  169. HOOK_MESSAGE(RequestState);
  170. }
  171. return 1;
  172. }
  173. BitmapImage* vgui_LoadMaterial( vgui::VPANEL pParent, const char *pFilename )
  174. {
  175. return new BitmapImage( pParent, pFilename );
  176. }
  177. void CVoiceStatus::VidInit()
  178. {
  179. }
  180. void CVoiceStatus::LevelInit( void )
  181. {
  182. for ( int k = 0; k < MAX_SPLITSCREEN_CLIENTS; ++ k )
  183. {
  184. m_bTalking[k] = false;
  185. m_bAboveThreshold[k] = false;
  186. m_bAboveThresholdTimer[k].Invalidate();
  187. }
  188. for ( int k = 0; k < VOICE_MAX_PLAYERS; ++k )
  189. {
  190. m_flTalkTime[k] = 0.0f;
  191. m_flTimeLastUpdate[k] = 0.0f;
  192. }
  193. }
  194. void CVoiceStatus::LevelShutdown( void )
  195. {
  196. for ( int k = 0; k < MAX_SPLITSCREEN_CLIENTS; ++ k )
  197. {
  198. m_bTalking[k] = false;
  199. m_bAboveThreshold[k] = false;
  200. m_bAboveThresholdTimer[k].Invalidate();
  201. }
  202. for ( int k = 0; k < VOICE_MAX_PLAYERS; ++k )
  203. {
  204. m_flTalkTime[k] = 0.0f;
  205. m_flTimeLastUpdate[k] = 0.0f;
  206. }
  207. }
  208. void CVoiceStatus::Frame(double frametime)
  209. {
  210. // check server banned players once per second
  211. if (gpGlobals->curtime - m_LastUpdateServerState > 1)
  212. {
  213. UpdateServerState(false);
  214. }
  215. }
  216. float CVoiceStatus::GetHeadLabelOffset( void ) const
  217. {
  218. return voice_head_icon_height.GetFloat();
  219. }
  220. void CVoiceStatus::DrawHeadLabels()
  221. {
  222. if ( voice_all_icons.GetBool() )
  223. {
  224. for(int i=0; i < VOICE_MAX_PLAYERS; i++)
  225. {
  226. IClientNetworkable *pClient = cl_entitylist->GetClientEntity( i+1 );
  227. // Don't show an icon if the player is not in our PVS.
  228. if ( !pClient || pClient->IsDormant() )
  229. continue;
  230. m_VoicePlayers[i] = voice_all_icons.GetInt() > 0;
  231. }
  232. }
  233. else if ( voice_local_icon.GetBool() )
  234. {
  235. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  236. m_VoicePlayers[ localPlayer->entindex() - 1 ] = IsLocalPlayerSpeakingAboveThreshold( localPlayer->GetSplitScreenPlayerSlot() );
  237. }
  238. if ( m_bHeadLabelsDisabled )
  239. return;
  240. if( !m_pHeadLabelMaterial )
  241. return;
  242. CMatRenderContextPtr pRenderContext( materials );
  243. for ( int i=0; i < VOICE_MAX_PLAYERS; i++)
  244. {
  245. IClientNetworkable *pClient = cl_entitylist->GetClientEntity( i+1 );
  246. C_BasePlayer *pPlayer = dynamic_cast< C_BasePlayer* >( pClient );
  247. if( !pPlayer )
  248. continue;
  249. if ( !m_VoicePlayers[i] )
  250. {
  251. if ( voice_icons_method.GetInt() > 0 )
  252. {
  253. pPlayer->UpdateSpeechVOIP( false );
  254. }
  255. continue;
  256. }
  257. // Don't show an icon if the player is not in our PVS.
  258. if ( !pClient || pClient->IsDormant() )
  259. {
  260. if ( voice_icons_method.GetInt() > 0 )
  261. {
  262. pPlayer->UpdateSpeechVOIP( false );
  263. }
  264. continue;
  265. }
  266. // Don't show an icon for dead or spectating players (ie: invisible entities).
  267. if( pPlayer->IsPlayerDead() )
  268. {
  269. if ( voice_icons_method.GetInt() > 0 )
  270. {
  271. pPlayer->UpdateSpeechVOIP( false );
  272. }
  273. continue;
  274. }
  275. if ( voice_icons_method.GetInt() > 0 )
  276. {
  277. pPlayer->UpdateSpeechVOIP( true );
  278. return;
  279. }
  280. // Don't show an icon for players we can't hear
  281. if ( !IsPlayerAudible( i+1 ) )
  282. continue;
  283. // Place it a fixed height above his head.
  284. Vector vOrigin = pPlayer->EyePosition( );
  285. vOrigin.z += GetHeadLabelOffset();
  286. // Align it so it never points up or down.
  287. Vector vUp( 0, 0, 1 );
  288. Vector vRight = CurrentViewRight();
  289. if ( fabs( vRight.z ) > 0.95 ) // don't draw it edge-on
  290. continue;
  291. vRight.z = 0;
  292. VectorNormalize( vRight );
  293. float flSize = voice_head_icon_size.GetFloat();
  294. pRenderContext->Bind( pPlayer->GetHeadLabelMaterial() );
  295. IMesh *pMesh = pRenderContext->GetDynamicMesh();
  296. CMeshBuilder meshBuilder;
  297. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  298. meshBuilder.Color3f( 1.0, 1.0, 1.0 );
  299. meshBuilder.TexCoord2f( 0,0,0 );
  300. meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * flSize)).Base() );
  301. meshBuilder.AdvanceVertex();
  302. meshBuilder.Color3f( 1.0, 1.0, 1.0 );
  303. meshBuilder.TexCoord2f( 0,1,0 );
  304. meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * flSize)).Base() );
  305. meshBuilder.AdvanceVertex();
  306. meshBuilder.Color3f( 1.0, 1.0, 1.0 );
  307. meshBuilder.TexCoord2f( 0,1,1 );
  308. meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * -flSize)).Base() );
  309. meshBuilder.AdvanceVertex();
  310. meshBuilder.Color3f( 1.0, 1.0, 1.0 );
  311. meshBuilder.TexCoord2f( 0,0,1 );
  312. meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * -flSize)).Base() );
  313. meshBuilder.AdvanceVertex();
  314. meshBuilder.End();
  315. pMesh->Draw();
  316. }
  317. }
  318. void CVoiceStatus::UpdateSpeakerStatus(int entindex, int iSsSlot, bool bTalking)
  319. {
  320. if( !m_pParentPanel )
  321. return;
  322. if( voice_clientdebug.GetInt() == 1 )
  323. {
  324. Msg( "CVoiceStatus::UpdateSpeakerStatus: ent %d ss[%d] talking = %d\n",
  325. entindex, iSsSlot, bTalking );
  326. }
  327. else if ( voice_clientdebug.GetInt() == 2 )
  328. {
  329. con_nprint_t np;
  330. np.index = 0;
  331. np.color[0] = 1.0f;
  332. np.color[1] = 1.0f;
  333. np.color[2] = 1.0f;
  334. np.time_to_live = 2.0f;
  335. np.fixed_width_font = true;
  336. int numActiveChannels = VOICE_MAX_PLAYERS;
  337. engine->Con_NXPrintf ( &np, "Total Players: %i", numActiveChannels);
  338. for ( int i = 1; i <= numActiveChannels; i++ )
  339. {
  340. np.index++;
  341. np.color[0] = np.color[1] = np.color[2] = ( i % 2 == 0 ? 0.9f : 0.7f );
  342. if ( !IsPlayerBlocked( i ) && IsPlayerAudible( i ) && !ShouldHideCommunicationFromPlayer( i ) && IsPlayerSpeaking( i ) )
  343. {
  344. np.color[0] = 0.0f;
  345. np.color[1] = 1.0f;
  346. np.color[2] = 0.0f;
  347. }
  348. engine->Con_NXPrintf ( &np, "%02i enabled(%s) blocked(%s) audible(%s) speaking(%s)",
  349. i,
  350. m_VoiceEnabledPlayers[ i - 1 ] != 0 ? "YES" : " NO",
  351. IsPlayerBlocked( i ) ? "YES" : " NO",
  352. IsPlayerAudible( i ) ? "YES" : " NO",
  353. IsPlayerSpeaking( i ) ? "YES" : " NO" );
  354. }
  355. np.color[0] = 1.0f;
  356. np.color[1] = 1.0f;
  357. np.color[2] = 1.0f;
  358. np.index += 2;
  359. numActiveChannels = MAX_SPLITSCREEN_CLIENTS;
  360. engine->Con_NXPrintf ( &np, "Local Players: %i", numActiveChannels);
  361. for ( int i = 0; i < numActiveChannels; i++ )
  362. {
  363. np.index++;
  364. np.color[0] = np.color[1] = np.color[2] = ( i % 2 == 0 ? 0.9f : 0.7f );
  365. if ( IsLocalPlayerSpeaking( i ) && IsLocalPlayerSpeakingAboveThreshold( i ) )
  366. {
  367. np.color[0] = 0.0f;
  368. np.color[1] = 1.0f;
  369. np.color[2] = 0.0f;
  370. }
  371. engine->Con_NXPrintf ( &np, "%02i speaking(%s) above_threshold(%s)",
  372. i,
  373. IsLocalPlayerSpeaking( i ) ? "YES" : " NO",
  374. IsLocalPlayerSpeakingAboveThreshold( i ) ? "YES" : " NO" );
  375. }
  376. }
  377. // Is it the local player talking?
  378. if( entindex == -1 && iSsSlot >= 0 )
  379. {
  380. m_bTalking[ iSsSlot ] = !!bTalking;
  381. #if !defined( CSTRIKE15 )
  382. if( bTalking )
  383. {
  384. // Enable voice for them automatically if they try to talk.
  385. char chClientCmd[0xFF];
  386. Q_snprintf( chClientCmd, sizeof( chClientCmd ),
  387. "cmd%d voice_modenable 1", iSsSlot + 1 );
  388. engine->ClientCmd( chClientCmd );
  389. }
  390. #endif
  391. }
  392. if( entindex == -2 && iSsSlot >= 0 )
  393. {
  394. m_bServerAcked[ iSsSlot ] = !!bTalking;
  395. }
  396. if ( entindex == -3 && iSsSlot >= 0 )
  397. {
  398. m_bAboveThreshold[ iSsSlot ] = !!bTalking;
  399. if ( bTalking )
  400. {
  401. const float AboveThresholdMinDuration = 0.5f;
  402. m_bAboveThresholdTimer[ iSsSlot ].Start( AboveThresholdMinDuration );
  403. }
  404. }
  405. if( entindex > 0 && entindex <= VOICE_MAX_PLAYERS )
  406. {
  407. int iClient = entindex - 1;
  408. if(iClient < 0)
  409. return;
  410. if(bTalking)
  411. {
  412. m_VoicePlayers[iClient] = true;
  413. m_VoiceEnabledPlayers[iClient] = true;
  414. }
  415. else
  416. {
  417. m_VoicePlayers[iClient] = false;
  418. }
  419. if ( bTalking && m_bAboveThresholdTimer[ iClient ].IsElapsed() )
  420. {
  421. m_flTalkTime[ iClient ] += (gpGlobals->curtime - m_flTimeLastUpdate[ iClient ]);
  422. }
  423. else
  424. {
  425. #if defined( PORTAL2 ) && !defined( _GAMECONSOLE )
  426. if ( m_flTalkTime[ iClient ] > 0.0f )
  427. {
  428. g_PortalGameStats.Event_MicUsage( entindex, m_flTalkTime[ iClient ], gpGlobals->curtime - m_flTalkTime[ iClient ] );
  429. }
  430. #endif //!defined( _GAMECONSOLE )
  431. m_flTalkTime[ iClient ] = 0.0f;
  432. }
  433. m_flTimeLastUpdate[ iClient ] = gpGlobals->curtime;
  434. }
  435. }
  436. void CVoiceStatus::UpdateServerState(bool bForce)
  437. {
  438. // Can't do anything when we're not in a level.
  439. if( !g_bLevelInitialized )
  440. {
  441. if( voice_clientdebug.GetInt() == 1 )
  442. {
  443. Msg( "CVoiceStatus::UpdateServerState: g_bLevelInitialized\n" );
  444. }
  445. return;
  446. }
  447. int bCVarModEnable = !!voice_modenable.GetInt();
  448. if(bForce || m_bServerModEnable != bCVarModEnable)
  449. {
  450. m_bServerModEnable = bCVarModEnable;
  451. char str[256];
  452. Q_snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable);
  453. {
  454. HACK_GETLOCALPLAYER_GUARD( "CVoiceStatus::UpdateServerState" );
  455. engine->ServerCmd(str);
  456. }
  457. if( voice_clientdebug.GetInt() == 1 )
  458. {
  459. Msg( "CVoiceStatus::UpdateServerState: Sending '%s'\n", str );
  460. }
  461. }
  462. char str[2048];
  463. Q_strncpy(str,"vban",sizeof(str));
  464. bool bChange = false;
  465. for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
  466. {
  467. unsigned long serverBanMask = 0;
  468. unsigned long banMask = 0;
  469. for(unsigned long i=0; i < 32; i++)
  470. {
  471. int playerIndex = ( dw * 32 + i );
  472. if ( playerIndex >= MAX_PLAYERS )
  473. break;
  474. player_info_t pi;
  475. if ( !engine->GetPlayerInfo( i+1, &pi ) )
  476. continue;
  477. if ( m_BanMgr.GetPlayerBan( pi.guid ) || ShouldHideCommunicationFromPlayer( i + 1 ) )
  478. {
  479. banMask |= 1 << i;
  480. }
  481. if ( m_ServerBannedPlayers[playerIndex] )
  482. {
  483. serverBanMask |= 1 << i;
  484. }
  485. }
  486. if ( serverBanMask != banMask )
  487. {
  488. bChange = true;
  489. }
  490. // Ok, the server needs to be updated.
  491. char numStr[512];
  492. Q_snprintf(numStr,sizeof(numStr), " %lx", banMask);
  493. Q_strncat(str, numStr, sizeof(str), COPY_ALL_CHARACTERS);
  494. }
  495. if(bChange || bForce)
  496. {
  497. if( voice_clientdebug.GetInt() == 1 )
  498. {
  499. Msg( "CVoiceStatus::UpdateServerState: Sending '%s'\n", str );
  500. }
  501. engine->ServerCmd( str, false ); // Tell the server..
  502. }
  503. else
  504. {
  505. if( voice_clientdebug.GetInt() == 1 )
  506. {
  507. Msg( "CVoiceStatus::UpdateServerState: no change\n" );
  508. }
  509. }
  510. m_LastUpdateServerState = gpGlobals->curtime;
  511. }
  512. bool CVoiceStatus::HandleVoiceMaskMsg(const CCSUsrMsg_VoiceMask &msg)
  513. {
  514. unsigned long dw;
  515. for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++)
  516. {
  517. m_AudiblePlayers.SetDWord(dw, (unsigned long)msg.player_masks(dw).game_rules_mask());
  518. m_ServerBannedPlayers.SetDWord(dw, (unsigned long)msg.player_masks(dw).ban_masks());
  519. if( voice_clientdebug.GetInt() == 1 )
  520. {
  521. Msg("CVoiceStatus::HandleVoiceMaskMsg\n");
  522. Msg(" - m_AudiblePlayers[%lu] = %u\n", dw, m_AudiblePlayers.GetDWord(dw));
  523. Msg(" - m_ServerBannedPlayers[%lu] = %u\n", dw, m_ServerBannedPlayers.GetDWord(dw));
  524. }
  525. }
  526. m_bServerModEnable = msg.player_mod_enable();
  527. return true;
  528. }
  529. bool CVoiceStatus::HandleReqStateMsg(const CCSUsrMsg_RequestState &msg)
  530. {
  531. if( voice_clientdebug.GetInt() == 1 )
  532. {
  533. Msg("CVoiceStatus::HandleReqStateMsg\n");
  534. }
  535. UpdateServerState(true);
  536. return true;
  537. }
  538. void CVoiceStatus::StartSquelchMode()
  539. {
  540. if(m_bInSquelchMode)
  541. return;
  542. m_bInSquelchMode = true;
  543. m_pHelper->UpdateCursorState();
  544. }
  545. void CVoiceStatus::StopSquelchMode()
  546. {
  547. m_bInSquelchMode = false;
  548. m_pHelper->UpdateCursorState();
  549. }
  550. bool CVoiceStatus::IsInSquelchMode()
  551. {
  552. return m_bInSquelchMode;
  553. }
  554. void SetOrUpdateBounds(
  555. vgui::Panel *pPanel,
  556. int left, int top, int wide, int tall,
  557. bool bOnlyUpdateBounds, int &topCoord, int &bottomCoord )
  558. {
  559. if ( bOnlyUpdateBounds )
  560. {
  561. if ( top < topCoord )
  562. topCoord = top;
  563. if ( (top+tall) >= bottomCoord )
  564. bottomCoord = top+tall;
  565. }
  566. else
  567. {
  568. pPanel->SetBounds( left, top, wide, tall );
  569. }
  570. }
  571. //-----------------------------------------------------------------------------
  572. // Purpose: returns true if the target client has been banned
  573. // Input : playerID -
  574. // Output : Returns true on success, false on failure.
  575. //-----------------------------------------------------------------------------
  576. bool CVoiceStatus::IsPlayerBlocked(int iPlayer)
  577. {
  578. player_info_t pi;
  579. if ( !engine->GetPlayerInfo( iPlayer, &pi ) )
  580. return false;
  581. return m_BanMgr.GetPlayerBan( pi.guid );
  582. }
  583. bool IsPartyMember( XUID xuidPlayer )
  584. {
  585. if ( IMatchSession *pMatchSession = g_pMatchFramework->GetMatchSession() )
  586. {
  587. return SessionMembersFindPlayer( pMatchSession->GetSessionSettings(), xuidPlayer ) != NULL;
  588. }
  589. return false;
  590. }
  591. bool CVoiceStatus::ShouldHideCommunicationFromPlayer( int iPlayerIndex )
  592. {
  593. #if defined ( CSTRIKE15 )
  594. C_CSPlayer* pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  595. if ( pLocalPlayer && pLocalPlayer->entindex() == iPlayerIndex )
  596. return false;
  597. if ( cl_mute_enemy_team.GetBool() )
  598. {
  599. if ( pLocalPlayer && pLocalPlayer->IsOtherEnemy( iPlayerIndex ) &&
  600. ( pLocalPlayer->GetTeamNumber() == TEAM_CT || pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST ) )
  601. return true;
  602. }
  603. if ( cl_mute_all_but_friends_and_party.GetBool() && CSGameRules() && !CSGameRules()->IsQueuedMatchmaking() )
  604. {
  605. // This type of muting doesn't make sense when playing back a demo
  606. if ( engine->IsPlayingDemo() )
  607. return false;
  608. C_CSPlayer * pOther = ToCSPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
  609. CSteamID otherID;
  610. bool bIsInParty = false;
  611. if ( pOther && pOther->GetSteamID( &otherID ) )
  612. {
  613. if ( IsPartyMember( otherID.ConvertToUint64() ) )
  614. bIsInParty = true;
  615. }
  616. if ( pLocalPlayer && !pLocalPlayer->HasPlayerAsFriend( pOther ) && !bIsInParty )
  617. return true;
  618. }
  619. #endif
  620. return false;
  621. }
  622. //-----------------------------------------------------------------------------
  623. //-----------------------------------------------------------------------------
  624. // Purpose: blocks/unblocks the target client from being heard
  625. // Input : playerID -
  626. // Output : Returns true on success, false on failure.
  627. //-----------------------------------------------------------------------------
  628. void CVoiceStatus::SetPlayerBlockedState( int iPlayer )
  629. {
  630. if ( voice_clientdebug.GetInt() == 1 )
  631. {
  632. Msg( "CVoiceStatus::SetPlayerBlockedState part 1\n" );
  633. }
  634. player_info_t pi;
  635. if ( !engine->GetPlayerInfo( iPlayer, &pi ) )
  636. return;
  637. if ( voice_clientdebug.GetInt() == 1 )
  638. {
  639. Msg( "CVoiceStatus::SetPlayerBlockedState part 2\n" );
  640. }
  641. // Squelch or (try to) unsquelch this player.
  642. if ( voice_clientdebug.GetInt() == 1 )
  643. {
  644. Msg("CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(pi.guid));
  645. }
  646. m_BanMgr.SetPlayerBan(pi.guid, !m_BanMgr.GetPlayerBan(pi.guid));
  647. UpdateServerState(false);
  648. }
  649. //-----------------------------------------------------------------------------
  650. // Purpose:
  651. //-----------------------------------------------------------------------------
  652. void CVoiceStatus::SetHeadLabelMaterial( const char *pszMaterial )
  653. {
  654. if ( m_pHeadLabelMaterial )
  655. {
  656. m_pHeadLabelMaterial->DecrementReferenceCount();
  657. m_pHeadLabelMaterial = NULL;
  658. }
  659. m_pHeadLabelMaterial = materials->FindMaterial( pszMaterial, TEXTURE_GROUP_VGUI );
  660. m_pHeadLabelMaterial->IncrementReferenceCount();
  661. }