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.

1493 lines
42 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Normal HUD mode
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "cbase.h"
  10. #include "clientmode_shared.h"
  11. #include "iinput.h"
  12. #include "view_shared.h"
  13. #include "iviewrender.h"
  14. #include "hud_basechat.h"
  15. #include "weapon_selection.h"
  16. #include <vgui/IVGui.h>
  17. #include <vgui/Cursor.h>
  18. #include <vgui/IPanel.h>
  19. #include <vgui/IInput.h>
  20. #include "engine/IEngineSound.h"
  21. #include <keyvalues.h>
  22. #include <vgui_controls/AnimationController.h>
  23. #include "vgui_int.h"
  24. #include "hud_macros.h"
  25. #include "hltvcamera.h"
  26. #include "hud.h"
  27. #include "hud_element_helper.h"
  28. #include "Scaleform/HUD/sfhud_chat.h"
  29. #include "Scaleform/HUD/sfhudfreezepanel.h"
  30. #include "Scaleform/HUD/sfhud_teamcounter.h"
  31. #include "Scaleform/mapoverview.h"
  32. #include "hltvreplaysystem.h"
  33. #include "netmessages.h"
  34. #if defined( REPLAY_ENABLED )
  35. #include "replaycamera.h"
  36. #endif
  37. #include "particlemgr.h"
  38. #include "c_vguiscreen.h"
  39. #include "c_team.h"
  40. #include "c_rumble.h"
  41. #include "fmtstr.h"
  42. #include "c_playerresource.h"
  43. #include <localize/ilocalize.h>
  44. #include "gameui_interface.h"
  45. #include "menu.h" // CHudMenu
  46. #if defined( _X360 )
  47. #include "xbox/xbox_console.h"
  48. #endif
  49. #include "matchmaking/imatchframework.h"
  50. #include "clientmode_csnormal.h"
  51. #ifdef PORTAL2
  52. #include "c_basehlplayer.h"
  53. #endif // PORTAL2
  54. #ifdef CSTRIKE15
  55. #include "c_cs_playerresource.h"
  56. #endif
  57. // memdbgon must be the last include file in a .cpp file!!!
  58. #include "tier0/memdbgon.h"
  59. class CHudWeaponSelection;
  60. class CHudChat;
  61. static vgui::HContext s_hVGuiContext = DEFAULT_VGUI_CONTEXT;
  62. ConVar cl_drawhud( "cl_drawhud", "1", FCVAR_CHEAT, "Enable the rendering of the hud" );
  63. ConVar hud_takesshots( "hud_takesshots", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Auto-save a scoreboard screenshot at the end of a map." );
  64. ConVar spec_usenumberkeys_nobinds( "spec_usenumberkeys_nobinds", "1", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "If set to 1, map voting and spectator view use the raw number keys instead of the weapon binds (slot1, slot2, etc)." );
  65. ConVar spec_cameraman_ui( "spec_cameraman_ui", "0", FCVAR_CLIENTDLL | FCVAR_CLIENTCMD_CAN_EXECUTE, "If a cameraman is active then use their UI commands (scoreboard, overview, etc.)" );
  66. ConVar spec_cameraman_xray( "spec_cameraman_xray", "0", FCVAR_CLIENTDLL | FCVAR_CLIENTCMD_CAN_EXECUTE, "If a cameraman is active then use their Xray state." );
  67. ConVar spec_cameraman_disable_with_user_control( "spec_cameraman_disable_with_user_control", "0", FCVAR_CLIENTDLL | FCVAR_CLIENTCMD_CAN_EXECUTE, "Disable cameraman UI control when user controls camera." );
  68. extern ConVar v_viewmodel_fov;
  69. extern ConVar spec_show_xray;
  70. extern ConVar spec_hide_players;
  71. extern bool IsInCommentaryMode( void );
  72. CON_COMMAND( hud_reloadscheme, "Reloads hud layout and animation scripts." )
  73. {
  74. g_pFullFileSystem->SyncDvdDevCache();
  75. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  76. {
  77. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  78. ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal();
  79. if ( mode )
  80. {
  81. mode->ReloadScheme();
  82. }
  83. }
  84. ClientModeShared *mode = ( ClientModeShared * )GetFullscreenClientMode();
  85. if ( mode )
  86. {
  87. mode->ReloadSchemeWithRoot( VGui_GetFullscreenRootVPANEL() );
  88. }
  89. }
  90. #if 0
  91. CON_COMMAND_F( crash, "Crash the client. Optional parameter -- type of crash:\n 0: read from NULL\n 1: write to NULL\n 2: DmCrashDump() (xbox360 only)", FCVAR_CHEAT )
  92. {
  93. int crashtype = 0;
  94. int dummy;
  95. if ( args.ArgC() > 1 )
  96. {
  97. crashtype = Q_atoi( args[1] );
  98. }
  99. switch (crashtype)
  100. {
  101. case 0:
  102. dummy = *((int *) NULL);
  103. Msg("Crashed! %d\n", dummy); // keeps dummy from optimizing out
  104. break;
  105. case 1:
  106. *((int *)NULL) = 42;
  107. break;
  108. #if defined( _GAMECONSOLE )
  109. case 2:
  110. XBX_CrashDump( false );
  111. break;
  112. case 3:
  113. XBX_CrashDumpFullHeap( true );
  114. break;
  115. #endif
  116. default:
  117. Msg("Unknown variety of crash. You have now failed to crash. I hope you're happy.\n");
  118. break;
  119. }
  120. }
  121. #endif // _DEBUG
  122. static bool __MsgFunc_Rumble( const CCSUsrMsg_Rumble &msg )
  123. {
  124. unsigned char waveformIndex;
  125. unsigned char rumbleData;
  126. unsigned char rumbleFlags;
  127. waveformIndex = msg.index();
  128. rumbleData = msg.data();
  129. rumbleFlags = msg.flags();
  130. int userID = XBX_GetActiveUserId();
  131. RumbleEffect( userID, waveformIndex, rumbleData, rumbleFlags );
  132. return true;
  133. }
  134. static bool __MsgFunc_VGUIMenu( const CCSUsrMsg_VGUIMenu &msg )
  135. {
  136. bool bShow = msg.show();
  137. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  138. KeyValues *keys = NULL;
  139. if ( msg.subkeys_size() > 0 )
  140. {
  141. keys = new KeyValues("data");
  142. for (int i = 0; i < msg.subkeys_size(); i ++ )
  143. {
  144. const CCSUsrMsg_VGUIMenu::Subkey& subkey = msg.subkeys( i );
  145. keys->SetString( subkey.name().c_str(), subkey.str().c_str() );
  146. }
  147. }
  148. GetViewPortInterface()->ShowPanel( msg.name().c_str(), bShow, keys, true );
  149. // Don't do this since ShowPanel auto-deletes the keys
  150. // keys->deleteThis();
  151. // is the server telling us to show the scoreboard (at the end of a map)?
  152. if ( Q_stricmp( msg.name().c_str(), "scores" ) == 0 )
  153. {
  154. if ( hud_takesshots.GetBool() == true )
  155. {
  156. GetHud().SetScreenShotTime( gpGlobals->curtime + 1.0 ); // take a screenshot in 1 second
  157. }
  158. }
  159. return true;
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. ClientModeShared::ClientModeShared()
  165. {
  166. m_pViewport = NULL;
  167. m_pChatElement = NULL;
  168. m_pWeaponSelection = NULL;
  169. m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Purpose:
  173. //-----------------------------------------------------------------------------
  174. ClientModeShared::~ClientModeShared()
  175. {
  176. // VGui_Shutdown() should have deleted/NULL'd
  177. Assert( !m_pViewport );
  178. }
  179. void ClientModeShared::ReloadScheme( void )
  180. {
  181. ReloadSchemeWithRoot( VGui_GetClientDLLRootPanel() );
  182. }
  183. void ClientModeShared::ReloadSchemeWithRoot( vgui::VPANEL pRoot )
  184. {
  185. if ( pRoot )
  186. {
  187. int wide, tall;
  188. vgui::ipanel()->GetSize(pRoot, wide, tall);
  189. m_nRootSize[ 0 ] = wide;
  190. m_nRootSize[ 1 ] = tall;
  191. }
  192. m_pViewport->ReloadScheme( "resource/ClientScheme.res" );
  193. if ( GET_ACTIVE_SPLITSCREEN_SLOT() == 0 )
  194. {
  195. ClearKeyValuesCache();
  196. }
  197. // Msg( "Reload scheme [%d]\n", GET_ACTIVE_SPLITSCREEN_SLOT() );
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose:
  201. //-----------------------------------------------------------------------------
  202. void ClientModeShared::Init()
  203. {
  204. InitChatHudElement();
  205. InitWeaponSelectionHudElement();
  206. // Derived ClientMode class must make sure m_Viewport is instantiated
  207. Assert( m_pViewport );
  208. m_pViewport->LoadHudLayout();
  209. ListenForGameEvent( "player_connect_full" );
  210. ListenForGameEvent( "player_connect" );
  211. ListenForGameEvent( "player_disconnect" );
  212. ListenForGameEvent( "player_team" );
  213. ListenForGameEvent( "server_cvar" );
  214. ListenForGameEvent( "player_changename" );
  215. ListenForGameEvent( "teamplay_broadcast_audio" );
  216. ListenForGameEvent( "achievement_earned" );
  217. #if defined( TF_CLIENT_DLL ) || defined( CSTRIKE_CLIENT_DLL )
  218. ListenForGameEvent( "item_found" );
  219. ListenForGameEvent( "items_gifted" );
  220. #endif
  221. #if defined( INFESTED_DLL )
  222. ListenForGameEvent( "player_fullyjoined" );
  223. #endif
  224. HLTVCamera()->Init();
  225. #if defined( REPLAY_ENABLED )
  226. ReplayCamera()->Init();
  227. #endif
  228. m_CursorNone = vgui::dc_none;
  229. HOOK_MESSAGE( VGUIMenu );
  230. HOOK_MESSAGE( Rumble );
  231. }
  232. void ClientModeShared::InitChatHudElement()
  233. {
  234. m_pChatElement = CBaseHudChat::GetHudChat();
  235. Assert( m_pChatElement );
  236. }
  237. void ClientModeShared::InitWeaponSelectionHudElement()
  238. {
  239. m_pWeaponSelection = ( CBaseHudWeaponSelection * )GET_HUDELEMENT( CHudWeaponSelection );
  240. Assert( m_pWeaponSelection );
  241. }
  242. void ClientModeShared::InitViewport()
  243. {
  244. }
  245. void ClientModeShared::VGui_Shutdown()
  246. {
  247. delete m_pViewport;
  248. m_pViewport = NULL;
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose:
  252. //-----------------------------------------------------------------------------
  253. void ClientModeShared::Shutdown()
  254. {
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Purpose:
  258. // Input : frametime -
  259. // *cmd -
  260. //-----------------------------------------------------------------------------
  261. bool ClientModeShared::CreateMove( float flInputSampleTime, CUserCmd *cmd )
  262. {
  263. // Let the player override the view.
  264. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  265. if(!pPlayer)
  266. return true;
  267. // Let the player at it
  268. return pPlayer->CreateMove( flInputSampleTime, cmd );
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose:
  272. // Input : *pSetup -
  273. //-----------------------------------------------------------------------------
  274. void ClientModeShared::OverrideView( CViewSetup *pSetup )
  275. {
  276. QAngle camAngles;
  277. // Let the player override the view.
  278. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  279. if(!pPlayer)
  280. return;
  281. pPlayer->OverrideView( pSetup );
  282. if( ::input->CAM_IsThirdPerson() )
  283. {
  284. Vector cam_ofs;
  285. ::input->CAM_GetCameraOffset( cam_ofs );
  286. camAngles[ PITCH ] = cam_ofs[ PITCH ];
  287. camAngles[ YAW ] = cam_ofs[ YAW ];
  288. camAngles[ ROLL ] = 0;
  289. Vector camForward, camRight, camUp;
  290. AngleVectors( camAngles, &camForward, &camRight, &camUp );
  291. float flSavedZ = pSetup->origin.z;
  292. pSetup->origin = pPlayer->GetThirdPersonViewPosition();
  293. pSetup->origin.z -= (pSetup->origin.z - flSavedZ);
  294. VectorMA( pSetup->origin, -cam_ofs[ ROLL ], camForward, pSetup->origin );
  295. static ConVarRef c_thirdpersonshoulder( "c_thirdpersonshoulder" );
  296. if ( c_thirdpersonshoulder.GetBool() )
  297. {
  298. static ConVarRef c_thirdpersonshoulderoffset( "c_thirdpersonshoulderoffset" );
  299. static ConVarRef c_thirdpersonshoulderheight( "c_thirdpersonshoulderheight" );
  300. static ConVarRef c_thirdpersonshoulderaimdist( "c_thirdpersonshoulderaimdist" );
  301. // add the shoulder offset to the origin in the cameras right vector
  302. VectorMA( pSetup->origin, c_thirdpersonshoulderoffset.GetFloat(), camRight, pSetup->origin );
  303. // add the shoulder height to the origin in the cameras up vector
  304. VectorMA( pSetup->origin, c_thirdpersonshoulderheight.GetFloat(), camUp, pSetup->origin );
  305. // adjust the yaw to the aim-point
  306. camAngles[ YAW ] += RAD2DEG( atan(c_thirdpersonshoulderoffset.GetFloat() / (c_thirdpersonshoulderaimdist.GetFloat() + cam_ofs[ ROLL ])) );
  307. // adjust the pitch to the aim-point
  308. camAngles[ PITCH ] += RAD2DEG( atan(c_thirdpersonshoulderheight.GetFloat() / (c_thirdpersonshoulderaimdist.GetFloat() + cam_ofs[ ROLL ])) );
  309. }
  310. // Override angles from third person camera
  311. VectorCopy( camAngles, pSetup->angles );
  312. }
  313. else if (::input->CAM_IsOrthographic())
  314. {
  315. pSetup->m_bOrtho = true;
  316. float w, h;
  317. ::input->CAM_OrthographicSize( w, h );
  318. w *= 0.5f;
  319. h *= 0.5f;
  320. pSetup->m_OrthoLeft = -w;
  321. pSetup->m_OrthoTop = -h;
  322. pSetup->m_OrthoRight = w;
  323. pSetup->m_OrthoBottom = h;
  324. }
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose:
  328. //-----------------------------------------------------------------------------
  329. bool ClientModeShared::ShouldDrawEntity(C_BaseEntity *pEnt)
  330. {
  331. return true;
  332. }
  333. bool ClientModeShared::ShouldDrawParticles( )
  334. {
  335. return true;
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Purpose: Allow weapons to override mouse input (for binoculars)
  339. //-----------------------------------------------------------------------------
  340. void ClientModeShared::OverrideMouseInput( float *x, float *y )
  341. {
  342. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  343. C_BaseCombatWeapon *pWeapon = pPlayer ? pPlayer->GetActiveWeapon() : NULL;;
  344. if ( pWeapon )
  345. {
  346. pWeapon->OverrideMouseInput( x, y );
  347. }
  348. }
  349. //-----------------------------------------------------------------------------
  350. // Purpose:
  351. //-----------------------------------------------------------------------------
  352. bool ClientModeShared::ShouldDrawViewModel()
  353. {
  354. return true;
  355. }
  356. bool ClientModeShared::ShouldDrawDetailObjects( )
  357. {
  358. return true;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // Purpose:
  362. // Output : Returns true on success, false on failure.
  363. //-----------------------------------------------------------------------------
  364. bool ClientModeShared::ShouldDrawCrosshair( void )
  365. {
  366. return true;
  367. }
  368. //-----------------------------------------------------------------------------
  369. // Purpose: Don't draw the current view entity if we are not in 3rd person
  370. //-----------------------------------------------------------------------------
  371. bool ClientModeShared::ShouldDrawLocalPlayer( C_BasePlayer *pPlayer )
  372. {
  373. if ( pPlayer->IsViewEntity() && !pPlayer->ShouldDrawLocalPlayer() )
  374. return false;
  375. return true;
  376. }
  377. //-----------------------------------------------------------------------------
  378. // Purpose: The mode can choose to not draw fog
  379. //-----------------------------------------------------------------------------
  380. bool ClientModeShared::ShouldDrawFog( void )
  381. {
  382. return true;
  383. }
  384. //-----------------------------------------------------------------------------
  385. // Purpose:
  386. //-----------------------------------------------------------------------------
  387. void ClientModeShared::AdjustEngineViewport( int& x, int& y, int& width, int& height )
  388. {
  389. }
  390. //-----------------------------------------------------------------------------
  391. // Purpose:
  392. //-----------------------------------------------------------------------------
  393. void ClientModeShared::PreRender( CViewSetup *pSetup )
  394. {
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose:
  398. //-----------------------------------------------------------------------------
  399. void ClientModeShared::PostRender()
  400. {
  401. // Let the particle manager simulate things that haven't been simulated.
  402. ParticleMgr()->PostRender();
  403. }
  404. void ClientModeShared::PostRenderVGui()
  405. {
  406. }
  407. //-----------------------------------------------------------------------------
  408. // Purpose:
  409. //-----------------------------------------------------------------------------
  410. void ClientModeShared::Update()
  411. {
  412. if ( m_pViewport->IsVisible() != cl_drawhud.GetBool() )
  413. {
  414. m_pViewport->SetVisible( cl_drawhud.GetBool() );
  415. }
  416. UpdateRumbleEffects( XBX_GetActiveUserId() );
  417. }
  418. //-----------------------------------------------------------------------------
  419. // This processes all input before SV Move messages are sent
  420. //-----------------------------------------------------------------------------
  421. void ClientModeShared::ProcessInput(bool bActive)
  422. {
  423. GetHud().ProcessInput( bActive );
  424. }
  425. //-----------------------------------------------------------------------------
  426. // Purpose: We've received a keypress from the engine. Return 1 if the engine is allowed to handle it.
  427. //-----------------------------------------------------------------------------
  428. int ClientModeShared::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  429. {
  430. if ( engine->Con_IsVisible() )
  431. return 1;
  432. // Should we start typing a message?
  433. if ( pszCurrentBinding &&
  434. ( Q_strcmp( pszCurrentBinding, "messagemode" ) == 0 ||
  435. Q_strcmp( pszCurrentBinding, "say" ) == 0 ) )
  436. {
  437. if ( down )
  438. {
  439. StartMessageMode( MM_SAY );
  440. }
  441. return 0;
  442. }
  443. else if ( pszCurrentBinding &&
  444. ( Q_strcmp( pszCurrentBinding, "messagemode2" ) == 0 ||
  445. Q_strcmp( pszCurrentBinding, "say_team" ) == 0 ) )
  446. {
  447. if ( down )
  448. {
  449. StartMessageMode( MM_SAY_TEAM );
  450. }
  451. return 0;
  452. }
  453. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  454. if ( IsJoystickCode( keynum ) )
  455. {
  456. keynum = GetBaseButtonCode( keynum );
  457. }
  458. // If SourceMod menu is open (they use CHudMenu), give it input priority.
  459. bool bIsHudMenuOpen = false;
  460. CHudMenu *pHudMenu = GET_HUDELEMENT( CHudMenu );
  461. bIsHudMenuOpen = ( pHudMenu && pHudMenu->IsMenuOpen() );
  462. if ( bIsHudMenuOpen && !HudElementKeyInput( down, keynum, pszCurrentBinding ) )
  463. {
  464. return 0;
  465. }
  466. // if ingame spectator mode, let spectator input intercept key event here
  467. if( pPlayer &&
  468. ( pPlayer->GetObserverMode() > OBS_MODE_DEATHCAM ) &&
  469. !HandleSpectatorKeyInput( down, keynum, pszCurrentBinding ) )
  470. {
  471. return 0;
  472. }
  473. // Let game-specific hud elements get a crack at the key input
  474. if ( !HudElementKeyInput( down, keynum, pszCurrentBinding ) )
  475. {
  476. return 0;
  477. }
  478. C_BaseCombatWeapon *pWeapon = pPlayer ? pPlayer->GetActiveWeapon() : NULL;
  479. if ( pWeapon )
  480. {
  481. return pWeapon->KeyInput( down, keynum, pszCurrentBinding );
  482. }
  483. return 1;
  484. }
  485. //-----------------------------------------------------------------------------
  486. // Purpose: Helper to find if a binding exists in a possible chain of bindings
  487. //-----------------------------------------------------------------------------
  488. bool ContainsBinding( const char *pszBindingString, const char *pszBinding, bool bSearchAliases /*= false*/ )
  489. {
  490. if ( !strchr( pszBindingString, ';' ) && !bSearchAliases )
  491. {
  492. return !Q_stricmp( pszBindingString, pszBinding );
  493. }
  494. else
  495. {
  496. // Tokenize the binding name
  497. CUtlVectorAutoPurge< char *> cmdStrings;
  498. V_SplitString( pszBindingString, ";", cmdStrings );
  499. FOR_EACH_VEC( cmdStrings, i )
  500. {
  501. char* szCmd = cmdStrings[ i ];
  502. if ( bSearchAliases )
  503. {
  504. // Search for command in any contained aliases.
  505. const char* szAliasCmd = engine->AliasToCommandString( szCmd );
  506. // NOTE: we could use some kind of recursion guard, but recursive aliases already infinite loop
  507. // when being processed by the cmd system.
  508. if ( szAliasCmd )
  509. {
  510. CUtlString strCmd( szAliasCmd );
  511. V_StripTrailingWhitespace( strCmd.Access() ); // Alias adds trailing spaces to commands, strip it here so the compare works
  512. if ( ContainsBinding( strCmd.Get(), pszBinding, true ) )
  513. return true;
  514. }
  515. }
  516. if ( !Q_stricmp( pszBinding, szCmd ) )
  517. {
  518. return true;
  519. }
  520. }
  521. return false;
  522. }
  523. }
  524. void ClientModeShared::UpdateCameraManUIState( int iType, int nOptionalParam, uint64 xuid )
  525. {
  526. /* Removed for partner depot */
  527. }
  528. void SendCameraManUIStateChange( HltvUiType_t eventType, int nOptionalParam )
  529. {
  530. // this sends a client command to the server which will then change the server side states and propagate that out to everyone
  531. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  532. if ( pPlayer && pPlayer->IsActiveCameraMan() )
  533. {
  534. char szTemp[ 256 ];
  535. V_sprintf_safe( szTemp, "cameraman_ui_state %d %d", eventType, nOptionalParam );
  536. engine->ClientCmd( szTemp );
  537. }
  538. }
  539. void ClientModeShared::ScoreboardOff()
  540. {
  541. //SendCameraManUIStateChange( HLTV_UI_SCOREBOARD_OFF );
  542. }
  543. void ClientModeShared::GraphPageChanged()
  544. {
  545. /* Removed for partner depot */
  546. }
  547. //-----------------------------------------------------------------------------
  548. // Purpose: See if spectator input occurred. Return 0 if the key is swallowed.
  549. //-----------------------------------------------------------------------------
  550. int ClientModeShared::HandleSpectatorKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  551. {
  552. /* Removed for partner depot */
  553. return 1;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Purpose: See if hud elements want key input. Return 0 if the key is swallowed
  557. //-----------------------------------------------------------------------------
  558. int ClientModeShared::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  559. {
  560. if ( GetFullscreenClientMode() && GetFullscreenClientMode() != this &&
  561. !GetFullscreenClientMode()->HudElementKeyInput( down, keynum, pszCurrentBinding ) )
  562. return 0;
  563. if ( CSGameRules() && CSGameRules()->IsEndMatchVotingForNextMap() )
  564. {
  565. // this looks messy, but essentially, if the convar is set to true, use the bindings, if not use the raw keys
  566. if ( down && (( spec_usenumberkeys_nobinds.GetBool() == false && pszCurrentBinding &&
  567. ( ContainsBinding( pszCurrentBinding, "slot1" ) ||
  568. ContainsBinding( pszCurrentBinding, "slot2" ) ||
  569. ContainsBinding( pszCurrentBinding, "slot3" ) ||
  570. ContainsBinding( pszCurrentBinding, "slot4" ) ||
  571. ContainsBinding( pszCurrentBinding, "slot5" ) ||
  572. ContainsBinding( pszCurrentBinding, "slot6" ) ||
  573. ContainsBinding( pszCurrentBinding, "slot7" ) ||
  574. ContainsBinding( pszCurrentBinding, "slot8" ) ||
  575. ContainsBinding( pszCurrentBinding, "slot9" ) ||
  576. ContainsBinding( pszCurrentBinding, "slot10" ) ) )
  577. ||
  578. ( spec_usenumberkeys_nobinds.GetBool() == true &&
  579. ( keynum == KEY_1 ||
  580. keynum == KEY_2 ||
  581. keynum == KEY_3 ||
  582. keynum == KEY_4 ||
  583. keynum == KEY_5 ||
  584. keynum == KEY_6 ||
  585. keynum == KEY_7 ||
  586. keynum == KEY_8 ||
  587. keynum == KEY_9 ||
  588. keynum == KEY_0 ) ) ) )
  589. {
  590. int slotnum = 0;
  591. if ( spec_usenumberkeys_nobinds.GetBool() )
  592. {
  593. slotnum = ( keynum - KEY_0 ) - 1;
  594. }
  595. else
  596. {
  597. char* slotnumberchar = ( char * )pszCurrentBinding + strlen( pszCurrentBinding ) - 1;
  598. slotnum = atoi( slotnumberchar ) - 1;
  599. }
  600. if ( slotnum < 0 )
  601. slotnum = 10 + slotnum;
  602. char commandBuffer[32];
  603. V_snprintf( commandBuffer, sizeof( commandBuffer ), "endmatch_votenextmap %d", slotnum );
  604. engine->ClientCmd( commandBuffer );
  605. return 0;
  606. }
  607. }
  608. if ( down && pszCurrentBinding && ContainsBinding( pszCurrentBinding, "radio1" ) )
  609. {
  610. /* Removed for partner depot */
  611. return 0;
  612. }
  613. if ( m_pWeaponSelection )
  614. {
  615. if ( !m_pWeaponSelection->KeyInput( down, keynum, pszCurrentBinding ) )
  616. {
  617. return 0;
  618. }
  619. }
  620. return 1;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Purpose:
  624. // Output : vgui::Panel
  625. //-----------------------------------------------------------------------------
  626. vgui::Panel *ClientModeShared::GetMessagePanel()
  627. {
  628. if ( m_pChatElement && m_pChatElement->GetInputPanel() && m_pChatElement->GetInputPanel()->IsVisible() )
  629. return m_pChatElement->GetInputPanel();
  630. return NULL;
  631. }
  632. //-----------------------------------------------------------------------------
  633. // Purpose: The player has started to type a message
  634. //-----------------------------------------------------------------------------
  635. void ClientModeShared::StartMessageMode( int iMessageModeType )
  636. {
  637. // Can only show chat UI in multiplayer!!!
  638. if ( gpGlobals->maxClients == 1 )
  639. {
  640. return;
  641. }
  642. SFHudChat* pChat = GET_HUDELEMENT( SFHudChat );
  643. if ( pChat )
  644. {
  645. pChat->StartMessageMode( iMessageModeType );
  646. }
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose:
  650. // Input : *newmap -
  651. //-----------------------------------------------------------------------------
  652. void ClientModeShared::LevelInit( const char *newmap )
  653. {
  654. m_pViewport->GetAnimationController()->StartAnimationSequence("LevelInit");
  655. // Tell the Chat Interface
  656. if ( m_pChatElement )
  657. {
  658. m_pChatElement->LevelInit( newmap );
  659. }
  660. // we have to fake this event clientside, because clients connect after that
  661. IGameEvent *event = gameeventmanager->CreateEvent( "game_newmap" );
  662. if ( event )
  663. {
  664. event->SetString("mapname", newmap );
  665. gameeventmanager->FireEventClientSide( event );
  666. }
  667. // Create a vgui context for all of the in-game vgui panels...
  668. if ( s_hVGuiContext == DEFAULT_VGUI_CONTEXT )
  669. {
  670. s_hVGuiContext = vgui::ivgui()->CreateContext();
  671. }
  672. // Reset any player explosion/shock effects
  673. CLocalPlayerFilter filter;
  674. enginesound->SetPlayerDSP( filter, 0, true );
  675. }
  676. //-----------------------------------------------------------------------------
  677. // Purpose:
  678. //-----------------------------------------------------------------------------
  679. void ClientModeShared::LevelShutdown( void )
  680. {
  681. if ( m_pChatElement )
  682. {
  683. m_pChatElement->LevelShutdown();
  684. }
  685. if ( s_hVGuiContext != DEFAULT_VGUI_CONTEXT )
  686. {
  687. vgui::ivgui()->DestroyContext( s_hVGuiContext );
  688. s_hVGuiContext = DEFAULT_VGUI_CONTEXT;
  689. }
  690. // Reset any player explosion/shock effects
  691. CLocalPlayerFilter filter;
  692. enginesound->SetPlayerDSP( filter, 0, true );
  693. }
  694. void ClientModeShared::Enable()
  695. {
  696. vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();
  697. EnableWithRootPanel( pRoot );
  698. }
  699. void ClientModeShared::EnableWithRootPanel( vgui::VPANEL pRoot )
  700. {
  701. // Add our viewport to the root panel.
  702. if( pRoot != NULL )
  703. {
  704. m_pViewport->SetParent( pRoot );
  705. }
  706. // All hud elements should be proportional
  707. // This sets that flag on the viewport and all child panels
  708. m_pViewport->SetProportional( true );
  709. m_pViewport->SetCursor( m_CursorNone );
  710. vgui::surface()->SetCursor( m_CursorNone );
  711. m_pViewport->SetVisible( true );
  712. if ( m_pViewport->IsKeyBoardInputEnabled() )
  713. {
  714. m_pViewport->RequestFocus();
  715. }
  716. Layout();
  717. }
  718. void ClientModeShared::Disable()
  719. {
  720. vgui::VPANEL pRoot;
  721. // Remove our viewport from the root panel.
  722. if( ( pRoot = VGui_GetClientDLLRootPanel() ) != NULL )
  723. {
  724. m_pViewport->SetParent( (vgui::VPANEL)NULL );
  725. }
  726. m_pViewport->SetVisible( false );
  727. }
  728. void ClientModeShared::Layout( bool bForce /*= false*/)
  729. {
  730. vgui::VPANEL pRoot;
  731. int wide, tall;
  732. // Make the viewport fill the root panel.
  733. if( ( pRoot = m_pViewport->GetVParent() ) != NULL )
  734. {
  735. vgui::ipanel()->GetSize(pRoot, wide, tall);
  736. bool changed = wide != m_nRootSize[ 0 ] || tall != m_nRootSize[ 1 ];
  737. m_pViewport->SetBounds(0, 0, wide, tall);
  738. if ( changed || bForce )
  739. {
  740. ReloadSchemeWithRoot( pRoot );
  741. }
  742. }
  743. }
  744. #ifdef IRONSIGHT
  745. #ifdef DEBUG
  746. ConVar ironsight_scoped_viewmodel_fov( "ironsight_scoped_viewmodel_fov", "54", FCVAR_CHEAT, "The fov of the viewmodel when ironsighted" );
  747. #else
  748. #define IRONSIGHT_SCOPED_FOV 54.0f
  749. #endif
  750. #endif
  751. float ClientModeShared::GetViewModelFOV( void )
  752. {
  753. #ifdef IRONSIGHT
  754. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  755. if ( pPlayer )
  756. {
  757. CWeaponCSBase *pIronSightWeapon = (CWeaponCSBase*)pPlayer->GetActiveWeapon();
  758. if ( pIronSightWeapon )
  759. {
  760. CIronSightController* pIronSightController = pIronSightWeapon->GetIronSightController();
  761. if ( pIronSightController && pIronSightController->IsInIronSight() )
  762. {
  763. return FLerp( v_viewmodel_fov.GetFloat(),
  764. #ifdef DEBUG
  765. ironsight_scoped_viewmodel_fov.GetFloat(),
  766. #else
  767. IRONSIGHT_SCOPED_FOV,
  768. #endif
  769. pIronSightController->GetIronSightAmount() );
  770. }
  771. }
  772. }
  773. #endif
  774. return v_viewmodel_fov.GetFloat();
  775. }
  776. vgui::Panel *ClientModeShared::GetPanelFromViewport( const char *pchNamePath )
  777. {
  778. char szTagetName[ 256 ];
  779. Q_strncpy( szTagetName, pchNamePath, sizeof(szTagetName) );
  780. char *pchName = szTagetName;
  781. char *pchEndToken = strchr( pchName, ';' );
  782. if ( pchEndToken )
  783. {
  784. *pchEndToken = '\0';
  785. }
  786. char *pchNextName = strchr( pchName, '/' );
  787. if ( pchNextName )
  788. {
  789. *pchNextName = '\0';
  790. pchNextName++;
  791. }
  792. // Comma means we want to count to a specific instance by name
  793. int nInstance = 0;
  794. char *pchInstancePos = strchr( pchName, ',' );
  795. if ( pchInstancePos )
  796. {
  797. *pchInstancePos = '\0';
  798. pchInstancePos++;
  799. nInstance = atoi( pchInstancePos );
  800. }
  801. // Find the child
  802. int nCurrentInstance = 0;
  803. vgui::Panel *pPanel = NULL;
  804. for ( int i = 0; i < GetViewport()->GetChildCount(); i++ )
  805. {
  806. Panel *pChild = GetViewport()->GetChild( i );
  807. if ( !pChild )
  808. continue;
  809. if ( stricmp( pChild->GetName(), pchName ) == 0 )
  810. {
  811. nCurrentInstance++;
  812. if ( nCurrentInstance > nInstance )
  813. {
  814. pPanel = pChild;
  815. break;
  816. }
  817. }
  818. }
  819. pchName = pchNextName;
  820. while ( pPanel )
  821. {
  822. if ( !pchName || pchName[ 0 ] == '\0' )
  823. {
  824. break;
  825. }
  826. pchNextName = strchr( pchName, '/' );
  827. if ( pchNextName )
  828. {
  829. *pchNextName = '\0';
  830. pchNextName++;
  831. }
  832. // Comma means we want to count to a specific instance by name
  833. nInstance = 0;
  834. pchInstancePos = strchr( pchName, ',' );
  835. if ( pchInstancePos )
  836. {
  837. *pchInstancePos = '\0';
  838. pchInstancePos++;
  839. nInstance = atoi( pchInstancePos );
  840. }
  841. // Find the child
  842. nCurrentInstance = 0;
  843. vgui::Panel *pNextPanel = NULL;
  844. for ( int i = 0; i < pPanel->GetChildCount(); i++ )
  845. {
  846. Panel *pChild = pPanel->GetChild( i );
  847. if ( !pChild )
  848. continue;
  849. if ( stricmp( pChild->GetName(), pchName ) == 0 )
  850. {
  851. nCurrentInstance++;
  852. if ( nCurrentInstance > nInstance )
  853. {
  854. pNextPanel = pChild;
  855. break;
  856. }
  857. }
  858. }
  859. pPanel = pNextPanel;
  860. pchName = pchNextName;
  861. }
  862. return pPanel;
  863. }
  864. class CHudChat;
  865. bool PlayerNameNotSetYet( const char *pszName )
  866. {
  867. if ( pszName && pszName[0] )
  868. {
  869. // Don't show "unconnected" if we haven't got the players name yet
  870. if ( StringHasPrefix( pszName, "unconnected" ) )
  871. return true;
  872. if ( StringHasPrefix( pszName, "NULLNAME" ) )
  873. return true;
  874. }
  875. return false;
  876. }
  877. void ClientModeShared::FireGameEvent( IGameEvent *event )
  878. {
  879. ACTIVE_SPLITSCREEN_PLAYER_GUARD( GetSplitScreenPlayerSlot() );
  880. CBaseHudChat *hudChat = CBaseHudChat::GetHudChat();
  881. const char *eventname = event->GetName();
  882. if ( Q_strcmp( "player_connect", eventname ) == 0 )
  883. {
  884. #ifdef PORTAL2
  885. // dont show these message on the console at all
  886. if ( IsGameConsole() )
  887. return;
  888. #endif
  889. if ( this == GetFullscreenClientMode() )
  890. return;
  891. if ( !hudChat )
  892. return;
  893. if ( PlayerNameNotSetYet(event->GetString("name")) )
  894. return;
  895. if ( !IsInCommentaryMode() )
  896. {
  897. wchar_t wszLocalized[100];
  898. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  899. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("name"), wszPlayerName, sizeof(wszPlayerName) );
  900. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_connecting" ), 1, wszPlayerName );
  901. char szLocalized[100];
  902. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  903. hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized );
  904. }
  905. }
  906. else if ( Q_strcmp( "player_connect_full", eventname ) == 0 )
  907. {
  908. CLocalPlayerFilter filter;
  909. C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "Music.StopMenuMusic" );
  910. GameUI().SetBackgroundMusicDesired( false );
  911. }
  912. else if ( Q_strcmp( "player_disconnect", eventname ) == 0 )
  913. {
  914. #ifdef PORTAL2
  915. // dont show these message on the console at all
  916. if ( IsGameConsole() )
  917. return;
  918. #endif
  919. if ( this == GetFullscreenClientMode() )
  920. return;
  921. int userID = event->GetInt("userid");
  922. C_BasePlayer *pPlayer = USERID2PLAYER( userID );
  923. // don't show disconnects for bots in coop
  924. if ( CSGameRules() && CSGameRules()->IsPlayingCooperativeGametype() && (pPlayer && pPlayer->IsBot()) )
  925. return;
  926. if ( !hudChat || !pPlayer )
  927. return;
  928. if ( PlayerNameNotSetYet(event->GetString("name")) )
  929. return;
  930. if ( !IsInCommentaryMode() )
  931. {
  932. #ifdef CSTRIKE15
  933. wchar_t wszPlayerName[MAX_DECORATED_PLAYER_NAME_LENGTH];
  934. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  935. pCSPR->GetDecoratedPlayerName( pPlayer->entindex(), wszPlayerName, sizeof( wszPlayerName ), ( EDecoratedPlayerNameFlag_t) ( k_EDecoratedPlayerNameFlag_DontUseNameOfControllingPlayer | k_EDecoratedPlayerNameFlag_DontUseAssassinationTargetName ) );
  936. #else
  937. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  938. g_pVGuiLocalize->ConvertANSIToUnicode( pPlayer->GetPlayerName(), wszPlayerName, sizeof(wszPlayerName) );
  939. #endif
  940. wchar_t wszReasonBuf[64];
  941. wchar_t const *wszReason = wszReasonBuf;
  942. char const *szReasonToken = event->GetString("reason");
  943. static bool s_bPerfectWorld = !!CommandLine()->FindParm( "-perfectworld" ); // we don't localize reasons in Perfect World because they are supplied by server
  944. if ( s_bPerfectWorld && !( szReasonToken && szReasonToken[0] == '#' ) )
  945. wszReason = g_pVGuiLocalize->Find( "#SFUI_Disconnect_Title" );
  946. else
  947. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString( "reason" ), wszReasonBuf, sizeof( wszReasonBuf ) );
  948. wchar_t wszLocalized[100];
  949. if ( IsPC() )
  950. {
  951. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 2, wszPlayerName, wszReason );
  952. }
  953. else
  954. {
  955. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_left_game" ), 1, wszPlayerName );
  956. }
  957. char szLocalized[100];
  958. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  959. hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized );
  960. }
  961. }
  962. else if ( Q_strcmp( "player_fullyjoined", eventname ) == 0 )
  963. {
  964. #ifdef PORTAL2
  965. // dont show these message on the console at all
  966. if ( IsGameConsole() )
  967. return;
  968. #endif
  969. if ( !hudChat )
  970. return;
  971. if ( PlayerNameNotSetYet(event->GetString("name")) )
  972. return;
  973. wchar_t wszLocalized[100];
  974. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  975. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("name"), wszPlayerName, sizeof(wszPlayerName) );
  976. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_game" ), 1, wszPlayerName );
  977. char szLocalized[100];
  978. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  979. hudChat->Printf( CHAT_FILTER_JOINLEAVE, "%s", szLocalized );
  980. }
  981. else if ( Q_strcmp( "player_team", eventname ) == 0 )
  982. {
  983. if ( this == GetFullscreenClientMode() )
  984. return;
  985. C_BasePlayer *pPlayer = USERID2PLAYER( event->GetInt("userid") );
  986. if ( !hudChat )
  987. return;
  988. if ( !pPlayer )
  989. return;
  990. bool bDisconnected = event->GetBool("disconnect");
  991. if ( bDisconnected )
  992. return;
  993. int team = event->GetInt( "team" );
  994. bool bAutoTeamed = event->GetBool( "autoteam", false );
  995. bool bSilent = event->GetBool( "silent", false );
  996. const char *pszName = pPlayer->GetPlayerName();
  997. if ( PlayerNameNotSetYet(pszName) )
  998. return;
  999. if ( !bSilent )
  1000. {
  1001. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  1002. g_pVGuiLocalize->ConvertANSIToUnicode( pszName, wszPlayerName, sizeof(wszPlayerName) );
  1003. wchar_t wszTeam[64];
  1004. C_Team *pTeam = GetGlobalTeam( team );
  1005. if ( pTeam )
  1006. {
  1007. g_pVGuiLocalize->ConvertANSIToUnicode( pTeam->Get_Name(), wszTeam, sizeof(wszTeam) );
  1008. }
  1009. else
  1010. {
  1011. Q_snwprintf ( wszTeam, sizeof( wszTeam ) / sizeof( wchar_t ), L"%d", team );
  1012. }
  1013. if ( !IsInCommentaryMode() )
  1014. {
  1015. wchar_t wszLocalized[100];
  1016. if ( bAutoTeamed )
  1017. {
  1018. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_autoteam" ), 2, wszPlayerName, wszTeam );
  1019. }
  1020. else
  1021. {
  1022. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_joined_team" ), 2, wszPlayerName, wszTeam );
  1023. }
  1024. char szLocalized[100];
  1025. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  1026. hudChat->Printf( CHAT_FILTER_TEAMCHANGE, "%s", szLocalized );
  1027. }
  1028. }
  1029. if ( C_BasePlayer::IsLocalPlayer( pPlayer ) )
  1030. {
  1031. ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( pPlayer );
  1032. // that's me
  1033. pPlayer->TeamChange( team );
  1034. }
  1035. }
  1036. else if ( Q_strcmp( "player_changename", eventname ) == 0 )
  1037. {
  1038. if ( this == GetFullscreenClientMode() )
  1039. return;
  1040. if ( !hudChat )
  1041. return;
  1042. const char *pszOldName = event->GetString("oldname");
  1043. if ( PlayerNameNotSetYet(pszOldName) )
  1044. return;
  1045. wchar_t wszOldName[MAX_PLAYER_NAME_LENGTH];
  1046. g_pVGuiLocalize->ConvertANSIToUnicode( pszOldName, wszOldName, sizeof(wszOldName) );
  1047. wchar_t wszNewName[MAX_PLAYER_NAME_LENGTH];
  1048. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString( "newname" ), wszNewName, sizeof(wszNewName) );
  1049. wchar_t wszLocalized[100];
  1050. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_player_changed_name" ), 2, wszOldName, wszNewName );
  1051. char szLocalized[100];
  1052. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  1053. hudChat->Printf( CHAT_FILTER_NAMECHANGE, "%s", szLocalized );
  1054. }
  1055. else if ( Q_strcmp( "teamplay_broadcast_audio", eventname ) == 0 )
  1056. {
  1057. if ( this == GetFullscreenClientMode() )
  1058. return;
  1059. int team = event->GetInt( "team" );
  1060. bool bValidTeam = false;
  1061. if ( (GetLocalTeam() && GetLocalTeam()->GetTeamNumber() == team) )
  1062. {
  1063. bValidTeam = true;
  1064. }
  1065. //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets.
  1066. if ( bValidTeam == false )
  1067. {
  1068. CBasePlayer *pSpectatorTarget = UTIL_PlayerByIndex( GetSpectatorTarget() );
  1069. if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE) )
  1070. {
  1071. if ( pSpectatorTarget->GetTeamNumber() == team )
  1072. {
  1073. bValidTeam = true;
  1074. }
  1075. }
  1076. }
  1077. if ( team == 0 && GetLocalTeam() > 0 )
  1078. {
  1079. bValidTeam = false;
  1080. }
  1081. if ( team == 255 )
  1082. {
  1083. bValidTeam = true;
  1084. }
  1085. if ( bValidTeam == true )
  1086. {
  1087. CLocalPlayerFilter filter;
  1088. const char *pszSoundName = event->GetString("sound");
  1089. C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, pszSoundName );
  1090. }
  1091. }
  1092. else if ( Q_strcmp( "teamplay_broadcast_audio", eventname ) == 0 )
  1093. {
  1094. if ( this == GetFullscreenClientMode() )
  1095. return;
  1096. int team = event->GetInt( "team" );
  1097. if ( !team || (GetLocalTeam() && GetLocalTeam()->GetTeamNumber() == team) )
  1098. {
  1099. CLocalPlayerFilter filter;
  1100. const char *pszSoundName = event->GetString("sound");
  1101. C_BaseEntity::EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, pszSoundName );
  1102. }
  1103. }
  1104. else if ( Q_strcmp( "server_cvar", eventname ) == 0 )
  1105. {
  1106. if ( (IsGameConsole() && IsCert()) || (IsGameConsole() && developer.GetInt() < 2) )
  1107. return;
  1108. if ( this == GetFullscreenClientMode() )
  1109. return;
  1110. static bool s_bPerfectWorld = !!CommandLine()->FindParm( "-perfectworld" );
  1111. if ( s_bPerfectWorld )
  1112. return; // Perfect World cvars are not printed in client
  1113. char const *szCvarName = event->GetString("cvarname");
  1114. char const * arrIgnoredCvars[] = { "nextlevel" };
  1115. bool bIgnoredCvar = false;
  1116. for ( int ii = 0; ii < Q_ARRAYSIZE( arrIgnoredCvars ); ++ ii )
  1117. {
  1118. if ( !V_stricmp( szCvarName, arrIgnoredCvars[ii] ) )
  1119. {
  1120. bIgnoredCvar = true;
  1121. break;
  1122. }
  1123. }
  1124. if ( !IsInCommentaryMode() && !bIgnoredCvar )
  1125. {
  1126. wchar_t wszCvarName[64];
  1127. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarname"), wszCvarName, sizeof(wszCvarName) );
  1128. wchar_t wszCvarValue[16];
  1129. g_pVGuiLocalize->ConvertANSIToUnicode( event->GetString("cvarvalue"), wszCvarValue, sizeof(wszCvarValue) );
  1130. wchar_t wszLocalized[100];
  1131. g_pVGuiLocalize->ConstructString( wszLocalized, sizeof( wszLocalized ), g_pVGuiLocalize->Find( "#game_server_cvar_changed" ), 2, wszCvarName, wszCvarValue );
  1132. char szLocalized[100];
  1133. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalized, szLocalized, sizeof(szLocalized) );
  1134. hudChat->Printf( CHAT_FILTER_SERVERMSG, "%s", szLocalized );
  1135. }
  1136. }
  1137. else if ( Q_strcmp( "achievement_earned", eventname ) == 0 )
  1138. {
  1139. if ( this == GetFullscreenClientMode() )
  1140. return;
  1141. int iPlayerIndex = event->GetInt( "player" );
  1142. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
  1143. int iAchievement = event->GetInt( "achievement" );
  1144. if ( !hudChat || !pPlayer )
  1145. return;
  1146. if ( !IsInCommentaryMode() )
  1147. {
  1148. char const *szAchievementName = NULL; // should arrive as part of event instead of achievement ID
  1149. if ( szAchievementName )
  1150. {
  1151. if ( !pPlayer->IsDormant() )
  1152. {
  1153. // no particle effect if the local player is the one with the achievement or the player is dead
  1154. if ( !C_BasePlayer::IsLocalPlayer( pPlayer ) && pPlayer->IsAlive() )
  1155. {
  1156. //tagES using the "head" attachment won't work for CS and DoD
  1157. pPlayer->ParticleProp()->Create( "achieved", PATTACH_POINT_FOLLOW, "head" );
  1158. }
  1159. pPlayer->OnAchievementAchieved( iAchievement );
  1160. }
  1161. if ( g_PR )
  1162. {
  1163. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  1164. g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) );
  1165. const wchar_t *pchLocalizedAchievement = g_pVGuiLocalize->Find( CFmtStr( "#%s_T", szAchievementName ) );
  1166. if ( pchLocalizedAchievement )
  1167. {
  1168. wchar_t wszLocalizedString[128];
  1169. g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), g_pVGuiLocalize->Find( "#Achievement_Earned" ), 2, wszPlayerName, pchLocalizedAchievement );
  1170. char szLocalized[128];
  1171. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) );
  1172. hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized );
  1173. }
  1174. }
  1175. }
  1176. }
  1177. }
  1178. #if defined( TF_CLIENT_DLL ) || defined( CSTRIKE_CLIENT_DLL )
  1179. else if ( Q_strcmp( "item_found", eventname ) == 0 )
  1180. {
  1181. int iPlayerIndex = event->GetInt( "player" );
  1182. //entityquality_t iItemQuality = event->GetInt( "quality" );
  1183. int iMethod = event->GetInt( "method" );
  1184. int iItemDef = event->GetInt( "itemdef" );
  1185. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
  1186. const GameItemDefinition_t *pItemDefinition = dynamic_cast<const GameItemDefinition_t *>( GetItemSchema()->GetItemDefinition( iItemDef ) );
  1187. if ( !pPlayer || !pItemDefinition )
  1188. return;
  1189. if ( g_PR )
  1190. {
  1191. wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH];
  1192. g_pVGuiLocalize->ConvertANSIToUnicode( g_PR->GetPlayerName( iPlayerIndex ), wszPlayerName, sizeof( wszPlayerName ) );
  1193. if ( iMethod < 0 || iMethod >= ARRAYSIZE( g_pszItemFoundMethodStrings ) )
  1194. {
  1195. iMethod = 0;
  1196. }
  1197. const char *pszLocString = g_pszItemFoundMethodStrings[iMethod];
  1198. if ( pszLocString )
  1199. {
  1200. wchar_t wszItemFound[256];
  1201. V_swprintf_safe( wszItemFound, L"%ls", g_pVGuiLocalize->Find( pszLocString ) );
  1202. wchar_t *colorMarker = wcsstr( wszItemFound, L"::" );
  1203. if ( colorMarker )
  1204. {
  1205. //const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality );
  1206. //if ( pszQualityColorString )
  1207. //{
  1208. // hudChat->SetCustomColor( pszQualityColorString );
  1209. // *(colorMarker+1) = COLOR_CUSTOM;
  1210. //}
  1211. *(colorMarker+1) = wszItemFound[ 0 ];
  1212. }
  1213. // TODO: Update the localization strings to only have two format parameters since that's all we need.
  1214. wchar_t wszLocalizedString[256];
  1215. g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), wszItemFound, 3, wszPlayerName, g_pVGuiLocalize->Find( pItemDefinition->GetItemBaseName() ), L"" );
  1216. char szLocalized[256];
  1217. g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) );
  1218. hudChat->ChatPrintf( iPlayerIndex, CHAT_FILTER_SERVERMSG, "%s", szLocalized );
  1219. }
  1220. }
  1221. }
  1222. #endif
  1223. else
  1224. {
  1225. DevMsg( 2, "Unhandled GameEvent in ClientModeShared::FireGameEvent - %s\n", event->GetName() );
  1226. }
  1227. }
  1228. //-----------------------------------------------------------------------------
  1229. // In-game VGUI context
  1230. //-----------------------------------------------------------------------------
  1231. void ClientModeShared::ActivateInGameVGuiContext( vgui::Panel *pPanel )
  1232. {
  1233. vgui::ivgui()->AssociatePanelWithContext( s_hVGuiContext, pPanel->GetVPanel() );
  1234. vgui::ivgui()->ActivateContext( s_hVGuiContext );
  1235. }
  1236. void ClientModeShared::DeactivateInGameVGuiContext()
  1237. {
  1238. vgui::ivgui()->ActivateContext( DEFAULT_VGUI_CONTEXT );
  1239. }
  1240. int ClientModeShared::GetSplitScreenPlayerSlot() const
  1241. {
  1242. int nSplitScreenUserSlot = vgui::ipanel()->GetMessageContextId( m_pViewport->GetVPanel() );
  1243. Assert( nSplitScreenUserSlot != -1 );
  1244. return nSplitScreenUserSlot;
  1245. }