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.

4933 lines
146 KiB

  1. //======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ======
  2. //
  3. //
  4. //===============================================================================
  5. #include "cbase.h"
  6. #include <crtmemdebug.h>
  7. #include "vgui_int.h"
  8. #include "clientmode.h"
  9. #include "iinput.h"
  10. #include "iviewrender.h"
  11. #include "ivieweffects.h"
  12. #include "ivmodemanager.h"
  13. #include "prediction.h"
  14. #include "clientsideeffects.h"
  15. #include "particlemgr.h"
  16. #include "steam/steam_api.h"
  17. #include "smoke_fog_overlay.h"
  18. #include "view.h"
  19. #include "ienginevgui.h"
  20. #include "iefx.h"
  21. #include "enginesprite.h"
  22. #include "networkstringtable_clientdll.h"
  23. #include "voice_status.h"
  24. #include "filesystem.h"
  25. #include "filesystem/IXboxInstaller.h"
  26. #include "c_te_legacytempents.h"
  27. #include "c_rope.h"
  28. #include "engine/ishadowmgr.h"
  29. #include "engine/IStaticPropMgr.h"
  30. #include "hud_basechat.h"
  31. #include "hud_crosshair.h"
  32. #include "view_shared.h"
  33. #include "env_wind_shared.h"
  34. #include "detailobjectsystem.h"
  35. #include "soundenvelope.h"
  36. #include "c_basetempentity.h"
  37. #include "materialsystem/imaterialsystemstub.h"
  38. #include "VGuiMatSurface/IMatSystemSurface.h"
  39. #include "materialsystem/imaterialsystemhardwareconfig.h"
  40. #include "c_soundscape.h"
  41. #include "engine/ivdebugoverlay.h"
  42. #include "vguicenterprint.h"
  43. #include "iviewrender_beams.h"
  44. #include "tier0/vprof.h"
  45. #include "engine/IEngineTrace.h"
  46. #include "engine/ivmodelinfo.h"
  47. #include "physics.h"
  48. #include "usermessages.h"
  49. #include "gamestringpool.h"
  50. #include "c_user_message_register.h"
  51. #include "IGameUIFuncs.h"
  52. #include "saverestoretypes.h"
  53. #include "saverestore.h"
  54. #include "physics_saverestore.h"
  55. #include "igameevents.h"
  56. #include "datacache/idatacache.h"
  57. #include "datacache/imdlcache.h"
  58. #include "kbutton.h"
  59. #include "tier0/icommandline.h"
  60. #include "vstdlib/jobthread.h"
  61. #include "gamerules_register.h"
  62. #include "game/client/iviewport.h"
  63. #include "vgui_controls/AnimationController.h"
  64. #include "bitmap/tgawriter.h"
  65. #include "c_world.h"
  66. #include "perfvisualbenchmark.h"
  67. #include "SoundEmitterSystem/isoundemittersystembase.h"
  68. #include "hud_closecaption.h"
  69. #include "colorcorrectionmgr.h"
  70. #include "physpropclientside.h"
  71. #include "panelmetaclassmgr.h"
  72. #include "c_vguiscreen.h"
  73. #include "imessagechars.h"
  74. #include "game/client/IGameClientExports.h"
  75. #include "client_factorylist.h"
  76. #include "ragdoll_shared.h"
  77. #include "rendertexture.h"
  78. #include "view_scene.h"
  79. #include "iclientmode.h"
  80. #include "con_nprint.h"
  81. #include "inputsystem/iinputsystem.h"
  82. #include "appframework/IAppSystemGroup.h"
  83. #include "scenefilecache/ISceneFileCache.h"
  84. #include "tier3/tier3.h"
  85. #include "avi/iavi.h"
  86. #include "avi/iquicktime.h"
  87. #include "ihudlcd.h"
  88. #include "toolframework_client.h"
  89. #include "hltvcamera.h"
  90. #include "hltvreplaysystem.h"
  91. #if defined( REPLAY_ENABLED )
  92. #include "replaycamera.h"
  93. #include "replay_ragdoll.h"
  94. #include "replay_ragdoll.h"
  95. #include "qlimits.h"
  96. #include "engine/ireplayhistorymanager.h"
  97. #endif
  98. #include "ixboxsystem.h"
  99. #include "matchmaking/imatchframework.h"
  100. #include "cdll_bounded_cvars.h"
  101. #include "matsys_controls/matsyscontrols.h"
  102. #include "GameStats.h"
  103. #include "videocfg/videocfg.h"
  104. #include "tier2/tier2_logging.h"
  105. #include "Sprite.h"
  106. #include "hud_savestatus.h"
  107. #include "vgui_video.h"
  108. #if defined( CSTRIKE15 )
  109. #include "gametypes/igametypes.h"
  110. #include "c_keyvalue_saver.h"
  111. #include "cs_workshop_manager.h"
  112. #include "c_team.h"
  113. #include "cstrike15/fatdemo.h"
  114. #endif
  115. #include "mumble.h"
  116. #include "vscript/ivscript.h"
  117. #include "activitylist.h"
  118. #include "eventlist.h"
  119. #ifdef GAMEUI_UISYSTEM2_ENABLED
  120. #include "gameui.h"
  121. #endif
  122. #ifdef GAMEUI_EMBEDDED
  123. #if defined( PORTAL2 )
  124. #ifdef GAMEUI_UISYSTEM2_ENABLED
  125. #include "gameui/basemodpanel.h"
  126. #else
  127. #include "portal2/gameui/portal2/basemodpanel.h"
  128. #endif
  129. #elif defined( SWARM_DLL )
  130. #include "swarm/gameui/swarm/basemodpanel.h"
  131. #elif defined( CSTRIKE15 )
  132. #include "cstrike15/gameui/basepanel.h"
  133. #else
  134. #error "GAMEUI_EMBEDDED"
  135. #endif
  136. #endif
  137. #include "game_controls/igameuisystemmgr.h"
  138. #ifdef DEMOPOLISH_ENABLED
  139. #include "demo_polish/demo_polish.h"
  140. #endif
  141. #include "imaterialproxydict.h"
  142. #include "vjobs_interface.h"
  143. #include "tier0/miniprofiler.h"
  144. #include "engine/iblackbox.h"
  145. #include "c_rumble.h"
  146. #include "viewpostprocess.h"
  147. #include "cstrike15_gcmessages.pb.h"
  148. #include "achievements_and_stats_interface.h"
  149. #if defined ( CSTRIKE15 )
  150. #include "iachievementmgr.h"
  151. #include "hud.h"
  152. #include "hud_element_helper.h"
  153. #include "Scaleform/HUD/sfhud_chat.h"
  154. #include "Scaleform/HUD/sfhud_radio.h"
  155. #include "Scaleform/options_scaleform.h"
  156. #include "Scaleform/loadingscreen_scaleform.h"
  157. #include "Scaleform/HUD/sfhud_deathnotice.h"
  158. #endif
  159. #ifdef PORTAL
  160. #include "PortalRender.h"
  161. #endif
  162. #ifdef PORTAL2
  163. #include "portal_util_shared.h"
  164. #include "portal_base2d_shared.h"
  165. #include "c_keyvalue_saver.h"
  166. #include "portal2/gameui/portal2/steamoverlay/isteamoverlaymgr.h"
  167. extern void ProcessPortalTeleportations( void );
  168. #if defined( PORTAL2_PUZZLEMAKER )
  169. #include "puzzlemaker/puzzlemaker.h"
  170. #endif // PORTAL2_PUZZLEMAKER
  171. #endif
  172. #ifdef INFESTED_PARTICLES
  173. #include "c_asw_generic_emitter.h"
  174. #endif
  175. #if defined( CSTRIKE15 )
  176. #include "p4lib/ip4.h"
  177. #endif
  178. #ifdef INFESTED_DLL
  179. #include "missionchooser/iasw_mission_chooser.h"
  180. #endif
  181. #include "clientsteamcontext.h"
  182. #include "tier1/utldict.h"
  183. #include "keybindinglistener.h"
  184. #ifdef SIXENSE
  185. #include "sixense/in_sixense.h"
  186. #endif
  187. #if defined(_PS3)
  188. #include "buildrenderables_PS3.h"
  189. #endif
  190. #include "viewrender.h"
  191. #include "irendertorthelperobject.h"
  192. #include "iloadingdisc.h"
  193. #include "bannedwords.h"
  194. // memdbgon must be the last include file in a .cpp file!!!
  195. #include "tier0/memdbgon.h"
  196. extern IClientMode *GetClientModeNormal();
  197. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_CONSOLE, "Console" );
  198. // IF YOU ADD AN INTERFACE, EXTERN IT IN THE HEADER FILE.
  199. IVEngineClient *engine = NULL;
  200. IVModelRender *modelrender = NULL;
  201. IVEfx *effects = NULL;
  202. IVRenderView *render = NULL;
  203. IVDebugOverlay *debugoverlay = NULL;
  204. IMaterialSystemStub *materials_stub = NULL;
  205. IDataCache *datacache = NULL;
  206. IVModelInfoClient *modelinfo = NULL;
  207. IEngineVGui *enginevgui = NULL;
  208. INetworkStringTableContainer *networkstringtable = NULL;
  209. ISpatialPartition* partition = NULL;
  210. IFileSystem *filesystem = NULL;
  211. IShadowMgr *shadowmgr = NULL;
  212. IStaticPropMgrClient *staticpropmgr = NULL;
  213. IEngineSound *enginesound = NULL;
  214. IUniformRandomStream *random = NULL;
  215. static CGaussianRandomStream s_GaussianRandomStream;
  216. CGaussianRandomStream *randomgaussian = &s_GaussianRandomStream;
  217. ISharedGameRules *sharedgamerules = NULL;
  218. IEngineTrace *enginetrace = NULL;
  219. IFileLoggingListener *filelogginglistener = NULL;
  220. IGameUIFuncs *gameuifuncs = NULL;
  221. IGameEventManager2 *gameeventmanager = NULL;
  222. ISoundEmitterSystemBase *soundemitterbase = NULL;
  223. IInputSystem *inputsystem = NULL;
  224. ISceneFileCache *scenefilecache = NULL;
  225. IXboxSystem *xboxsystem = NULL; // Xbox 360 only
  226. IAvi *avi = NULL;
  227. IBik *bik = NULL;
  228. IQuickTime *pQuicktime = NULL;
  229. IVJobs * g_pVJobs = NULL;
  230. IRenderToRTHelper *g_pRenderToRTHelper = NULL;
  231. #if defined( INCLUDE_SCALEFORM )
  232. IScaleformUI* g_pScaleformUI = NULL;
  233. #endif
  234. IUploadGameStats *gamestatsuploader = NULL;
  235. IBlackBox *blackboxrecorder = NULL;
  236. #ifdef INFESTED_DLL
  237. IASW_Mission_Chooser *missionchooser = NULL;
  238. #endif
  239. #if defined( REPLAY_ENABLED )
  240. IReplayHistoryManager *g_pReplayHistoryManager = NULL;
  241. #endif
  242. AchievementsAndStatsInterface* g_pAchievementsAndStatsInterface = NULL;
  243. IScriptManager *scriptmanager = NULL;
  244. IGameSystem *SoundEmitterSystem();
  245. IGameSystem *ToolFrameworkClientSystem();
  246. IViewRender *GetViewRenderInstance();
  247. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_VJOBS, "VJOBS" );
  248. bool g_bEngineIsHLTV = false;
  249. static bool g_bRequestCacheUsedMaterials = false;
  250. void RequestCacheUsedMaterials()
  251. {
  252. g_bRequestCacheUsedMaterials = true;
  253. }
  254. void ProcessCacheUsedMaterials()
  255. {
  256. if ( !g_bRequestCacheUsedMaterials )
  257. return;
  258. g_bRequestCacheUsedMaterials = false;
  259. if ( materials )
  260. {
  261. materials->CacheUsedMaterials();
  262. }
  263. }
  264. static bool g_bHeadTrackingEnabled = false;
  265. bool IsHeadTrackingEnabled()
  266. {
  267. #if defined( HL2_CLIENT_DLL )
  268. return g_bHeadTrackingEnabled;
  269. #else
  270. return false;
  271. #endif
  272. }
  273. void VGui_ClearVideoPanels();
  274. // String tables
  275. INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
  276. INetworkStringTable *g_pStringTableExtraParticleFiles = NULL;
  277. INetworkStringTable *g_StringTableEffectDispatch = NULL;
  278. INetworkStringTable *g_StringTableVguiScreen = NULL;
  279. INetworkStringTable *g_pStringTableMaterials = NULL;
  280. INetworkStringTable *g_pStringTableInfoPanel = NULL;
  281. INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL;
  282. INetworkStringTable *g_pStringTableMovies = NULL;
  283. static CGlobalVarsBase dummyvars( true );
  284. // So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer.
  285. // Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine
  286. CGlobalVarsBase *gpGlobals = &dummyvars;
  287. class CHudChat;
  288. class CViewRender;
  289. static C_BaseEntityClassList *s_pClassLists = NULL;
  290. C_BaseEntityClassList::C_BaseEntityClassList()
  291. {
  292. m_pNextClassList = s_pClassLists;
  293. s_pClassLists = this;
  294. }
  295. C_BaseEntityClassList::~C_BaseEntityClassList()
  296. {
  297. }
  298. // Any entities that want an OnDataChanged during simulation register for it here.
  299. class CDataChangedEvent
  300. {
  301. public:
  302. CDataChangedEvent() {}
  303. CDataChangedEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
  304. {
  305. if ( ent != NULL )
  306. {
  307. m_nEntityIndex = ent->entindex();
  308. }
  309. else
  310. {
  311. m_nEntityIndex = -1;
  312. }
  313. m_UpdateType = updateType;
  314. m_pStoredEvent = pStoredEvent;
  315. }
  316. IClientNetworkable *GetEntity()
  317. {
  318. if ( m_nEntityIndex == -1 )
  319. return NULL;
  320. return ClientEntityList().GetClientNetworkable( m_nEntityIndex );
  321. }
  322. int m_nEntityIndex;
  323. DataUpdateType_t m_UpdateType;
  324. int *m_pStoredEvent;
  325. };
  326. ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler();
  327. ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler();
  328. ISaveRestoreBlockHandler *GetGameInstructorRestoreBlockHandler();
  329. CUtlLinkedList<CDataChangedEvent, unsigned short> g_DataChangedEvents;
  330. CUtlLinkedList<CDataChangedEvent, unsigned short> g_DataChangedPostEvents;
  331. bool g_bDataChangedPostEventsAllowed = false;
  332. class IMoveHelper;
  333. void DispatchHudText( const char *pszName );
  334. static ConVar s_CV_ShowParticleCounts("showparticlecounts", "0", 0, "Display number of particles drawn per frame");
  335. // static ConVar s_cl_team("cl_team", "default", FCVAR_ARCHIVE, "Default team when joining a game");
  336. // static ConVar s_cl_class("cl_class", "default", FCVAR_ARCHIVE, "Default class when joining a game");
  337. static ConVar cl_join_advertise( "cl_join_advertise", "1", FCVAR_ARCHIVE, "Advertise joinable game in progress to Steam friends, otherwise need a Steam invite (2: all servers, 1: official servers, 0: none)" );
  338. // Physics system
  339. bool g_bLevelInitialized;
  340. bool g_bTextMode = false;
  341. ClientFrameStage_t g_CurFrameStage = FRAME_UNDEFINED;
  342. static ConVar *g_pcv_ThreadMode = NULL;
  343. // implements ACTIVE_SPLITSCREEN_PLAYER_GUARD (cdll_client_int.h)
  344. CSetActiveSplitScreenPlayerGuard::CSetActiveSplitScreenPlayerGuard( char const *pchContext, int nLine ) :
  345. CVGuiScreenSizeSplitScreenPlayerGuard( false, engine->GetActiveSplitScreenPlayerSlot(), engine->GetActiveSplitScreenPlayerSlot() )
  346. {
  347. m_bChanged = true;
  348. m_pchContext = pchContext;
  349. m_nLine = nLine;
  350. m_nSaveSlot = engine->SetActiveSplitScreenPlayerSlot( -1 );
  351. m_bSaveGetLocalPlayerAllowed = engine->SetLocalPlayerIsResolvable( pchContext, nLine, false );
  352. }
  353. CSetActiveSplitScreenPlayerGuard::CSetActiveSplitScreenPlayerGuard( char const *pchContext, int nLine, int slot, int nOldSlot, bool bSetVguiScreenSize ) :
  354. CVGuiScreenSizeSplitScreenPlayerGuard( bSetVguiScreenSize, slot, nOldSlot )
  355. {
  356. if ( nOldSlot == slot && engine->IsLocalPlayerResolvable() )
  357. {
  358. m_bChanged = false;
  359. return;
  360. }
  361. m_bChanged = true;
  362. m_pchContext = pchContext;
  363. m_nLine = nLine;
  364. m_nSaveSlot = engine->SetActiveSplitScreenPlayerSlot( slot >= 0 ? slot : 0 );
  365. m_bSaveGetLocalPlayerAllowed = engine->SetLocalPlayerIsResolvable( pchContext, nLine, slot >= 0 );
  366. }
  367. CSetActiveSplitScreenPlayerGuard::CSetActiveSplitScreenPlayerGuard( char const *pchContext, int nLine, C_BaseEntity *pEntity, int nOldSlot, bool bSetVguiScreenSize ) :
  368. CVGuiScreenSizeSplitScreenPlayerGuard( bSetVguiScreenSize, pEntity, nOldSlot )
  369. {
  370. int slot = C_BasePlayer::GetSplitScreenSlotForPlayer( pEntity );
  371. if ( slot == -1 )
  372. {
  373. m_bChanged = false;
  374. return;
  375. }
  376. if ( nOldSlot == slot && engine->IsLocalPlayerResolvable())
  377. {
  378. m_bChanged = false;
  379. return;
  380. }
  381. m_bChanged = true;
  382. m_pchContext = pchContext;
  383. m_nLine = nLine;
  384. m_nSaveSlot = engine->SetActiveSplitScreenPlayerSlot( slot >= 0 ? slot : 0 );
  385. m_bSaveGetLocalPlayerAllowed = engine->SetLocalPlayerIsResolvable( pchContext, nLine, slot >= 0 );
  386. }
  387. CSetActiveSplitScreenPlayerGuard::~CSetActiveSplitScreenPlayerGuard()
  388. {
  389. if ( !m_bChanged )
  390. return;
  391. engine->SetActiveSplitScreenPlayerSlot( m_nSaveSlot );
  392. engine->SetLocalPlayerIsResolvable( m_pchContext, m_nLine, m_bSaveGetLocalPlayerAllowed );
  393. }
  394. static CUtlRBTree< const char *, int > g_Hacks( 0, 0, DefLessFunc( char const * ) );
  395. CON_COMMAND( cl_dumpsplithacks, "Dump split screen workarounds." )
  396. {
  397. for ( int i = g_Hacks.FirstInorder(); i != g_Hacks.InvalidIndex(); i = g_Hacks.NextInorder( i ) )
  398. {
  399. Msg( "%s\n", g_Hacks[ i ] );
  400. }
  401. }
  402. CHackForGetLocalPlayerAccessAllowedGuard::CHackForGetLocalPlayerAccessAllowedGuard( char const *pszContext, bool bOldState )
  403. {
  404. if ( bOldState )
  405. {
  406. m_bChanged = false;
  407. return;
  408. }
  409. m_bChanged = true;
  410. m_pszContext = pszContext;
  411. if ( g_Hacks.Find( pszContext ) == g_Hacks.InvalidIndex() )
  412. {
  413. g_Hacks.Insert( pszContext );
  414. }
  415. m_bSaveGetLocalPlayerAllowed = engine->SetLocalPlayerIsResolvable( pszContext, 0, true );
  416. }
  417. CHackForGetLocalPlayerAccessAllowedGuard::~CHackForGetLocalPlayerAccessAllowedGuard()
  418. {
  419. if ( !m_bChanged )
  420. return;
  421. engine->SetLocalPlayerIsResolvable( m_pszContext, 0, m_bSaveGetLocalPlayerAllowed );
  422. }
  423. CVGuiScreenSizeSplitScreenPlayerGuard::CVGuiScreenSizeSplitScreenPlayerGuard( bool bActive, int slot, int nOldSlot )
  424. {
  425. if ( !bActive )
  426. {
  427. m_bNoRestore = true;
  428. return;
  429. }
  430. if ( vgui::surface()->IsScreenSizeOverrideActive() && nOldSlot == slot && engine->IsLocalPlayerResolvable() )
  431. {
  432. m_bNoRestore = true;
  433. return;
  434. }
  435. m_bNoRestore = false;
  436. vgui::surface()->GetScreenSize( m_nOldSize[ 0 ], m_nOldSize[ 1 ] );
  437. int x, y, w, h;
  438. VGui_GetHudBounds( slot >= 0 ? slot : 0, x, y, w, h );
  439. m_bOldSetting = vgui::surface()->ForceScreenSizeOverride( true, w, h );
  440. }
  441. CVGuiScreenSizeSplitScreenPlayerGuard::CVGuiScreenSizeSplitScreenPlayerGuard( bool bActive, C_BaseEntity *pEntity, int nOldSlot )
  442. {
  443. if ( !bActive )
  444. {
  445. m_bNoRestore = true;
  446. return;
  447. }
  448. int slot = C_BasePlayer::GetSplitScreenSlotForPlayer( pEntity );
  449. if ( vgui::surface()->IsScreenSizeOverrideActive() && nOldSlot == slot && engine->IsLocalPlayerResolvable() )
  450. {
  451. m_bNoRestore = true;
  452. return;
  453. }
  454. m_bNoRestore = false;
  455. vgui::surface()->GetScreenSize( m_nOldSize[ 0 ], m_nOldSize[ 1 ] );
  456. // Get size for this user
  457. int x, y, w, h;
  458. VGui_GetHudBounds( slot >= 0 ? slot : 0, x, y, w, h );
  459. m_bOldSetting = vgui::surface()->ForceScreenSizeOverride( true, w, h );
  460. }
  461. CVGuiScreenSizeSplitScreenPlayerGuard::~CVGuiScreenSizeSplitScreenPlayerGuard()
  462. {
  463. if ( m_bNoRestore )
  464. return;
  465. vgui::surface()->ForceScreenSizeOverride( m_bOldSetting, m_nOldSize[ 0 ], m_nOldSize[ 1 ] );
  466. }
  467. CVGuiAbsPosSplitScreenPlayerGuard::CVGuiAbsPosSplitScreenPlayerGuard( int slot, int nOldSlot, bool bInvert /*=false*/ )
  468. {
  469. if ( nOldSlot == slot && engine->IsLocalPlayerResolvable() && vgui::surface()->IsScreenPosOverrideActive() )
  470. {
  471. m_bNoRestore = true;
  472. return;
  473. }
  474. m_bNoRestore = false;
  475. // Get size for this user
  476. int x, y, w, h;
  477. VGui_GetHudBounds( slot, x, y, w, h );
  478. if ( bInvert )
  479. {
  480. x = -x;
  481. y = -y;
  482. }
  483. vgui::surface()->ForceScreenPosOffset( true, x, y );
  484. }
  485. CVGuiAbsPosSplitScreenPlayerGuard::~CVGuiAbsPosSplitScreenPlayerGuard()
  486. {
  487. if ( m_bNoRestore )
  488. return;
  489. vgui::surface()->ForceScreenPosOffset( false, 0, 0 );
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Purpose: interface for gameui to modify voice bans
  493. //-----------------------------------------------------------------------------
  494. class CGameClientExports : public IGameClientExports
  495. {
  496. public:
  497. // ingame voice manipulation
  498. bool IsPlayerGameVoiceMuted(int playerIndex)
  499. {
  500. return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex);
  501. }
  502. void MutePlayerGameVoice(int playerIndex)
  503. {
  504. if ( !GetClientVoiceMgr()->IsPlayerBlocked( playerIndex ) )
  505. {
  506. GetClientVoiceMgr()->SetPlayerBlockedState( playerIndex );
  507. }
  508. }
  509. void UnmutePlayerGameVoice(int playerIndex)
  510. {
  511. if ( GetClientVoiceMgr()->IsPlayerBlocked( playerIndex ) )
  512. {
  513. GetClientVoiceMgr()->SetPlayerBlockedState( playerIndex );
  514. }
  515. }
  516. void OnGameUIActivated( void )
  517. {
  518. IGameEvent *event = gameeventmanager->CreateEvent( "gameui_activated" );
  519. if ( event )
  520. {
  521. gameeventmanager->FireEventClientSide( event );
  522. }
  523. }
  524. void OnGameUIHidden( void )
  525. {
  526. IGameEvent *event = gameeventmanager->CreateEvent( "gameui_hidden" );
  527. if ( event )
  528. {
  529. gameeventmanager->FireEventClientSide( event );
  530. }
  531. }
  532. // if true, the gameui applies the blur effect
  533. bool ClientWantsBlurEffect( void )
  534. {
  535. ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
  536. if ( GetViewPortInterface()->GetActivePanel() && GetViewPortInterface()->GetActivePanel()->WantsBackgroundBlurred() )
  537. return true;
  538. return false;
  539. }
  540. void CreateAchievementsPanel( vgui::Panel* pParent )
  541. {
  542. if (g_pAchievementsAndStatsInterface)
  543. {
  544. g_pAchievementsAndStatsInterface->CreatePanel( pParent );
  545. }
  546. }
  547. void DisplayAchievementPanel()
  548. {
  549. if (g_pAchievementsAndStatsInterface)
  550. {
  551. g_pAchievementsAndStatsInterface->DisplayPanel();
  552. }
  553. }
  554. void ShutdownAchievementPanel()
  555. {
  556. if (g_pAchievementsAndStatsInterface)
  557. {
  558. g_pAchievementsAndStatsInterface->ReleasePanel();
  559. }
  560. }
  561. int GetAchievementsPanelMinWidth( void ) const
  562. {
  563. if ( g_pAchievementsAndStatsInterface )
  564. {
  565. return g_pAchievementsAndStatsInterface->GetAchievementsPanelMinWidth();
  566. }
  567. return 0;
  568. }
  569. };
  570. EXPOSE_SINGLE_INTERFACE( CGameClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION );
  571. class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems
  572. {
  573. public:
  574. CClientDLLSharedAppSystems()
  575. {
  576. AddAppSystem( "soundemittersystem" , SOUNDEMITTERSYSTEM_INTERFACE_VERSION );
  577. AddAppSystem( "scenefilecache", SCENE_FILE_CACHE_INTERFACE_VERSION );
  578. #ifdef GAMEUI_UISYSTEM2_ENABLED
  579. AddAppSystem( "client", GAMEUISYSTEMMGR_INTERFACE_VERSION );
  580. #endif
  581. #ifdef INFESTED_DLL
  582. AddAppSystem( "missionchooser", ASW_MISSION_CHOOSER_VERSION );
  583. #endif
  584. }
  585. virtual int Count()
  586. {
  587. return m_Systems.Count();
  588. }
  589. virtual char const *GetDllName( int idx )
  590. {
  591. return m_Systems[ idx ].m_pModuleName;
  592. }
  593. virtual char const *GetInterfaceName( int idx )
  594. {
  595. return m_Systems[ idx ].m_pInterfaceName;
  596. }
  597. private:
  598. void AddAppSystem( char const *moduleName, char const *interfaceName )
  599. {
  600. AppSystemInfo_t sys;
  601. sys.m_pModuleName = moduleName;
  602. sys.m_pInterfaceName = interfaceName;
  603. m_Systems.AddToTail( sys );
  604. }
  605. CUtlVector< AppSystemInfo_t > m_Systems;
  606. };
  607. EXPOSE_SINGLE_INTERFACE( CClientDLLSharedAppSystems, IClientDLLSharedAppSystems, CLIENT_DLL_SHARED_APPSYSTEMS );
  608. //-----------------------------------------------------------------------------
  609. // Helper interface for voice.
  610. //-----------------------------------------------------------------------------
  611. class CHLVoiceStatusHelper : public IVoiceStatusHelper
  612. {
  613. public:
  614. virtual void GetPlayerTextColor(int entindex, int color[3])
  615. {
  616. color[0] = color[1] = color[2] = 128;
  617. }
  618. virtual void UpdateCursorState()
  619. {
  620. }
  621. virtual bool CanShowSpeakerLabels()
  622. {
  623. return true;
  624. }
  625. };
  626. static CHLVoiceStatusHelper g_VoiceStatusHelper;
  627. //-----------------------------------------------------------------------------
  628. // Code to display which entities are having their bones setup each frame.
  629. //-----------------------------------------------------------------------------
  630. ConVar cl_ShowBoneSetupEnts( "cl_ShowBoneSetupEnts", "0", 0, "Show which entities are having their bones setup each frame." );
  631. class CBoneSetupEnt
  632. {
  633. public:
  634. char m_ModelName[128];
  635. int m_Index;
  636. int m_Count;
  637. };
  638. bool BoneSetupCompare( const CBoneSetupEnt &a, const CBoneSetupEnt &b )
  639. {
  640. return a.m_Index < b.m_Index;
  641. }
  642. CUtlRBTree<CBoneSetupEnt> g_BoneSetupEnts( BoneSetupCompare );
  643. void TrackBoneSetupEnt( C_BaseAnimating *pEnt )
  644. {
  645. #ifdef _DEBUG
  646. if ( !cl_ShowBoneSetupEnts.GetInt() )
  647. return;
  648. CBoneSetupEnt ent;
  649. ent.m_Index = pEnt->entindex();
  650. unsigned short i = g_BoneSetupEnts.Find( ent );
  651. if ( i == g_BoneSetupEnts.InvalidIndex() )
  652. {
  653. Q_strncpy( ent.m_ModelName, modelinfo->GetModelName( pEnt->GetModel() ), sizeof( ent.m_ModelName ) );
  654. ent.m_Count = 1;
  655. g_BoneSetupEnts.Insert( ent );
  656. }
  657. else
  658. {
  659. g_BoneSetupEnts[i].m_Count++;
  660. }
  661. #endif
  662. }
  663. void DisplayBoneSetupEnts()
  664. {
  665. #ifdef _DEBUG
  666. if ( !cl_ShowBoneSetupEnts.GetInt() )
  667. return;
  668. unsigned short i;
  669. int nElements = 0;
  670. for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
  671. ++nElements;
  672. engine->Con_NPrintf( 0, "%d bone setup ents (name/count/entindex) ------------", nElements );
  673. con_nprint_s printInfo;
  674. printInfo.time_to_live = -1;
  675. printInfo.fixed_width_font = true;
  676. printInfo.color[0] = printInfo.color[1] = printInfo.color[2] = 1;
  677. printInfo.index = 2;
  678. for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
  679. {
  680. CBoneSetupEnt *pEnt = &g_BoneSetupEnts[i];
  681. if ( pEnt->m_Count >= 3 )
  682. {
  683. printInfo.color[0] = 1;
  684. printInfo.color[1] = printInfo.color[2] = 0;
  685. }
  686. else if ( pEnt->m_Count == 2 )
  687. {
  688. printInfo.color[0] = (float)200 / 255;
  689. printInfo.color[1] = (float)220 / 255;
  690. printInfo.color[2] = 0;
  691. }
  692. else
  693. {
  694. printInfo.color[0] = printInfo.color[0] = printInfo.color[0] = 1;
  695. }
  696. engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index );
  697. printInfo.index++;
  698. }
  699. g_BoneSetupEnts.RemoveAll();
  700. #endif
  701. }
  702. //-----------------------------------------------------------------------------
  703. // Purpose: engine to client .dll interface
  704. //-----------------------------------------------------------------------------
  705. class CHLClient : public IBaseClientDLL
  706. {
  707. public:
  708. CHLClient();
  709. virtual int Connect( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals );
  710. virtual void Disconnect();
  711. virtual int Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals );
  712. virtual void PostInit();
  713. virtual void Shutdown( void );
  714. virtual void LevelInitPreEntity( const char *pMapName );
  715. virtual void LevelInitPostEntity();
  716. virtual void LevelShutdown( void );
  717. virtual ClientClass *GetAllClasses( void );
  718. virtual int HudVidInit( void );
  719. virtual void HudProcessInput( bool bActive );
  720. virtual void HudUpdate( bool bActive );
  721. virtual void HudReset( void );
  722. virtual void HudText( const char * message );
  723. // Mouse Input Interfaces
  724. virtual void IN_ActivateMouse( void );
  725. virtual void IN_DeactivateMouse( void );
  726. virtual void IN_Accumulate( void );
  727. virtual void IN_ClearStates( void );
  728. virtual bool IN_IsKeyDown( const char *name, bool& isdown );
  729. // Raw signal
  730. virtual int IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding );
  731. virtual void IN_SetSampleTime( float frametime );
  732. // Create movement command
  733. virtual void CreateMove ( int sequence_number, float input_sample_frametime, bool active );
  734. virtual void ExtraMouseSample( float frametime, bool active );
  735. virtual bool WriteUsercmdDeltaToBuffer( int nSlot, bf_write *buf, int from, int to, bool isnewcommand );
  736. virtual void EncodeUserCmdToBuffer( int nSlot, bf_write& buf, int slot );
  737. virtual void DecodeUserCmdFromBuffer( int nSlot, bf_read& buf, int slot );
  738. virtual void View_Render( vrect_t *rect );
  739. virtual void RenderView( const CViewSetup &view, int nClearFlags, int whatToDraw );
  740. virtual void View_Fade( ScreenFade_t *pSF );
  741. virtual void SetCrosshairAngle( const QAngle& angle );
  742. virtual void InitSprite( CEngineSprite *pSprite, const char *loadname );
  743. virtual void ShutdownSprite( CEngineSprite *pSprite );
  744. virtual int GetSpriteSize( void ) const;
  745. virtual void VoiceStatus( int entindex, int iSsSlot, qboolean bTalking );
  746. virtual bool PlayerAudible( int iPlayerIndex );
  747. virtual void InstallStringTableCallback( const char *tableName );
  748. virtual void FrameStageNotify( ClientFrameStage_t curStage );
  749. virtual bool DispatchUserMessage( int msg_type, int32 nFlags, int size, const void *msg );
  750. // Save/restore system hooks
  751. virtual CSaveRestoreData *SaveInit( int size );
  752. virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
  753. virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
  754. virtual void PreSave( CSaveRestoreData * );
  755. virtual void Save( CSaveRestoreData * );
  756. virtual void WriteSaveHeaders( CSaveRestoreData * );
  757. virtual void ReadRestoreHeaders( CSaveRestoreData * );
  758. virtual void Restore( CSaveRestoreData *, bool );
  759. virtual void DispatchOnRestore();
  760. virtual void WriteSaveGameScreenshot( const char *pFilename );
  761. // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
  762. // the appropriate close caption if running with closecaption = 1
  763. virtual void EmitSentenceCloseCaption( char const *tokenstream );
  764. virtual void EmitCloseCaption( char const *captionname, float duration );
  765. virtual CStandardRecvProxies* GetStandardRecvProxies();
  766. virtual bool CanRecordDemo( char *errorMsg, int length ) const;
  767. virtual bool CanStopRecordDemo( char *errorMsg, int length ) const;
  768. virtual void OnDemoRecordStart( char const* pDemoBaseName );
  769. virtual void OnDemoRecordStop();
  770. virtual void OnDemoPlaybackStart( char const* pDemoBaseName );
  771. virtual void OnDemoPlaybackRestart();
  772. virtual void OnDemoPlaybackStop();
  773. virtual void SetDemoPlaybackHighlightXuid( uint64 xuid, bool bLowlights );
  774. virtual void ShowHighlightSkippingMessage( bool bState, int nCurrentTick = 0, int nTickStart = 0, int nTickStop = 0 );
  775. virtual void RecordDemoPolishUserInput( int nCmdIndex );
  776. // Cache replay ragdolls
  777. virtual bool CacheReplayRagdolls( const char* pFilename, int nStartTick );
  778. // Send a message to the replay browser
  779. virtual void ReplayUI_SendMessage( KeyValues *pMsg );
  780. // Get the client replay factory
  781. virtual IReplayFactory *GetReplayFactory();
  782. // Clear out the local player's replay pointer so it doesn't get deleted
  783. virtual void ClearLocalPlayerReplayPtr();
  784. virtual bool ShouldDrawDropdownConsole();
  785. // Get client screen dimensions
  786. virtual int GetScreenWidth();
  787. virtual int GetScreenHeight();
  788. // save game screenshot writing
  789. virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, bool bWriteVTF/*=false*/ );
  790. // Write a .VTF screenshot to disk for the replay system
  791. virtual void WriteReplayScreenshot( WriteReplayScreenshotParams_t &params );
  792. // Reallocate memory for replay screenshots - called if user changes resolution or if the convar "replay_screenshotresolution" changes
  793. virtual void UpdateReplayScreenshotCache();
  794. // Gets the location of the player viewpoint
  795. virtual bool GetPlayerView( CViewSetup &playerView );
  796. virtual bool ShouldHideLoadingPlaque( void );
  797. virtual void InvalidateMdlCache();
  798. virtual void OnActiveSplitscreenPlayerChanged( int nNewSlot );
  799. virtual void OnSplitScreenStateChanged();
  800. virtual int GetSpectatorTarget( ClientDLLObserverMode_t* pObserverMode );
  801. virtual void CenterStringOff();
  802. virtual void OnScreenSizeChanged( int nOldWidth, int nOldHeight );
  803. virtual IMaterialProxy *InstantiateMaterialProxy( const char *proxyName );
  804. virtual vgui::VPANEL GetFullscreenClientDLLVPanel( void );
  805. virtual void MarkEntitiesAsTouching( IClientEntity *e1, IClientEntity *e2 );
  806. virtual void OnKeyBindingChanged( ButtonCode_t buttonCode, char const *pchKeyName, char const *pchNewBinding );
  807. virtual bool HandleGameUIEvent( const InputEvent_t &event );
  808. virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
  809. public:
  810. void PrecacheMaterial( const char *pMaterialName );
  811. void PrecacheMovie( const char *pMovieName );
  812. virtual void SetBlurFade( float scale );
  813. virtual void ResetHudCloseCaption();
  814. virtual void Hud_SaveStarted();
  815. virtual void ShutdownMovies();
  816. virtual void GetStatus( char *buffer, int bufsize );
  817. #if defined ( CSTRIKE15 )
  818. virtual bool IsChatRaised( void );
  819. virtual bool IsRadioPanelRaised( void );
  820. virtual bool IsBindMenuRaised( void );
  821. virtual bool IsTeamMenuRaised( void );
  822. virtual bool IsLoadingScreenRaised( void );
  823. #endif
  824. #if defined(_PS3)
  825. virtual int GetDrawFlags( void );
  826. virtual int GetBuildViewID( void );
  827. virtual bool IsSPUBuildWRJobsOn( void );
  828. virtual void CacheFrustumData( Frustum_t *pFrustum, Frustum_t *pAreaFrustum, void *pRenderAreaBits, int numArea, bool bViewerInSolidSpace );
  829. virtual void *GetBuildViewVolumeCuller( void );
  830. virtual Frustum_t *GetBuildViewFrustum( void );
  831. virtual Frustum_t *GetBuildViewAreaFrustum( void );
  832. virtual unsigned char *GetBuildViewRenderAreaBits( void );
  833. #else
  834. virtual bool IsBuildWRThreaded( void );
  835. virtual void QueueBuildWorldListJob( CJob* pJob );
  836. virtual void CacheFrustumData( const Frustum_t& frustum, const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >& aeraFrustums );
  837. virtual const Frustum_t* GetBuildViewFrustum( void ) const;
  838. virtual const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >* GetBuildViewAeraFrustums( void ) const;
  839. #endif
  840. virtual bool IsSubscribedMap( const char *pchMapName, bool bOnlyOnDisk );
  841. virtual bool IsFeaturedMap( const char *pchMapName, bool bOnlyOnDisk );
  842. virtual void DownloadCommunityMapFile( PublishedFileId_t id );
  843. virtual float GetUGCFileDownloadProgress( PublishedFileId_t id );
  844. virtual void RecordUIEvent( const char* szEvent );
  845. virtual void OnHltvReplay( const CSVCMsg_HltvReplay &msg ) OVERRIDE { g_HltvReplaySystem.OnHltvReplay( msg ); }
  846. virtual void OnHltvReplayTick() OVERRIDE { g_HltvReplaySystem.OnHltvReplayTick(); }
  847. virtual int GetHltvReplayDelay() OVERRIDE { return g_HltvReplaySystem.GetHltvReplayDelay(); }
  848. virtual void OnDemoPlaybackTimeJump();
  849. // Inventory access
  850. virtual float FindInventoryItemWithMaxAttributeValue( char const *szItemType, char const *szAttrClass );
  851. virtual void DetermineSubscriptionKvToAdvertise( KeyValues *kvLocalPlayer );
  852. // Overwatchsupport for engine
  853. virtual bool ValidateSignedEvidenceHeader( char const *szKey, void const *pvHeader, CDemoPlaybackParameters_t *pPlaybackParameters );
  854. virtual void PrepareSignedEvidenceData( void *pvData, int numBytes, CDemoPlaybackParameters_t const *pPlaybackParameters );
  855. virtual bool ShouldSkipEvidencePlayback( CDemoPlaybackParameters_t const *pPlaybackParameters );
  856. // Scaleform slot controller
  857. virtual IScaleformSlotInitController * GetScaleformSlotInitController();
  858. virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar );
  859. virtual void OnCommandDuringPlayback( char const *cmd );
  860. virtual void RetireAllPlayerDecals( bool bRenderContextValid );
  861. virtual void EngineGotvSyncPacket( const CEngineGotvSyncPacket *pPkt ) OVERRIDE;
  862. virtual void OnTickPre( int tickcount ) OVERRIDE;
  863. virtual char const * GetRichPresenceStatusString();
  864. virtual int GetInEyeEntity() const;
  865. private:
  866. void UncacheAllMaterials();
  867. void UncacheAllMovies();
  868. void ResetStringTablePointers();
  869. CUtlRBTree< IMaterial * > m_CachedMaterials;
  870. CUtlSymbolTable m_CachedMovies;
  871. CHudCloseCaption *m_pHudCloseCaption;
  872. };
  873. CHLClient gHLClient;
  874. IBaseClientDLL *clientdll = &gHLClient;
  875. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLClient, IBaseClientDLL, CLIENT_DLL_INTERFACE_VERSION, gHLClient );
  876. //-----------------------------------------------------------------------------
  877. // Precaches a material
  878. //-----------------------------------------------------------------------------
  879. void PrecacheMaterial( const char *pMaterialName )
  880. {
  881. gHLClient.PrecacheMaterial( pMaterialName );
  882. }
  883. //-----------------------------------------------------------------------------
  884. // Converts a previously precached material into an index
  885. //-----------------------------------------------------------------------------
  886. int GetMaterialIndex( const char *pMaterialName )
  887. {
  888. if (pMaterialName)
  889. {
  890. int nIndex = g_pStringTableMaterials->FindStringIndex( pMaterialName );
  891. Assert( nIndex >= 0 );
  892. if (nIndex >= 0)
  893. return nIndex;
  894. }
  895. // This is the invalid string index
  896. return 0;
  897. }
  898. //-----------------------------------------------------------------------------
  899. // Converts precached material indices into strings
  900. //-----------------------------------------------------------------------------
  901. const char *GetMaterialNameFromIndex( int nIndex )
  902. {
  903. if (nIndex != (g_pStringTableMaterials->GetMaxStrings() - 1))
  904. {
  905. return g_pStringTableMaterials->GetString( nIndex );
  906. }
  907. else
  908. {
  909. return NULL;
  910. }
  911. }
  912. //-----------------------------------------------------------------------------
  913. // Precaches a movie
  914. //-----------------------------------------------------------------------------
  915. void PrecacheMovie( const char *pMovieName )
  916. {
  917. gHLClient.PrecacheMovie( pMovieName );
  918. }
  919. //-----------------------------------------------------------------------------
  920. // Converts a previously precached movie into an index
  921. //-----------------------------------------------------------------------------
  922. int GetMovieIndex( const char *pMovieName )
  923. {
  924. if ( pMovieName )
  925. {
  926. int nIndex = g_pStringTableMovies->FindStringIndex( pMovieName );
  927. Assert( nIndex >= 0 );
  928. if ( nIndex >= 0 )
  929. {
  930. return nIndex;
  931. }
  932. }
  933. // This is the invalid string index
  934. return 0;
  935. }
  936. //-----------------------------------------------------------------------------
  937. // Converts precached movie indices into strings
  938. //-----------------------------------------------------------------------------
  939. const char *GetMovieNameFromIndex( int nIndex )
  940. {
  941. if ( nIndex != ( g_pStringTableMovies->GetMaxStrings() - 1 ) )
  942. {
  943. return g_pStringTableMovies->GetString( nIndex );
  944. }
  945. else
  946. {
  947. return NULL;
  948. }
  949. }
  950. //-----------------------------------------------------------------------------
  951. // Precaches a particle system
  952. //-----------------------------------------------------------------------------
  953. int PrecacheParticleSystem( const char *pParticleSystemName )
  954. {
  955. int nIndex = g_pStringTableParticleEffectNames->AddString( false, pParticleSystemName );
  956. g_pParticleSystemMgr->PrecacheParticleSystem( nIndex, pParticleSystemName );
  957. return nIndex;
  958. }
  959. //-----------------------------------------------------------------------------
  960. // Converts a previously precached particle system into an index
  961. //-----------------------------------------------------------------------------
  962. int GetParticleSystemIndex( const char *pParticleSystemName )
  963. {
  964. if ( pParticleSystemName )
  965. {
  966. int nIndex = g_pStringTableParticleEffectNames->FindStringIndex( pParticleSystemName );
  967. if ( nIndex != INVALID_STRING_INDEX )
  968. return nIndex;
  969. DevWarning("Client: Missing precache for particle system \"%s\"!\n", pParticleSystemName );
  970. }
  971. // This is the invalid string index
  972. return 0;
  973. }
  974. //-----------------------------------------------------------------------------
  975. // Converts precached particle system indices into strings
  976. //-----------------------------------------------------------------------------
  977. const char *GetParticleSystemNameFromIndex( int nIndex )
  978. {
  979. if ( nIndex < g_pStringTableParticleEffectNames->GetMaxStrings() )
  980. return g_pStringTableParticleEffectNames->GetString( nIndex );
  981. return "error";
  982. }
  983. //-----------------------------------------------------------------------------
  984. // Precache-related methods for effects
  985. //-----------------------------------------------------------------------------
  986. void PrecacheEffect( const char *pEffectName )
  987. {
  988. // Bring in dependent resources
  989. g_pPrecacheSystem->Cache( g_pPrecacheHandler, DISPATCH_EFFECT, pEffectName, true, RESOURCE_LIST_INVALID, true );
  990. }
  991. //-----------------------------------------------------------------------------
  992. // Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode)
  993. //-----------------------------------------------------------------------------
  994. bool IsEngineThreaded()
  995. {
  996. if ( g_pcv_ThreadMode )
  997. {
  998. return g_pcv_ThreadMode->GetBool();
  999. }
  1000. return false;
  1001. }
  1002. //-----------------------------------------------------------------------------
  1003. // Constructor
  1004. //-----------------------------------------------------------------------------
  1005. CHLClient::CHLClient()
  1006. {
  1007. // Kinda bogus, but the logic in the engine is too convoluted to put it there
  1008. g_bLevelInitialized = false;
  1009. m_pHudCloseCaption = NULL;
  1010. SetDefLessFunc( m_CachedMaterials );
  1011. }
  1012. extern IGameSystem *ViewportClientSystem();
  1013. // enable threaded init functions on x360
  1014. static ConVar cl_threaded_init("cl_threaded_init", IsGameConsole() ? "1" : "0");
  1015. bool InitParticleManager()
  1016. {
  1017. if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials))
  1018. return false;
  1019. return true;
  1020. }
  1021. CEG_NOINLINE bool InitGameSystems( CreateInterfaceFn appSystemFactory )
  1022. {
  1023. CEG_ENCRYPT_FUNCTION( InitGameSystems );
  1024. if (!VGui_Startup( appSystemFactory ))
  1025. return false;
  1026. // Keep the spinner going.
  1027. materials->RefreshFrontBufferNonInteractive();
  1028. vgui::VGui_InitMatSysInterfacesList( "ClientDLL", &appSystemFactory, 1 );
  1029. // Keep the spinner going.
  1030. materials->RefreshFrontBufferNonInteractive();
  1031. // Add the client systems.
  1032. // Client Leaf System has to be initialized first, since DetailObjectSystem uses it
  1033. IGameSystem::Add( GameStringSystem() );
  1034. IGameSystem::Add( g_pPrecacheRegister );
  1035. IGameSystem::Add( SoundEmitterSystem() );
  1036. IGameSystem::Add( ToolFrameworkClientSystem() );
  1037. IGameSystem::Add( ClientLeafSystem() );
  1038. IGameSystem::Add( DetailObjectSystem() );
  1039. IGameSystem::Add( ViewportClientSystem() );
  1040. IGameSystem::Add( g_pClientShadowMgr );
  1041. IGameSystem::Add( g_pColorCorrectionMgr );
  1042. #ifdef GAMEUI_UISYSTEM2_ENABLED
  1043. IGameSystem::Add( g_pGameUIGameSystem );
  1044. #endif
  1045. IGameSystem::Add( ClientThinkList() );
  1046. IGameSystem::Add( ClientSoundscapeSystem() );
  1047. IGameSystem::Add( PerfVisualBenchmark() );
  1048. IGameSystem::Add( MumbleSystem() );
  1049. #if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST )
  1050. IGameSystem::Add( GetPredictionCopyTester() );
  1051. #endif
  1052. ActivityList_Init();
  1053. ActivityList_RegisterSharedActivities();
  1054. EventList_Init();
  1055. EventList_RegisterSharedEvents();
  1056. modemanager->Init( );
  1057. // Load the ClientScheme just once
  1058. vgui::scheme()->LoadSchemeFromFileEx( VGui_GetFullscreenRootVPANEL(), "resource/ClientScheme.res", "ClientScheme");
  1059. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1060. {
  1061. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1062. GetClientMode()->InitViewport();
  1063. if ( hh == 0 )
  1064. {
  1065. GetFullscreenClientMode()->InitViewport();
  1066. }
  1067. }
  1068. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1069. {
  1070. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1071. GetHud().Init();
  1072. }
  1073. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1074. {
  1075. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1076. GetClientMode()->Init();
  1077. if ( hh == 0 )
  1078. {
  1079. GetFullscreenClientMode()->Init();
  1080. }
  1081. }
  1082. if ( !IGameSystem::InitAllSystems() )
  1083. return false;
  1084. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1085. {
  1086. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1087. GetClientMode()->Enable();
  1088. if ( hh == 0 )
  1089. {
  1090. GetFullscreenClientMode()->EnableWithRootPanel( VGui_GetFullscreenRootVPANEL() );
  1091. }
  1092. }
  1093. // Each mod is required to implement this
  1094. view = GetViewRenderInstance();
  1095. if ( !view )
  1096. {
  1097. Error( "GetViewRenderInstance() must be implemented by game." );
  1098. }
  1099. view->Init();
  1100. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1101. {
  1102. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1103. GetViewEffects()->Init();
  1104. }
  1105. C_BaseTempEntity::PrecacheTempEnts();
  1106. input->Init_All();
  1107. VGui_CreateGlobalPanels();
  1108. InitSmokeFogOverlay();
  1109. // Register user messages..
  1110. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1111. {
  1112. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1113. CUserMessageRegisterBase::RegisterAll();
  1114. }
  1115. ClientVoiceMgr_Init();
  1116. // Embed voice status icons inside chat element
  1117. {
  1118. vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL );
  1119. GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent );
  1120. }
  1121. if ( !PhysicsDLLInit( appSystemFactory ) )
  1122. return false;
  1123. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() );
  1124. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );
  1125. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() );
  1126. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetGameInstructorRestoreBlockHandler() );
  1127. ClientWorldFactoryInit();
  1128. // Keep the spinner going.
  1129. materials->RefreshFrontBufferNonInteractive();
  1130. return true;
  1131. }
  1132. CON_COMMAND( cl_modemanager_reload, "Reloads the panel metaclasses for vgui screens." )
  1133. {
  1134. modemanager->Init();
  1135. }
  1136. //CEG_PROTECT_FUNCTION( InitGameSystems );
  1137. //-----------------------------------------------------------------------------
  1138. // Purpose: Called when the DLL is first loaded.
  1139. // Input : engineFactory -
  1140. // Output : int
  1141. //-----------------------------------------------------------------------------
  1142. int CHLClient::Connect( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals )
  1143. {
  1144. if( !STEAMWORKS_INITCEGLIBRARY() )
  1145. {
  1146. return false;
  1147. }
  1148. STEAMWORKS_REGISTERTHREAD();
  1149. InitCRTMemDebug();
  1150. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
  1151. #ifdef SIXENSE
  1152. g_pSixenseInput = new SixenseInput;
  1153. #endif
  1154. // Hook up global variables
  1155. gpGlobals = pGlobals;
  1156. ConnectTier1Libraries( &appSystemFactory, 1 );
  1157. ConnectTier2Libraries( &appSystemFactory, 1 );
  1158. ConnectTier3Libraries( &appSystemFactory, 1 );
  1159. #if defined( INCLUDE_SCALEFORM )
  1160. g_pScaleformUI = ( IScaleformUI* ) appSystemFactory( SCALEFORMUI_INTERFACE_VERSION, NULL );
  1161. #endif
  1162. #ifndef NO_STEAM
  1163. #ifndef _PS3
  1164. SteamAPI_InitSafe();
  1165. SteamAPI_SetTryCatchCallbacks( false ); // We don't use exceptions, so tell steam not to use try/catch in callback handlers
  1166. #endif
  1167. ClientSteamContext().Activate();
  1168. if ( !ClientSteamContext().SteamFriends() || !ClientSteamContext().SteamUser() || !ClientSteamContext().SteamUtils() ||
  1169. !ClientSteamContext().SteamNetworking() || !ClientSteamContext().SteamMatchmaking() ||
  1170. !ClientSteamContext().SteamUser()->GetSteamID().IsValid() // << this is catching the case when Steam client is running, but showing logon username/password screen
  1171. )
  1172. {
  1173. fprintf( stderr, "FATAL ERROR: This game requires latest version of Steam to be running!\nYour Steam Client can be updated using Steam > Check for Steam Client Updates...\n" );
  1174. #if IS_WINDOWS_PC || ( defined ( LINUX ) && !defined ( DEDICATED ) )
  1175. Error( "FATAL ERROR: Failed to connect with local Steam Client process!\n\nPlease make sure that you are running latest version of Steam Client.\nYou can check for Steam Client updates using Steam main menu:\n Steam > Check for Steam Client Updates..." );
  1176. #endif
  1177. Plat_ExitProcess( 100 );
  1178. return false;
  1179. }
  1180. #endif
  1181. // Initialize the console variables.
  1182. ConVar_Register( FCVAR_CLIENTDLL );
  1183. return true;
  1184. }
  1185. void CHLClient::Disconnect()
  1186. {
  1187. ConVar_Unregister( );
  1188. STEAMWORKS_UNREGISTERTHREAD();
  1189. STEAMWORKS_TERMCEGLIBRARY();
  1190. }
  1191. int CHLClient::Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals )
  1192. {
  1193. STEAMWORKS_TESTSECRETALWAYS();
  1194. STEAMWORKS_SELFCHECK();
  1195. COM_TimestampedLog( "ClientDLL factories - Start" );
  1196. // We aren't happy unless we get all of our interfaces.
  1197. // please don't collapse this into one monolithic boolean expression (impossible to debug)
  1198. if ( (engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
  1199. return false;
  1200. if ( (modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) == NULL )
  1201. return false;
  1202. if ( (effects = (IVEfx *)appSystemFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL )) == NULL )
  1203. return false;
  1204. if ( (enginetrace = (IEngineTrace *)appSystemFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL )) == NULL )
  1205. return false;
  1206. if ( (filelogginglistener = (IFileLoggingListener *)appSystemFactory(FILELOGGINGLISTENER_INTERFACE_VERSION, NULL)) == NULL )
  1207. return false;
  1208. if ( (render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) == NULL )
  1209. return false;
  1210. if ( (debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL )) == NULL )
  1211. return false;
  1212. if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL )
  1213. return false;
  1214. if ( !mdlcache )
  1215. return false;
  1216. if ( (modelinfo = (IVModelInfoClient *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
  1217. return false;
  1218. if ( (enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) == NULL )
  1219. return false;
  1220. if ( (networkstringtable = (INetworkStringTableContainer *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLECLIENT,NULL)) == NULL )
  1221. return false;
  1222. if ( (::partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) == NULL )
  1223. return false;
  1224. if ( (shadowmgr = (IShadowMgr *)appSystemFactory(ENGINE_SHADOWMGR_INTERFACE_VERSION, NULL)) == NULL )
  1225. return false;
  1226. if ( (staticpropmgr = (IStaticPropMgrClient *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_CLIENT, NULL)) == NULL )
  1227. return false;
  1228. if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) == NULL )
  1229. return false;
  1230. if ( (filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  1231. return false;
  1232. if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) == NULL )
  1233. return false;
  1234. if ( (gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) == NULL )
  1235. return false;
  1236. if ( (gameeventmanager = (IGameEventManager2 *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2,NULL)) == NULL )
  1237. return false;
  1238. if ( (soundemitterbase = (ISoundEmitterSystemBase *)appSystemFactory(SOUNDEMITTERSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  1239. return false;
  1240. if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  1241. return false;
  1242. #if defined ( AVI_VIDEO )
  1243. if ( IsPC() && !IsPosix() && (avi = (IAvi *)appSystemFactory(AVI_INTERFACE_VERSION, NULL)) == NULL )
  1244. return false;
  1245. #endif
  1246. #if ( !defined( _GAMECONSOLE ) || defined( BINK_ENABLED_FOR_CONSOLE ) ) && defined( BINK_VIDEO )
  1247. if ( (bik = (IBik *)appSystemFactory(BIK_INTERFACE_VERSION, NULL)) == NULL )
  1248. return false;
  1249. #endif
  1250. #if defined( QUICKTIME_VIDEO )
  1251. if ( (pQuicktime = (IQuickTime*)appSystemFactory( QUICKTIME_INTERFACE_VERSION, NULL)) == NULL )
  1252. return false;
  1253. #endif
  1254. if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL )
  1255. return false;
  1256. if ( (blackboxrecorder = (IBlackBox *)appSystemFactory(BLACKBOX_INTERFACE_VERSION, NULL)) == NULL )
  1257. return false;
  1258. if ( (xboxsystem = (IXboxSystem *)appSystemFactory( XBOXSYSTEM_INTERFACE_VERSION, NULL )) == NULL )
  1259. return false;
  1260. if ( (g_pRenderToRTHelper = (IRenderToRTHelper *)appSystemFactory( RENDER_TO_RT_HELPER_INTERFACE_VERSION, NULL )) == NULL )
  1261. return false;
  1262. if ( !g_pRenderToRTHelper->Init() )
  1263. return false;
  1264. #if defined( CSTRIKE15 )
  1265. if ( ( g_pGameTypes = (IGameTypes *)appSystemFactory( VENGINE_GAMETYPES_VERSION, NULL )) == NULL )
  1266. return false;
  1267. // load the p4 lib - not doing it in CS:GO to prevent extra .dlls from being loaded
  1268. CSysModule *m_pP4Module = Sys_LoadModule( "p4lib" );
  1269. if ( m_pP4Module )
  1270. {
  1271. CreateInterfaceFn factory = Sys_GetFactory( m_pP4Module );
  1272. if ( factory )
  1273. {
  1274. p4 = ( IP4 * )factory( P4_INTERFACE_VERSION, NULL );
  1275. if ( p4 )
  1276. {
  1277. p4->Connect( appSystemFactory );
  1278. p4->Init();
  1279. }
  1280. }
  1281. }
  1282. #endif
  1283. #if defined( REPLAY_ENABLED )
  1284. if ( IsPC() && (g_pReplayHistoryManager = (IReplayHistoryManager *)appSystemFactory( REPLAYHISTORYMANAGER_INTERFACE_VERSION, NULL )) == NULL )
  1285. return false;
  1286. #endif
  1287. #ifndef _GAMECONSOLE
  1288. if ( ( gamestatsuploader = (IUploadGameStats *)appSystemFactory( INTERFACEVERSION_UPLOADGAMESTATS, NULL )) == NULL )
  1289. return false;
  1290. #endif
  1291. if (!g_pMatSystemSurface)
  1292. return false;
  1293. #ifdef INFESTED_DLL
  1294. if ( (missionchooser = (IASW_Mission_Chooser *)appSystemFactory(ASW_MISSION_CHOOSER_VERSION, NULL)) == NULL )
  1295. return false;
  1296. #endif
  1297. #ifdef TERROR
  1298. if ( ( g_pMatchExtL4D = ( IMatchExtL4D * ) appSystemFactory( IMATCHEXT_L4D_INTERFACE, NULL ) ) == NULL )
  1299. return false;
  1300. if ( !g_pMatchFramework )
  1301. return false;
  1302. // if client.dll needs to register any matchmaking extensions do it here:
  1303. // if ( IMatchExtensions *pIMatchExtensions = g_pMatchFramework->GetMatchExtensions() )
  1304. // pIMatchExtensions->RegisterExtensionInterface(
  1305. // INTERFACEVERSION_SERVERGAMEDLL, static_cast< IServerGameDLL * >( this ) );
  1306. #endif
  1307. #ifdef PORTAL2
  1308. if ( !g_pMatchFramework )
  1309. return false;
  1310. GameInstructor_Init();
  1311. // if client.dll needs to register any matchmaking extensions do it here:
  1312. // if ( IMatchExtensions *pIMatchExtensions = g_pMatchFramework->GetMatchExtensions() )
  1313. // pIMatchExtensions->RegisterExtensionInterface(
  1314. // INTERFACEVERSION_SERVERGAMEDLL, static_cast< IServerGameDLL * >( this ) );
  1315. #endif // PORTAL2
  1316. #ifdef CSTRIKE15
  1317. if ( !g_pMatchFramework )
  1318. return false;
  1319. GameInstructor_Init();
  1320. #endif
  1321. if ( !g_pMatchFramework )
  1322. return false;
  1323. if ( IMatchExtensions *pIMatchExtensions = g_pMatchFramework->GetMatchExtensions() )
  1324. pIMatchExtensions->RegisterExtensionInterface(
  1325. CLIENT_DLL_INTERFACE_VERSION, static_cast< IBaseClientDLL * >( this ) );
  1326. #if defined(_PS3)
  1327. // VJOBS is used to spawn jobs on SPUs
  1328. if ( (g_pVJobs = (IVJobs *)appSystemFactory( VJOBS_INTERFACE_VERSION, NULL )) == NULL)
  1329. return false;
  1330. // init client SPURS jobs
  1331. g_pBuildRenderablesJob->Init();
  1332. #endif
  1333. if ( !CommandLine()->CheckParm( "-noscripting") )
  1334. {
  1335. scriptmanager = (IScriptManager *)appSystemFactory( VSCRIPT_INTERFACE_VERSION, NULL );
  1336. }
  1337. factorylist_t factories;
  1338. factories.appSystemFactory = appSystemFactory;
  1339. FactoryList_Store( factories );
  1340. COM_TimestampedLog( "soundemitterbase->Connect" );
  1341. // Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully
  1342. if ( !soundemitterbase->Connect( appSystemFactory ) )
  1343. {
  1344. return false;
  1345. }
  1346. #if defined( ALLOW_TEXT_MODE )
  1347. if ( CommandLine()->FindParm( "-textmode" ) )
  1348. g_bTextMode = true;
  1349. #endif
  1350. if ( CommandLine()->FindParm( "-makedevshots" ) )
  1351. g_MakingDevShots = true;
  1352. if ( CommandLine()->FindParm( "-headtracking" ) )
  1353. g_bHeadTrackingEnabled = true;
  1354. // Not fatal if the material system stub isn't around.
  1355. materials_stub = (IMaterialSystemStub*)appSystemFactory( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION, NULL );
  1356. if( !g_pMaterialSystemHardwareConfig )
  1357. return false;
  1358. // Hook up the gaussian random number generator
  1359. s_GaussianRandomStream.AttachToStream( random );
  1360. g_pcv_ThreadMode = g_pCVar->FindVar( "host_thread_mode" );
  1361. #if defined( PORTAL2 )
  1362. engine->EnablePaintmapRender();
  1363. #endif
  1364. COM_TimestampedLog( "InitGameSystems" );
  1365. bool bInitSuccess = false;
  1366. if ( cl_threaded_init.GetBool() )
  1367. {
  1368. CFunctorJob *pGameJob = new CFunctorJob( CreateFunctor( InitParticleManager ) );
  1369. g_pThreadPool->AddJob( pGameJob );
  1370. bInitSuccess = InitGameSystems( appSystemFactory );
  1371. // While the InitParticleManager job isn't finished, try to update the spinner
  1372. while( !pGameJob->IsFinished() )
  1373. {
  1374. g_pMaterialSystem->RefreshFrontBufferNonInteractive();
  1375. // Don't just update as fast as we can
  1376. ThreadSleep( 50 );
  1377. }
  1378. pGameJob->Release();
  1379. }
  1380. else
  1381. {
  1382. COM_TimestampedLog( "ParticleMgr()->Init" );
  1383. if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials))
  1384. return false;
  1385. COM_TimestampedLog( "InitGameSystems - Start" );
  1386. bInitSuccess = InitGameSystems( appSystemFactory );
  1387. COM_TimestampedLog( "InitGameSystems - End" );
  1388. }
  1389. #ifdef INFESTED_PARTICLES // let the emitter cache load in our standard
  1390. g_ASWGenericEmitterCache.PrecacheTemplates();
  1391. #endif
  1392. COM_TimestampedLog( "C_BaseAnimating::InitBoneSetupThreadPool" );
  1393. C_BaseAnimating::InitBoneSetupThreadPool();
  1394. // This is a fullscreen element, so only lives on slot 0!!!
  1395. m_pHudCloseCaption = GET_FULLSCREEN_HUDELEMENT( CHudCloseCaption );
  1396. #if defined( PORTAL2_PUZZLEMAKER )
  1397. // This must be called after all other VGui initialization (i.e after InitGameSystems)
  1398. g_PuzzleMaker.Init();
  1399. #endif // PORTAL2_PUZZLEMAKER
  1400. #if defined( CSTRIKE15 )
  1401. // Load the game types.
  1402. g_pGameTypes->Initialize();
  1403. #endif
  1404. //
  1405. // Censoring banlist loads here
  1406. //
  1407. bool bLoadBannedWords = !!CommandLine()->FindParm( "-perfectworld" );
  1408. bLoadBannedWords |= !!CommandLine()->FindParm( "-usebanlist" );
  1409. if ( bLoadBannedWords )
  1410. {
  1411. g_BannedWords.InitFromFile( "banlist.res" );
  1412. }
  1413. COM_TimestampedLog( "ClientDLL Init - Finish" );
  1414. return true;
  1415. }
  1416. //-----------------------------------------------------------------------------
  1417. // Purpose: Called after client & server DLL are loaded and all systems initialized
  1418. //-----------------------------------------------------------------------------
  1419. CEG_NOINLINE void CHLClient::PostInit()
  1420. {
  1421. CEG_PROTECT_VIRTUAL_FUNCTION( CHLCLient_PostInit );
  1422. Init_GCVs();
  1423. COM_TimestampedLog( "IGameSystem::PostInitAllSystems - Start" );
  1424. IGameSystem::PostInitAllSystems();
  1425. COM_TimestampedLog( "IGameSystem::PostInitAllSystems - Finish" );
  1426. // Turn 7L rendering optimisations ON if "-rdropt" is specified on the command line
  1427. if ( CommandLine()->FindParm( "-rdropt" ) != 0 )
  1428. {
  1429. engine->ExecuteClientCmd( "toggleRdrOpt" );
  1430. }
  1431. #ifdef SIXENSE
  1432. // allow sixnese input to perform post-init operations
  1433. g_pSixenseInput->PostInit();
  1434. #endif
  1435. STEAMWORKS_TESTSECRETALWAYS();
  1436. }
  1437. //-----------------------------------------------------------------------------
  1438. // Purpose: Called when the client .dll is being dismissed
  1439. //-----------------------------------------------------------------------------
  1440. CEG_NOINLINE void CHLClient::Shutdown( void )
  1441. {
  1442. if ( g_pRenderToRTHelper )
  1443. {
  1444. g_pRenderToRTHelper->Shutdown();
  1445. }
  1446. #ifdef PORTAL2
  1447. GameInstructor_Shutdown();
  1448. #endif
  1449. if ( g_pAchievementsAndStatsInterface )
  1450. {
  1451. g_pAchievementsAndStatsInterface->ReleasePanel();
  1452. }
  1453. ActivityList_Free();
  1454. EventList_Free();
  1455. VGui_ClearVideoPanels();
  1456. #ifdef SIXENSE
  1457. g_pSixenseInput->Shutdown();
  1458. delete g_pSixenseInput;
  1459. g_pSixenseInput = NULL;
  1460. #endif
  1461. C_BaseAnimating::ShutdownBoneSetupThreadPool();
  1462. ClientWorldFactoryShutdown();
  1463. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetGameInstructorRestoreBlockHandler() );
  1464. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() );
  1465. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() );
  1466. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() );
  1467. ClientVoiceMgr_Shutdown();
  1468. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1469. {
  1470. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1471. GetClientMode()->Disable();
  1472. if ( hh == 0 )
  1473. {
  1474. GetFullscreenClientMode()->Disable();
  1475. }
  1476. }
  1477. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1478. {
  1479. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1480. GetClientMode()->Shutdown();
  1481. if ( hh == 0 )
  1482. {
  1483. GetFullscreenClientMode()->Shutdown();
  1484. }
  1485. }
  1486. CEG_PROTECT_VIRTUAL_FUNCTION( CHLClient_Shutdown );
  1487. input->Shutdown_All();
  1488. C_BaseTempEntity::ClearDynamicTempEnts();
  1489. TermSmokeFogOverlay();
  1490. view->Shutdown();
  1491. g_pParticleSystemMgr->UncacheAllParticleSystems();
  1492. UncacheAllMovies();
  1493. UncacheAllMaterials();
  1494. IGameSystem::ShutdownAllSystems();
  1495. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1496. {
  1497. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  1498. GetHud().Shutdown();
  1499. }
  1500. VGui_Shutdown();
  1501. ParticleMgr()->Term();
  1502. #ifdef USE_BLOBULATOR
  1503. Blobulator::ShutdownBlob();
  1504. #endif // USE_BLOBULATOR
  1505. ClearKeyValuesCache();
  1506. #ifndef NO_STEAM
  1507. ClientSteamContext().Shutdown();
  1508. // SteamAPI_Shutdown(); << Steam shutdown is controlled by engine
  1509. #endif
  1510. DisconnectTier3Libraries( );
  1511. DisconnectTier2Libraries( );
  1512. ConVar_Unregister();
  1513. DisconnectTier1Libraries( );
  1514. gameeventmanager = NULL;
  1515. }
  1516. //-----------------------------------------------------------------------------
  1517. // Purpose:
  1518. // Called when the game initializes
  1519. // and whenever the vid_mode is changed
  1520. // so the HUD can reinitialize itself.
  1521. // Output : int
  1522. //-----------------------------------------------------------------------------
  1523. int CHLClient::HudVidInit( void )
  1524. {
  1525. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1526. {
  1527. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1528. GetHud().VidInit();
  1529. }
  1530. GetClientVoiceMgr()->VidInit();
  1531. return 1;
  1532. }
  1533. //-----------------------------------------------------------------------------
  1534. // Method used to allow the client to filter input messages before the
  1535. // move record is transmitted to the server
  1536. //-----------------------------------------------------------------------------
  1537. void CHLClient::HudProcessInput( bool bActive )
  1538. {
  1539. GetClientMode()->ProcessInput( bActive );
  1540. }
  1541. //-----------------------------------------------------------------------------
  1542. // Purpose: Called when shared data gets changed, allows dll to modify data
  1543. // Input : bActive -
  1544. //-----------------------------------------------------------------------------
  1545. void CHLClient::HudUpdate( bool bActive )
  1546. {
  1547. float frametime = gpGlobals->frametime;
  1548. GetClientVoiceMgr()->Frame( frametime );
  1549. ASSERT_LOCAL_PLAYER_NOT_RESOLVABLE();
  1550. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  1551. {
  1552. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1553. GetHud().UpdateHud( bActive );
  1554. }
  1555. ASSERT_LOCAL_PLAYER_NOT_RESOLVABLE();
  1556. {
  1557. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1558. IGameSystem::UpdateAllSystems( frametime );
  1559. }
  1560. // run vgui animations
  1561. vgui::GetAnimationController()->UpdateAnimations( Plat_FloatTime() );
  1562. if ( hudlcd )
  1563. {
  1564. hudlcd->SetGlobalStat( "(time_int)", VarArgs( "%d", (int)gpGlobals->curtime ) );
  1565. hudlcd->SetGlobalStat( "(time_float)", VarArgs( "%.2f", gpGlobals->curtime ) );
  1566. }
  1567. // I don't think this is necessary any longer, but I will leave it until
  1568. // I can check into this further.
  1569. C_BaseTempEntity::CheckDynamicTempEnts();
  1570. #ifdef SIXENSE
  1571. // If we're not connected, update sixense so we can move the mouse cursor when in the menus
  1572. if( !engine->IsConnected() || engine->IsPaused() )
  1573. {
  1574. g_pSixenseInput->SixenseFrame( 0, NULL );
  1575. }
  1576. #endif
  1577. }
  1578. //-----------------------------------------------------------------------------
  1579. // Purpose: Called to restore to "non"HUD state.
  1580. //-----------------------------------------------------------------------------
  1581. void CHLClient::HudReset( void )
  1582. {
  1583. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1584. {
  1585. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1586. GetHud().VidInit();
  1587. }
  1588. PhysicsReset();
  1589. }
  1590. //-----------------------------------------------------------------------------
  1591. // Purpose: Called to add hud text message
  1592. //-----------------------------------------------------------------------------
  1593. void CHLClient::HudText( const char * message )
  1594. {
  1595. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  1596. {
  1597. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1598. DispatchHudText( message );
  1599. }
  1600. }
  1601. //-----------------------------------------------------------------------------
  1602. // Handler for input events for the new game ui system
  1603. //-----------------------------------------------------------------------------
  1604. bool CHLClient::HandleGameUIEvent( const InputEvent_t &inputEvent )
  1605. {
  1606. #ifdef GAMEUI_UISYSTEM2_ENABLED
  1607. // TODO: when embedded UI will be used for HUD, we will need it to maintain
  1608. // a separate screen for HUD and a separate screen stack for pause menu & main menu.
  1609. // for now only render embedded UI in pause menu & main menu
  1610. BaseModUI::CBaseModPanel *pBaseModPanel = BaseModUI::CBaseModPanel::GetSingletonPtr();
  1611. if ( !pBaseModPanel || !pBaseModPanel->IsVisible() )
  1612. return false;
  1613. return g_pGameUIGameSystem->RegisterInputEvent( inputEvent );
  1614. #else
  1615. return false;
  1616. #endif
  1617. }
  1618. //-----------------------------------------------------------------------------
  1619. // Process any extra client specific, non-entity based sound positioning.
  1620. //-----------------------------------------------------------------------------
  1621. bool CHLClient::GetSoundSpatialization( SpatializationInfo_t& info )
  1622. {
  1623. #ifdef PORTAL2
  1624. // Vector vListenerOrigin;
  1625. // VectorCopy( info.info.vListenerOrigin, vListenerOrigin );
  1626. Vector vSoundOrigin;
  1627. if( info.pOrigin )
  1628. {
  1629. VectorCopy( *info.pOrigin, vSoundOrigin );
  1630. }
  1631. else
  1632. {
  1633. VectorCopy( info.info.vOrigin, vSoundOrigin );
  1634. }
  1635. UTIL_Portal_VectorToGlobalTransforms( vSoundOrigin, info.m_pUtlVecMultiOrigins );
  1636. // // portal2
  1637. // Vector vListenerOrigin, vSoundOrigin;
  1638. //
  1639. // VectorCopy( info.info.vListenerOrigin, vListenerOrigin );
  1640. // if( info.pOrigin )
  1641. // {
  1642. // VectorCopy( *info.pOrigin, vSoundOrigin );
  1643. // }
  1644. // else
  1645. // {
  1646. // VectorCopy( info.info.vOrigin, vSoundOrigin );
  1647. // }
  1648. //
  1649. // CPortal_Base2D *pShortestDistPortal_Out = NULL;
  1650. // float flMinDist = UTIL_Portal_ShortestDistanceSqr( vListenerOrigin , vSoundOrigin, &pShortestDistPortal_Out );
  1651. //
  1652. // if( pShortestDistPortal_Out )
  1653. // {
  1654. // if( pShortestDistPortal_Out->m_bActivated )
  1655. // {
  1656. // CPortal_Base2D *pLinkedPortal = pShortestDistPortal_Out->m_hLinkedPortal.Get();
  1657. // if( pLinkedPortal != NULL )
  1658. // {
  1659. //
  1660. // VMatrix matrixFromPortal;
  1661. // MatrixInverseTR( pShortestDistPortal_Out->MatrixThisToLinked(), matrixFromPortal );
  1662. //
  1663. // Vector vPoint1Transformed = matrixFromPortal * vSoundOrigin;
  1664. // if( info.pOrigin )
  1665. // {
  1666. // *info.pOrigin = vPoint1Transformed;
  1667. // }
  1668. // else
  1669. // {
  1670. // info.info.vOrigin = vPoint1Transformed;
  1671. // }
  1672. //
  1673. // //DevMsg("****sound portaled: %f %f %f\n", vPoint1Transformed[0], vPoint1Transformed[1], vPoint1Transformed[2] );
  1674. //
  1675. // }
  1676. // }
  1677. // }
  1678. #endif
  1679. return true;
  1680. }
  1681. //-----------------------------------------------------------------------------
  1682. // Purpose:
  1683. //-----------------------------------------------------------------------------
  1684. bool CHLClient::ShouldDrawDropdownConsole()
  1685. {
  1686. #if defined( TF_CLIENT_DLL )
  1687. extern ConVar hud_freezecamhide;
  1688. extern bool IsTakingAFreezecamScreenshot();
  1689. if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() )
  1690. {
  1691. return false;
  1692. }
  1693. #endif
  1694. return true;
  1695. }
  1696. //-----------------------------------------------------------------------------
  1697. // Purpose:
  1698. // Output : ClientClass
  1699. //-----------------------------------------------------------------------------
  1700. ClientClass *CHLClient::GetAllClasses( void )
  1701. {
  1702. return g_pClientClassHead;
  1703. }
  1704. //-----------------------------------------------------------------------------
  1705. // Purpose:
  1706. //-----------------------------------------------------------------------------
  1707. void CHLClient::IN_ActivateMouse( void )
  1708. {
  1709. input->ActivateMouse();
  1710. }
  1711. //-----------------------------------------------------------------------------
  1712. // Purpose:
  1713. //-----------------------------------------------------------------------------
  1714. void CHLClient::IN_DeactivateMouse( void )
  1715. {
  1716. input->DeactivateMouse();
  1717. }
  1718. extern ConVar in_forceuser;
  1719. //-----------------------------------------------------------------------------
  1720. // Purpose:
  1721. //-----------------------------------------------------------------------------
  1722. void CHLClient::IN_Accumulate ( void )
  1723. {
  1724. ACTIVE_SPLITSCREEN_PLAYER_GUARD( in_forceuser.GetInt() );
  1725. input->AccumulateMouse( GET_ACTIVE_SPLITSCREEN_SLOT() );
  1726. }
  1727. //-----------------------------------------------------------------------------
  1728. // Purpose:
  1729. //-----------------------------------------------------------------------------
  1730. void CHLClient::IN_ClearStates ( void )
  1731. {
  1732. input->ClearStates();
  1733. }
  1734. //-----------------------------------------------------------------------------
  1735. // Purpose: Engine can query for particular keys
  1736. // Input : *name -
  1737. //-----------------------------------------------------------------------------
  1738. bool CHLClient::IN_IsKeyDown( const char *name, bool& isdown )
  1739. {
  1740. kbutton_t *key = input->FindKey( name );
  1741. if ( !key )
  1742. {
  1743. return false;
  1744. }
  1745. isdown = ( key->GetPerUser().state & 1 ) ? true : false;
  1746. // Found the key by name
  1747. return true;
  1748. }
  1749. //-----------------------------------------------------------------------------
  1750. // Purpose: Engine can issue a key event
  1751. // Input : eventcode -
  1752. // keynum -
  1753. // *pszCurrentBinding -
  1754. // Output : int
  1755. //-----------------------------------------------------------------------------
  1756. int CHLClient::IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding )
  1757. {
  1758. return input->KeyEvent( eventcode, keynum, pszCurrentBinding );
  1759. }
  1760. void CHLClient::ExtraMouseSample( float frametime, bool active )
  1761. {
  1762. bool bSave = C_BaseEntity::IsAbsRecomputationsEnabled();
  1763. C_BaseEntity::EnableAbsRecomputations( true );
  1764. // [mariod] - testing, see note in c_baseanimating.cpp
  1765. //C_BaseAnimating::EnableNewBoneSetupRequest( false );
  1766. ABS_QUERY_GUARD( true );
  1767. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1768. MDLCACHE_CRITICAL_SECTION();
  1769. input->ExtraMouseSample( frametime, active );
  1770. // [mariod] - testing, see note in c_baseanimating.cpp
  1771. //C_BaseAnimating::EnableNewBoneSetupRequest( true );
  1772. C_BaseEntity::EnableAbsRecomputations( bSave );
  1773. }
  1774. void CHLClient::IN_SetSampleTime( float frametime )
  1775. {
  1776. input->Joystick_SetSampleTime( frametime );
  1777. input->IN_SetSampleTime( frametime );
  1778. #ifdef SIXENSE
  1779. g_pSixenseInput->ResetFrameTime( frametime );
  1780. #endif
  1781. }
  1782. //-----------------------------------------------------------------------------
  1783. // Purpose: Fills in usercmd_s structure based on current view angles and key/controller inputs
  1784. // Input : frametime - timestamp for last frame
  1785. // *cmd - the command to fill in
  1786. // active - whether the user is fully connected to a server
  1787. //-----------------------------------------------------------------------------
  1788. void CHLClient::CreateMove ( int sequence_number, float input_sample_frametime, bool active )
  1789. {
  1790. Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
  1791. Assert( C_BaseEntity::IsAbsQueriesValid() );
  1792. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1793. // [mariod] - testing, see note in c_baseanimating.cpp
  1794. //C_BaseAnimating::EnableNewBoneSetupRequest( false );
  1795. MDLCACHE_CRITICAL_SECTION();
  1796. input->CreateMove( sequence_number, input_sample_frametime, active );
  1797. // [mariod] - testing, see note in c_baseanimating.cpp
  1798. //C_BaseAnimating::EnableNewBoneSetupRequest( true );
  1799. }
  1800. //-----------------------------------------------------------------------------
  1801. // Purpose:
  1802. // Input : *buf -
  1803. // from -
  1804. // to -
  1805. //-----------------------------------------------------------------------------
  1806. bool CHLClient::WriteUsercmdDeltaToBuffer( int nSlot, bf_write *buf, int from, int to, bool isnewcommand )
  1807. {
  1808. return input->WriteUsercmdDeltaToBuffer( nSlot, buf, from, to, isnewcommand );
  1809. }
  1810. //-----------------------------------------------------------------------------
  1811. // Purpose:
  1812. // Input : buf -
  1813. // buffersize -
  1814. //-----------------------------------------------------------------------------
  1815. void CHLClient::EncodeUserCmdToBuffer( int nSlot, bf_write& buf, int slot )
  1816. {
  1817. input->EncodeUserCmdToBuffer( nSlot, buf, slot );
  1818. }
  1819. //-----------------------------------------------------------------------------
  1820. // Purpose:
  1821. // Input : buf -
  1822. // buffersize -
  1823. // slot -
  1824. //-----------------------------------------------------------------------------
  1825. void CHLClient::DecodeUserCmdFromBuffer( int nSlot, bf_read& buf, int slot )
  1826. {
  1827. input->DecodeUserCmdFromBuffer( nSlot, buf, slot );
  1828. }
  1829. //-----------------------------------------------------------------------------
  1830. // Purpose:
  1831. //-----------------------------------------------------------------------------
  1832. void CHLClient::View_Render( vrect_t *rect )
  1833. {
  1834. VPROF( "View_Render" );
  1835. // UNDONE: This gets hit at startup sometimes, investigate - will cause NaNs in calcs inside Render()
  1836. if ( rect->width == 0 || rect->height == 0 )
  1837. return;
  1838. view->Render( rect );
  1839. #if !defined( _GAMECONSOLE ) && !defined( NO_STEAM )
  1840. UpdatePerfStats();
  1841. #endif
  1842. }
  1843. //-----------------------------------------------------------------------------
  1844. // Gets the location of the player viewpoint
  1845. //-----------------------------------------------------------------------------
  1846. bool CHLClient::GetPlayerView( CViewSetup &playerView )
  1847. {
  1848. playerView = *view->GetPlayerViewSetup();
  1849. return true;
  1850. }
  1851. //-----------------------------------------------------------------------------
  1852. //
  1853. //-----------------------------------------------------------------------------
  1854. void CHLClient::InvalidateMdlCache()
  1855. {
  1856. C_BaseAnimating *pAnimating;
  1857. for ( C_BaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity(pEntity) )
  1858. {
  1859. pAnimating = pEntity->GetBaseAnimating();
  1860. if ( pAnimating )
  1861. {
  1862. pAnimating->InvalidateMdlCache();
  1863. }
  1864. }
  1865. CStudioHdr::CActivityToSequenceMapping::ResetMappings();
  1866. }
  1867. //-----------------------------------------------------------------------------
  1868. // Purpose:
  1869. // Input : *pSF -
  1870. //-----------------------------------------------------------------------------
  1871. void CHLClient::View_Fade( ScreenFade_t *pSF )
  1872. {
  1873. if ( pSF != NULL )
  1874. {
  1875. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  1876. {
  1877. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  1878. GetViewEffects()->Fade( *pSF );
  1879. }
  1880. }
  1881. }
  1882. // CPU level
  1883. //-----------------------------------------------------------------------------
  1884. void ConfigureCurrentSystemLevel( );
  1885. void OnCPULevelChanged( IConVar *var, const char *pOldValue, float flOldValue )
  1886. {
  1887. ConfigureCurrentSystemLevel();
  1888. }
  1889. #if defined( DX_TO_GL_ABSTRACTION )
  1890. static ConVar cpu_level( "cpu_level", "3", 0, "CPU Level - Default: High", OnCPULevelChanged );
  1891. #else
  1892. static ConVar cpu_level( "cpu_level", "2", 0, "CPU Level - Default: High", OnCPULevelChanged );
  1893. #endif
  1894. CPULevel_t GetCPULevel()
  1895. {
  1896. if ( IsX360() )
  1897. return CPU_LEVEL_360;
  1898. if ( IsPS3() )
  1899. return CPU_LEVEL_PS3;
  1900. return GetActualCPULevel();
  1901. }
  1902. CPULevel_t GetActualCPULevel()
  1903. {
  1904. // Should we cache system_level off during level init?
  1905. CPULevel_t nSystemLevel = (CPULevel_t)clamp( cpu_level.GetInt(), 0, CPU_LEVEL_PC_COUNT-1 );
  1906. return nSystemLevel;
  1907. }
  1908. //-----------------------------------------------------------------------------
  1909. // GPU level
  1910. //-----------------------------------------------------------------------------
  1911. void OnGPULevelChanged( IConVar *var, const char *pOldValue, float flOldValue )
  1912. {
  1913. ConfigureCurrentSystemLevel();
  1914. }
  1915. static ConVar gpu_level( "gpu_level", "3", 0, "GPU Level - Default: High", OnGPULevelChanged );
  1916. GPULevel_t GetGPULevel()
  1917. {
  1918. if ( IsX360() )
  1919. return GPU_LEVEL_360;
  1920. if ( IsPS3() )
  1921. return GPU_LEVEL_PS3;
  1922. // Should we cache system_level off during level init?
  1923. GPULevel_t nSystemLevel = (GPULevel_t)clamp( gpu_level.GetInt(), 0, GPU_LEVEL_PC_COUNT-1 );
  1924. return nSystemLevel;
  1925. }
  1926. //-----------------------------------------------------------------------------
  1927. // System Memory level
  1928. //-----------------------------------------------------------------------------
  1929. void OnMemLevelChanged( IConVar *var, const char *pOldValue, float flOldValue )
  1930. {
  1931. ConfigureCurrentSystemLevel();
  1932. }
  1933. #if defined( DX_TO_GL_ABSTRACTION )
  1934. static ConVar mem_level( "mem_level", "3", 0, "Memory Level - Default: High", OnMemLevelChanged );
  1935. #else
  1936. static ConVar mem_level( "mem_level", "2", 0, "Memory Level - Default: High", OnMemLevelChanged );
  1937. #endif
  1938. MemLevel_t GetMemLevel()
  1939. {
  1940. if ( IsX360() )
  1941. return MEM_LEVEL_360;
  1942. if ( IsPS3() )
  1943. return MEM_LEVEL_PS3;
  1944. #ifdef POSIX
  1945. const int nMinMemLevel = 2;
  1946. #else
  1947. const int nMinMemLevel = 0;
  1948. #endif
  1949. // Should we cache system_level off during level init?
  1950. MemLevel_t nSystemLevel = (MemLevel_t)clamp( mem_level.GetInt(), nMinMemLevel, MEM_LEVEL_PC_COUNT-1 );
  1951. return nSystemLevel;
  1952. }
  1953. //-----------------------------------------------------------------------------
  1954. // GPU Memory level
  1955. //-----------------------------------------------------------------------------
  1956. void OnGPUMemLevelChanged( IConVar *var, const char *pOldValue, float flOldValue )
  1957. {
  1958. ConfigureCurrentSystemLevel();
  1959. }
  1960. #if defined( DX_TO_GL_ABSTRACTION )
  1961. static ConVar gpu_mem_level( "gpu_mem_level", "3", 0, "Memory Level - Default: High", OnGPUMemLevelChanged );
  1962. #else
  1963. static ConVar gpu_mem_level( "gpu_mem_level", "2", 0, "Memory Level - Default: High", OnGPUMemLevelChanged );
  1964. #endif
  1965. GPUMemLevel_t GetGPUMemLevel()
  1966. {
  1967. if ( IsX360() )
  1968. return GPU_MEM_LEVEL_360;
  1969. if ( IsPS3() )
  1970. return GPU_MEM_LEVEL_PS3;
  1971. // Should we cache system_level off during level init?
  1972. GPUMemLevel_t nSystemLevel = (GPUMemLevel_t)clamp( gpu_mem_level.GetInt(), 0, GPU_MEM_LEVEL_PC_COUNT-1 );
  1973. return nSystemLevel;
  1974. }
  1975. ConVar cl_disable_splitscreen_cpu_level_cfgs_in_pip( "cl_disable_splitscreen_cpu_level_cfgs_in_pip", "1", 0, "" );
  1976. CEG_NOINLINE void ConfigureCurrentSystemLevel()
  1977. {
  1978. CEG_ENCRYPT_FUNCTION( ConfigureCurrentSystemLevel );
  1979. int nCPULevel = GetCPULevel();
  1980. if ( nCPULevel == CPU_LEVEL_360 )
  1981. {
  1982. nCPULevel = CONSOLE_SYSTEM_LEVEL_360;
  1983. }
  1984. else if ( nCPULevel == CPU_LEVEL_PS3 )
  1985. {
  1986. nCPULevel = CONSOLE_SYSTEM_LEVEL_PS3;
  1987. }
  1988. int nGPULevel = GetGPULevel();
  1989. if ( nGPULevel == GPU_LEVEL_360 )
  1990. {
  1991. nGPULevel = CONSOLE_SYSTEM_LEVEL_360;
  1992. }
  1993. else if ( nGPULevel == GPU_LEVEL_PS3 )
  1994. {
  1995. nGPULevel = CONSOLE_SYSTEM_LEVEL_PS3;
  1996. }
  1997. int nMemLevel = GetMemLevel();
  1998. if ( nMemLevel == MEM_LEVEL_360 )
  1999. {
  2000. nMemLevel = CONSOLE_SYSTEM_LEVEL_360;
  2001. }
  2002. else if ( nMemLevel == MEM_LEVEL_PS3 )
  2003. {
  2004. nMemLevel = CONSOLE_SYSTEM_LEVEL_PS3;
  2005. }
  2006. int nGPUMemLevel = GetGPUMemLevel();
  2007. if ( nGPUMemLevel == GPU_MEM_LEVEL_360 )
  2008. {
  2009. nGPUMemLevel = CONSOLE_SYSTEM_LEVEL_360;
  2010. }
  2011. else if ( nGPUMemLevel == GPU_MEM_LEVEL_PS3 )
  2012. {
  2013. nGPUMemLevel = CONSOLE_SYSTEM_LEVEL_PS3;
  2014. }
  2015. #if defined ( TERROR )
  2016. char szModName[32] = "left4dead";
  2017. #elif defined ( PAINT )
  2018. char szModName[32] = "paint";
  2019. #elif defined ( PORTAL2 )
  2020. char szModName[32] = "portal2";
  2021. #elif defined( INFESTED_DLL )
  2022. char szModName[32] = "infested";
  2023. #elif defined ( HL2_EPISODIC )
  2024. char szModName[32] = "ep2";
  2025. #elif defined ( TF_CLIENT_DLL )
  2026. char szModName[32] = "tf";
  2027. #elif defined ( DOTA_CLIENT_DLL )
  2028. char szModName[32] = "dota";
  2029. #elif defined ( SDK_CLIENT_DLL )
  2030. char szModName[32] = "sdk";
  2031. #elif defined ( SOB_CLIENT_DLL )
  2032. char szModName[32] = "ep2";
  2033. #elif defined ( CSTRIKE15 )
  2034. char szModName[32] = "csgo";
  2035. #endif
  2036. bool bVGUIIsSplitscreen = VGui_IsSplitScreen();
  2037. if ( cl_disable_splitscreen_cpu_level_cfgs_in_pip.GetBool() && bVGUIIsSplitscreen && VGui_IsSplitScreenPIP() )
  2038. {
  2039. bVGUIIsSplitscreen = false;
  2040. }
  2041. UpdateSystemLevel( nCPULevel, nGPULevel, nMemLevel, nGPUMemLevel, bVGUIIsSplitscreen, szModName );
  2042. if ( engine )
  2043. {
  2044. engine->ConfigureSystemLevel( nCPULevel, nGPULevel );
  2045. }
  2046. C_BaseEntity::UpdateVisibilityAllEntities();
  2047. if ( view )
  2048. {
  2049. view->InitFadeData();
  2050. }
  2051. }
  2052. //CEG_PROTECT_FUNCTION( ConfigureCurrentSystemLevel );
  2053. //-----------------------------------------------------------------------------
  2054. // Purpose: Per level init
  2055. //-----------------------------------------------------------------------------
  2056. CEG_NOINLINE void CHLClient::LevelInitPreEntity( char const* pMapName )
  2057. {
  2058. // HACK: Bogus, but the logic is too complicated in the engine
  2059. if (g_bLevelInitialized)
  2060. return;
  2061. g_bLevelInitialized = true;
  2062. engine->TickProgressBar();
  2063. // this is a "connected" state
  2064. g_HltvReplaySystem.StopHltvReplay( );
  2065. input->LevelInit();
  2066. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2067. {
  2068. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2069. GetViewEffects()->LevelInit();
  2070. }
  2071. // Tell mode manager that map is changing
  2072. modemanager->LevelInit( pMapName );
  2073. ParticleMgr()->LevelInit();
  2074. ClientVoiceMgr_LevelInit();
  2075. if ( hudlcd )
  2076. {
  2077. hudlcd->SetGlobalStat( "(mapname)", pMapName );
  2078. }
  2079. C_BaseTempEntity::ClearDynamicTempEnts();
  2080. clienteffects->Flush();
  2081. view->LevelInit();
  2082. tempents->LevelInit();
  2083. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2084. {
  2085. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2086. ResetToneMapping(1.0);
  2087. }
  2088. CEG_PROTECT_MEMBER_FUNCTION( CHLClient_LevelInitPreEntity );
  2089. IGameSystem::LevelInitPreEntityAllSystems(pMapName);
  2090. ResetWindspeed();
  2091. #if !defined( NO_ENTITY_PREDICTION )
  2092. //[msmith] Portal 2 wanted to turn off prediction for local clients.
  2093. // We want to keep it for CStrike15 (and probably other games) because of the noticable lag without it, particularly when firing a weapon.
  2094. #if defined( PORTAL2 )
  2095. // don't do prediction if single player!
  2096. // don't set direct because of FCVAR_USERINFO
  2097. if ( gpGlobals->IsRemoteClient() && gpGlobals->maxClients > 1 )
  2098. #else
  2099. // Turn off prediction if we're in split screen because there are a lot of third person animation and render issues with prediction.
  2100. if ( !engine->IsSplitScreenActive() )
  2101. #endif
  2102. {
  2103. if ( !cl_predict->GetInt() )
  2104. {
  2105. engine->ClientCmd( "cl_predict 1" );
  2106. }
  2107. }
  2108. else
  2109. {
  2110. if ( cl_predict->GetInt() )
  2111. {
  2112. engine->ClientCmd( "cl_predict 0" );
  2113. }
  2114. }
  2115. #endif
  2116. // Check low violence settings for this map
  2117. g_RagdollLVManager.SetLowViolence( pMapName );
  2118. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2119. {
  2120. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2121. engine->TickProgressBar();
  2122. GetHud().LevelInit();
  2123. if ( GetViewPortInterface() )
  2124. {
  2125. GetViewPortInterface()->LevelInit();
  2126. }
  2127. }
  2128. #if defined( REPLAY_ENABLED )
  2129. // Initialize replay ragdoll recorder
  2130. if ( !engine->IsPlayingDemo() )
  2131. {
  2132. CReplayRagdollRecorder::Instance().Init();
  2133. }
  2134. #endif
  2135. }
  2136. //-----------------------------------------------------------------------------
  2137. // Purpose: Per level init
  2138. //-----------------------------------------------------------------------------
  2139. CEG_NOINLINE void CHLClient::LevelInitPostEntity( )
  2140. {
  2141. ABS_QUERY_GUARD( true );
  2142. IGameSystem::LevelInitPostEntityAllSystems();
  2143. C_PhysPropClientside::RecreateAll();
  2144. C_Sprite::RecreateAllClientside();
  2145. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2146. {
  2147. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2148. GetCenterPrint()->Clear();
  2149. }
  2150. g_HltvReplaySystem.OnLevelInit();
  2151. CEG_PROTECT_MEMBER_FUNCTION( CHLClient_LevelInitPostEntity );
  2152. }
  2153. //-----------------------------------------------------------------------------
  2154. // Purpose: Reset our global string table pointers
  2155. //-----------------------------------------------------------------------------
  2156. void CHLClient::ResetStringTablePointers()
  2157. {
  2158. g_pStringTableParticleEffectNames = NULL;
  2159. g_StringTableEffectDispatch = NULL;
  2160. g_StringTableVguiScreen = NULL;
  2161. g_pStringTableMaterials = NULL;
  2162. g_pStringTableInfoPanel = NULL;
  2163. g_pStringTableClientSideChoreoScenes = NULL;
  2164. g_pStringTableMovies = NULL;
  2165. }
  2166. //-----------------------------------------------------------------------------
  2167. // Purpose: Per level de-init
  2168. //-----------------------------------------------------------------------------
  2169. CEG_NOINLINE void CHLClient::LevelShutdown( void )
  2170. {
  2171. g_HltvReplaySystem.OnLevelShutdown();
  2172. // HACK: Bogus, but the logic is too complicated in the engine
  2173. if (!g_bLevelInitialized)
  2174. {
  2175. ResetStringTablePointers();
  2176. return;
  2177. }
  2178. g_bLevelInitialized = false;
  2179. // this is a "connected" state
  2180. g_HltvReplaySystem.StopHltvReplay();
  2181. // Disable abs recomputations when everything is shutting down
  2182. CBaseEntity::EnableAbsRecomputations( false );
  2183. // Level shutdown sequence.
  2184. // First do the pre-entity shutdown of all systems
  2185. IGameSystem::LevelShutdownPreEntityAllSystems();
  2186. C_Sprite::DestroyAllClientside();
  2187. C_PhysPropClientside::DestroyAll();
  2188. modemanager->LevelShutdown();
  2189. // Remove temporary entities before removing entities from the client entity list so that the te_* may
  2190. // clean up before hand.
  2191. tempents->LevelShutdown();
  2192. // Now release/delete the entities
  2193. cl_entitylist->Release();
  2194. C_BaseEntityClassList *pClassList = s_pClassLists;
  2195. while ( pClassList )
  2196. {
  2197. pClassList->LevelShutdown();
  2198. pClassList = pClassList->m_pNextClassList;
  2199. }
  2200. CEG_ENCRYPT_FUNCTION( CHLClient_LevelShutdown );
  2201. // Now do the post-entity shutdown of all systems
  2202. IGameSystem::LevelShutdownPostEntityAllSystems();
  2203. view->LevelShutdown();
  2204. beams->ClearBeams();
  2205. ParticleMgr()->RemoveAllEffects();
  2206. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2207. {
  2208. StopAllRumbleEffects( hh );
  2209. }
  2210. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2211. {
  2212. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2213. GetHud().LevelShutdown();
  2214. }
  2215. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2216. {
  2217. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2218. GetCenterPrint()->Clear();
  2219. }
  2220. ClientVoiceMgr_LevelShutdown();
  2221. messagechars->Clear();
  2222. g_pParticleSystemMgr->LevelShutdown();
  2223. g_pParticleSystemMgr->UncacheAllParticleSystems();
  2224. UncacheAllMovies();
  2225. UncacheAllMaterials();
  2226. // string tables are cleared on disconnect from a server, so reset our global pointers to NULL
  2227. ResetStringTablePointers();
  2228. CStudioHdr::CActivityToSequenceMapping::ResetMappings();
  2229. #if defined( REPLAY_ENABLED )
  2230. // Shutdown the ragdoll recorder
  2231. CReplayRagdollRecorder::Instance().Shutdown();
  2232. CReplayRagdollCache::Instance().Shutdown();
  2233. #endif
  2234. }
  2235. //-----------------------------------------------------------------------------
  2236. // Purpose: Engine received crosshair offset ( autoaim )
  2237. // Input : angle -
  2238. //-----------------------------------------------------------------------------
  2239. void CHLClient::SetCrosshairAngle( const QAngle& angle )
  2240. {
  2241. #ifndef INFESTED_DLL
  2242. CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
  2243. if ( crosshair )
  2244. {
  2245. crosshair->SetCrosshairAngle( angle );
  2246. }
  2247. #endif
  2248. }
  2249. //-----------------------------------------------------------------------------
  2250. // Purpose: Helper to initialize sprite from .spr semaphor
  2251. // Input : *pSprite -
  2252. // *loadname -
  2253. //-----------------------------------------------------------------------------
  2254. void CHLClient::InitSprite( CEngineSprite *pSprite, const char *loadname )
  2255. {
  2256. if ( pSprite )
  2257. {
  2258. pSprite->Init( loadname );
  2259. }
  2260. }
  2261. //-----------------------------------------------------------------------------
  2262. // Purpose:
  2263. // Input : *pSprite -
  2264. //-----------------------------------------------------------------------------
  2265. void CHLClient::ShutdownSprite( CEngineSprite *pSprite )
  2266. {
  2267. if ( pSprite )
  2268. {
  2269. pSprite->Shutdown();
  2270. }
  2271. }
  2272. //-----------------------------------------------------------------------------
  2273. // Purpose: Tells engine how much space to allocate for sprite objects
  2274. // Output : int
  2275. //-----------------------------------------------------------------------------
  2276. int CHLClient::GetSpriteSize( void ) const
  2277. {
  2278. return sizeof( CEngineSprite );
  2279. }
  2280. //-----------------------------------------------------------------------------
  2281. // Purpose:
  2282. // Input : entindex -
  2283. // bTalking -
  2284. //-----------------------------------------------------------------------------
  2285. void CHLClient::VoiceStatus( int entindex, int iSsSlot, qboolean bTalking )
  2286. {
  2287. GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, iSsSlot, !!bTalking );
  2288. }
  2289. //-----------------------------------------------------------------------------
  2290. // Purpose:
  2291. // Input : entindex -
  2292. //-----------------------------------------------------------------------------
  2293. bool CHLClient::PlayerAudible( int iPlayerIndex )
  2294. {
  2295. return GetClientVoiceMgr()->IsPlayerAudible( iPlayerIndex );
  2296. }
  2297. //-----------------------------------------------------------------------------
  2298. // Called when the string table for materials changes
  2299. //-----------------------------------------------------------------------------
  2300. void OnMaterialStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2301. {
  2302. // Make sure this puppy is precached
  2303. gHLClient.PrecacheMaterial( newString );
  2304. RequestCacheUsedMaterials();
  2305. }
  2306. //-----------------------------------------------------------------------------
  2307. // Called when the string table for movies changes
  2308. //-----------------------------------------------------------------------------
  2309. void OnMovieStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2310. {
  2311. // Make sure this puppy is precached
  2312. gHLClient.PrecacheMovie( newString );
  2313. }
  2314. //-----------------------------------------------------------------------------
  2315. // Called when the string table for dispatch effects changes
  2316. //-----------------------------------------------------------------------------
  2317. void OnEffectStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2318. {
  2319. // Make sure this puppy is precached
  2320. g_pPrecacheSystem->Cache( g_pPrecacheHandler, DISPATCH_EFFECT, newString, true, RESOURCE_LIST_INVALID, true );
  2321. RequestCacheUsedMaterials();
  2322. }
  2323. //-----------------------------------------------------------------------------
  2324. // Called when the string table for particle systems changes
  2325. //-----------------------------------------------------------------------------
  2326. void OnParticleSystemStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2327. {
  2328. // Make sure this puppy is precached
  2329. g_pParticleSystemMgr->PrecacheParticleSystem( stringNumber, newString );
  2330. RequestCacheUsedMaterials();
  2331. }
  2332. //-----------------------------------------------------------------------------
  2333. // Called when the string table for particle files changes
  2334. //-----------------------------------------------------------------------------
  2335. void OnPrecacheParticleFile( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2336. {
  2337. g_pParticleSystemMgr->ShouldLoadSheets( true );
  2338. g_pParticleSystemMgr->ReadParticleConfigFile( newString, true, false );
  2339. g_pParticleSystemMgr->DecommitTempMemory();
  2340. }
  2341. //-----------------------------------------------------------------------------
  2342. // Called when the string table for VGUI changes
  2343. //-----------------------------------------------------------------------------
  2344. void OnVguiScreenTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2345. {
  2346. // Make sure this puppy is precached
  2347. vgui::Panel *pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( newString, 100, NULL, NULL );
  2348. if ( pPanel )
  2349. PanelMetaClassMgr()->DestroyPanelMetaClass( pPanel );
  2350. }
  2351. //-----------------------------------------------------------------------------
  2352. // Purpose: Preload the string on the client (if single player it should already be in the cache from the server!!!)
  2353. // Input : *object -
  2354. // *stringTable -
  2355. // stringNumber -
  2356. // *newString -
  2357. // *newData -
  2358. //-----------------------------------------------------------------------------
  2359. void OnSceneStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  2360. {
  2361. }
  2362. //-----------------------------------------------------------------------------
  2363. // Purpose: Hook up any callbacks here, the table definition has been parsed but
  2364. // no data has been added yet
  2365. //-----------------------------------------------------------------------------
  2366. void CHLClient::InstallStringTableCallback( const char *tableName )
  2367. {
  2368. // Here, cache off string table IDs
  2369. if (!Q_strcasecmp(tableName, "VguiScreen"))
  2370. {
  2371. // Look up the id
  2372. g_StringTableVguiScreen = networkstringtable->FindTable( tableName );
  2373. // When the material list changes, we need to know immediately
  2374. g_StringTableVguiScreen->SetStringChangedCallback( NULL, OnVguiScreenTableChanged );
  2375. }
  2376. else if (!Q_strcasecmp(tableName, "Materials"))
  2377. {
  2378. // Look up the id
  2379. g_pStringTableMaterials = networkstringtable->FindTable( tableName );
  2380. // When the material list changes, we need to know immediately
  2381. g_pStringTableMaterials->SetStringChangedCallback( NULL, OnMaterialStringTableChanged );
  2382. }
  2383. else if ( !Q_strcasecmp( tableName, "EffectDispatch" ) )
  2384. {
  2385. g_StringTableEffectDispatch = networkstringtable->FindTable( tableName );
  2386. // When the material list changes, we need to know immediately
  2387. g_StringTableEffectDispatch->SetStringChangedCallback( NULL, OnEffectStringTableChanged );
  2388. }
  2389. else if ( !Q_strcasecmp( tableName, "InfoPanel" ) )
  2390. {
  2391. g_pStringTableInfoPanel = networkstringtable->FindTable( tableName );
  2392. }
  2393. else if ( !Q_strcasecmp( tableName, "Scenes" ) )
  2394. {
  2395. g_pStringTableClientSideChoreoScenes = networkstringtable->FindTable( tableName );
  2396. networkstringtable->SetAllowClientSideAddString( g_pStringTableClientSideChoreoScenes, true );
  2397. g_pStringTableClientSideChoreoScenes->SetStringChangedCallback( NULL, OnSceneStringTableChanged );
  2398. }
  2399. else if ( !Q_strcasecmp( tableName, "ParticleEffectNames" ) )
  2400. {
  2401. g_pStringTableParticleEffectNames = networkstringtable->FindTable( tableName );
  2402. networkstringtable->SetAllowClientSideAddString( g_pStringTableParticleEffectNames, true );
  2403. // When the particle system list changes, we need to know immediately
  2404. g_pStringTableParticleEffectNames->SetStringChangedCallback( NULL, OnParticleSystemStringTableChanged );
  2405. }
  2406. else if ( !Q_strcasecmp( tableName, "ExtraParticleFilesTable" ) )
  2407. {
  2408. g_pStringTableExtraParticleFiles = networkstringtable->FindTable( tableName );
  2409. networkstringtable->SetAllowClientSideAddString( g_pStringTableExtraParticleFiles, true );
  2410. // When the particle system list changes, we need to know immediately
  2411. g_pStringTableExtraParticleFiles->SetStringChangedCallback( NULL, OnPrecacheParticleFile );
  2412. }
  2413. else if ( !Q_strcasecmp( tableName, "Movies" ) )
  2414. {
  2415. // Look up the id
  2416. g_pStringTableMovies = networkstringtable->FindTable( tableName );
  2417. // When the movie list changes, we need to know immediately
  2418. g_pStringTableMovies->SetStringChangedCallback( NULL, OnMovieStringTableChanged );
  2419. }
  2420. else
  2421. {
  2422. // Pass tablename to gamerules last if all other checks fail
  2423. InstallStringTableCallback_GameRules( tableName );
  2424. }
  2425. }
  2426. //-----------------------------------------------------------------------------
  2427. // Material precache
  2428. //-----------------------------------------------------------------------------
  2429. void CHLClient::PrecacheMaterial( const char *pMaterialName )
  2430. {
  2431. Assert( pMaterialName );
  2432. int nLen = Q_strlen( pMaterialName );
  2433. char *pTempBuf = (char*)stackalloc( nLen + 1 );
  2434. memcpy( pTempBuf, pMaterialName, nLen + 1 );
  2435. char *pFound = Q_strstr( pTempBuf, ".vmt\0" );
  2436. if ( pFound )
  2437. {
  2438. *pFound = 0;
  2439. }
  2440. RANDOM_CEG_TEST_SECRET_PERIOD( 0x0400, 0x0fff );
  2441. IMaterial *pMaterial = materials->FindMaterial( pTempBuf, TEXTURE_GROUP_PRECACHED );
  2442. if ( !IsErrorMaterial( pMaterial ) )
  2443. {
  2444. int idx = m_CachedMaterials.Find( pMaterial );
  2445. if ( idx == m_CachedMaterials.InvalidIndex() )
  2446. {
  2447. pMaterial->IncrementReferenceCount();
  2448. m_CachedMaterials.Insert( pMaterial );
  2449. }
  2450. }
  2451. else
  2452. {
  2453. if (IsOSX())
  2454. {
  2455. printf("\n ##### CHLClient::PrecacheMaterial could not find material %s (%s)", pMaterialName, pTempBuf );
  2456. }
  2457. }
  2458. }
  2459. void CHLClient::UncacheAllMaterials()
  2460. {
  2461. for ( int i = m_CachedMaterials.FirstInorder(); i != m_CachedMaterials.InvalidIndex(); i = m_CachedMaterials.NextInorder( i ) )
  2462. {
  2463. m_CachedMaterials[i]->DecrementReferenceCount();
  2464. }
  2465. m_CachedMaterials.RemoveAll();
  2466. }
  2467. //-----------------------------------------------------------------------------
  2468. // Movie precache
  2469. //-----------------------------------------------------------------------------
  2470. void CHLClient::PrecacheMovie( const char *pMovieName )
  2471. {
  2472. if ( m_CachedMovies.Find( pMovieName ) != UTL_INVAL_SYMBOL )
  2473. {
  2474. // already precached
  2475. return;
  2476. }
  2477. // hint the movie system to precache our movie resource
  2478. m_CachedMovies.AddString( pMovieName );
  2479. #if defined( BINK_VIDEO )
  2480. g_pBIK->PrecacheMovie( pMovieName );
  2481. #endif
  2482. }
  2483. void CHLClient::UncacheAllMovies()
  2484. {
  2485. #if defined( BINK_VIDEO )
  2486. for ( int i = 0; i < m_CachedMovies.GetNumStrings(); i++ )
  2487. {
  2488. g_pBIK->EvictPrecachedMovie( m_CachedMovies.String( i ) );
  2489. }
  2490. #endif
  2491. m_CachedMovies.RemoveAll();
  2492. }
  2493. //-----------------------------------------------------------------------------
  2494. // Purpose:
  2495. // Input : *pszName -
  2496. // iSize -
  2497. // *pbuf -
  2498. // Output : Returns true on success, false on failure.
  2499. //-----------------------------------------------------------------------------
  2500. bool CHLClient::DispatchUserMessage( int msg_type, int32 nPassthroughFlags, int size, const void *msg )
  2501. {
  2502. return UserMessages()->DispatchUserMessage( msg_type, nPassthroughFlags, size, msg );
  2503. }
  2504. bool BSerializeUserMessageToSVCMSG( CSVCMsg_UserMessage &svcmsg, int nType, const ::google::protobuf::Message &msg )
  2505. {
  2506. if ( !msg.IsInitialized() || !svcmsg.IsInitialized() )
  2507. {
  2508. return false;
  2509. }
  2510. int size = msg.ByteSize();
  2511. svcmsg.set_msg_type( nType );
  2512. svcmsg.mutable_msg_data()->resize( size );
  2513. if ( !msg.SerializeWithCachedSizesToArray( ( uint8* ) &( *svcmsg.mutable_msg_data() )[ 0 ] ) )
  2514. {
  2515. return false;
  2516. }
  2517. return true;
  2518. }
  2519. void SimulateEntities()
  2520. {
  2521. VPROF_BUDGET("Client SimulateEntities", VPROF_BUDGETGROUP_CLIENT_SIM);
  2522. // Service timer events (think functions).
  2523. ClientThinkList()->PerformThinkFunctions();
  2524. C_BaseEntity::SimulateEntities();
  2525. }
  2526. bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
  2527. {
  2528. VPROF( "AddDataChangeEvent" );
  2529. Assert( ent );
  2530. if ( updateType == DATA_UPDATE_POST_UPDATE )
  2531. {
  2532. Assert( g_bDataChangedPostEventsAllowed );
  2533. *pStoredEvent = g_DataChangedPostEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) );
  2534. return true;
  2535. }
  2536. // Make sure we don't already have an event queued for this guy.
  2537. if ( *pStoredEvent >= 0 )
  2538. {
  2539. if ( uint( *pStoredEvent ) < uint( g_DataChangedEvents.Count() ) )
  2540. {
  2541. Assert( g_DataChangedEvents[ *pStoredEvent ].GetEntity() == ent );
  2542. // DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED.
  2543. if ( updateType == DATA_UPDATE_CREATED )
  2544. g_DataChangedEvents[ *pStoredEvent ].m_UpdateType = updateType;
  2545. }
  2546. return false;
  2547. }
  2548. else
  2549. {
  2550. *pStoredEvent = g_DataChangedEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) );
  2551. return true;
  2552. }
  2553. }
  2554. void ClearDataChangedEvent( int iStoredEvent )
  2555. {
  2556. if ( iStoredEvent != -1 )
  2557. g_DataChangedEvents.Remove( iStoredEvent );
  2558. }
  2559. void ProcessOnDataChangedEvents()
  2560. {
  2561. VPROF_("ProcessOnDataChangedEvents", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  2562. int nSave = GET_ACTIVE_SPLITSCREEN_SLOT();
  2563. bool bSaveAccess = engine->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  2564. g_bDataChangedPostEventsAllowed = true;
  2565. FOR_EACH_LL( g_DataChangedEvents, i )
  2566. {
  2567. CDataChangedEvent *pEvent = &g_DataChangedEvents[i];
  2568. // Reset their stored event identifier.
  2569. *pEvent->m_pStoredEvent = -1;
  2570. IClientNetworkable *pEntity = pEvent->GetEntity();
  2571. if ( pEntity )
  2572. {
  2573. // Send the event.
  2574. pEntity->OnDataChanged( pEvent->m_UpdateType );
  2575. }
  2576. }
  2577. g_bDataChangedPostEventsAllowed = false;
  2578. FOR_EACH_LL( g_DataChangedPostEvents, i )
  2579. {
  2580. CDataChangedEvent *pEvent = &g_DataChangedPostEvents[ i ];
  2581. // Reset their stored event identifier.
  2582. *pEvent->m_pStoredEvent = -1;
  2583. IClientNetworkable *pEntity = pEvent->GetEntity();
  2584. if ( pEntity )
  2585. {
  2586. // Send the event.
  2587. pEntity->OnDataChanged( pEvent->m_UpdateType );
  2588. }
  2589. }
  2590. //now run through the list again and initialize any predictables that are ready
  2591. FOR_EACH_LL( g_DataChangedEvents, i )
  2592. {
  2593. IClientNetworkable *pNetworkable = g_DataChangedEvents[i].GetEntity();
  2594. if ( !pNetworkable )
  2595. continue;
  2596. IClientUnknown *pUnk = pNetworkable->GetIClientUnknown();
  2597. if ( !pUnk )
  2598. continue;
  2599. C_BaseEntity *pEntity = pUnk->GetBaseEntity();
  2600. if ( !pEntity )
  2601. continue;
  2602. pEntity->CheckInitPredictable( "ProcessOnDataChangedEvents()" );
  2603. }
  2604. g_DataChangedEvents.Purge();
  2605. g_DataChangedPostEvents.Purge();
  2606. engine->SetActiveSplitScreenPlayerSlot( nSave );
  2607. engine->SetLocalPlayerIsResolvable( __FILE__, __LINE__, bSaveAccess );
  2608. }
  2609. void PurgeOnDataChangedEvents()
  2610. {
  2611. if ( int nPurging = g_DataChangedEvents.Count() )
  2612. {
  2613. DevMsg( "Purging %d data change events without processing\n", nPurging );
  2614. }
  2615. g_DataChangedEvents.Purge();
  2616. }
  2617. void UpdateClientRenderableInPVSStatus()
  2618. {
  2619. // Vis for this view should already be setup at this point.
  2620. // For each client-only entity, notify it if it's newly coming into the PVS.
  2621. CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
  2622. FOR_EACH_LL( theList, i )
  2623. {
  2624. CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
  2625. if ( pInfo->m_InPVSStatus & INPVS_YES )
  2626. {
  2627. // Ok, this entity already thinks it's in the PVS. No need to notify it.
  2628. // We need to set the INPVS_YES_THISFRAME flag if it's in this frame at all, so we
  2629. // don't tell the entity it's not in the PVS anymore at the end of the frame.
  2630. if ( !( pInfo->m_InPVSStatus & INPVS_THISFRAME ) )
  2631. {
  2632. if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
  2633. {
  2634. pInfo->m_InPVSStatus |= INPVS_THISFRAME;
  2635. }
  2636. }
  2637. }
  2638. else
  2639. {
  2640. // This entity doesn't think it's in the PVS yet. If it is now in the PVS, let it know.
  2641. if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
  2642. {
  2643. pInfo->m_InPVSStatus |= ( INPVS_YES | INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
  2644. }
  2645. }
  2646. }
  2647. }
  2648. void UpdatePVSNotifiers()
  2649. {
  2650. MDLCACHE_CRITICAL_SECTION();
  2651. // At this point, all the entities that were rendered in the previous frame have INPVS_THISFRAME set
  2652. // so we can tell the entities that aren't in the PVS anymore so.
  2653. CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
  2654. FOR_EACH_LL( theList, i )
  2655. {
  2656. CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
  2657. // If this entity thinks it's in the PVS, but it wasn't in the PVS this frame, tell it so.
  2658. if ( pInfo->m_InPVSStatus & INPVS_YES )
  2659. {
  2660. if ( pInfo->m_InPVSStatus & INPVS_THISFRAME )
  2661. {
  2662. if ( pInfo->m_InPVSStatus & INPVS_NEEDSNOTIFY )
  2663. {
  2664. pInfo->m_pNotify->OnPVSStatusChanged( true );
  2665. }
  2666. // Clear it for the next time around.
  2667. pInfo->m_InPVSStatus &= ~( INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
  2668. }
  2669. else
  2670. {
  2671. pInfo->m_InPVSStatus &= ~INPVS_YES;
  2672. pInfo->m_pNotify->OnPVSStatusChanged( false );
  2673. }
  2674. }
  2675. }
  2676. }
  2677. void OnRenderStart()
  2678. {
  2679. CMatRenderContextPtr pRenderContext( materials );
  2680. PIXEVENT( pRenderContext, "OnRenderStart" );
  2681. VPROF( "OnRenderStart" );
  2682. MDLCACHE_CRITICAL_SECTION();
  2683. MDLCACHE_COARSE_LOCK();
  2684. #ifdef PORTAL
  2685. g_pPortalRender->UpdatePortalPixelVisibility(); //updating this one or two lines before querying again just isn't cutting it. Update as soon as it's cheap to do so.
  2686. #endif
  2687. // [mariod] - testing, see note in c_baseanimating.cpp
  2688. C_BaseAnimating::EnableInvalidateBoneCache( true );
  2689. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
  2690. C_BaseEntity::SetAbsQueriesValid( false );
  2691. Rope_ResetCounters();
  2692. // Interpolate server entities and move aiments.
  2693. {
  2694. PREDICTION_TRACKVALUECHANGESCOPE( "interpolation" );
  2695. C_BaseEntity::InterpolateServerEntities();
  2696. }
  2697. {
  2698. // vprof node for this bloc of math
  2699. VPROF( "OnRenderStart: dirty bone caches");
  2700. // Invalidate any bone information.
  2701. C_BaseAnimating::InvalidateBoneCaches();
  2702. C_BaseFlex::InvalidateFlexCaches();
  2703. C_BaseEntity::SetAbsQueriesValid( true );
  2704. C_BaseEntity::EnableAbsRecomputations( true );
  2705. // Enable access to all model bones except view models.
  2706. // This is necessary for aim-ent computation to occur properly
  2707. C_BaseAnimating::PushAllowBoneAccess( true, false, "OnRenderStart->CViewRender::SetUpView" ); // pops in CViewRender::SetUpView
  2708. // FIXME: This needs to be done before the player moves; it forces
  2709. // aiments the player may be attached to to forcibly update their position
  2710. C_BaseEntity::MarkAimEntsDirty();
  2711. }
  2712. // Make sure the camera simulation happens before OnRenderStart, where it's used.
  2713. // NOTE: the only thing that happens in CAM_Think is thirdperson related code.
  2714. for ( int hh = 0; hh < MAX_SPLITSCREEN_PLAYERS; ++hh )
  2715. {
  2716. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  2717. input->CAM_Think();
  2718. }
  2719. C_BaseAnimating::PopBoneAccess( "OnRenderStart->CViewRender::SetUpView" ); // pops the (true, false) bone access set in OnRenderStart
  2720. // Enable access to all model bones until rendering is done
  2721. C_BaseAnimating::PushAllowBoneAccess( true, true, "CViewRender::SetUpView->OnRenderEnd" ); // pop is in OnRenderEnd()
  2722. #ifdef DEMOPOLISH_ENABLED
  2723. // Update demo polish subsystem if necessary
  2724. DemoPolish_Think();
  2725. #endif
  2726. // This will place all entities in the correct position in world space and in the KD-tree
  2727. // NOTE: Doing this before view->OnRenderStart() because the player can be in hierarchy with
  2728. // a client-side animated entity. So the viewport position is dependent on this animation sometimes.
  2729. C_BaseAnimating::UpdateClientSideAnimations();
  2730. // This will place the player + the view models + all parent
  2731. // entities at the correct abs position so that their attachment points
  2732. // are at the correct location
  2733. view->OnRenderStart();
  2734. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
  2735. // Process OnDataChanged events.
  2736. ProcessOnDataChangedEvents();
  2737. // Reset the overlay alpha. Entities can change the state of this in their think functions.
  2738. g_SmokeFogOverlayAlpha = 0;
  2739. g_SmokeFogOverlayColor.Init( 0.0f, 0.0f, 0.0f );
  2740. {
  2741. // Simulate all the entities.
  2742. PIXEVENT( pRenderContext, "SimulateEntities" );
  2743. SimulateEntities();
  2744. }
  2745. {
  2746. PIXEVENT( pRenderContext, "PhysicsSimulate" );
  2747. PhysicsSimulate();
  2748. }
  2749. C_BaseAnimating::ThreadedBoneSetup();
  2750. {
  2751. VPROF_("Client TempEnts", 0, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  2752. // This creates things like temp entities.
  2753. engine->FireEvents();
  2754. // Update temp entities
  2755. tempents->Update();
  2756. // Update temp ent beams...
  2757. beams->UpdateTempEntBeams();
  2758. // Lock the frame from beam additions
  2759. SetBeamCreationAllowed( false );
  2760. }
  2761. // Update particle effects (eventually, the effects should use Simulate() instead of having
  2762. // their own update system).
  2763. {
  2764. VPROF_BUDGET( "ParticleMgr()->Simulate", VPROF_BUDGETGROUP_PARTICLE_SIMULATION );
  2765. ParticleMgr()->Simulate( gpGlobals->frametime );
  2766. }
  2767. // Now that the view model's position is setup and aiments are marked dirty, update
  2768. // their positions so they're in the leaf system correctly.
  2769. C_BaseEntity::CalcAimEntPositions();
  2770. // For entities marked for recording, post bone messages to IToolSystems
  2771. if ( ToolsEnabled() )
  2772. {
  2773. C_BaseEntity::ToolRecordEntities();
  2774. }
  2775. #if defined( REPLAY_ENABLED )
  2776. // This will record any ragdolls if Replay mode is enabled on the server
  2777. CReplayRagdollRecorder::Instance().Think();
  2778. CReplayRagdollCache::Instance().Think();
  2779. #endif
  2780. // update dynamic light state. Necessary for light cache to work properly for d- and elights
  2781. engine->UpdateDAndELights();
  2782. // Finally, link all the entities into the leaf system right before rendering.
  2783. C_BaseEntity::AddVisibleEntities();
  2784. g_pClientLeafSystem->RecomputeRenderableLeaves();
  2785. g_pClientShadowMgr->ReprojectShadows();
  2786. g_pClientShadowMgr->AdvanceFrame();
  2787. g_pClientLeafSystem->DisableLeafReinsertion( true );
  2788. }
  2789. void OnRenderEnd()
  2790. {
  2791. g_pClientLeafSystem->DisableLeafReinsertion( false );
  2792. // Disallow access to bones (access is enabled in CViewRender::SetUpView).
  2793. C_BaseAnimating::PopBoneAccess( "CViewRender::SetUpView->OnRenderEnd" );
  2794. // [mariod] - testing, see note in c_baseanimating.cpp
  2795. C_BaseAnimating::EnableInvalidateBoneCache( false );
  2796. UpdatePVSNotifiers();
  2797. DisplayBoneSetupEnts();
  2798. }
  2799. void CHLClient::FrameStageNotify( ClientFrameStage_t curStage )
  2800. {
  2801. g_CurFrameStage = curStage;
  2802. g_bEngineIsHLTV = engine->IsHLTV();
  2803. switch( curStage )
  2804. {
  2805. default:
  2806. break;
  2807. case FRAME_RENDER_START:
  2808. {
  2809. VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_START" );
  2810. engine->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  2811. // Last thing before rendering, run simulation.
  2812. OnRenderStart();
  2813. }
  2814. break;
  2815. case FRAME_RENDER_END:
  2816. {
  2817. VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_END" );
  2818. OnRenderEnd();
  2819. engine->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  2820. PREDICTION_SPEWVALUECHANGES();
  2821. }
  2822. break;
  2823. case FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE:
  2824. {
  2825. ParticleMgr()->RemoveAllNewEffects(); // new effects linger past entity recreation, creating a flurry of asserts, that's not good
  2826. Assert( g_DataChangedEvents.Count() == 0 ); // this may only happen when we didn't render anything between getting an update and then a full frame update
  2827. // NOTE: There are no entities at this point if it's a full frame update!
  2828. PurgeOnDataChangedEvents();
  2829. }
  2830. break;
  2831. case FRAME_NET_UPDATE_START:
  2832. {
  2833. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_START" );
  2834. // disabled all recomputations while we update entities
  2835. C_BaseEntity::EnableAbsRecomputations( false );
  2836. C_BaseEntity::SetAbsQueriesValid( false );
  2837. Interpolation_SetLastPacketTimeStamp( engine->GetLastTimeStamp() );
  2838. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
  2839. PREDICTION_STARTTRACKVALUE( "netupdate" );
  2840. }
  2841. break;
  2842. case FRAME_NET_UPDATE_END:
  2843. {
  2844. ProcessCacheUsedMaterials();
  2845. // reenable abs recomputation since now all entities have been updated
  2846. C_BaseEntity::EnableAbsRecomputations( true );
  2847. C_BaseEntity::SetAbsQueriesValid( true );
  2848. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
  2849. PREDICTION_ENDTRACKVALUE();
  2850. }
  2851. break;
  2852. case FRAME_NET_UPDATE_POSTDATAUPDATE_START:
  2853. {
  2854. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START" );
  2855. PREDICTION_STARTTRACKVALUE( "postdataupdate" );
  2856. }
  2857. break;
  2858. case FRAME_NET_UPDATE_POSTDATAUPDATE_END:
  2859. {
  2860. if ( !C_BasePlayer::GetLocalPlayer( 0 ) )
  2861. {
  2862. // this is only possible when we're playing back the past, when our killer hasn't been spawned yet
  2863. if ( C_BasePlayer *pPlayer = UTIL_PlayerByIndex( engine->GetLocalPlayer() ) )
  2864. {
  2865. pPlayer->SetAsLocalPlayer();
  2866. }
  2867. else
  2868. {
  2869. Warning( "No local player %d after full frame update\n", engine->GetLocalPlayer() );
  2870. for ( int i = 0; i < MAX_PLAYERS; ++i )
  2871. if ( C_BasePlayer*p = UTIL_PlayerByIndex( i ) )
  2872. {
  2873. Msg( "Setting fallback player %s as local player\n", p->GetPlayerName() );
  2874. p->SetAsLocalPlayer();
  2875. break;
  2876. }
  2877. }
  2878. }
  2879. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END" );
  2880. #if defined( PORTAL )
  2881. ProcessPortalTeleportations();
  2882. #endif
  2883. PREDICTION_ENDTRACKVALUE();
  2884. // Let prediction copy off pristine data
  2885. prediction->PostEntityPacketReceived();
  2886. HLTVCamera()->PostEntityPacketReceived();
  2887. #if defined( REPLAY_ENABLED )
  2888. ReplayCamera()->PostEntityPacketReceived();
  2889. #endif
  2890. }
  2891. break;
  2892. case FRAME_START:
  2893. {
  2894. // Mark the frame as open for client fx additions
  2895. SetFXCreationAllowed( true );
  2896. SetBeamCreationAllowed( true );
  2897. C_BaseEntity::CheckCLInterpChanged();
  2898. engine->SetLocalPlayerIsResolvable( __FILE__, __LINE__, false );
  2899. if ( !g_bEngineIsHLTV )
  2900. {
  2901. // if we stopped Hltv Replay abruptly for some reason (maybe an issue with the connection to the server) - just reset the Hltv Replay state
  2902. g_HltvReplaySystem.StopHltvReplay();
  2903. }
  2904. g_HltvReplaySystem.Update();
  2905. }
  2906. break;
  2907. }
  2908. }
  2909. CSaveRestoreData *SaveInit( int size );
  2910. // Save/restore system hooks
  2911. CSaveRestoreData *CHLClient::SaveInit( int size )
  2912. {
  2913. return ::SaveInit(size);
  2914. }
  2915. void CHLClient::SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
  2916. {
  2917. CSave saveHelper( pSaveData );
  2918. saveHelper.WriteFields( pname, pBaseData, pMap, pFields, fieldCount );
  2919. }
  2920. void CHLClient::SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
  2921. {
  2922. CRestore restoreHelper( pSaveData );
  2923. restoreHelper.ReadFields( pname, pBaseData, pMap, pFields, fieldCount );
  2924. }
  2925. void CHLClient::PreSave( CSaveRestoreData *s )
  2926. {
  2927. g_pGameSaveRestoreBlockSet->PreSave( s );
  2928. }
  2929. void CHLClient::Save( CSaveRestoreData *s )
  2930. {
  2931. CSave saveHelper( s );
  2932. g_pGameSaveRestoreBlockSet->Save( &saveHelper );
  2933. }
  2934. void CHLClient::WriteSaveHeaders( CSaveRestoreData *s )
  2935. {
  2936. CSave saveHelper( s );
  2937. g_pGameSaveRestoreBlockSet->WriteSaveHeaders( &saveHelper );
  2938. g_pGameSaveRestoreBlockSet->PostSave();
  2939. }
  2940. CEG_NOINLINE void CHLClient::ReadRestoreHeaders( CSaveRestoreData *s )
  2941. {
  2942. CRestore restoreHelper( s );
  2943. CEG_ENCRYPT_FUNCTION( CHLClient_ReadRestoreHeaders );
  2944. g_pGameSaveRestoreBlockSet->PreRestore();
  2945. g_pGameSaveRestoreBlockSet->ReadRestoreHeaders( &restoreHelper );
  2946. }
  2947. CEG_NOINLINE void CHLClient::Restore( CSaveRestoreData *s, bool b )
  2948. {
  2949. CRestore restore(s);
  2950. g_pGameSaveRestoreBlockSet->Restore( &restore, b );
  2951. g_pGameSaveRestoreBlockSet->PostRestore();
  2952. CEG_PROTECT_VIRTUAL_FUNCTION( CHLClient_Restore );
  2953. }
  2954. static CUtlVector<EHANDLE> g_RestoredEntities;
  2955. void AddRestoredEntity( C_BaseEntity *pEntity )
  2956. {
  2957. if ( !pEntity )
  2958. return;
  2959. g_RestoredEntities.AddToTail( pEntity );
  2960. }
  2961. void CHLClient::DispatchOnRestore()
  2962. {
  2963. for ( int i = 0; i < g_RestoredEntities.Count(); i++ )
  2964. {
  2965. if ( g_RestoredEntities[i] != NULL )
  2966. {
  2967. MDLCACHE_CRITICAL_SECTION();
  2968. g_RestoredEntities[i]->OnRestore();
  2969. }
  2970. }
  2971. g_RestoredEntities.RemoveAll();
  2972. }
  2973. void CHLClient::WriteSaveGameScreenshot( const char *pFilename )
  2974. {
  2975. // Single player doesn't support split screen yet!!!
  2976. ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
  2977. view->WriteSaveGameScreenshot( pFilename );
  2978. }
  2979. // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
  2980. // the appropriate close caption if running with closecaption = 1
  2981. void CHLClient::EmitSentenceCloseCaption( char const *tokenstream )
  2982. {
  2983. extern ConVar closecaption;
  2984. if ( !closecaption.GetBool() )
  2985. return;
  2986. if ( m_pHudCloseCaption )
  2987. {
  2988. m_pHudCloseCaption->ProcessSentenceCaptionStream( tokenstream );
  2989. }
  2990. }
  2991. void CHLClient::EmitCloseCaption( char const *captionname, float duration )
  2992. {
  2993. extern ConVar closecaption;
  2994. if ( !closecaption.GetBool() )
  2995. return;
  2996. if ( m_pHudCloseCaption )
  2997. {
  2998. RANDOM_CEG_TEST_SECRET_PERIOD( 0x40, 0xff )
  2999. m_pHudCloseCaption->ProcessCaption( captionname, duration );
  3000. }
  3001. }
  3002. CStandardRecvProxies* CHLClient::GetStandardRecvProxies()
  3003. {
  3004. return &g_StandardRecvProxies;
  3005. }
  3006. bool CHLClient::CanRecordDemo( char *errorMsg, int length ) const
  3007. {
  3008. if ( GetClientModeNormal() )
  3009. {
  3010. return GetClientModeNormal()->CanRecordDemo( errorMsg, length );
  3011. }
  3012. return true;
  3013. }
  3014. bool CHLClient::CanStopRecordDemo( char *errorMsg, int length ) const
  3015. {
  3016. if ( CSGameRules() )
  3017. {
  3018. if ( CSGameRules()->IsWarmupPeriod() )
  3019. return true; // can always stop in warmup
  3020. if ( CSGameRules()->IsRoundOver() )
  3021. return true; // can stop when round is over
  3022. if ( CSGameRules()->IsPlayingGunGameProgressive() )
  3023. return true; // can always stop during arms race
  3024. if ( CSGameRules()->IsPlayingGunGameDeathmatch() )
  3025. return true; // can always stop during deathmatch
  3026. if ( engine->IsClientLocalToActiveServer() )
  3027. return true; // listen server clients can always stop whenever
  3028. Q_strncpy( errorMsg, "Demo recording will stop as soon as the round is over.", length );
  3029. CSGameRules()->MarkClientStopRecordAtRoundEnd( true );
  3030. return false;
  3031. }
  3032. return true;
  3033. }
  3034. void CHLClient::OnDemoRecordStart( char const* pDemoBaseName )
  3035. {
  3036. #ifdef DEMOPOLISH_ENABLED
  3037. if ( IsDemoPolishEnabled() )
  3038. {
  3039. if ( !CDemoPolishRecorder::Instance().Init( pDemoBaseName ) )
  3040. {
  3041. CDemoPolishRecorder::Instance().Shutdown();
  3042. }
  3043. }
  3044. #endif
  3045. if ( CSGameRules() )
  3046. {
  3047. // If client was previously marked to stop recording at round end then mark it now as not requiring to stop
  3048. CSGameRules()->MarkClientStopRecordAtRoundEnd( false );
  3049. }
  3050. }
  3051. void CHLClient::OnDemoRecordStop()
  3052. {
  3053. #ifdef DEMOPOLISH_ENABLED
  3054. if ( DemoPolish_GetRecorder().m_bInit )
  3055. {
  3056. DemoPolish_GetRecorder().Shutdown();
  3057. }
  3058. #endif
  3059. }
  3060. void CHLClient::OnDemoPlaybackStart( char const* pDemoBaseName )
  3061. {
  3062. #ifdef DEMOPOLISH_ENABLED
  3063. if ( IsDemoPolishEnabled() )
  3064. {
  3065. Assert( pDemoBaseName );
  3066. if ( !DemoPolish_GetController().Init( pDemoBaseName ) )
  3067. {
  3068. DemoPolish_GetController().Shutdown();
  3069. }
  3070. }
  3071. #endif
  3072. #if defined( REPLAY_ENABLED )
  3073. // Load any ragdoll override frames from disk
  3074. char szRagdollFile[MAX_OSPATH];
  3075. V_snprintf( szRagdollFile, sizeof(szRagdollFile), "%s.dmx", pDemoBaseName );
  3076. CReplayRagdollCache::Instance().Init( szRagdollFile );
  3077. #endif
  3078. KeyValues *pImportantEvents = new KeyValues( "DemoImportantEvents" );
  3079. if ( pImportantEvents )
  3080. {
  3081. pImportantEvents->LoadFromFile( g_pFullFileSystem, "resource/DemoImportantEvents.res" );
  3082. engine->SetDemoImportantEventData( pImportantEvents );
  3083. pImportantEvents->deleteThis();
  3084. }
  3085. g_HltvReplaySystem.OnDemoPlayback( true );
  3086. }
  3087. void CHLClient::OnDemoPlaybackRestart()
  3088. {
  3089. /* Removed for partner depot */
  3090. }
  3091. void CHLClient::OnDemoPlaybackStop()
  3092. {
  3093. #ifdef DEMOPOLISH_ENABLED
  3094. if ( DemoPolish_GetController().m_bInit )
  3095. {
  3096. DemoPolish_GetController().Shutdown();
  3097. }
  3098. #endif
  3099. #if defined( REPLAY_ENABLED )
  3100. CReplayRagdollCache::Instance().Shutdown();
  3101. #endif
  3102. g_HltvReplaySystem.OnDemoPlayback( false );
  3103. }
  3104. void CHLClient::SetDemoPlaybackHighlightXuid( uint64 xuid, bool bLowlights )
  3105. {
  3106. g_HltvReplaySystem.SetDemoPlaybackHighlightXuid( xuid, bLowlights );
  3107. }
  3108. void CHLClient::ShowHighlightSkippingMessage( bool bState, int nCurrentTick, int nTickStart, int nTickStop )
  3109. {
  3110. loadingdisc->SetFastForwardVisible( bState, true );
  3111. g_HltvReplaySystem.SetDemoPlaybackFadeBrackets( nCurrentTick, nTickStart, nTickStop );
  3112. }
  3113. void CHLClient::RecordDemoPolishUserInput( int nCmdIndex )
  3114. {
  3115. #ifdef DEMOPOLISH_ENABLED
  3116. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  3117. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  3118. Assert( engine->IsRecordingDemo() );
  3119. Assert( IsDemoPolishEnabled() ); // NOTE: cl_demo_polish_enabled checked in engine.
  3120. CUserCmd const* pUserCmd = input->GetUserCmd( nSlot, nCmdIndex );
  3121. Assert( pUserCmd );
  3122. if ( pUserCmd )
  3123. {
  3124. DemoPolish_GetRecorder().RecordUserInput( pUserCmd );
  3125. }
  3126. #endif
  3127. }
  3128. bool CHLClient::CacheReplayRagdolls( const char* pFilename, int nStartTick )
  3129. {
  3130. #if defined( REPLAY_ENABLED )
  3131. return Replay_CacheRagdolls( pFilename, nStartTick );
  3132. #else
  3133. return false;
  3134. #endif
  3135. }
  3136. void CHLClient::ReplayUI_SendMessage( KeyValues *pMsg )
  3137. {
  3138. #if defined( REPLAY_ENABLED ) && defined( TF_CLIENT_DLL )
  3139. const char *pType = pMsg->GetString( "type", NULL );
  3140. if ( !V_stricmp( pType, "newentry" ) )
  3141. {
  3142. if ( pMsg->GetInt( "showinputdlg", 0 ) )
  3143. {
  3144. // Get a name for the replay, saves to disk, add thumbnail to replay browser
  3145. ShowReplayInputPanel( pMsg );
  3146. }
  3147. else
  3148. {
  3149. // Just add the thumbnail if the replay browser exists
  3150. CReplayBrowserPanel* pReplayBrowser = ReplayUI_GetBrowserPanel();
  3151. if ( pReplayBrowser )
  3152. {
  3153. pReplayBrowser->SendMessage( pMsg );
  3154. }
  3155. }
  3156. }
  3157. // If we're deleting a replay notify the replay browser if necessary
  3158. else if ( !V_stricmp( pType, "delete" ) )
  3159. {
  3160. CReplayBrowserPanel* pReplayBrowser = ReplayUI_GetBrowserPanel();
  3161. if ( pReplayBrowser )
  3162. {
  3163. pReplayBrowser->SendMessage( pMsg );
  3164. }
  3165. }
  3166. // Confirm that the user wants to quit, even if there are unrendered replays
  3167. else if ( !V_stricmp( pType, "confirmquit" ) )
  3168. {
  3169. // ReplayUI_ShowConfirmQuitDlg();
  3170. // Until rendering actually works, just quit - don't display the confirmation dialog
  3171. engine->ClientCmd_Unrestricted( "quit" );
  3172. }
  3173. else if ( !V_stricmp( pType, "display_message" ) )
  3174. {
  3175. const char *pLocalizeStr = pMsg->GetString( "localize" );
  3176. // Display a message?
  3177. if ( pLocalizeStr && pLocalizeStr[0] )
  3178. {
  3179. char szLocalized[256];
  3180. g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pLocalizeStr ), szLocalized, sizeof(szLocalized) );
  3181. g_pClientMode->DisplayReplayMessage( szLocalized, -1.0f, NULL, pMsg->GetString( "sound", NULL ), false );
  3182. }
  3183. }
  3184. else if ( !V_stricmp( pType, "render_start" ) )
  3185. {
  3186. extern void ReplayUI_OpenReplayEditPanel();
  3187. ReplayUI_OpenReplayEditPanel();
  3188. }
  3189. else if ( !V_stricmp( pType, "render_complete" ) )
  3190. {
  3191. extern void ReplayUI_HideRenderEditPanel();
  3192. ReplayUI_HideRenderEditPanel();
  3193. ReplayUI_ReloadBrowser();
  3194. }
  3195. // Delete the KeyValues unless delete is explicitly set to 0
  3196. if ( pMsg->GetInt( "should_free", 1 ) )
  3197. {
  3198. pMsg->deleteThis();
  3199. }
  3200. #endif
  3201. }
  3202. // Get the client replay factory
  3203. IReplayFactory *CHLClient::GetReplayFactory()
  3204. {
  3205. #if defined( REPLAY_ENABLED ) && defined( TF_CLIENT_DLL ) // FIXME: Need run-time check for whether replay is enabled
  3206. extern IReplayFactory *g_pReplayFactory;
  3207. return g_pReplayFactory;
  3208. #else
  3209. return NULL;
  3210. #endif
  3211. }
  3212. // Clear out the local player's replay pointer so it doesn't get deleted
  3213. void CHLClient::ClearLocalPlayerReplayPtr()
  3214. {
  3215. #if defined( REPLAY_ENABLED )
  3216. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  3217. Assert( pLocalPlayer );
  3218. pLocalPlayer->ClearCachedReplayPtr();
  3219. #endif
  3220. }
  3221. int CHLClient::GetScreenWidth()
  3222. {
  3223. return ScreenWidth();
  3224. }
  3225. int CHLClient::GetScreenHeight()
  3226. {
  3227. return ScreenHeight();
  3228. }
  3229. void CHLClient::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded /* = false */, bool bWriteVTF /* = false */ )
  3230. {
  3231. view->WriteSaveGameScreenshotOfSize( pFilename, width, height /*, bCreatePowerOf2Padded, bWriteVTF */ );
  3232. }
  3233. void CHLClient::WriteReplayScreenshot( WriteReplayScreenshotParams_t &params )
  3234. {
  3235. #if defined( TF_CLIENT_DLL ) && defined( REPLAY_ENABLED ) // FIXME: Need run-time check for whether replay is enabled
  3236. view->WriteReplayScreenshot( params );
  3237. #endif
  3238. }
  3239. void CHLClient::UpdateReplayScreenshotCache()
  3240. {
  3241. #if defined( TF_CLIENT_DLL ) && defined( REPLAY_ENABLED ) // FIXME: Need run-time check for whether replay is enabled
  3242. view->UpdateReplayScreenshotCache();
  3243. #endif
  3244. }
  3245. // See RenderViewInfo_t
  3246. void CHLClient::RenderView( const CViewSetup &setup, int nClearFlags, int whatToDraw )
  3247. {
  3248. VPROF("RenderView");
  3249. view->RenderView( setup, setup, nClearFlags, whatToDraw );
  3250. }
  3251. bool CHLClient::ShouldHideLoadingPlaque( void )
  3252. {
  3253. return false;
  3254. }
  3255. void CHLClient::OnActiveSplitscreenPlayerChanged( int nNewSlot )
  3256. {
  3257. }
  3258. CEG_NOINLINE void CHLClient::OnSplitScreenStateChanged()
  3259. {
  3260. VGui_OnSplitScreenStateChanged();
  3261. IterateRemoteSplitScreenViewSlots_Push( true );
  3262. FOR_EACH_VALID_SPLITSCREEN_PLAYER( i )
  3263. {
  3264. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( i );
  3265. GetClientMode()->Layout();
  3266. GetHud().OnSplitScreenStateChanged();
  3267. }
  3268. IterateRemoteSplitScreenViewSlots_Pop();
  3269. CEG_ENCRYPT_FUNCTION( CHLClient_OnSplitScreenStateChanged );
  3270. GetFullscreenClientMode()->Layout( true );
  3271. #if 0
  3272. // APS: This cannot be done in this way, the schemes also need to be reloaded as they hook the fonts and
  3273. // various font metrics for custom drawing/sizing etc.
  3274. // See CMatSystemSurface::OnScreenSizeChanged() which is doing the better thing.
  3275. // However, that is still not good enough due to questionable code in CScheme::ReloadFontGlyphs() which
  3276. // prevents the reload due to it's cached concept of the screensize not changing, except the purge is already partialy done,
  3277. // which results in a broken font state.
  3278. // Instead, we are doing the same thing the consoles do (which cannot change video sizes) which is to NOT ditch the glyphs
  3279. // when changing split screen state. When SS for PC gets turned into a primary concept this can be revisited.
  3280. vgui::surface()->ResetFontCaches();
  3281. #endif
  3282. // Update visibility for all ents so that the second viewport for the split player guy looks right, etc.
  3283. C_BaseEntityIterator iterator;
  3284. C_BaseEntity *pEnt;
  3285. while ( (pEnt = iterator.Next()) != NULL )
  3286. {
  3287. pEnt->UpdateVisibility();
  3288. }
  3289. }
  3290. int CHLClient::GetSpectatorTarget( ClientDLLObserverMode_t* pObserverMode )
  3291. {
  3292. if ( pObserverMode )
  3293. {
  3294. *pObserverMode = CLIENT_DLL_OBSERVER_NONE;
  3295. }
  3296. C_CSPlayer *pPlayer = GetLocalOrInEyeCSPlayer();
  3297. if ( pPlayer != NULL )
  3298. {
  3299. return pPlayer->entindex();
  3300. }
  3301. return -1;
  3302. }
  3303. void CHLClient::CenterStringOff()
  3304. {
  3305. FOR_EACH_VALID_SPLITSCREEN_PLAYER( i )
  3306. {
  3307. ACTIVE_SPLITSCREEN_PLAYER_GUARD( i );
  3308. GetCenterPrint()->Clear();
  3309. }
  3310. }
  3311. void CHLClient::OnScreenSizeChanged( int nOldWidth, int nOldHeight )
  3312. {
  3313. // Tell split screen system
  3314. VGui_OnScreenSizeChanged();
  3315. }
  3316. IMaterialProxy *CHLClient::InstantiateMaterialProxy( const char *proxyName )
  3317. {
  3318. #ifdef GAMEUI_UISYSTEM2_ENABLED
  3319. IMaterialProxy *pProxy = g_pGameUIGameSystem->CreateProxy( proxyName );
  3320. if ( pProxy )
  3321. return pProxy;
  3322. #endif
  3323. return GetMaterialProxyDict().CreateProxy( proxyName );
  3324. }
  3325. vgui::VPANEL CHLClient::GetFullscreenClientDLLVPanel( void )
  3326. {
  3327. return VGui_GetFullscreenRootVPANEL();
  3328. }
  3329. int XBX_GetActiveUserId()
  3330. {
  3331. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  3332. return XBX_GetUserId( GET_ACTIVE_SPLITSCREEN_SLOT() );
  3333. }
  3334. //-----------------------------------------------------------------------------
  3335. // Purpose: Marks entities as touching
  3336. // Input : *e1 -
  3337. // *e2 -
  3338. //-----------------------------------------------------------------------------
  3339. void CHLClient::MarkEntitiesAsTouching( IClientEntity *e1, IClientEntity *e2 )
  3340. {
  3341. CBaseEntity *entity = e1->GetBaseEntity();
  3342. CBaseEntity *entityTouched = e2->GetBaseEntity();
  3343. if ( entity && entityTouched )
  3344. {
  3345. trace_t tr;
  3346. UTIL_ClearTrace( tr );
  3347. tr.endpos = (entity->GetAbsOrigin() + entityTouched->GetAbsOrigin()) * 0.5;
  3348. entity->PhysicsMarkEntitiesAsTouching( entityTouched, tr );
  3349. }
  3350. }
  3351. class CKeyBindingListenerMgr : public IKeyBindingListenerMgr
  3352. {
  3353. public:
  3354. struct BindingListeners_t
  3355. {
  3356. BindingListeners_t()
  3357. {
  3358. }
  3359. BindingListeners_t( const BindingListeners_t &other )
  3360. {
  3361. m_List.CopyArray( other.m_List.Base(), other.m_List.Count() );
  3362. }
  3363. CUtlVector< IKeyBindingListener * > m_List;
  3364. };
  3365. // Callback when button is bound
  3366. virtual void AddListenerForCode( IKeyBindingListener *pListener, ButtonCode_t buttonCode )
  3367. {
  3368. CUtlVector< IKeyBindingListener * > &list = m_CodeListeners[ buttonCode ];
  3369. if ( list.Find( pListener ) != list.InvalidIndex() )
  3370. return;
  3371. list.AddToTail( pListener );
  3372. }
  3373. // Callback whenver binding is set to a button
  3374. virtual void AddListenerForBinding( IKeyBindingListener *pListener, char const *pchBindingString )
  3375. {
  3376. int idx = m_BindingListeners.Find( pchBindingString );
  3377. if ( idx == m_BindingListeners.InvalidIndex() )
  3378. {
  3379. idx = m_BindingListeners.Insert( pchBindingString );
  3380. }
  3381. CUtlVector< IKeyBindingListener * > &list = m_BindingListeners[ idx ].m_List;
  3382. if ( list.Find( pListener ) != list.InvalidIndex() )
  3383. return;
  3384. list.AddToTail( pListener );
  3385. }
  3386. virtual void RemoveListener( IKeyBindingListener *pListener )
  3387. {
  3388. for ( int i = 0; i < ARRAYSIZE( m_CodeListeners ); ++i )
  3389. {
  3390. CUtlVector< IKeyBindingListener * > &list = m_CodeListeners[ i ];
  3391. list.FindAndRemove( pListener );
  3392. }
  3393. for ( int i = m_BindingListeners.First(); i != m_BindingListeners.InvalidIndex(); i = m_BindingListeners.Next( i ) )
  3394. {
  3395. CUtlVector< IKeyBindingListener * > &list = m_BindingListeners[ i ].m_List;
  3396. list.FindAndRemove( pListener );
  3397. }
  3398. }
  3399. void OnKeyBindingChanged( ButtonCode_t buttonCode, char const *pchKeyName, char const *pchNewBinding )
  3400. {
  3401. int nSplitScreenSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  3402. CUtlVector< IKeyBindingListener * > &list = m_CodeListeners[ buttonCode ];
  3403. for ( int i = 0 ; i < list.Count(); ++i )
  3404. {
  3405. list[ i ]->OnKeyBindingChanged( nSplitScreenSlot, buttonCode, pchKeyName, pchNewBinding );
  3406. }
  3407. int idx = m_BindingListeners.Find( pchNewBinding );
  3408. if ( idx != m_BindingListeners.InvalidIndex() )
  3409. {
  3410. CUtlVector< IKeyBindingListener * > &list = m_BindingListeners[ idx ].m_List;
  3411. for ( int i = 0 ; i < list.Count(); ++i )
  3412. {
  3413. list[ i ]->OnKeyBindingChanged( nSplitScreenSlot, buttonCode, pchKeyName, pchNewBinding );
  3414. }
  3415. }
  3416. }
  3417. private:
  3418. CUtlVector< IKeyBindingListener * > m_CodeListeners[ BUTTON_CODE_COUNT ];
  3419. CUtlDict< BindingListeners_t, int > m_BindingListeners;
  3420. };
  3421. static CKeyBindingListenerMgr g_KeyBindingListenerMgr;
  3422. IKeyBindingListenerMgr *g_pKeyBindingListenerMgr = &g_KeyBindingListenerMgr;
  3423. void CHLClient::OnKeyBindingChanged( ButtonCode_t buttonCode, char const *pchKeyName, char const *pchNewBinding )
  3424. {
  3425. g_KeyBindingListenerMgr.OnKeyBindingChanged( buttonCode, pchKeyName, pchNewBinding );
  3426. }
  3427. void CHLClient::SetBlurFade( float scale )
  3428. {
  3429. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  3430. {
  3431. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  3432. GetClientMode()->SetBlurFade( scale );
  3433. }
  3434. }
  3435. void CHLClient::ResetHudCloseCaption()
  3436. {
  3437. if ( !IsGameConsole() )
  3438. {
  3439. // only xbox needs to force the close caption system to remount
  3440. return;
  3441. }
  3442. if ( m_pHudCloseCaption )
  3443. {
  3444. // force the caption dictionary to remount
  3445. m_pHudCloseCaption->InitCaptionDictionary( NULL, true );
  3446. }
  3447. }
  3448. void CHLClient::Hud_SaveStarted()
  3449. {
  3450. CHudSaveStatus *pSaveStatus = GET_FULLSCREEN_HUDELEMENT( CHudSaveStatus );
  3451. if ( pSaveStatus )
  3452. {
  3453. pSaveStatus->SaveStarted();
  3454. }
  3455. }
  3456. void CHLClient::ShutdownMovies()
  3457. {
  3458. //VGui_StopAllVideoPanels();
  3459. }
  3460. void CHLClient::GetStatus( char *buffer, int bufsize )
  3461. {
  3462. UTIL_GetClientStatusText( buffer, bufsize );
  3463. }
  3464. #if defined ( CSTRIKE15 )
  3465. bool CHLClient::IsChatRaised( void )
  3466. {
  3467. SFHudChat* pChat = GET_HUDELEMENT( SFHudChat );
  3468. if ( pChat == NULL )
  3469. {
  3470. return false;
  3471. }
  3472. else
  3473. {
  3474. return pChat->ChatRaised();
  3475. }
  3476. }
  3477. bool CHLClient::IsRadioPanelRaised( void )
  3478. {
  3479. SFHudRadio* pRadio = GET_HUDELEMENT( SFHudRadio );
  3480. if ( pRadio == NULL )
  3481. {
  3482. return false;
  3483. }
  3484. else
  3485. {
  3486. return pRadio->PanelRaised();
  3487. }
  3488. }
  3489. bool CHLClient::IsBindMenuRaised( void )
  3490. {
  3491. return COptionsScaleform::IsBindMenuRaised();
  3492. }
  3493. bool CHLClient::IsTeamMenuRaised( void )
  3494. {
  3495. if ( !GetViewPortInterface() )
  3496. {
  3497. return false;
  3498. }
  3499. IViewPortPanel * pTeam = GetViewPortInterface()->FindPanelByName( PANEL_TEAM );
  3500. if ( pTeam && pTeam->IsVisible() )
  3501. {
  3502. return true;
  3503. }
  3504. return false;
  3505. }
  3506. bool CHLClient::IsLoadingScreenRaised( void )
  3507. {
  3508. return CLoadingScreenScaleform::IsOpen();
  3509. }
  3510. #endif // CSTRIKE15
  3511. #if defined(_PS3)
  3512. int CHLClient::GetDrawFlags( void )
  3513. {
  3514. return g_viewBuilder.GetDrawFlags();
  3515. }
  3516. int CHLClient::GetBuildViewID( void )
  3517. {
  3518. return g_viewBuilder.GetBuildViewID();
  3519. }
  3520. bool CHLClient::IsSPUBuildWRJobsOn( void )
  3521. {
  3522. return g_viewBuilder.IsSPUBuildRWJobsOn();
  3523. }
  3524. void CHLClient::CacheFrustumData( Frustum_t *pFrustum, Frustum_t *pAreaFrustum, void *pRenderAreaBits, int numArea, bool bViewerInSolidSpace )
  3525. {
  3526. g_viewBuilder.CacheFrustumData( pFrustum, pAreaFrustum, pRenderAreaBits, numArea, bViewerInSolidSpace );
  3527. }
  3528. void *CHLClient::GetBuildViewVolumeCuller( void )
  3529. {
  3530. return g_viewBuilder.GetBuildViewVolumeCuller();
  3531. }
  3532. Frustum_t *CHLClient::GetBuildViewFrustum( void )
  3533. {
  3534. return g_viewBuilder.GetBuildViewFrustum();
  3535. }
  3536. Frustum_t *CHLClient::GetBuildViewAreaFrustum( void )
  3537. {
  3538. return g_viewBuilder.GetBuildViewAreaFrustum();
  3539. }
  3540. unsigned char *CHLClient::GetBuildViewRenderAreaBits( void )
  3541. {
  3542. return g_viewBuilder.GetBuildViewRenderAreaBits();
  3543. }
  3544. #else
  3545. bool CHLClient::IsBuildWRThreaded( void )
  3546. {
  3547. return g_viewBuilder.GetBuildWRThreaded();
  3548. }
  3549. void CHLClient::QueueBuildWorldListJob( CJob* pJob )
  3550. {
  3551. g_viewBuilder.QueueBuildWorldListJob( pJob );
  3552. }
  3553. void CHLClient::CacheFrustumData( const Frustum_t& frustum, const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >& aeraFrustums )
  3554. {
  3555. g_viewBuilder.CacheFrustumData( frustum, aeraFrustums );
  3556. }
  3557. const Frustum_t* CHLClient::GetBuildViewFrustum( void ) const
  3558. {
  3559. return g_viewBuilder.GetBuildViewFrustum();
  3560. }
  3561. const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >* CHLClient::GetBuildViewAeraFrustums( void ) const
  3562. {
  3563. return g_viewBuilder.GetBuildViewAeraFrustums();
  3564. }
  3565. #endif // PS3, CConcurrentView helper fns
  3566. bool CHLClient::IsSubscribedMap( const char *pchMapName, bool bOnlyOnDisk )
  3567. {
  3568. #if !defined ( NO_STEAM ) && defined( CSTRIKE15 )
  3569. return g_CSGOWorkshopMaps.IsSubscribedMap( pchMapName, bOnlyOnDisk );
  3570. #endif
  3571. return false;
  3572. }
  3573. bool CHLClient::IsFeaturedMap( const char *pchMapName, bool bOnlyOnDisk )
  3574. {
  3575. #if !defined ( NO_STEAM ) && defined( CSTRIKE15 )
  3576. return g_CSGOWorkshopMaps.IsFeaturedMap( pchMapName, bOnlyOnDisk );
  3577. #endif
  3578. return false;
  3579. }
  3580. void CHLClient::DownloadCommunityMapFile( PublishedFileId_t id )
  3581. {
  3582. #if !defined ( NO_STEAM ) && defined( CSTRIKE15 )
  3583. g_CSGOWorkshopMaps.DownloadMapFile( id );
  3584. #endif
  3585. }
  3586. float CHLClient::GetUGCFileDownloadProgress( PublishedFileId_t id )
  3587. {
  3588. #if !defined ( NO_STEAM ) && defined( CSTRIKE15 )
  3589. return g_CSGOWorkshopMaps.GetFileDownloadProgress( id );
  3590. #endif
  3591. }
  3592. void CHLClient::RecordUIEvent( const char* szEvent )
  3593. {
  3594. /* Removed for partner depot */
  3595. }
  3596. void CHLClient::OnDemoPlaybackTimeJump()
  3597. {
  3598. if ( C_HLTVCamera *pCamera = HLTVCamera() )
  3599. {
  3600. //Cbuf_AddText( Cbuf_GetCurrentPlayer(), "spec_prev;spec_mode 4;+showscores;-showscores\n" ); // go to the next/prev available player; just go to some player, if they've already connected
  3601. pCamera->SetMode( 4 );
  3602. pCamera->SpecNextPlayer( true );
  3603. }
  3604. }
  3605. // Inventory access
  3606. float CHLClient::FindInventoryItemWithMaxAttributeValue( char const *szItemType, char const *szAttrClass )
  3607. {
  3608. CCSPlayerInventory *pLocalInv = CSInventoryManager()->GetLocalCSInventory();
  3609. return pLocalInv ? pLocalInv->FindInventoryItemWithMaxAttributeValue( szItemType, szAttrClass ) : -1.0f;
  3610. }
  3611. void CHLClient::DetermineSubscriptionKvToAdvertise( KeyValues *kvLocalPlayer )
  3612. {
  3613. /* Removed for partner depot */
  3614. }
  3615. class CHLClientAutoRichPresenceUpdateOnConnect
  3616. {
  3617. public:
  3618. CHLClientAutoRichPresenceUpdateOnConnect() : m_SteamCallback_OnServersConnected( this, &CHLClientAutoRichPresenceUpdateOnConnect::Steam_OnServersConnected ) {}
  3619. STEAM_CALLBACK( CHLClientAutoRichPresenceUpdateOnConnect, Steam_OnServersConnected, SteamServersConnected_t, m_SteamCallback_OnServersConnected )
  3620. {
  3621. ( void ) clientdll->GetRichPresenceStatusString();
  3622. }
  3623. };
  3624. char const * CHLClient::GetRichPresenceStatusString()
  3625. {
  3626. ISteamFriends *pf = steamapicontext->SteamFriends();
  3627. if ( !pf )
  3628. return "";
  3629. bool bConnectedToServer = engine->IsInGame();
  3630. static CHLClientAutoRichPresenceUpdateOnConnect s_RPUpdater; // construct auto RP updater upon first rich presence update
  3631. // Status string
  3632. static CFmtStr sRichPresence;
  3633. sRichPresence.Clear();
  3634. // Map (Dust II, Office, etc.)
  3635. char const *szMap = NULL;
  3636. char const *szGameMap = NULL;
  3637. if ( bConnectedToServer )
  3638. {
  3639. szMap = engine->GetLevelNameShort();
  3640. szGameMap = szMap;
  3641. { // Resolve known map names
  3642. if ( !V_stricmp( szGameMap, "cs_assault" ) ) szGameMap = "Assault" ;
  3643. else if ( !V_stricmp( szGameMap, "cs_italy" ) ) szGameMap = "Italy" ;
  3644. else if ( !V_stricmp( szGameMap, "cs_militia" ) ) szGameMap = "Militia" ;
  3645. else if ( !V_stricmp( szGameMap, "cs_office" ) ) szGameMap = "Office" ;
  3646. else if ( !V_stricmp( szGameMap, "de_aztec" ) ) szGameMap = "Aztec" ;
  3647. else if ( !V_stricmp( szGameMap, "de_dust" ) ) szGameMap = "Dust" ;
  3648. else if ( !V_stricmp( szGameMap, "de_dust2" ) ) szGameMap = "Dust II" ;
  3649. else if ( !V_stricmp( szGameMap, "de_mirage" ) ) szGameMap = "Mirage" ;
  3650. else if ( !V_stricmp( szGameMap, "de_overpass" ) ) szGameMap = "Overpass" ;
  3651. else if ( !V_stricmp( szGameMap, "de_cbble" ) ) szGameMap = "Cobblestone" ;
  3652. else if ( !V_stricmp( szGameMap, "de_train" ) ) szGameMap = "Train" ;
  3653. else if ( !V_stricmp( szGameMap, "de_inferno" ) ) szGameMap = "Inferno" ;
  3654. else if ( !V_stricmp( szGameMap, "de_nuke" ) ) szGameMap = "Nuke" ;
  3655. else if ( !V_stricmp( szGameMap, "de_shorttrain" ) ) szGameMap = "Shorttrain" ;
  3656. else if ( !V_stricmp( szGameMap, "de_shortdust" ) ) szGameMap = "Shortdust" ;
  3657. else if ( !V_stricmp( szGameMap, "de_vertigo" ) ) szGameMap = "Vertigo" ;
  3658. else if ( !V_stricmp( szGameMap, "de_balkan" ) ) szGameMap = "Balkan" ;
  3659. else if ( !V_stricmp( szGameMap, "random" ) ) szGameMap = "Random" ;
  3660. else if ( !V_stricmp( szGameMap, "ar_baggage" ) ) szGameMap = "Baggage" ;
  3661. else if ( !V_stricmp( szGameMap, "ar_monastery" ) ) szGameMap = "Monastery" ;
  3662. else if ( !V_stricmp( szGameMap, "ar_shoots" ) ) szGameMap = "Shoots" ;
  3663. else if ( !V_stricmp( szGameMap, "de_embassy" ) ) szGameMap = "Embassy" ;
  3664. else if ( !V_stricmp( szGameMap, "de_bank" ) ) szGameMap = "Bank" ;
  3665. else if ( !V_stricmp( szGameMap, "de_lake" ) ) szGameMap = "Lake" ;
  3666. else if ( !V_stricmp( szGameMap, "de_depot" ) ) szGameMap = "Depot" ;
  3667. else if ( !V_stricmp( szGameMap, "de_safehouse" ) ) szGameMap = "Safehouse" ;
  3668. else if ( !V_stricmp( szGameMap, "de_sugarcane" ) ) szGameMap = "Sugarcane" ;
  3669. else if ( !V_stricmp( szGameMap, "de_stmarc" ) ) szGameMap = "St. Marc" ;
  3670. else if ( !V_stricmp( szGameMap, "training1" ) ) szGameMap = "Weapons Course" ;
  3671. else if ( !V_stricmp( szGameMap, "cs_museum" ) ) szGameMap = "Museum" ;
  3672. else if ( !V_stricmp( szGameMap, "cs_thunder" ) ) szGameMap = "Thunder" ;
  3673. else if ( !V_stricmp( szGameMap, "de_favela" ) ) szGameMap = "Favela" ;
  3674. else if ( !V_stricmp( szGameMap, "cs_downtown" ) ) szGameMap = "Downtown" ;
  3675. else if ( !V_stricmp( szGameMap, "de_seaside" ) ) szGameMap = "Seaside" ;
  3676. else if ( !V_stricmp( szGameMap, "de_library" ) ) szGameMap = "Library" ;
  3677. else if ( !V_stricmp( szGameMap, "cs_motel" ) ) szGameMap = "Motel" ;
  3678. else if ( !V_stricmp( szGameMap, "de_cache" ) ) szGameMap = "Cache" ;
  3679. else if ( !V_stricmp( szGameMap, "de_ali" ) ) szGameMap = "Ali" ;
  3680. else if ( !V_stricmp( szGameMap, "de_ruins" ) ) szGameMap = "Ruins" ;
  3681. else if ( !V_stricmp( szGameMap, "de_chinatown" ) ) szGameMap = "Chinatown" ;
  3682. else if ( !V_stricmp( szGameMap, "de_gwalior" ) ) szGameMap = "Gwalior" ;
  3683. else if ( !V_stricmp( szGameMap, "cs_agency" ) ) szGameMap = "Agency" ;
  3684. else if ( !V_stricmp( szGameMap, "cs_siege" ) ) szGameMap = "Siege" ;
  3685. else if ( !V_stricmp( szGameMap, "de_blackgold" ) ) szGameMap = "Black Gold" ;
  3686. else if ( !V_stricmp( szGameMap, "de_castle" ) ) szGameMap = "Castle" ;
  3687. else if ( !V_stricmp( szGameMap, "de_overgrown" ) ) szGameMap = "Overgrown" ;
  3688. else if ( !V_stricmp( szGameMap, "de_mist" ) ) szGameMap = "Mist" ;
  3689. else if ( !V_stricmp( szGameMap, "cs_rush" ) ) szGameMap = "Rush" ;
  3690. else if ( !V_stricmp( szGameMap, "cs_insertion" ) ) szGameMap = "Insertion" ;
  3691. else if ( !V_stricmp( szGameMap, "cs_workout" ) ) szGameMap = "Workout" ;
  3692. else if ( !V_stricmp( szGameMap, "cs_backalley" ) ) szGameMap = "Back Alley" ;
  3693. else if ( !V_stricmp( szGameMap, "de_bazaar" ) ) szGameMap = "Bazaar" ;
  3694. else if ( !V_stricmp( szGameMap, "de_marquis" ) ) szGameMap = "Marquis" ;
  3695. else if ( !V_stricmp( szGameMap, "de_season" ) ) szGameMap = "Season" ;
  3696. else if ( !V_stricmp( szGameMap, "de_facade" ) ) szGameMap = "Facade" ;
  3697. else if ( !V_stricmp( szGameMap, "de_log" ) ) szGameMap = "Log" ;
  3698. else if ( !V_stricmp( szGameMap, "de_rails" ) ) szGameMap = "Rails" ;
  3699. else if ( !V_stricmp( szGameMap, "de_resort" ) ) szGameMap = "Resort" ;
  3700. else if ( !V_stricmp( szGameMap, "de_zoo" ) ) szGameMap = "Zoo" ;
  3701. else if ( !V_stricmp( szGameMap, "cs_cruise" ) ) szGameMap = "Cruise" ;
  3702. else if ( !V_stricmp( szGameMap, "de_coast" ) ) szGameMap = "Coast" ;
  3703. else if ( !V_stricmp( szGameMap, "de_empire" ) ) szGameMap = "Empire" ;
  3704. else if ( !V_stricmp( szGameMap, "de_mikla" ) ) szGameMap = "Mikla" ;
  3705. else if ( !V_stricmp( szGameMap, "de_royal" ) ) szGameMap = "Royal" ;
  3706. else if ( !V_stricmp( szGameMap, "de_santorini" ) ) szGameMap = "Santorini" ;
  3707. else if ( !V_stricmp( szGameMap, "de_tulip" ) ) szGameMap = "Tulip" ;
  3708. else if ( !V_stricmp( szGameMap, "gd_crashsite" ) ) szGameMap = "Crashsite" ;
  3709. else if ( !V_stricmp( szGameMap, "gd_lake" ) ) szGameMap = "Lake" ;
  3710. else if ( !V_stricmp( szGameMap, "gd_bank" ) ) szGameMap = "Bank" ;
  3711. else if ( !V_stricmp( szGameMap, "gd_cbble" ) ) szGameMap = "Cobblestone" ;
  3712. else if ( !V_stricmp( szGameMap, "gd_sugarcane" ) ) szGameMap = "Sugarcane" ;
  3713. else if ( !V_stricmp( szGameMap, "coop_cementplant" ) ) szGameMap = "Phoenix Compound" ;
  3714. }
  3715. }
  3716. // Map group
  3717. char const *szMapGroup = NULL;
  3718. char const *szGameMapGroup = NULL;
  3719. if ( bConnectedToServer )
  3720. {
  3721. szMapGroup = engine->GetMapGroupName();
  3722. szGameMapGroup = szMapGroup;
  3723. {
  3724. if ( !V_stricmp( szGameMapGroup, "mg_active" ) ) szGameMapGroup = "Active Duty" ;
  3725. else if ( !V_stricmp( szGameMapGroup, "mg_reserves" ) ) szGameMapGroup = "Reserves" ;
  3726. else if ( !V_stricmp( szGameMapGroup, "mg_op_06" ) ) szGameMapGroup = "Operation Bloodhound" ;
  3727. }
  3728. }
  3729. // Game mode (Arms Race, Demolition, etc.)
  3730. char const *szMode = NULL;
  3731. char const *szGameMode = NULL;
  3732. if ( bConnectedToServer )
  3733. {
  3734. extern ConVar game_type;
  3735. extern ConVar game_mode;
  3736. switch ( game_type.GetInt() )
  3737. {
  3738. case 0:
  3739. switch ( game_mode.GetInt() )
  3740. {
  3741. case 1:
  3742. szMode = "competitive";
  3743. szGameMode = "Competitive";
  3744. break;
  3745. default:
  3746. szMode = "casual";
  3747. szGameMode = "Casual";
  3748. break;
  3749. }
  3750. break;
  3751. case 1:
  3752. switch ( game_mode.GetInt() )
  3753. {
  3754. case 0:
  3755. szMode = "gungameprogressive";
  3756. szGameMode = "Arms Race";
  3757. break;
  3758. case 1:
  3759. szMode = "gungametrbomb";
  3760. szGameMode = "Demolition";
  3761. break;
  3762. default:
  3763. szMode = "deathmatch";
  3764. szGameMode = "Deathmatch";
  3765. break;
  3766. }
  3767. break;
  3768. case 2:
  3769. szMode = "training";
  3770. szGameMode = "Weapons Course";
  3771. break;
  3772. case 4:
  3773. szMode = "cooperative";
  3774. szGameMode = "Mission";
  3775. break;
  3776. default:
  3777. szMode = "custom";
  3778. szGameMode = "Custom";
  3779. break;
  3780. }
  3781. }
  3782. // Score of the match
  3783. char chScore[64] = {};
  3784. char const *szScore = NULL;
  3785. if ( bConnectedToServer && !g_bEngineIsHLTV && CSGameRules() )
  3786. {
  3787. // Append the score using local player's team first, or CT first
  3788. bool bLocalPlayerT = false;
  3789. if ( C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer() )
  3790. {
  3791. bLocalPlayerT = ( pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST );
  3792. }
  3793. C_Team *tTeam = GetGlobalTeam( TEAM_TERRORIST );
  3794. int nTscore = tTeam ? tTeam->Get_Score() : 0;
  3795. C_Team *ctTeam = GetGlobalTeam( TEAM_CT );
  3796. int nCTscore = ctTeam ? ctTeam->Get_Score() : 0;
  3797. if ( nTscore + nCTscore > 0 )
  3798. {
  3799. V_sprintf_safe( chScore, "[ %d : %d ]", bLocalPlayerT ? nTscore : nCTscore, bLocalPlayerT ? nCTscore : nTscore );
  3800. szScore = chScore;
  3801. }
  3802. }
  3803. // Server type
  3804. char const *szServerType = NULL; // V for Valve, P for Pinion
  3805. char const *szConnectAddress = NULL;
  3806. bool bCanInvite = false;
  3807. bool bCanWatch = false;
  3808. bool bPlayingDemo = engine->IsPlayingDemo();
  3809. CDemoPlaybackParameters_t const *pDemoPlaybackParameters = bPlayingDemo ? engine->GetDemoPlaybackParameters() : NULL;
  3810. bool bWatchingLiveBroadcast = bPlayingDemo && pDemoPlaybackParameters && pDemoPlaybackParameters->m_bPlayingLiveRemoteBroadcast;
  3811. if ( bConnectedToServer )
  3812. {
  3813. if ( bWatchingLiveBroadcast )
  3814. {
  3815. if ( CSGameRules() && CSGameRules()->IsValveDS() )
  3816. {
  3817. szServerType = "kv";
  3818. // Some official game modes aren't watchable
  3819. if ( !CSGameRules()->IsPlayingCooperativeGametype() )
  3820. bCanWatch = true;
  3821. }
  3822. }
  3823. else if ( !bPlayingDemo )
  3824. {
  3825. // Check if the connection is to a Valve official server
  3826. INetChannelInfo *pNetChanInfo = engine->GetNetChannelInfo();
  3827. netadr_t adrRemote( pNetChanInfo ? pNetChanInfo->GetAddress() : "127.0.0.1" );
  3828. if ( pNetChanInfo && ( pNetChanInfo->IsLoopback() || adrRemote.IsLocalhost() ) )
  3829. {
  3830. szServerType = "offline";
  3831. }
  3832. else if ( pNetChanInfo )
  3833. {
  3834. szConnectAddress = pNetChanInfo->GetAddress();
  3835. if ( CSGameRules() && CSGameRules()->IsValveDS() )
  3836. {
  3837. szServerType = "kv";
  3838. // Some official game modes aren't watchable
  3839. if ( !CSGameRules()->IsPlayingCooperativeGametype() )
  3840. bCanWatch = true;
  3841. }
  3842. if ( !szServerType )
  3843. {
  3844. szServerType = "community";
  3845. if ( ( steamapicontext->SteamUtils()->GetConnectedUniverse() != k_EUniversePublic ) && ( cl_join_advertise.GetInt() >= 3 ) )
  3846. { // cl_join_advertise 3 can override SteamBeta testing to show up as Valve servers
  3847. szServerType = "kv";
  3848. bCanWatch = true;
  3849. }
  3850. }
  3851. bCanInvite = ( CSGameRules() && !CSGameRules()->IsQueuedMatchmaking() && // queued official competitive
  3852. !engine->IsHLTV() && // demo preview or GOTV
  3853. ( adrRemote.GetPort() != 1 ) // SteamID steamcnx for a private match, address is not valid
  3854. );
  3855. if ( bCanInvite && Q_strcmp( szServerType, "community" ) )
  3856. {
  3857. // Make sure we don't have a max number of players
  3858. int numPlayers = 0;
  3859. for ( int j = 1; j <= gpGlobals->maxClients; j++ )
  3860. {
  3861. CBasePlayer *pPlayer = UTIL_PlayerByIndex( j );
  3862. if ( pPlayer && !pPlayer->IsBot() )
  3863. ++numPlayers;
  3864. }
  3865. int numPlayersLimit = 10;
  3866. if ( !Q_strcmp( szMode, "casual" ) )
  3867. numPlayersLimit = 20;
  3868. else if ( !Q_strcmp( szMode, "deathmatch" ) )
  3869. numPlayersLimit = 16;
  3870. if ( numPlayersLimit && ( numPlayers >= numPlayersLimit ) )
  3871. bCanInvite = false;
  3872. }
  3873. }
  3874. }
  3875. }
  3876. // Activity
  3877. char const *szActivity = NULL;
  3878. char const *szGameActivity = NULL;
  3879. if ( bConnectedToServer && bPlayingDemo && !bWatchingLiveBroadcast )
  3880. {
  3881. CDemoPlaybackParameters_t const *pParams = engine->GetDemoPlaybackParameters();
  3882. if ( pParams && pParams->m_bAnonymousPlayerIdentity )
  3883. {
  3884. szActivity = "overwatch";
  3885. szGameActivity = "Overwatch";
  3886. }
  3887. else
  3888. {
  3889. szActivity = "review";
  3890. szGameActivity = "Replaying";
  3891. }
  3892. }
  3893. else if ( bConnectedToServer && engine->IsHLTV() )
  3894. {
  3895. szActivity = "watch";
  3896. szGameActivity = "Watching";
  3897. }
  3898. else if ( szServerType && !Q_strcmp( "offline", szServerType ) )
  3899. {
  3900. szActivity = "offline";
  3901. szGameActivity = "Offline";
  3902. }
  3903. else if ( szServerType && !Q_strcmp( "community", szServerType ) )
  3904. {
  3905. szActivity = "community";
  3906. szGameActivity = "Community";
  3907. }
  3908. //
  3909. // Build the special status string
  3910. // [Activity] [Mode] [Map / MapGroup] [Score]
  3911. //
  3912. if ( szGameActivity && *szGameActivity )
  3913. {
  3914. if ( sRichPresence.Length() > 0 )
  3915. sRichPresence.Append( ' ' );
  3916. sRichPresence.AppendFormat( "%s", szGameActivity );
  3917. }
  3918. if ( szGameMode && *szGameMode )
  3919. {
  3920. if ( sRichPresence.Length() > 0 )
  3921. sRichPresence.Append( ' ' );
  3922. sRichPresence.AppendFormat( "%s", szGameMode );
  3923. }
  3924. if ( szGameMap && *szGameMap )
  3925. {
  3926. if ( sRichPresence.Length() > 0 )
  3927. sRichPresence.Append( ' ' );
  3928. sRichPresence.AppendFormat( "%s", szGameMap );
  3929. }
  3930. if ( szScore && *szScore )
  3931. {
  3932. if ( sRichPresence.Length() > 0 )
  3933. sRichPresence.Append( ' ' );
  3934. sRichPresence.AppendFormat( "%s", szScore );
  3935. }
  3936. if ( !sRichPresence.Length() )
  3937. { // Default RP
  3938. sRichPresence.AppendFormat( "Playing CS:GO" );
  3939. }
  3940. pf->SetRichPresence( "status", sRichPresence.Get() );
  3941. pf->SetRichPresence( "version", CFmtStr( "%d", engine->GetEngineBuildNumber() ) );
  3942. pf->SetRichPresence( "time", CFmtStr( "%f", Plat_FloatTime() ) ); // cause RP upload in case we drop from Steam and reconnect
  3943. pf->SetRichPresence( "game:act", szActivity );
  3944. pf->SetRichPresence( "game:mode", szMode );
  3945. pf->SetRichPresence( "game:mapgroupname", szMapGroup );
  3946. pf->SetRichPresence( "game:map", szMap );
  3947. pf->SetRichPresence( "game:score", szScore );
  3948. pf->SetRichPresence( "game:server", szServerType );
  3949. pf->SetRichPresence( "watch", bCanWatch ? "1" : NULL );
  3950. if ( bCanInvite && szConnectAddress )
  3951. {
  3952. uint32 uiRandomThing = RandomInt( 1, INT_MAX );
  3953. CUtlString strConnectHash;
  3954. ns_address adr;
  3955. if ( adr.SetFromString( szConnectAddress ) && adr.GetAddressType() == NSAT_PROXIED_GAMESERVER )
  3956. strConnectHash.Format( "%u:%u:%llu", uiRandomThing, steamapicontext->SteamUser()->GetSteamID().GetAccountID(), adr.m_steamID.GetSteamID().ConvertToUint64() );
  3957. else
  3958. strConnectHash.Format( "%u:%u:%s", uiRandomThing, steamapicontext->SteamUser()->GetSteamID().GetAccountID(), szConnectAddress );
  3959. CRC32_t crcConnectHash = CRC32_ProcessSingleBuffer( strConnectHash.Access(), strConnectHash.Length() );
  3960. bool bPublicConnect = false;
  3961. if ( !Q_strcmp( szServerType, "community" ) )
  3962. bPublicConnect = ( cl_join_advertise.GetInt() >= 2 );
  3963. else
  3964. bPublicConnect = ( cl_join_advertise.GetInt() >= 1 );
  3965. CFmtStr fmtConnectValue( "+gcconnect%08X%08X%08X",
  3966. uiRandomThing, steamapicontext->SteamUser()->GetSteamID().GetAccountID(), crcConnectHash );
  3967. pf->SetRichPresence( "connect", bPublicConnect ? fmtConnectValue.Access() : NULL );
  3968. pf->SetRichPresence( "connect_private", fmtConnectValue.Access() );
  3969. }
  3970. else
  3971. {
  3972. pf->SetRichPresence( "connect", NULL );
  3973. pf->SetRichPresence( "connect_private", NULL );
  3974. }
  3975. return sRichPresence.Get();
  3976. }
  3977. int CHLClient::GetInEyeEntity() const
  3978. {
  3979. C_CSPlayer* player = GetLocalOrInEyeCSPlayer();
  3980. if (player != nullptr)
  3981. {
  3982. return player->entindex();
  3983. }
  3984. return -1;
  3985. }
  3986. bool CHLClient::ValidateSignedEvidenceHeader( char const *szKey, void const *pvHeader, CDemoPlaybackParameters_t *pPlaybackParameters )
  3987. {
  3988. /* Removed for partner depot */
  3989. return true;
  3990. }
  3991. void CHLClient::PrepareSignedEvidenceData( void *pvData, int numBytes, CDemoPlaybackParameters_t const *pPlaybackParameters )
  3992. {
  3993. /* Removed for partner depot */
  3994. }
  3995. bool CHLClient::ShouldSkipEvidencePlayback( CDemoPlaybackParameters_t const *pPlaybackParameters )
  3996. {
  3997. /* Removed for partner depot */
  3998. return true;
  3999. }
  4000. // Scaleform slot controller
  4001. IScaleformSlotInitController * CHLClient::GetScaleformSlotInitController()
  4002. {
  4003. /* Removed for partner depot */
  4004. return nullptr;
  4005. }
  4006. bool CHLClient::IsConnectedUserInfoChangeAllowed( IConVar *pCvar )
  4007. {
  4008. return CSGameRules() ? CSGameRules()->IsConnectedUserInfoChangeAllowed( NULL ) : true;
  4009. }
  4010. void CHLClient::OnCommandDuringPlayback( char const *cmd )
  4011. {
  4012. /* Removed for partner depot */
  4013. }
  4014. void CHLClient::RetireAllPlayerDecals( bool bRenderContextValid )
  4015. {
  4016. extern void OnPlayerDecalsLevelShutdown();
  4017. OnPlayerDecalsLevelShutdown();
  4018. if ( bRenderContextValid )
  4019. {
  4020. // If the render context is valid (i.e. manual r_cleardecals)
  4021. // then we should immediately update and reapply to avoid flickers
  4022. extern void OnPlayerDecalsUpdate();
  4023. OnPlayerDecalsUpdate();
  4024. }
  4025. }
  4026. void CHLClient::EngineGotvSyncPacket( const CEngineGotvSyncPacket *pPkt )
  4027. {
  4028. /* Removed for partner depot */
  4029. }
  4030. void CHLClient::OnTickPre( int tickcount )
  4031. {
  4032. #if defined( CSTRIKE15 ) && !defined( CSTRIKE_REL_BUILD )
  4033. // We always strip this out in REL builds.
  4034. // We're about to tick over, notify g_pFatDemoRecorder so it can do its magic.
  4035. g_pFatDemoRecorder->OnTickPre( tickcount );
  4036. #endif
  4037. }
  4038. class ClientJob_EMsgGCCStrike15_GotvSyncPacket : public GCSDK::CGCClientJob
  4039. {
  4040. public:
  4041. explicit ClientJob_EMsgGCCStrike15_GotvSyncPacket( GCSDK::CGCClient *pGCClient ) : GCSDK::CGCClientJob( pGCClient )
  4042. {
  4043. }
  4044. virtual bool BYieldingRunJobFromMsg( GCSDK::IMsgNetPacket *pNetPacket )
  4045. {
  4046. GCSDK::CProtoBufMsg<CMsgGCCStrike15_GotvSyncPacket> msg( pNetPacket );
  4047. return engine->EngineGotvSyncPacket( &msg.Body().data() );
  4048. }
  4049. };
  4050. GC_REG_CLIENT_JOB( ClientJob_EMsgGCCStrike15_GotvSyncPacket, k_EMsgGCCStrike15_v2_GotvSyncPacket );
  4051. //-----------------------------------------------------------------------------
  4052. // Purpose: Spew application info (primarily for log file data mining)
  4053. //-----------------------------------------------------------------------------
  4054. void SpewInstallStatus( void )
  4055. {
  4056. #if defined( _X360 )
  4057. g_pXboxInstaller->SpewStatus();
  4058. #endif
  4059. }
  4060. extern IViewRender *view;
  4061. //-----------------------------------------------------------------------------
  4062. // Purpose: interface from materialsystem to client, currently just for recording into tools
  4063. //-----------------------------------------------------------------------------
  4064. class CClientMaterialSystem : public IClientMaterialSystem
  4065. {
  4066. virtual HTOOLHANDLE GetCurrentRecordingEntity()
  4067. {
  4068. if ( !ToolsEnabled() )
  4069. return HTOOLHANDLE_INVALID;
  4070. if ( !clienttools->IsInRecordingMode() )
  4071. return HTOOLHANDLE_INVALID;
  4072. const C_BaseEntity *pEnt = NULL;
  4073. if( m_pProxyData ) //dynamic_cast not possible with void *. Just going to have to search to verify that it actually is an entity
  4074. {
  4075. CClientEntityList &entList = ClientEntityList();
  4076. C_BaseEntity *pIter = entList.FirstBaseEntity();
  4077. while( pIter )
  4078. {
  4079. if( (pIter == m_pProxyData) || (pIter->GetClientRenderable() == m_pProxyData) )
  4080. {
  4081. pEnt = pIter;
  4082. break;
  4083. }
  4084. pIter = entList.NextBaseEntity( pIter );
  4085. }
  4086. }
  4087. if( !pEnt && (materials->GetThreadMode() == MATERIAL_SINGLE_THREADED) )
  4088. {
  4089. pEnt = view->GetCurrentlyDrawingEntity();
  4090. }
  4091. if ( !pEnt || !pEnt->IsToolRecording() )
  4092. return HTOOLHANDLE_INVALID;
  4093. return pEnt->GetToolHandle();
  4094. }
  4095. virtual void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *pMsg )
  4096. {
  4097. ToolFramework_PostToolMessage( hEntity, pMsg );
  4098. }
  4099. virtual void SetMaterialProxyData( void *pProxyData )
  4100. {
  4101. m_pProxyData = pProxyData;
  4102. }
  4103. void *m_pProxyData;
  4104. };
  4105. //-----------------------------------------------------------------------------
  4106. // Singleton instance
  4107. //-----------------------------------------------------------------------------
  4108. static CClientMaterialSystem s_ClientMaterialSystem;
  4109. IClientMaterialSystem *g_pClientMaterialSystem = &s_ClientMaterialSystem;
  4110. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientMaterialSystem, IClientMaterialSystem, VCLIENTMATERIALSYSTEM_INTERFACE_VERSION, s_ClientMaterialSystem );