Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2644 lines
78 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include <crtmemdebug.h>
  9. #include "vgui_int.h"
  10. #include "clientmode.h"
  11. #include "iinput.h"
  12. #include "iviewrender.h"
  13. #include "ivieweffects.h"
  14. #include "ivmodemanager.h"
  15. #include "prediction.h"
  16. #include "clientsideeffects.h"
  17. #include "particlemgr.h"
  18. #include "steam/steam_api.h"
  19. #include "initializer.h"
  20. #include "smoke_fog_overlay.h"
  21. #include "view.h"
  22. #include "ienginevgui.h"
  23. #include "iefx.h"
  24. #include "enginesprite.h"
  25. #include "networkstringtable_clientdll.h"
  26. #include "voice_status.h"
  27. #include "filesystem.h"
  28. #include "c_te_legacytempents.h"
  29. #include "c_rope.h"
  30. #include "engine/ishadowmgr.h"
  31. #include "engine/IStaticPropMgr.h"
  32. #include "hud_basechat.h"
  33. #include "hud_crosshair.h"
  34. #include "view_shared.h"
  35. #include "env_wind_shared.h"
  36. #include "detailobjectsystem.h"
  37. #include "clienteffectprecachesystem.h"
  38. #include "soundenvelope.h"
  39. #include "c_basetempentity.h"
  40. #include "materialsystem/imaterialsystemstub.h"
  41. #include "VGuiMatSurface/IMatSystemSurface.h"
  42. #include "materialsystem/imaterialsystemhardwareconfig.h"
  43. #include "c_soundscape.h"
  44. #include "engine/ivdebugoverlay.h"
  45. #include "vguicenterprint.h"
  46. #include "iviewrender_beams.h"
  47. #include "tier0/vprof.h"
  48. #include "engine/IEngineTrace.h"
  49. #include "engine/ivmodelinfo.h"
  50. #include "physics.h"
  51. #include "usermessages.h"
  52. #include "gamestringpool.h"
  53. #include "c_user_message_register.h"
  54. #include "IGameUIFuncs.h"
  55. #include "saverestoretypes.h"
  56. #include "saverestore.h"
  57. #include "physics_saverestore.h"
  58. #include "igameevents.h"
  59. #include "datacache/idatacache.h"
  60. #include "datacache/imdlcache.h"
  61. #include "kbutton.h"
  62. #include "tier0/icommandline.h"
  63. #include "gamerules_register.h"
  64. #include "vgui_controls/AnimationController.h"
  65. #include "bitmap/tgawriter.h"
  66. #include "c_world.h"
  67. #include "perfvisualbenchmark.h"
  68. #include "SoundEmitterSystem/isoundemittersystembase.h"
  69. #include "hud_closecaption.h"
  70. #include "colorcorrectionmgr.h"
  71. #include "physpropclientside.h"
  72. #include "panelmetaclassmgr.h"
  73. #include "c_vguiscreen.h"
  74. #include "imessagechars.h"
  75. #include "game/client/IGameClientExports.h"
  76. #include "client_factorylist.h"
  77. #include "ragdoll_shared.h"
  78. #include "rendertexture.h"
  79. #include "view_scene.h"
  80. #include "iclientmode.h"
  81. #include "con_nprint.h"
  82. #include "inputsystem/iinputsystem.h"
  83. #include "appframework/IAppSystemGroup.h"
  84. #include "scenefilecache/ISceneFileCache.h"
  85. #include "tier2/tier2dm.h"
  86. #include "tier3/tier3.h"
  87. #include "ihudlcd.h"
  88. #include "toolframework_client.h"
  89. #include "hltvcamera.h"
  90. #if defined( REPLAY_ENABLED )
  91. #include "replay/replaycamera.h"
  92. #include "replay/replay_ragdoll.h"
  93. #include "qlimits.h"
  94. #include "replay/replay.h"
  95. #include "replay/ireplaysystem.h"
  96. #include "replay/iclientreplay.h"
  97. #include "replay/ienginereplay.h"
  98. #include "replay/ireplaymanager.h"
  99. #include "replay/ireplayscreenshotmanager.h"
  100. #include "replay/iclientreplaycontext.h"
  101. #include "replay/vgui/replayconfirmquitdlg.h"
  102. #include "replay/vgui/replaybrowsermainpanel.h"
  103. #include "replay/vgui/replayinputpanel.h"
  104. #include "replay/vgui/replayperformanceeditor.h"
  105. #endif
  106. #include "vgui/ILocalize.h"
  107. #include "vgui/IVGui.h"
  108. #include "ixboxsystem.h"
  109. #include "ipresence.h"
  110. #include "engine/imatchmaking.h"
  111. #include "cdll_bounded_cvars.h"
  112. #include "matsys_controls/matsyscontrols.h"
  113. #include "gamestats.h"
  114. #include "particle_parse.h"
  115. #if defined( TF_CLIENT_DLL )
  116. #include "rtime.h"
  117. #include "tf_hud_disconnect_prompt.h"
  118. #include "../engine/audio/public/sound.h"
  119. #include "tf_shared_content_manager.h"
  120. #include "tf_gamerules.h"
  121. #endif
  122. #include "clientsteamcontext.h"
  123. #include "renamed_recvtable_compat.h"
  124. #include "mouthinfo.h"
  125. #include "sourcevr/isourcevirtualreality.h"
  126. #include "client_virtualreality.h"
  127. #include "mumble.h"
  128. #include "vgui_controls/BuildGroup.h"
  129. // NVNT includes
  130. #include "hud_macros.h"
  131. #include "haptics/ihaptics.h"
  132. #include "haptics/haptic_utils.h"
  133. #include "haptics/haptic_msgs.h"
  134. #if defined( TF_CLIENT_DLL )
  135. #include "abuse_report.h"
  136. #endif
  137. #ifdef USES_ECON_ITEMS
  138. #include "econ_item_system.h"
  139. #endif // USES_ECON_ITEMS
  140. #if defined( TF_CLIENT_DLL )
  141. #include "econ/tool_items/custom_texture_cache.h"
  142. #endif
  143. #ifdef WORKSHOP_IMPORT_ENABLED
  144. #include "fbxsystem/fbxsystem.h"
  145. #endif
  146. extern vgui::IInputInternal *g_InputInternal;
  147. //=============================================================================
  148. // HPE_BEGIN
  149. // [dwenger] Necessary for stats display
  150. //=============================================================================
  151. #include "achievements_and_stats_interface.h"
  152. //=============================================================================
  153. // HPE_END
  154. //=============================================================================
  155. #ifdef PORTAL
  156. #include "PortalRender.h"
  157. #endif
  158. #ifdef SIXENSE
  159. #include "sixense/in_sixense.h"
  160. #endif
  161. // memdbgon must be the last include file in a .cpp file!!!
  162. #include "tier0/memdbgon.h"
  163. extern IClientMode *GetClientModeNormal();
  164. // IF YOU ADD AN INTERFACE, EXTERN IT IN THE HEADER FILE.
  165. IVEngineClient *engine = NULL;
  166. IVModelRender *modelrender = NULL;
  167. IVEfx *effects = NULL;
  168. IVRenderView *render = NULL;
  169. IVDebugOverlay *debugoverlay = NULL;
  170. IMaterialSystemStub *materials_stub = NULL;
  171. IDataCache *datacache = NULL;
  172. IVModelInfoClient *modelinfo = NULL;
  173. IEngineVGui *enginevgui = NULL;
  174. INetworkStringTableContainer *networkstringtable = NULL;
  175. ISpatialPartition* partition = NULL;
  176. IFileSystem *filesystem = NULL;
  177. IShadowMgr *shadowmgr = NULL;
  178. IStaticPropMgrClient *staticpropmgr = NULL;
  179. IEngineSound *enginesound = NULL;
  180. IUniformRandomStream *random = NULL;
  181. static CGaussianRandomStream s_GaussianRandomStream;
  182. CGaussianRandomStream *randomgaussian = &s_GaussianRandomStream;
  183. ISharedGameRules *sharedgamerules = NULL;
  184. IEngineTrace *enginetrace = NULL;
  185. IGameUIFuncs *gameuifuncs = NULL;
  186. IGameEventManager2 *gameeventmanager = NULL;
  187. ISoundEmitterSystemBase *soundemitterbase = NULL;
  188. IInputSystem *inputsystem = NULL;
  189. ISceneFileCache *scenefilecache = NULL;
  190. IXboxSystem *xboxsystem = NULL; // Xbox 360 only
  191. IMatchmaking *matchmaking = NULL;
  192. IUploadGameStats *gamestatsuploader = NULL;
  193. IClientReplayContext *g_pClientReplayContext = NULL;
  194. #if defined( REPLAY_ENABLED )
  195. IReplayManager *g_pReplayManager = NULL;
  196. IReplayMovieManager *g_pReplayMovieManager = NULL;
  197. IReplayScreenshotManager *g_pReplayScreenshotManager = NULL;
  198. IReplayPerformanceManager *g_pReplayPerformanceManager = NULL;
  199. IReplayPerformanceController *g_pReplayPerformanceController = NULL;
  200. IEngineReplay *g_pEngineReplay = NULL;
  201. IEngineClientReplay *g_pEngineClientReplay = NULL;
  202. IReplaySystem *g_pReplay = NULL;
  203. #endif
  204. IHaptics* haptics = NULL;// NVNT haptics system interface singleton
  205. //=============================================================================
  206. // HPE_BEGIN
  207. // [dwenger] Necessary for stats display
  208. //=============================================================================
  209. AchievementsAndStatsInterface* g_pAchievementsAndStatsInterface = NULL;
  210. //=============================================================================
  211. // HPE_END
  212. //=============================================================================
  213. IGameSystem *SoundEmitterSystem();
  214. IGameSystem *ToolFrameworkClientSystem();
  215. // Engine player info, no game related infos here
  216. BEGIN_BYTESWAP_DATADESC( player_info_s )
  217. DEFINE_ARRAY( name, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ),
  218. DEFINE_FIELD( userID, FIELD_INTEGER ),
  219. DEFINE_ARRAY( guid, FIELD_CHARACTER, SIGNED_GUID_LEN + 1 ),
  220. DEFINE_FIELD( friendsID, FIELD_INTEGER ),
  221. DEFINE_ARRAY( friendsName, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ),
  222. DEFINE_FIELD( fakeplayer, FIELD_BOOLEAN ),
  223. DEFINE_FIELD( ishltv, FIELD_BOOLEAN ),
  224. #if defined( REPLAY_ENABLED )
  225. DEFINE_FIELD( isreplay, FIELD_BOOLEAN ),
  226. #endif
  227. DEFINE_ARRAY( customFiles, FIELD_INTEGER, MAX_CUSTOM_FILES ),
  228. DEFINE_FIELD( filesDownloaded, FIELD_INTEGER ),
  229. END_BYTESWAP_DATADESC()
  230. static bool g_bRequestCacheUsedMaterials = false;
  231. void RequestCacheUsedMaterials()
  232. {
  233. g_bRequestCacheUsedMaterials = true;
  234. }
  235. void ProcessCacheUsedMaterials()
  236. {
  237. if ( !g_bRequestCacheUsedMaterials )
  238. return;
  239. g_bRequestCacheUsedMaterials = false;
  240. if ( materials )
  241. {
  242. materials->CacheUsedMaterials();
  243. }
  244. }
  245. // String tables
  246. INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
  247. INetworkStringTable *g_StringTableEffectDispatch = NULL;
  248. INetworkStringTable *g_StringTableVguiScreen = NULL;
  249. INetworkStringTable *g_pStringTableMaterials = NULL;
  250. INetworkStringTable *g_pStringTableInfoPanel = NULL;
  251. INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL;
  252. INetworkStringTable *g_pStringTableServerMapCycle = NULL;
  253. #ifdef TF_CLIENT_DLL
  254. INetworkStringTable *g_pStringTableServerPopFiles = NULL;
  255. INetworkStringTable *g_pStringTableServerMapCycleMvM = NULL;
  256. #endif
  257. static CGlobalVarsBase dummyvars( true );
  258. // So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer.
  259. // Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine
  260. CGlobalVarsBase *gpGlobals = &dummyvars;
  261. class CHudChat;
  262. class CViewRender;
  263. extern CViewRender g_DefaultViewRender;
  264. extern void StopAllRumbleEffects( void );
  265. static C_BaseEntityClassList *s_pClassLists = NULL;
  266. C_BaseEntityClassList::C_BaseEntityClassList()
  267. {
  268. m_pNextClassList = s_pClassLists;
  269. s_pClassLists = this;
  270. }
  271. C_BaseEntityClassList::~C_BaseEntityClassList()
  272. {
  273. }
  274. // Any entities that want an OnDataChanged during simulation register for it here.
  275. class CDataChangedEvent
  276. {
  277. public:
  278. CDataChangedEvent() {}
  279. CDataChangedEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
  280. {
  281. m_pEntity = ent;
  282. m_UpdateType = updateType;
  283. m_pStoredEvent = pStoredEvent;
  284. }
  285. IClientNetworkable *m_pEntity;
  286. DataUpdateType_t m_UpdateType;
  287. int *m_pStoredEvent;
  288. };
  289. ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler();
  290. ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler();
  291. CUtlLinkedList<CDataChangedEvent, unsigned short> g_DataChangedEvents;
  292. ClientFrameStage_t g_CurFrameStage = FRAME_UNDEFINED;
  293. class IMoveHelper;
  294. void DispatchHudText( const char *pszName );
  295. static ConVar s_CV_ShowParticleCounts("showparticlecounts", "0", 0, "Display number of particles drawn per frame");
  296. static ConVar s_cl_team("cl_team", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default team when joining a game");
  297. static ConVar s_cl_class("cl_class", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default class when joining a game");
  298. #ifdef HL1MP_CLIENT_DLL
  299. static ConVar s_cl_load_hl1_content("cl_load_hl1_content", "0", FCVAR_ARCHIVE, "Mount the content from Half-Life: Source if possible");
  300. #endif
  301. // Physics system
  302. bool g_bLevelInitialized;
  303. bool g_bTextMode = false;
  304. class IClientPurchaseInterfaceV2 *g_pClientPurchaseInterface = (class IClientPurchaseInterfaceV2 *)(&g_bTextMode + 156);
  305. static ConVar *g_pcv_ThreadMode = NULL;
  306. //-----------------------------------------------------------------------------
  307. // Purpose: interface for gameui to modify voice bans
  308. //-----------------------------------------------------------------------------
  309. class CGameClientExports : public IGameClientExports
  310. {
  311. public:
  312. // ingame voice manipulation
  313. bool IsPlayerGameVoiceMuted(int playerIndex)
  314. {
  315. return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex);
  316. }
  317. void MutePlayerGameVoice(int playerIndex)
  318. {
  319. GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true);
  320. }
  321. void UnmutePlayerGameVoice(int playerIndex)
  322. {
  323. GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false);
  324. }
  325. void OnGameUIActivated( void )
  326. {
  327. IGameEvent *event = gameeventmanager->CreateEvent( "gameui_activated" );
  328. if ( event )
  329. {
  330. gameeventmanager->FireEventClientSide( event );
  331. }
  332. }
  333. void OnGameUIHidden( void )
  334. {
  335. IGameEvent *event = gameeventmanager->CreateEvent( "gameui_hidden" );
  336. if ( event )
  337. {
  338. gameeventmanager->FireEventClientSide( event );
  339. }
  340. }
  341. //=============================================================================
  342. // HPE_BEGIN
  343. // [dwenger] Necessary for stats display
  344. //=============================================================================
  345. void CreateAchievementsPanel( vgui::Panel* pParent )
  346. {
  347. if (g_pAchievementsAndStatsInterface)
  348. {
  349. g_pAchievementsAndStatsInterface->CreatePanel( pParent );
  350. }
  351. }
  352. void DisplayAchievementPanel()
  353. {
  354. if (g_pAchievementsAndStatsInterface)
  355. {
  356. g_pAchievementsAndStatsInterface->DisplayPanel();
  357. }
  358. }
  359. void ShutdownAchievementPanel()
  360. {
  361. if (g_pAchievementsAndStatsInterface)
  362. {
  363. g_pAchievementsAndStatsInterface->ReleasePanel();
  364. }
  365. }
  366. int GetAchievementsPanelMinWidth( void ) const
  367. {
  368. if ( g_pAchievementsAndStatsInterface )
  369. {
  370. return g_pAchievementsAndStatsInterface->GetAchievementsPanelMinWidth();
  371. }
  372. return 0;
  373. }
  374. //=============================================================================
  375. // HPE_END
  376. //=============================================================================
  377. const char *GetHolidayString()
  378. {
  379. return UTIL_GetActiveHolidayString();
  380. }
  381. };
  382. EXPOSE_SINGLE_INTERFACE( CGameClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION );
  383. class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems
  384. {
  385. public:
  386. CClientDLLSharedAppSystems()
  387. {
  388. AddAppSystem( "soundemittersystem" DLL_EXT_STRING, SOUNDEMITTERSYSTEM_INTERFACE_VERSION );
  389. AddAppSystem( "scenefilecache" DLL_EXT_STRING, SCENE_FILE_CACHE_INTERFACE_VERSION );
  390. }
  391. virtual int Count()
  392. {
  393. return m_Systems.Count();
  394. }
  395. virtual char const *GetDllName( int idx )
  396. {
  397. return m_Systems[ idx ].m_pModuleName;
  398. }
  399. virtual char const *GetInterfaceName( int idx )
  400. {
  401. return m_Systems[ idx ].m_pInterfaceName;
  402. }
  403. private:
  404. void AddAppSystem( char const *moduleName, char const *interfaceName )
  405. {
  406. AppSystemInfo_t sys;
  407. sys.m_pModuleName = moduleName;
  408. sys.m_pInterfaceName = interfaceName;
  409. m_Systems.AddToTail( sys );
  410. }
  411. CUtlVector< AppSystemInfo_t > m_Systems;
  412. };
  413. EXPOSE_SINGLE_INTERFACE( CClientDLLSharedAppSystems, IClientDLLSharedAppSystems, CLIENT_DLL_SHARED_APPSYSTEMS );
  414. //-----------------------------------------------------------------------------
  415. // Helper interface for voice.
  416. //-----------------------------------------------------------------------------
  417. class CHLVoiceStatusHelper : public IVoiceStatusHelper
  418. {
  419. public:
  420. virtual void GetPlayerTextColor(int entindex, int color[3])
  421. {
  422. color[0] = color[1] = color[2] = 128;
  423. }
  424. virtual void UpdateCursorState()
  425. {
  426. }
  427. virtual bool CanShowSpeakerLabels()
  428. {
  429. return true;
  430. }
  431. };
  432. static CHLVoiceStatusHelper g_VoiceStatusHelper;
  433. //-----------------------------------------------------------------------------
  434. // Code to display which entities are having their bones setup each frame.
  435. //-----------------------------------------------------------------------------
  436. ConVar cl_ShowBoneSetupEnts( "cl_ShowBoneSetupEnts", "0", 0, "Show which entities are having their bones setup each frame." );
  437. class CBoneSetupEnt
  438. {
  439. public:
  440. char m_ModelName[128];
  441. int m_Index;
  442. int m_Count;
  443. };
  444. bool BoneSetupCompare( const CBoneSetupEnt &a, const CBoneSetupEnt &b )
  445. {
  446. return a.m_Index < b.m_Index;
  447. }
  448. CUtlRBTree<CBoneSetupEnt> g_BoneSetupEnts( BoneSetupCompare );
  449. void TrackBoneSetupEnt( C_BaseAnimating *pEnt )
  450. {
  451. #ifdef _DEBUG
  452. if ( IsRetail() )
  453. return;
  454. if ( !cl_ShowBoneSetupEnts.GetInt() )
  455. return;
  456. CBoneSetupEnt ent;
  457. ent.m_Index = pEnt->entindex();
  458. unsigned short i = g_BoneSetupEnts.Find( ent );
  459. if ( i == g_BoneSetupEnts.InvalidIndex() )
  460. {
  461. Q_strncpy( ent.m_ModelName, modelinfo->GetModelName( pEnt->GetModel() ), sizeof( ent.m_ModelName ) );
  462. ent.m_Count = 1;
  463. g_BoneSetupEnts.Insert( ent );
  464. }
  465. else
  466. {
  467. g_BoneSetupEnts[i].m_Count++;
  468. }
  469. #endif
  470. }
  471. void DisplayBoneSetupEnts()
  472. {
  473. #ifdef _DEBUG
  474. if ( IsRetail() )
  475. return;
  476. if ( !cl_ShowBoneSetupEnts.GetInt() )
  477. return;
  478. unsigned short i;
  479. int nElements = 0;
  480. for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
  481. ++nElements;
  482. engine->Con_NPrintf( 0, "%d bone setup ents (name/count/entindex) ------------", nElements );
  483. con_nprint_s printInfo;
  484. printInfo.time_to_live = -1;
  485. printInfo.fixed_width_font = true;
  486. printInfo.color[0] = printInfo.color[1] = printInfo.color[2] = 1;
  487. printInfo.index = 2;
  488. for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
  489. {
  490. CBoneSetupEnt *pEnt = &g_BoneSetupEnts[i];
  491. if ( pEnt->m_Count >= 3 )
  492. {
  493. printInfo.color[0] = 1;
  494. printInfo.color[1] = 0;
  495. printInfo.color[2] = 0;
  496. }
  497. else if ( pEnt->m_Count == 2 )
  498. {
  499. printInfo.color[0] = (float)200 / 255;
  500. printInfo.color[1] = (float)220 / 255;
  501. printInfo.color[2] = 0;
  502. }
  503. else
  504. {
  505. printInfo.color[0] = 1;
  506. printInfo.color[1] = 1;
  507. printInfo.color[2] = 1;
  508. }
  509. engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index );
  510. printInfo.index++;
  511. }
  512. g_BoneSetupEnts.RemoveAll();
  513. #endif
  514. }
  515. //-----------------------------------------------------------------------------
  516. // Purpose: engine to client .dll interface
  517. //-----------------------------------------------------------------------------
  518. class CHLClient : public IBaseClientDLL
  519. {
  520. public:
  521. CHLClient();
  522. virtual int Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals );
  523. virtual void PostInit();
  524. virtual void Shutdown( void );
  525. virtual bool ReplayInit( CreateInterfaceFn fnReplayFactory );
  526. virtual bool ReplayPostInit();
  527. virtual void LevelInitPreEntity( const char *pMapName );
  528. virtual void LevelInitPostEntity();
  529. virtual void LevelShutdown( void );
  530. virtual ClientClass *GetAllClasses( void );
  531. virtual int HudVidInit( void );
  532. virtual void HudProcessInput( bool bActive );
  533. virtual void HudUpdate( bool bActive );
  534. virtual void HudReset( void );
  535. virtual void HudText( const char * message );
  536. // Mouse Input Interfaces
  537. virtual void IN_ActivateMouse( void );
  538. virtual void IN_DeactivateMouse( void );
  539. virtual void IN_Accumulate( void );
  540. virtual void IN_ClearStates( void );
  541. virtual bool IN_IsKeyDown( const char *name, bool& isdown );
  542. virtual void IN_OnMouseWheeled( int nDelta );
  543. // Raw signal
  544. virtual int IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding );
  545. virtual void IN_SetSampleTime( float frametime );
  546. // Create movement command
  547. virtual void CreateMove ( int sequence_number, float input_sample_frametime, bool active );
  548. virtual void ExtraMouseSample( float frametime, bool active );
  549. virtual bool WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand );
  550. virtual void EncodeUserCmdToBuffer( bf_write& buf, int slot );
  551. virtual void DecodeUserCmdFromBuffer( bf_read& buf, int slot );
  552. virtual void View_Render( vrect_t *rect );
  553. virtual void RenderView( const CViewSetup &view, int nClearFlags, int whatToDraw );
  554. virtual void View_Fade( ScreenFade_t *pSF );
  555. virtual void SetCrosshairAngle( const QAngle& angle );
  556. virtual void InitSprite( CEngineSprite *pSprite, const char *loadname );
  557. virtual void ShutdownSprite( CEngineSprite *pSprite );
  558. virtual int GetSpriteSize( void ) const;
  559. virtual void VoiceStatus( int entindex, qboolean bTalking );
  560. virtual void InstallStringTableCallback( const char *tableName );
  561. virtual void FrameStageNotify( ClientFrameStage_t curStage );
  562. virtual bool DispatchUserMessage( int msg_type, bf_read &msg_data );
  563. // Save/restore system hooks
  564. virtual CSaveRestoreData *SaveInit( int size );
  565. virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
  566. virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
  567. virtual void PreSave( CSaveRestoreData * );
  568. virtual void Save( CSaveRestoreData * );
  569. virtual void WriteSaveHeaders( CSaveRestoreData * );
  570. virtual void ReadRestoreHeaders( CSaveRestoreData * );
  571. virtual void Restore( CSaveRestoreData *, bool );
  572. virtual void DispatchOnRestore();
  573. virtual void WriteSaveGameScreenshot( const char *pFilename );
  574. // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
  575. // the appropriate close caption if running with closecaption = 1
  576. virtual void EmitSentenceCloseCaption( char const *tokenstream );
  577. virtual void EmitCloseCaption( char const *captionname, float duration );
  578. virtual CStandardRecvProxies* GetStandardRecvProxies();
  579. virtual bool CanRecordDemo( char *errorMsg, int length ) const;
  580. virtual void OnDemoRecordStart( char const* pDemoBaseName );
  581. virtual void OnDemoRecordStop();
  582. virtual void OnDemoPlaybackStart( char const* pDemoBaseName );
  583. virtual void OnDemoPlaybackStop();
  584. virtual bool ShouldDrawDropdownConsole();
  585. // Get client screen dimensions
  586. virtual int GetScreenWidth();
  587. virtual int GetScreenHeight();
  588. // save game screenshot writing
  589. virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, bool bWriteVTF/*=false*/ );
  590. // Gets the location of the player viewpoint
  591. virtual bool GetPlayerView( CViewSetup &playerView );
  592. // Matchmaking
  593. virtual void SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties );
  594. virtual uint GetPresenceID( const char *pIDName );
  595. virtual const char *GetPropertyIdString( const uint id );
  596. virtual void GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes );
  597. virtual void StartStatsReporting( HANDLE handle, bool bArbitrated );
  598. virtual void InvalidateMdlCache();
  599. virtual void ReloadFilesInList( IFileList *pFilesToReload );
  600. // Let the client handle UI toggle - if this function returns false, the UI will toggle, otherwise it will not.
  601. virtual bool HandleUiToggle();
  602. // Allow the console to be shown?
  603. virtual bool ShouldAllowConsole();
  604. // Get renamed recv tables
  605. virtual CRenamedRecvTableInfo *GetRenamedRecvTableInfos();
  606. // Get the mouthinfo for the sound being played inside UI panels
  607. virtual CMouthInfo *GetClientUIMouthInfo();
  608. // Notify the client that a file has been received from the game server
  609. virtual void FileReceived( const char * fileName, unsigned int transferID );
  610. virtual const char* TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName );
  611. virtual void ClientAdjustStartSoundParams( struct StartSoundParams_t& params );
  612. // Returns true if the disconnect command has been handled by the client
  613. virtual bool DisconnectAttempt( void );
  614. public:
  615. void PrecacheMaterial( const char *pMaterialName );
  616. virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar );
  617. private:
  618. void UncacheAllMaterials( );
  619. void ResetStringTablePointers();
  620. CUtlVector< IMaterial * > m_CachedMaterials;
  621. };
  622. CHLClient gHLClient;
  623. IBaseClientDLL *clientdll = &gHLClient;
  624. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLClient, IBaseClientDLL, CLIENT_DLL_INTERFACE_VERSION, gHLClient );
  625. //-----------------------------------------------------------------------------
  626. // Precaches a material
  627. //-----------------------------------------------------------------------------
  628. void PrecacheMaterial( const char *pMaterialName )
  629. {
  630. gHLClient.PrecacheMaterial( pMaterialName );
  631. }
  632. //-----------------------------------------------------------------------------
  633. // Converts a previously precached material into an index
  634. //-----------------------------------------------------------------------------
  635. int GetMaterialIndex( const char *pMaterialName )
  636. {
  637. if (pMaterialName)
  638. {
  639. int nIndex = g_pStringTableMaterials->FindStringIndex( pMaterialName );
  640. Assert( nIndex >= 0 );
  641. if (nIndex >= 0)
  642. return nIndex;
  643. }
  644. // This is the invalid string index
  645. return 0;
  646. }
  647. //-----------------------------------------------------------------------------
  648. // Converts precached material indices into strings
  649. //-----------------------------------------------------------------------------
  650. const char *GetMaterialNameFromIndex( int nIndex )
  651. {
  652. if (nIndex != (g_pStringTableMaterials->GetMaxStrings() - 1))
  653. {
  654. return g_pStringTableMaterials->GetString( nIndex );
  655. }
  656. else
  657. {
  658. return NULL;
  659. }
  660. }
  661. //-----------------------------------------------------------------------------
  662. // Precaches a particle system
  663. //-----------------------------------------------------------------------------
  664. void PrecacheParticleSystem( const char *pParticleSystemName )
  665. {
  666. g_pStringTableParticleEffectNames->AddString( false, pParticleSystemName );
  667. g_pParticleSystemMgr->PrecacheParticleSystem( pParticleSystemName );
  668. }
  669. //-----------------------------------------------------------------------------
  670. // Converts a previously precached particle system into an index
  671. //-----------------------------------------------------------------------------
  672. int GetParticleSystemIndex( const char *pParticleSystemName )
  673. {
  674. if ( pParticleSystemName )
  675. {
  676. int nIndex = g_pStringTableParticleEffectNames->FindStringIndex( pParticleSystemName );
  677. if ( nIndex != INVALID_STRING_INDEX )
  678. return nIndex;
  679. DevWarning("Client: Missing precache for particle system \"%s\"!\n", pParticleSystemName );
  680. }
  681. // This is the invalid string index
  682. return 0;
  683. }
  684. //-----------------------------------------------------------------------------
  685. // Converts precached particle system indices into strings
  686. //-----------------------------------------------------------------------------
  687. const char *GetParticleSystemNameFromIndex( int nIndex )
  688. {
  689. if ( nIndex < g_pStringTableParticleEffectNames->GetMaxStrings() )
  690. return g_pStringTableParticleEffectNames->GetString( nIndex );
  691. return "error";
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode)
  695. //-----------------------------------------------------------------------------
  696. bool IsEngineThreaded()
  697. {
  698. if ( g_pcv_ThreadMode )
  699. {
  700. return g_pcv_ThreadMode->GetBool();
  701. }
  702. return false;
  703. }
  704. //-----------------------------------------------------------------------------
  705. // Constructor
  706. //-----------------------------------------------------------------------------
  707. CHLClient::CHLClient()
  708. {
  709. // Kinda bogus, but the logic in the engine is too convoluted to put it there
  710. g_bLevelInitialized = false;
  711. }
  712. extern IGameSystem *ViewportClientSystem();
  713. //-----------------------------------------------------------------------------
  714. ISourceVirtualReality *g_pSourceVR = NULL;
  715. // Purpose: Called when the DLL is first loaded.
  716. // Input : engineFactory -
  717. // Output : int
  718. //-----------------------------------------------------------------------------
  719. int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals )
  720. {
  721. InitCRTMemDebug();
  722. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
  723. #ifdef SIXENSE
  724. g_pSixenseInput = new SixenseInput;
  725. #endif
  726. // Hook up global variables
  727. gpGlobals = pGlobals;
  728. ConnectTier1Libraries( &appSystemFactory, 1 );
  729. ConnectTier2Libraries( &appSystemFactory, 1 );
  730. ConnectTier3Libraries( &appSystemFactory, 1 );
  731. #ifndef NO_STEAM
  732. ClientSteamContext().Activate();
  733. #endif
  734. // We aren't happy unless we get all of our interfaces.
  735. // please don't collapse this into one monolithic boolean expression (impossible to debug)
  736. if ( (engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
  737. return false;
  738. if ( (modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) == NULL )
  739. return false;
  740. if ( (effects = (IVEfx *)appSystemFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL )) == NULL )
  741. return false;
  742. if ( (enginetrace = (IEngineTrace *)appSystemFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL )) == NULL )
  743. return false;
  744. if ( (render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) == NULL )
  745. return false;
  746. if ( (debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL )) == NULL )
  747. return false;
  748. if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL )
  749. return false;
  750. if ( !mdlcache )
  751. return false;
  752. if ( (modelinfo = (IVModelInfoClient *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
  753. return false;
  754. if ( (enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) == NULL )
  755. return false;
  756. if ( (networkstringtable = (INetworkStringTableContainer *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLECLIENT,NULL)) == NULL )
  757. return false;
  758. if ( (::partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) == NULL )
  759. return false;
  760. if ( (shadowmgr = (IShadowMgr *)appSystemFactory(ENGINE_SHADOWMGR_INTERFACE_VERSION, NULL)) == NULL )
  761. return false;
  762. if ( (staticpropmgr = (IStaticPropMgrClient *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_CLIENT, NULL)) == NULL )
  763. return false;
  764. if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) == NULL )
  765. return false;
  766. if ( (filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  767. return false;
  768. if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) == NULL )
  769. return false;
  770. if ( (gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) == NULL )
  771. return false;
  772. if ( (gameeventmanager = (IGameEventManager2 *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2,NULL)) == NULL )
  773. return false;
  774. if ( (soundemitterbase = (ISoundEmitterSystemBase *)appSystemFactory(SOUNDEMITTERSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  775. return false;
  776. if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
  777. return false;
  778. if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL )
  779. return false;
  780. if ( IsX360() && (xboxsystem = (IXboxSystem *)appSystemFactory( XBOXSYSTEM_INTERFACE_VERSION, NULL )) == NULL )
  781. return false;
  782. if ( IsX360() && (matchmaking = (IMatchmaking *)appSystemFactory( VENGINE_MATCHMAKING_VERSION, NULL )) == NULL )
  783. return false;
  784. #ifndef _XBOX
  785. if ( ( gamestatsuploader = (IUploadGameStats *)appSystemFactory( INTERFACEVERSION_UPLOADGAMESTATS, NULL )) == NULL )
  786. return false;
  787. #endif
  788. #if defined( REPLAY_ENABLED )
  789. if ( IsPC() && (g_pEngineReplay = (IEngineReplay *)appSystemFactory( ENGINE_REPLAY_INTERFACE_VERSION, NULL )) == NULL )
  790. return false;
  791. if ( IsPC() && (g_pEngineClientReplay = (IEngineClientReplay *)appSystemFactory( ENGINE_REPLAY_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
  792. return false;
  793. #endif
  794. if (!g_pMatSystemSurface)
  795. return false;
  796. #ifdef WORKSHOP_IMPORT_ENABLED
  797. if ( !ConnectDataModel( appSystemFactory ) )
  798. return false;
  799. if ( InitDataModel() != INIT_OK )
  800. return false;
  801. InitFbx();
  802. #endif
  803. // it's ok if this is NULL. That just means the sourcevr.dll wasn't found
  804. if ( CommandLine()->CheckParm( "-vr" ) )
  805. g_pSourceVR = (ISourceVirtualReality *)appSystemFactory(SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION, NULL);
  806. factorylist_t factories;
  807. factories.appSystemFactory = appSystemFactory;
  808. factories.physicsFactory = physicsFactory;
  809. FactoryList_Store( factories );
  810. // Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully
  811. if ( !soundemitterbase->Connect( appSystemFactory ) )
  812. {
  813. return false;
  814. }
  815. if ( CommandLine()->FindParm( "-textmode" ) )
  816. g_bTextMode = true;
  817. if ( CommandLine()->FindParm( "-makedevshots" ) )
  818. g_MakingDevShots = true;
  819. // Not fatal if the material system stub isn't around.
  820. materials_stub = (IMaterialSystemStub*)appSystemFactory( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION, NULL );
  821. if( !g_pMaterialSystemHardwareConfig )
  822. return false;
  823. // Hook up the gaussian random number generator
  824. s_GaussianRandomStream.AttachToStream( random );
  825. // Initialize the console variables.
  826. ConVar_Register( FCVAR_CLIENTDLL );
  827. g_pcv_ThreadMode = g_pCVar->FindVar( "host_thread_mode" );
  828. if (!Initializer::InitializeAllObjects())
  829. return false;
  830. if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials))
  831. return false;
  832. if (!VGui_Startup( appSystemFactory ))
  833. return false;
  834. vgui::VGui_InitMatSysInterfacesList( "ClientDLL", &appSystemFactory, 1 );
  835. // Add the client systems.
  836. // Client Leaf System has to be initialized first, since DetailObjectSystem uses it
  837. IGameSystem::Add( GameStringSystem() );
  838. IGameSystem::Add( SoundEmitterSystem() );
  839. IGameSystem::Add( ToolFrameworkClientSystem() );
  840. IGameSystem::Add( ClientLeafSystem() );
  841. IGameSystem::Add( DetailObjectSystem() );
  842. IGameSystem::Add( ViewportClientSystem() );
  843. IGameSystem::Add( ClientEffectPrecacheSystem() );
  844. IGameSystem::Add( g_pClientShadowMgr );
  845. IGameSystem::Add( g_pColorCorrectionMgr ); // NOTE: This must happen prior to ClientThinkList (color correction is updated there)
  846. IGameSystem::Add( ClientThinkList() );
  847. IGameSystem::Add( ClientSoundscapeSystem() );
  848. IGameSystem::Add( PerfVisualBenchmark() );
  849. IGameSystem::Add( MumbleSystem() );
  850. #if defined( TF_CLIENT_DLL )
  851. IGameSystem::Add( CustomTextureToolCacheGameSystem() );
  852. IGameSystem::Add( TFSharedContentManager() );
  853. #endif
  854. #if defined( TF_CLIENT_DLL )
  855. if ( g_AbuseReportMgr != NULL )
  856. {
  857. IGameSystem::Add( g_AbuseReportMgr );
  858. }
  859. #endif
  860. #if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST )
  861. IGameSystem::Add( GetPredictionCopyTester() );
  862. #endif
  863. modemanager->Init( );
  864. g_pClientMode->InitViewport();
  865. gHUD.Init();
  866. g_pClientMode->Init();
  867. if ( !IGameSystem::InitAllSystems() )
  868. return false;
  869. g_pClientMode->Enable();
  870. if ( !view )
  871. {
  872. view = ( IViewRender * )&g_DefaultViewRender;
  873. }
  874. view->Init();
  875. vieweffects->Init();
  876. C_BaseTempEntity::PrecacheTempEnts();
  877. input->Init_All();
  878. VGui_CreateGlobalPanels();
  879. InitSmokeFogOverlay();
  880. // Register user messages..
  881. CUserMessageRegister::RegisterAll();
  882. ClientVoiceMgr_Init();
  883. // Embed voice status icons inside chat element
  884. {
  885. vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL );
  886. GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent );
  887. }
  888. if ( !PhysicsDLLInit( physicsFactory ) )
  889. return false;
  890. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() );
  891. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );
  892. g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() );
  893. ClientWorldFactoryInit();
  894. C_BaseAnimating::InitBoneSetupThreadPool();
  895. #if defined( WIN32 ) && !defined( _X360 )
  896. // NVNT connect haptics sytem
  897. ConnectHaptics(appSystemFactory);
  898. #endif
  899. #ifndef _X360
  900. HookHapticMessages(); // Always hook the messages
  901. #endif
  902. return true;
  903. }
  904. bool CHLClient::ReplayInit( CreateInterfaceFn fnReplayFactory )
  905. {
  906. #if defined( REPLAY_ENABLED )
  907. if ( !IsPC() )
  908. return false;
  909. if ( (g_pReplay = (IReplaySystem *)fnReplayFactory( REPLAY_INTERFACE_VERSION, NULL ) ) == NULL )
  910. return false;
  911. if ( (g_pClientReplayContext = g_pReplay->CL_GetContext()) == NULL )
  912. return false;
  913. return true;
  914. #else
  915. return false;
  916. #endif
  917. }
  918. bool CHLClient::ReplayPostInit()
  919. {
  920. #if defined( REPLAY_ENABLED )
  921. if ( ( g_pReplayManager = g_pClientReplayContext->GetReplayManager() ) == NULL )
  922. return false;
  923. if ( ( g_pReplayScreenshotManager = g_pClientReplayContext->GetScreenshotManager() ) == NULL )
  924. return false;
  925. if ( ( g_pReplayPerformanceManager = g_pClientReplayContext->GetPerformanceManager() ) == NULL )
  926. return false;
  927. if ( ( g_pReplayPerformanceController = g_pClientReplayContext->GetPerformanceController() ) == NULL )
  928. return false;
  929. if ( ( g_pReplayMovieManager = g_pClientReplayContext->GetMovieManager() ) == NULL )
  930. return false;
  931. return true;
  932. #else
  933. return false;
  934. #endif
  935. }
  936. //-----------------------------------------------------------------------------
  937. // Purpose: Called after client & server DLL are loaded and all systems initialized
  938. //-----------------------------------------------------------------------------
  939. void CHLClient::PostInit()
  940. {
  941. IGameSystem::PostInitAllSystems();
  942. #ifdef SIXENSE
  943. // allow sixnese input to perform post-init operations
  944. g_pSixenseInput->PostInit();
  945. #endif
  946. g_ClientVirtualReality.StartupComplete();
  947. #ifdef HL1MP_CLIENT_DLL
  948. if ( s_cl_load_hl1_content.GetBool() && steamapicontext && steamapicontext->SteamApps() )
  949. {
  950. char szPath[ MAX_PATH*2 ];
  951. int ccFolder= steamapicontext->SteamApps()->GetAppInstallDir( 280, szPath, sizeof(szPath) );
  952. if ( ccFolder > 0 )
  953. {
  954. V_AppendSlash( szPath, sizeof(szPath) );
  955. V_strncat( szPath, "hl1", sizeof( szPath ) );
  956. g_pFullFileSystem->AddSearchPath( szPath, "HL1" );
  957. g_pFullFileSystem->AddSearchPath( szPath, "GAME" );
  958. }
  959. }
  960. #endif
  961. }
  962. //-----------------------------------------------------------------------------
  963. // Purpose: Called when the client .dll is being dismissed
  964. //-----------------------------------------------------------------------------
  965. void CHLClient::Shutdown( void )
  966. {
  967. if (g_pAchievementsAndStatsInterface)
  968. {
  969. g_pAchievementsAndStatsInterface->ReleasePanel();
  970. }
  971. #ifdef SIXENSE
  972. g_pSixenseInput->Shutdown();
  973. delete g_pSixenseInput;
  974. g_pSixenseInput = NULL;
  975. #endif
  976. C_BaseAnimating::ShutdownBoneSetupThreadPool();
  977. ClientWorldFactoryShutdown();
  978. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() );
  979. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() );
  980. g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() );
  981. ClientVoiceMgr_Shutdown();
  982. Initializer::FreeAllObjects();
  983. g_pClientMode->Disable();
  984. g_pClientMode->Shutdown();
  985. input->Shutdown_All();
  986. C_BaseTempEntity::ClearDynamicTempEnts();
  987. TermSmokeFogOverlay();
  988. view->Shutdown();
  989. g_pParticleSystemMgr->UncacheAllParticleSystems();
  990. UncacheAllMaterials();
  991. IGameSystem::ShutdownAllSystems();
  992. gHUD.Shutdown();
  993. VGui_Shutdown();
  994. ParticleMgr()->Term();
  995. vgui::BuildGroup::ClearResFileCache();
  996. #ifndef NO_STEAM
  997. ClientSteamContext().Shutdown();
  998. #endif
  999. #ifdef WORKSHOP_IMPORT_ENABLED
  1000. ShutdownDataModel();
  1001. DisconnectDataModel();
  1002. ShutdownFbx();
  1003. #endif
  1004. // This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
  1005. // DisconnectTier3Libraries( );
  1006. DisconnectTier2Libraries( );
  1007. ConVar_Unregister();
  1008. DisconnectTier1Libraries( );
  1009. gameeventmanager = NULL;
  1010. #if defined( WIN32 ) && !defined( _X360 )
  1011. // NVNT Disconnect haptics system
  1012. DisconnectHaptics();
  1013. #endif
  1014. }
  1015. //-----------------------------------------------------------------------------
  1016. // Purpose:
  1017. // Called when the game initializes
  1018. // and whenever the vid_mode is changed
  1019. // so the HUD can reinitialize itself.
  1020. // Output : int
  1021. //-----------------------------------------------------------------------------
  1022. int CHLClient::HudVidInit( void )
  1023. {
  1024. gHUD.VidInit();
  1025. GetClientVoiceMgr()->VidInit();
  1026. return 1;
  1027. }
  1028. //-----------------------------------------------------------------------------
  1029. // Method used to allow the client to filter input messages before the
  1030. // move record is transmitted to the server
  1031. //-----------------------------------------------------------------------------
  1032. void CHLClient::HudProcessInput( bool bActive )
  1033. {
  1034. g_pClientMode->ProcessInput( bActive );
  1035. }
  1036. //-----------------------------------------------------------------------------
  1037. // Purpose: Called when shared data gets changed, allows dll to modify data
  1038. // Input : bActive -
  1039. //-----------------------------------------------------------------------------
  1040. void CHLClient::HudUpdate( bool bActive )
  1041. {
  1042. float frametime = gpGlobals->frametime;
  1043. #if defined( TF_CLIENT_DLL )
  1044. CRTime::UpdateRealTime();
  1045. #endif
  1046. GetClientVoiceMgr()->Frame( frametime );
  1047. gHUD.UpdateHud( bActive );
  1048. {
  1049. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1050. IGameSystem::UpdateAllSystems( frametime );
  1051. }
  1052. // run vgui animations
  1053. vgui::GetAnimationController()->UpdateAnimations( engine->Time() );
  1054. hudlcd->SetGlobalStat( "(time_int)", VarArgs( "%d", (int)gpGlobals->curtime ) );
  1055. hudlcd->SetGlobalStat( "(time_float)", VarArgs( "%.2f", gpGlobals->curtime ) );
  1056. // I don't think this is necessary any longer, but I will leave it until
  1057. // I can check into this further.
  1058. C_BaseTempEntity::CheckDynamicTempEnts();
  1059. #ifdef SIXENSE
  1060. // If we're not connected, update sixense so we can move the mouse cursor when in the menus
  1061. if( !engine->IsConnected() || engine->IsPaused() )
  1062. {
  1063. g_pSixenseInput->SixenseFrame( 0, NULL );
  1064. }
  1065. #endif
  1066. }
  1067. //-----------------------------------------------------------------------------
  1068. // Purpose: Called to restore to "non"HUD state.
  1069. //-----------------------------------------------------------------------------
  1070. void CHLClient::HudReset( void )
  1071. {
  1072. gHUD.VidInit();
  1073. PhysicsReset();
  1074. }
  1075. //-----------------------------------------------------------------------------
  1076. // Purpose: Called to add hud text message
  1077. //-----------------------------------------------------------------------------
  1078. void CHLClient::HudText( const char * message )
  1079. {
  1080. DispatchHudText( message );
  1081. }
  1082. //-----------------------------------------------------------------------------
  1083. // Purpose:
  1084. //-----------------------------------------------------------------------------
  1085. bool CHLClient::ShouldDrawDropdownConsole()
  1086. {
  1087. #if defined( REPLAY_ENABLED )
  1088. extern ConVar hud_freezecamhide;
  1089. extern bool IsTakingAFreezecamScreenshot();
  1090. if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() )
  1091. {
  1092. return false;
  1093. }
  1094. #endif
  1095. return true;
  1096. }
  1097. //-----------------------------------------------------------------------------
  1098. // Purpose:
  1099. // Output : ClientClass
  1100. //-----------------------------------------------------------------------------
  1101. ClientClass *CHLClient::GetAllClasses( void )
  1102. {
  1103. return g_pClientClassHead;
  1104. }
  1105. //-----------------------------------------------------------------------------
  1106. // Purpose:
  1107. //-----------------------------------------------------------------------------
  1108. void CHLClient::IN_ActivateMouse( void )
  1109. {
  1110. input->ActivateMouse();
  1111. }
  1112. //-----------------------------------------------------------------------------
  1113. // Purpose:
  1114. //-----------------------------------------------------------------------------
  1115. void CHLClient::IN_DeactivateMouse( void )
  1116. {
  1117. input->DeactivateMouse();
  1118. }
  1119. //-----------------------------------------------------------------------------
  1120. // Purpose:
  1121. //-----------------------------------------------------------------------------
  1122. void CHLClient::IN_Accumulate ( void )
  1123. {
  1124. input->AccumulateMouse();
  1125. }
  1126. //-----------------------------------------------------------------------------
  1127. // Purpose:
  1128. //-----------------------------------------------------------------------------
  1129. void CHLClient::IN_ClearStates ( void )
  1130. {
  1131. input->ClearStates();
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Purpose: Engine can query for particular keys
  1135. // Input : *name -
  1136. //-----------------------------------------------------------------------------
  1137. bool CHLClient::IN_IsKeyDown( const char *name, bool& isdown )
  1138. {
  1139. kbutton_t *key = input->FindKey( name );
  1140. if ( !key )
  1141. {
  1142. return false;
  1143. }
  1144. isdown = ( key->state & 1 ) ? true : false;
  1145. // Found the key by name
  1146. return true;
  1147. }
  1148. //-----------------------------------------------------------------------------
  1149. // Purpose: Engine can issue a key event
  1150. // Input : eventcode -
  1151. // keynum -
  1152. // *pszCurrentBinding -
  1153. void CHLClient::IN_OnMouseWheeled( int nDelta )
  1154. {
  1155. #if defined( REPLAY_ENABLED )
  1156. CReplayPerformanceEditorPanel *pPerfEditor = ReplayUI_GetPerformanceEditor();
  1157. if ( pPerfEditor )
  1158. {
  1159. pPerfEditor->OnInGameMouseWheelEvent( nDelta );
  1160. }
  1161. #endif
  1162. }
  1163. //-----------------------------------------------------------------------------
  1164. // Purpose: Engine can issue a key event
  1165. // Input : eventcode -
  1166. // keynum -
  1167. // *pszCurrentBinding -
  1168. // Output : int
  1169. //-----------------------------------------------------------------------------
  1170. int CHLClient::IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding )
  1171. {
  1172. return input->KeyEvent( eventcode, keynum, pszCurrentBinding );
  1173. }
  1174. void CHLClient::ExtraMouseSample( float frametime, bool active )
  1175. {
  1176. Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
  1177. Assert( C_BaseEntity::IsAbsQueriesValid() );
  1178. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1179. MDLCACHE_CRITICAL_SECTION();
  1180. input->ExtraMouseSample( frametime, active );
  1181. }
  1182. void CHLClient::IN_SetSampleTime( float frametime )
  1183. {
  1184. input->Joystick_SetSampleTime( frametime );
  1185. input->IN_SetSampleTime( frametime );
  1186. #ifdef SIXENSE
  1187. g_pSixenseInput->ResetFrameTime( frametime );
  1188. #endif
  1189. }
  1190. //-----------------------------------------------------------------------------
  1191. // Purpose: Fills in usercmd_s structure based on current view angles and key/controller inputs
  1192. // Input : frametime - timestamp for last frame
  1193. // *cmd - the command to fill in
  1194. // active - whether the user is fully connected to a server
  1195. //-----------------------------------------------------------------------------
  1196. void CHLClient::CreateMove ( int sequence_number, float input_sample_frametime, bool active )
  1197. {
  1198. Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
  1199. Assert( C_BaseEntity::IsAbsQueriesValid() );
  1200. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
  1201. MDLCACHE_CRITICAL_SECTION();
  1202. input->CreateMove( sequence_number, input_sample_frametime, active );
  1203. }
  1204. //-----------------------------------------------------------------------------
  1205. // Purpose:
  1206. // Input : *buf -
  1207. // from -
  1208. // to -
  1209. //-----------------------------------------------------------------------------
  1210. bool CHLClient::WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand )
  1211. {
  1212. return input->WriteUsercmdDeltaToBuffer( buf, from, to, isnewcommand );
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. // Purpose:
  1216. // Input : buf -
  1217. // buffersize -
  1218. // slot -
  1219. //-----------------------------------------------------------------------------
  1220. void CHLClient::EncodeUserCmdToBuffer( bf_write& buf, int slot )
  1221. {
  1222. input->EncodeUserCmdToBuffer( buf, slot );
  1223. }
  1224. //-----------------------------------------------------------------------------
  1225. // Purpose:
  1226. // Input : buf -
  1227. // buffersize -
  1228. // slot -
  1229. //-----------------------------------------------------------------------------
  1230. void CHLClient::DecodeUserCmdFromBuffer( bf_read& buf, int slot )
  1231. {
  1232. input->DecodeUserCmdFromBuffer( buf, slot );
  1233. }
  1234. //-----------------------------------------------------------------------------
  1235. // Purpose:
  1236. //-----------------------------------------------------------------------------
  1237. void CHLClient::View_Render( vrect_t *rect )
  1238. {
  1239. VPROF( "View_Render" );
  1240. // UNDONE: This gets hit at startup sometimes, investigate - will cause NaNs in calcs inside Render()
  1241. if ( rect->width == 0 || rect->height == 0 )
  1242. return;
  1243. view->Render( rect );
  1244. UpdatePerfStats();
  1245. }
  1246. //-----------------------------------------------------------------------------
  1247. // Gets the location of the player viewpoint
  1248. //-----------------------------------------------------------------------------
  1249. bool CHLClient::GetPlayerView( CViewSetup &playerView )
  1250. {
  1251. playerView = *view->GetPlayerViewSetup();
  1252. return true;
  1253. }
  1254. //-----------------------------------------------------------------------------
  1255. // Matchmaking
  1256. //-----------------------------------------------------------------------------
  1257. void CHLClient::SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties )
  1258. {
  1259. presence->SetupGameProperties( contexts, properties );
  1260. }
  1261. uint CHLClient::GetPresenceID( const char *pIDName )
  1262. {
  1263. return presence->GetPresenceID( pIDName );
  1264. }
  1265. const char *CHLClient::GetPropertyIdString( const uint id )
  1266. {
  1267. return presence->GetPropertyIdString( id );
  1268. }
  1269. void CHLClient::GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes )
  1270. {
  1271. presence->GetPropertyDisplayString( id, value, pOutput, nBytes );
  1272. }
  1273. void CHLClient::StartStatsReporting( HANDLE handle, bool bArbitrated )
  1274. {
  1275. presence->StartStatsReporting( handle, bArbitrated );
  1276. }
  1277. //-----------------------------------------------------------------------------
  1278. //
  1279. //-----------------------------------------------------------------------------
  1280. void CHLClient::InvalidateMdlCache()
  1281. {
  1282. C_BaseAnimating *pAnimating;
  1283. for ( C_BaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity(pEntity) )
  1284. {
  1285. pAnimating = dynamic_cast<C_BaseAnimating *>(pEntity);
  1286. if ( pAnimating )
  1287. {
  1288. pAnimating->InvalidateMdlCache();
  1289. }
  1290. }
  1291. }
  1292. //-----------------------------------------------------------------------------
  1293. // Purpose:
  1294. // Input : *pSF -
  1295. //-----------------------------------------------------------------------------
  1296. void CHLClient::View_Fade( ScreenFade_t *pSF )
  1297. {
  1298. if ( pSF != NULL )
  1299. vieweffects->Fade( *pSF );
  1300. }
  1301. //-----------------------------------------------------------------------------
  1302. // Purpose: Per level init
  1303. //-----------------------------------------------------------------------------
  1304. void CHLClient::LevelInitPreEntity( char const* pMapName )
  1305. {
  1306. // HACK: Bogus, but the logic is too complicated in the engine
  1307. if (g_bLevelInitialized)
  1308. return;
  1309. g_bLevelInitialized = true;
  1310. input->LevelInit();
  1311. vieweffects->LevelInit();
  1312. //Tony; loadup per-map manifests.
  1313. ParseParticleEffectsMap( pMapName, true );
  1314. // Tell mode manager that map is changing
  1315. modemanager->LevelInit( pMapName );
  1316. ParticleMgr()->LevelInit();
  1317. hudlcd->SetGlobalStat( "(mapname)", pMapName );
  1318. C_BaseTempEntity::ClearDynamicTempEnts();
  1319. clienteffects->Flush();
  1320. view->LevelInit();
  1321. tempents->LevelInit();
  1322. ResetToneMapping(1.0);
  1323. IGameSystem::LevelInitPreEntityAllSystems(pMapName);
  1324. #ifdef USES_ECON_ITEMS
  1325. GameItemSchema_t *pItemSchema = ItemSystem()->GetItemSchema();
  1326. if ( pItemSchema )
  1327. {
  1328. pItemSchema->BInitFromDelayedBuffer();
  1329. }
  1330. #endif // USES_ECON_ITEMS
  1331. ResetWindspeed();
  1332. #if !defined( NO_ENTITY_PREDICTION )
  1333. // don't do prediction if single player!
  1334. // don't set direct because of FCVAR_USERINFO
  1335. if ( gpGlobals->maxClients > 1 )
  1336. {
  1337. if ( !cl_predict->GetInt() )
  1338. {
  1339. engine->ClientCmd( "cl_predict 1" );
  1340. }
  1341. }
  1342. else
  1343. {
  1344. if ( cl_predict->GetInt() )
  1345. {
  1346. engine->ClientCmd( "cl_predict 0" );
  1347. }
  1348. }
  1349. #endif
  1350. // Check low violence settings for this map
  1351. g_RagdollLVManager.SetLowViolence( pMapName );
  1352. gHUD.LevelInit();
  1353. #if defined( REPLAY_ENABLED )
  1354. // Initialize replay ragdoll recorder
  1355. if ( !engine->IsPlayingDemo() )
  1356. {
  1357. CReplayRagdollRecorder::Instance().Init();
  1358. }
  1359. #endif
  1360. }
  1361. //-----------------------------------------------------------------------------
  1362. // Purpose: Per level init
  1363. //-----------------------------------------------------------------------------
  1364. void CHLClient::LevelInitPostEntity( )
  1365. {
  1366. IGameSystem::LevelInitPostEntityAllSystems();
  1367. C_PhysPropClientside::RecreateAll();
  1368. internalCenterPrint->Clear();
  1369. }
  1370. //-----------------------------------------------------------------------------
  1371. // Purpose: Reset our global string table pointers
  1372. //-----------------------------------------------------------------------------
  1373. void CHLClient::ResetStringTablePointers()
  1374. {
  1375. g_pStringTableParticleEffectNames = NULL;
  1376. g_StringTableEffectDispatch = NULL;
  1377. g_StringTableVguiScreen = NULL;
  1378. g_pStringTableMaterials = NULL;
  1379. g_pStringTableInfoPanel = NULL;
  1380. g_pStringTableClientSideChoreoScenes = NULL;
  1381. g_pStringTableServerMapCycle = NULL;
  1382. #ifdef TF_CLIENT_DLL
  1383. g_pStringTableServerPopFiles = NULL;
  1384. g_pStringTableServerMapCycleMvM = NULL;
  1385. #endif
  1386. }
  1387. //-----------------------------------------------------------------------------
  1388. // Purpose: Per level de-init
  1389. //-----------------------------------------------------------------------------
  1390. void CHLClient::LevelShutdown( void )
  1391. {
  1392. // HACK: Bogus, but the logic is too complicated in the engine
  1393. if (!g_bLevelInitialized)
  1394. return;
  1395. g_bLevelInitialized = false;
  1396. // Disable abs recomputations when everything is shutting down
  1397. CBaseEntity::EnableAbsRecomputations( false );
  1398. // Level shutdown sequence.
  1399. // First do the pre-entity shutdown of all systems
  1400. IGameSystem::LevelShutdownPreEntityAllSystems();
  1401. C_PhysPropClientside::DestroyAll();
  1402. modemanager->LevelShutdown();
  1403. // Remove temporary entities before removing entities from the client entity list so that the te_* may
  1404. // clean up before hand.
  1405. tempents->LevelShutdown();
  1406. // Now release/delete the entities
  1407. cl_entitylist->Release();
  1408. C_BaseEntityClassList *pClassList = s_pClassLists;
  1409. while ( pClassList )
  1410. {
  1411. pClassList->LevelShutdown();
  1412. pClassList = pClassList->m_pNextClassList;
  1413. }
  1414. // Now do the post-entity shutdown of all systems
  1415. IGameSystem::LevelShutdownPostEntityAllSystems();
  1416. view->LevelShutdown();
  1417. beams->ClearBeams();
  1418. ParticleMgr()->RemoveAllEffects();
  1419. StopAllRumbleEffects();
  1420. gHUD.LevelShutdown();
  1421. internalCenterPrint->Clear();
  1422. messagechars->Clear();
  1423. #ifndef TF_CLIENT_DLL
  1424. // don't want to do this for TF2 because we have particle systems in our
  1425. // character loadout screen that can be viewed when we're not connected to a server
  1426. g_pParticleSystemMgr->UncacheAllParticleSystems();
  1427. #endif
  1428. UncacheAllMaterials();
  1429. #ifdef _XBOX
  1430. ReleaseRenderTargets();
  1431. #endif
  1432. // string tables are cleared on disconnect from a server, so reset our global pointers to NULL
  1433. ResetStringTablePointers();
  1434. #if defined( REPLAY_ENABLED )
  1435. // Shutdown the ragdoll recorder
  1436. CReplayRagdollRecorder::Instance().Shutdown();
  1437. CReplayRagdollCache::Instance().Shutdown();
  1438. #endif
  1439. }
  1440. //-----------------------------------------------------------------------------
  1441. // Purpose: Engine received crosshair offset ( autoaim )
  1442. // Input : angle -
  1443. //-----------------------------------------------------------------------------
  1444. void CHLClient::SetCrosshairAngle( const QAngle& angle )
  1445. {
  1446. CHudCrosshair *pCrosshair = GET_HUDELEMENT( CHudCrosshair );
  1447. if ( pCrosshair )
  1448. {
  1449. pCrosshair->SetCrosshairAngle( angle );
  1450. }
  1451. }
  1452. //-----------------------------------------------------------------------------
  1453. // Purpose: Helper to initialize sprite from .spr semaphor
  1454. // Input : *pSprite -
  1455. // *loadname -
  1456. //-----------------------------------------------------------------------------
  1457. void CHLClient::InitSprite( CEngineSprite *pSprite, const char *loadname )
  1458. {
  1459. if ( pSprite )
  1460. {
  1461. pSprite->Init( loadname );
  1462. }
  1463. }
  1464. //-----------------------------------------------------------------------------
  1465. // Purpose:
  1466. // Input : *pSprite -
  1467. //-----------------------------------------------------------------------------
  1468. void CHLClient::ShutdownSprite( CEngineSprite *pSprite )
  1469. {
  1470. if ( pSprite )
  1471. {
  1472. pSprite->Shutdown();
  1473. }
  1474. }
  1475. //-----------------------------------------------------------------------------
  1476. // Purpose: Tells engine how much space to allocate for sprite objects
  1477. // Output : int
  1478. //-----------------------------------------------------------------------------
  1479. int CHLClient::GetSpriteSize( void ) const
  1480. {
  1481. return sizeof( CEngineSprite );
  1482. }
  1483. //-----------------------------------------------------------------------------
  1484. // Purpose:
  1485. // Input : entindex -
  1486. // bTalking -
  1487. //-----------------------------------------------------------------------------
  1488. void CHLClient::VoiceStatus( int entindex, qboolean bTalking )
  1489. {
  1490. GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, !!bTalking );
  1491. }
  1492. //-----------------------------------------------------------------------------
  1493. // Called when the string table for materials changes
  1494. //-----------------------------------------------------------------------------
  1495. void OnMaterialStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  1496. {
  1497. // Make sure this puppy is precached
  1498. gHLClient.PrecacheMaterial( newString );
  1499. RequestCacheUsedMaterials();
  1500. }
  1501. //-----------------------------------------------------------------------------
  1502. // Called when the string table for particle systems changes
  1503. //-----------------------------------------------------------------------------
  1504. void OnParticleSystemStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  1505. {
  1506. // Make sure this puppy is precached
  1507. g_pParticleSystemMgr->PrecacheParticleSystem( newString );
  1508. RequestCacheUsedMaterials();
  1509. }
  1510. //-----------------------------------------------------------------------------
  1511. // Called when the string table for VGUI changes
  1512. //-----------------------------------------------------------------------------
  1513. void OnVguiScreenTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  1514. {
  1515. // Make sure this puppy is precached
  1516. vgui::Panel *pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( newString, 100, NULL, NULL );
  1517. if ( pPanel )
  1518. PanelMetaClassMgr()->DestroyPanelMetaClass( pPanel );
  1519. }
  1520. //-----------------------------------------------------------------------------
  1521. // Purpose: Preload the string on the client (if single player it should already be in the cache from the server!!!)
  1522. // Input : *object -
  1523. // *stringTable -
  1524. // stringNumber -
  1525. // *newString -
  1526. // *newData -
  1527. //-----------------------------------------------------------------------------
  1528. void OnSceneStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
  1529. {
  1530. }
  1531. //-----------------------------------------------------------------------------
  1532. // Purpose: Hook up any callbacks here, the table definition has been parsed but
  1533. // no data has been added yet
  1534. //-----------------------------------------------------------------------------
  1535. void CHLClient::InstallStringTableCallback( const char *tableName )
  1536. {
  1537. // Here, cache off string table IDs
  1538. if (!Q_strcasecmp(tableName, "VguiScreen"))
  1539. {
  1540. // Look up the id
  1541. g_StringTableVguiScreen = networkstringtable->FindTable( tableName );
  1542. // When the material list changes, we need to know immediately
  1543. g_StringTableVguiScreen->SetStringChangedCallback( NULL, OnVguiScreenTableChanged );
  1544. }
  1545. else if (!Q_strcasecmp(tableName, "Materials"))
  1546. {
  1547. // Look up the id
  1548. g_pStringTableMaterials = networkstringtable->FindTable( tableName );
  1549. // When the material list changes, we need to know immediately
  1550. g_pStringTableMaterials->SetStringChangedCallback( NULL, OnMaterialStringTableChanged );
  1551. }
  1552. else if ( !Q_strcasecmp( tableName, "EffectDispatch" ) )
  1553. {
  1554. g_StringTableEffectDispatch = networkstringtable->FindTable( tableName );
  1555. }
  1556. else if ( !Q_strcasecmp( tableName, "InfoPanel" ) )
  1557. {
  1558. g_pStringTableInfoPanel = networkstringtable->FindTable( tableName );
  1559. }
  1560. else if ( !Q_strcasecmp( tableName, "Scenes" ) )
  1561. {
  1562. g_pStringTableClientSideChoreoScenes = networkstringtable->FindTable( tableName );
  1563. g_pStringTableClientSideChoreoScenes->SetStringChangedCallback( NULL, OnSceneStringTableChanged );
  1564. }
  1565. else if ( !Q_strcasecmp( tableName, "ParticleEffectNames" ) )
  1566. {
  1567. g_pStringTableParticleEffectNames = networkstringtable->FindTable( tableName );
  1568. networkstringtable->SetAllowClientSideAddString( g_pStringTableParticleEffectNames, true );
  1569. // When the particle system list changes, we need to know immediately
  1570. g_pStringTableParticleEffectNames->SetStringChangedCallback( NULL, OnParticleSystemStringTableChanged );
  1571. }
  1572. else if ( !Q_strcasecmp( tableName, "ServerMapCycle" ) )
  1573. {
  1574. g_pStringTableServerMapCycle = networkstringtable->FindTable( tableName );
  1575. }
  1576. #ifdef TF_CLIENT_DLL
  1577. else if ( !Q_strcasecmp( tableName, "ServerPopFiles" ) )
  1578. {
  1579. g_pStringTableServerPopFiles = networkstringtable->FindTable( tableName );
  1580. }
  1581. else if ( !Q_strcasecmp( tableName, "ServerMapCycleMvM" ) )
  1582. {
  1583. g_pStringTableServerMapCycleMvM = networkstringtable->FindTable( tableName );
  1584. }
  1585. #endif
  1586. InstallStringTableCallback_GameRules();
  1587. }
  1588. //-----------------------------------------------------------------------------
  1589. // Material precache
  1590. //-----------------------------------------------------------------------------
  1591. void CHLClient::PrecacheMaterial( const char *pMaterialName )
  1592. {
  1593. Assert( pMaterialName );
  1594. int nLen = Q_strlen( pMaterialName );
  1595. char *pTempBuf = (char*)stackalloc( nLen + 1 );
  1596. memcpy( pTempBuf, pMaterialName, nLen + 1 );
  1597. char *pFound = Q_strstr( pTempBuf, ".vmt\0" );
  1598. if ( pFound )
  1599. {
  1600. *pFound = 0;
  1601. }
  1602. IMaterial *pMaterial = materials->FindMaterial( pTempBuf, TEXTURE_GROUP_PRECACHED );
  1603. if ( !IsErrorMaterial( pMaterial ) )
  1604. {
  1605. pMaterial->IncrementReferenceCount();
  1606. m_CachedMaterials.AddToTail( pMaterial );
  1607. }
  1608. else
  1609. {
  1610. if (IsOSX())
  1611. {
  1612. printf("\n ##### CHLClient::PrecacheMaterial could not find material %s (%s)", pMaterialName, pTempBuf );
  1613. }
  1614. }
  1615. }
  1616. void CHLClient::UncacheAllMaterials( )
  1617. {
  1618. for (int i = m_CachedMaterials.Count(); --i >= 0; )
  1619. {
  1620. m_CachedMaterials[i]->DecrementReferenceCount();
  1621. }
  1622. m_CachedMaterials.RemoveAll();
  1623. }
  1624. //-----------------------------------------------------------------------------
  1625. // Purpose:
  1626. // Input : *pszName -
  1627. // iSize -
  1628. // *pbuf -
  1629. // Output : Returns true on success, false on failure.
  1630. //-----------------------------------------------------------------------------
  1631. bool CHLClient::DispatchUserMessage( int msg_type, bf_read &msg_data )
  1632. {
  1633. return usermessages->DispatchUserMessage( msg_type, msg_data );
  1634. }
  1635. void SimulateEntities()
  1636. {
  1637. VPROF_BUDGET("Client SimulateEntities", VPROF_BUDGETGROUP_CLIENT_SIM);
  1638. // Service timer events (think functions).
  1639. ClientThinkList()->PerformThinkFunctions();
  1640. // TODO: make an ISimulateable interface so C_BaseNetworkables can simulate?
  1641. {
  1642. VPROF_("C_BaseEntity::Simulate", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  1643. C_BaseEntityIterator iterator;
  1644. C_BaseEntity *pEnt;
  1645. while ( (pEnt = iterator.Next()) != NULL )
  1646. {
  1647. pEnt->Simulate();
  1648. }
  1649. }
  1650. }
  1651. bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
  1652. {
  1653. VPROF( "AddDataChangeEvent" );
  1654. Assert( ent );
  1655. // Make sure we don't already have an event queued for this guy.
  1656. if ( *pStoredEvent >= 0 )
  1657. {
  1658. Assert( g_DataChangedEvents[*pStoredEvent].m_pEntity == ent );
  1659. // DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED.
  1660. if ( updateType == DATA_UPDATE_CREATED )
  1661. g_DataChangedEvents[*pStoredEvent].m_UpdateType = updateType;
  1662. return false;
  1663. }
  1664. else
  1665. {
  1666. *pStoredEvent = g_DataChangedEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) );
  1667. return true;
  1668. }
  1669. }
  1670. void ClearDataChangedEvent( int iStoredEvent )
  1671. {
  1672. if ( iStoredEvent != -1 )
  1673. g_DataChangedEvents.Remove( iStoredEvent );
  1674. }
  1675. void ProcessOnDataChangedEvents()
  1676. {
  1677. VPROF_("ProcessOnDataChangedEvents", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  1678. FOR_EACH_LL( g_DataChangedEvents, i )
  1679. {
  1680. CDataChangedEvent *pEvent = &g_DataChangedEvents[i];
  1681. // Reset their stored event identifier.
  1682. *pEvent->m_pStoredEvent = -1;
  1683. // Send the event.
  1684. IClientNetworkable *pNetworkable = pEvent->m_pEntity;
  1685. pNetworkable->OnDataChanged( pEvent->m_UpdateType );
  1686. }
  1687. g_DataChangedEvents.Purge();
  1688. }
  1689. void UpdateClientRenderableInPVSStatus()
  1690. {
  1691. // Vis for this view should already be setup at this point.
  1692. // For each client-only entity, notify it if it's newly coming into the PVS.
  1693. CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
  1694. FOR_EACH_LL( theList, i )
  1695. {
  1696. CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
  1697. if ( pInfo->m_InPVSStatus & INPVS_YES )
  1698. {
  1699. // Ok, this entity already thinks it's in the PVS. No need to notify it.
  1700. // We need to set the INPVS_YES_THISFRAME flag if it's in this frame at all, so we
  1701. // don't tell the entity it's not in the PVS anymore at the end of the frame.
  1702. if ( !( pInfo->m_InPVSStatus & INPVS_THISFRAME ) )
  1703. {
  1704. if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
  1705. {
  1706. pInfo->m_InPVSStatus |= INPVS_THISFRAME;
  1707. }
  1708. }
  1709. }
  1710. else
  1711. {
  1712. // This entity doesn't think it's in the PVS yet. If it is now in the PVS, let it know.
  1713. if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
  1714. {
  1715. pInfo->m_InPVSStatus |= ( INPVS_YES | INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
  1716. }
  1717. }
  1718. }
  1719. }
  1720. void UpdatePVSNotifiers()
  1721. {
  1722. MDLCACHE_CRITICAL_SECTION();
  1723. // At this point, all the entities that were rendered in the previous frame have INPVS_THISFRAME set
  1724. // so we can tell the entities that aren't in the PVS anymore so.
  1725. CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
  1726. FOR_EACH_LL( theList, i )
  1727. {
  1728. CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
  1729. // If this entity thinks it's in the PVS, but it wasn't in the PVS this frame, tell it so.
  1730. if ( pInfo->m_InPVSStatus & INPVS_YES )
  1731. {
  1732. if ( pInfo->m_InPVSStatus & INPVS_THISFRAME )
  1733. {
  1734. if ( pInfo->m_InPVSStatus & INPVS_NEEDSNOTIFY )
  1735. {
  1736. pInfo->m_pNotify->OnPVSStatusChanged( true );
  1737. }
  1738. // Clear it for the next time around.
  1739. pInfo->m_InPVSStatus &= ~( INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
  1740. }
  1741. else
  1742. {
  1743. pInfo->m_InPVSStatus &= ~INPVS_YES;
  1744. pInfo->m_pNotify->OnPVSStatusChanged( false );
  1745. }
  1746. }
  1747. }
  1748. }
  1749. void OnRenderStart()
  1750. {
  1751. VPROF( "OnRenderStart" );
  1752. MDLCACHE_CRITICAL_SECTION();
  1753. MDLCACHE_COARSE_LOCK();
  1754. #ifdef PORTAL
  1755. 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.
  1756. #endif
  1757. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
  1758. C_BaseEntity::SetAbsQueriesValid( false );
  1759. Rope_ResetCounters();
  1760. UpdateLocalPlayerVisionFlags();
  1761. // Interpolate server entities and move aiments.
  1762. {
  1763. PREDICTION_TRACKVALUECHANGESCOPE( "interpolation" );
  1764. C_BaseEntity::InterpolateServerEntities();
  1765. }
  1766. {
  1767. // vprof node for this bloc of math
  1768. VPROF( "OnRenderStart: dirty bone caches");
  1769. // Invalidate any bone information.
  1770. C_BaseAnimating::InvalidateBoneCaches();
  1771. C_BaseEntity::SetAbsQueriesValid( true );
  1772. C_BaseEntity::EnableAbsRecomputations( true );
  1773. // Enable access to all model bones except view models.
  1774. // This is necessary for aim-ent computation to occur properly
  1775. C_BaseAnimating::PushAllowBoneAccess( true, false, "OnRenderStart->CViewRender::SetUpView" ); // pops in CViewRender::SetUpView
  1776. // FIXME: This needs to be done before the player moves; it forces
  1777. // aiments the player may be attached to to forcibly update their position
  1778. C_BaseEntity::MarkAimEntsDirty();
  1779. }
  1780. // Make sure the camera simulation happens before OnRenderStart, where it's used.
  1781. // NOTE: the only thing that happens in CAM_Think is thirdperson related code.
  1782. input->CAM_Think();
  1783. // This will place the player + the view models + all parent
  1784. // entities at the correct abs position so that their attachment points
  1785. // are at the correct location
  1786. view->OnRenderStart();
  1787. RopeManager()->OnRenderStart();
  1788. // This will place all entities in the correct position in world space and in the KD-tree
  1789. C_BaseAnimating::UpdateClientSideAnimations();
  1790. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
  1791. // Process OnDataChanged events.
  1792. ProcessOnDataChangedEvents();
  1793. // Reset the overlay alpha. Entities can change the state of this in their think functions.
  1794. g_SmokeFogOverlayAlpha = 0;
  1795. // This must occur prior to SimulatEntities,
  1796. // which is where the client thinks for c_colorcorrection + c_colorcorrectionvolumes
  1797. // update the color correction weights.
  1798. // FIXME: The place where IGameSystem::Update is called should be in here
  1799. // so we don't have to explicitly call ResetColorCorrectionWeights + SimulateEntities, etc.
  1800. g_pColorCorrectionMgr->ResetColorCorrectionWeights();
  1801. // Simulate all the entities.
  1802. SimulateEntities();
  1803. PhysicsSimulate();
  1804. C_BaseAnimating::ThreadedBoneSetup();
  1805. {
  1806. VPROF_("Client TempEnts", 0, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
  1807. // This creates things like temp entities.
  1808. engine->FireEvents();
  1809. // Update temp entities
  1810. tempents->Update();
  1811. // Update temp ent beams...
  1812. beams->UpdateTempEntBeams();
  1813. // Lock the frame from beam additions
  1814. SetBeamCreationAllowed( false );
  1815. }
  1816. // Update particle effects (eventually, the effects should use Simulate() instead of having
  1817. // their own update system).
  1818. {
  1819. // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
  1820. // to help track down bad math.
  1821. FPExceptionEnabler enableExceptions;
  1822. VPROF_BUDGET( "ParticleMgr()->Simulate", VPROF_BUDGETGROUP_PARTICLE_SIMULATION );
  1823. ParticleMgr()->Simulate( gpGlobals->frametime );
  1824. }
  1825. // Now that the view model's position is setup and aiments are marked dirty, update
  1826. // their positions so they're in the leaf system correctly.
  1827. C_BaseEntity::CalcAimEntPositions();
  1828. // For entities marked for recording, post bone messages to IToolSystems
  1829. if ( ToolsEnabled() )
  1830. {
  1831. C_BaseEntity::ToolRecordEntities();
  1832. }
  1833. #if defined( REPLAY_ENABLED )
  1834. // This will record any ragdolls if Replay mode is enabled on the server
  1835. CReplayRagdollRecorder::Instance().Think();
  1836. CReplayRagdollCache::Instance().Think();
  1837. #endif
  1838. // Finally, link all the entities into the leaf system right before rendering.
  1839. C_BaseEntity::AddVisibleEntities();
  1840. }
  1841. void OnRenderEnd()
  1842. {
  1843. // Disallow access to bones (access is enabled in CViewRender::SetUpView).
  1844. C_BaseAnimating::PopBoneAccess( "CViewRender::SetUpView->OnRenderEnd" );
  1845. UpdatePVSNotifiers();
  1846. DisplayBoneSetupEnts();
  1847. }
  1848. void CHLClient::FrameStageNotify( ClientFrameStage_t curStage )
  1849. {
  1850. g_CurFrameStage = curStage;
  1851. switch( curStage )
  1852. {
  1853. default:
  1854. break;
  1855. case FRAME_RENDER_START:
  1856. {
  1857. VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_START" );
  1858. // Last thing before rendering, run simulation.
  1859. OnRenderStart();
  1860. }
  1861. break;
  1862. case FRAME_RENDER_END:
  1863. {
  1864. VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_END" );
  1865. OnRenderEnd();
  1866. PREDICTION_SPEWVALUECHANGES();
  1867. }
  1868. break;
  1869. case FRAME_NET_UPDATE_START:
  1870. {
  1871. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_START" );
  1872. // disabled all recomputations while we update entities
  1873. C_BaseEntity::EnableAbsRecomputations( false );
  1874. C_BaseEntity::SetAbsQueriesValid( false );
  1875. Interpolation_SetLastPacketTimeStamp( engine->GetLastTimeStamp() );
  1876. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
  1877. PREDICTION_STARTTRACKVALUE( "netupdate" );
  1878. }
  1879. break;
  1880. case FRAME_NET_UPDATE_END:
  1881. {
  1882. ProcessCacheUsedMaterials();
  1883. // reenable abs recomputation since now all entities have been updated
  1884. C_BaseEntity::EnableAbsRecomputations( true );
  1885. C_BaseEntity::SetAbsQueriesValid( true );
  1886. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
  1887. PREDICTION_ENDTRACKVALUE();
  1888. }
  1889. break;
  1890. case FRAME_NET_UPDATE_POSTDATAUPDATE_START:
  1891. {
  1892. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START" );
  1893. PREDICTION_STARTTRACKVALUE( "postdataupdate" );
  1894. }
  1895. break;
  1896. case FRAME_NET_UPDATE_POSTDATAUPDATE_END:
  1897. {
  1898. VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END" );
  1899. PREDICTION_ENDTRACKVALUE();
  1900. // Let prediction copy off pristine data
  1901. prediction->PostEntityPacketReceived();
  1902. HLTVCamera()->PostEntityPacketReceived();
  1903. #if defined( REPLAY_ENABLED )
  1904. ReplayCamera()->PostEntityPacketReceived();
  1905. #endif
  1906. }
  1907. break;
  1908. case FRAME_START:
  1909. {
  1910. // Mark the frame as open for client fx additions
  1911. SetFXCreationAllowed( true );
  1912. SetBeamCreationAllowed( true );
  1913. C_BaseEntity::CheckCLInterpChanged();
  1914. }
  1915. break;
  1916. }
  1917. }
  1918. CSaveRestoreData *SaveInit( int size );
  1919. // Save/restore system hooks
  1920. CSaveRestoreData *CHLClient::SaveInit( int size )
  1921. {
  1922. return ::SaveInit(size);
  1923. }
  1924. void CHLClient::SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
  1925. {
  1926. CSave saveHelper( pSaveData );
  1927. saveHelper.WriteFields( pname, pBaseData, pMap, pFields, fieldCount );
  1928. }
  1929. void CHLClient::SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
  1930. {
  1931. CRestore restoreHelper( pSaveData );
  1932. restoreHelper.ReadFields( pname, pBaseData, pMap, pFields, fieldCount );
  1933. }
  1934. void CHLClient::PreSave( CSaveRestoreData *s )
  1935. {
  1936. g_pGameSaveRestoreBlockSet->PreSave( s );
  1937. }
  1938. void CHLClient::Save( CSaveRestoreData *s )
  1939. {
  1940. CSave saveHelper( s );
  1941. g_pGameSaveRestoreBlockSet->Save( &saveHelper );
  1942. }
  1943. void CHLClient::WriteSaveHeaders( CSaveRestoreData *s )
  1944. {
  1945. CSave saveHelper( s );
  1946. g_pGameSaveRestoreBlockSet->WriteSaveHeaders( &saveHelper );
  1947. g_pGameSaveRestoreBlockSet->PostSave();
  1948. }
  1949. void CHLClient::ReadRestoreHeaders( CSaveRestoreData *s )
  1950. {
  1951. CRestore restoreHelper( s );
  1952. g_pGameSaveRestoreBlockSet->PreRestore();
  1953. g_pGameSaveRestoreBlockSet->ReadRestoreHeaders( &restoreHelper );
  1954. }
  1955. void CHLClient::Restore( CSaveRestoreData *s, bool b )
  1956. {
  1957. CRestore restore(s);
  1958. g_pGameSaveRestoreBlockSet->Restore( &restore, b );
  1959. g_pGameSaveRestoreBlockSet->PostRestore();
  1960. }
  1961. static CUtlVector<EHANDLE> g_RestoredEntities;
  1962. void AddRestoredEntity( C_BaseEntity *pEntity )
  1963. {
  1964. if ( !pEntity )
  1965. return;
  1966. g_RestoredEntities.AddToTail( EHANDLE(pEntity) );
  1967. }
  1968. void CHLClient::DispatchOnRestore()
  1969. {
  1970. for ( int i = 0; i < g_RestoredEntities.Count(); i++ )
  1971. {
  1972. if ( g_RestoredEntities[i] != NULL )
  1973. {
  1974. MDLCACHE_CRITICAL_SECTION();
  1975. g_RestoredEntities[i]->OnRestore();
  1976. }
  1977. }
  1978. g_RestoredEntities.RemoveAll();
  1979. }
  1980. void CHLClient::WriteSaveGameScreenshot( const char *pFilename )
  1981. {
  1982. view->WriteSaveGameScreenshot( pFilename );
  1983. }
  1984. // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
  1985. // the appropriate close caption if running with closecaption = 1
  1986. void CHLClient::EmitSentenceCloseCaption( char const *tokenstream )
  1987. {
  1988. extern ConVar closecaption;
  1989. if ( !closecaption.GetBool() )
  1990. return;
  1991. CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
  1992. if ( hudCloseCaption )
  1993. {
  1994. hudCloseCaption->ProcessSentenceCaptionStream( tokenstream );
  1995. }
  1996. }
  1997. void CHLClient::EmitCloseCaption( char const *captionname, float duration )
  1998. {
  1999. extern ConVar closecaption;
  2000. if ( !closecaption.GetBool() )
  2001. return;
  2002. CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
  2003. if ( hudCloseCaption )
  2004. {
  2005. hudCloseCaption->ProcessCaption( captionname, duration );
  2006. }
  2007. }
  2008. CStandardRecvProxies* CHLClient::GetStandardRecvProxies()
  2009. {
  2010. return &g_StandardRecvProxies;
  2011. }
  2012. bool CHLClient::CanRecordDemo( char *errorMsg, int length ) const
  2013. {
  2014. if ( GetClientModeNormal() )
  2015. {
  2016. return GetClientModeNormal()->CanRecordDemo( errorMsg, length );
  2017. }
  2018. return true;
  2019. }
  2020. void CHLClient::OnDemoRecordStart( char const* pDemoBaseName )
  2021. {
  2022. if ( GetClientModeNormal() )
  2023. {
  2024. return GetClientModeNormal()->OnDemoRecordStart( pDemoBaseName );
  2025. }
  2026. }
  2027. void CHLClient::OnDemoRecordStop()
  2028. {
  2029. if ( GetClientModeNormal() )
  2030. {
  2031. return GetClientModeNormal()->OnDemoRecordStop();
  2032. }
  2033. }
  2034. void CHLClient::OnDemoPlaybackStart( char const* pDemoBaseName )
  2035. {
  2036. #if defined( REPLAY_ENABLED )
  2037. // Load any ragdoll override frames from disk
  2038. char szRagdollFile[MAX_OSPATH];
  2039. V_snprintf( szRagdollFile, sizeof(szRagdollFile), "%s.dmx", pDemoBaseName );
  2040. CReplayRagdollCache::Instance().Init( szRagdollFile );
  2041. #endif
  2042. }
  2043. void CHLClient::OnDemoPlaybackStop()
  2044. {
  2045. #ifdef DEMOPOLISH_ENABLED
  2046. if ( DemoPolish_GetController().m_bInit )
  2047. {
  2048. DemoPolish_GetController().Shutdown();
  2049. }
  2050. #endif
  2051. #if defined( REPLAY_ENABLED )
  2052. CReplayRagdollCache::Instance().Shutdown();
  2053. #endif
  2054. }
  2055. int CHLClient::GetScreenWidth()
  2056. {
  2057. return ScreenWidth();
  2058. }
  2059. int CHLClient::GetScreenHeight()
  2060. {
  2061. return ScreenHeight();
  2062. }
  2063. // NEW INTERFACES
  2064. // save game screenshot writing
  2065. void CHLClient::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/,
  2066. bool bWriteVTF/*=false*/ )
  2067. {
  2068. view->WriteSaveGameScreenshotOfSize( pFilename, width, height, bCreatePowerOf2Padded, bWriteVTF );
  2069. }
  2070. // See RenderViewInfo_t
  2071. void CHLClient::RenderView( const CViewSetup &setup, int nClearFlags, int whatToDraw )
  2072. {
  2073. VPROF("RenderView");
  2074. view->RenderView( setup, nClearFlags, whatToDraw );
  2075. }
  2076. void ReloadSoundEntriesInList( IFileList *pFilesToReload );
  2077. //-----------------------------------------------------------------------------
  2078. // For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences.
  2079. //-----------------------------------------------------------------------------
  2080. void CHLClient::ReloadFilesInList( IFileList *pFilesToReload )
  2081. {
  2082. ReloadParticleEffectsInList( pFilesToReload );
  2083. ReloadSoundEntriesInList( pFilesToReload );
  2084. }
  2085. bool CHLClient::HandleUiToggle()
  2086. {
  2087. #if defined( REPLAY_ENABLED )
  2088. if ( !g_pEngineReplay || !g_pEngineReplay->IsSupportedModAndPlatform() )
  2089. return false;
  2090. CReplayPerformanceEditorPanel *pEditor = ReplayUI_GetPerformanceEditor();
  2091. if ( !pEditor )
  2092. return false;
  2093. pEditor->HandleUiToggle();
  2094. return true;
  2095. #else
  2096. return false;
  2097. #endif
  2098. }
  2099. bool CHLClient::ShouldAllowConsole()
  2100. {
  2101. return true;
  2102. }
  2103. CRenamedRecvTableInfo *CHLClient::GetRenamedRecvTableInfos()
  2104. {
  2105. return g_pRenamedRecvTableInfoHead;
  2106. }
  2107. CMouthInfo g_ClientUIMouth;
  2108. // Get the mouthinfo for the sound being played inside UI panels
  2109. CMouthInfo *CHLClient::GetClientUIMouthInfo()
  2110. {
  2111. return &g_ClientUIMouth;
  2112. }
  2113. void CHLClient::FileReceived( const char * fileName, unsigned int transferID )
  2114. {
  2115. if ( g_pGameRules )
  2116. {
  2117. g_pGameRules->OnFileReceived( fileName, transferID );
  2118. }
  2119. }
  2120. void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params )
  2121. {
  2122. #ifdef TF_CLIENT_DLL
  2123. CBaseEntity *pEntity = ClientEntityList().GetEnt( params.soundsource );
  2124. // A player speaking
  2125. if ( params.entchannel == CHAN_VOICE && GameRules() && pEntity && pEntity->IsPlayer() )
  2126. {
  2127. // Use high-pitched voices for other players if the local player has an item that allows them to hear it (Pyro Goggles)
  2128. if ( !GameRules()->IsLocalPlayer( params.soundsource ) && IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
  2129. {
  2130. params.pitch *= 1.3f;
  2131. }
  2132. // Halloween voice futzery?
  2133. else
  2134. {
  2135. float flVoicePitchScale = 1.f;
  2136. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flVoicePitchScale, voice_pitch_scale );
  2137. int iHalloweenVoiceSpell = 0;
  2138. if ( TF_IsHolidayActive( kHoliday_HalloweenOrFullMoon ) )
  2139. {
  2140. CALL_ATTRIB_HOOK_INT_ON_OTHER( pEntity, iHalloweenVoiceSpell, halloween_voice_modulation );
  2141. }
  2142. if ( iHalloweenVoiceSpell > 0 )
  2143. {
  2144. params.pitch *= 0.8f;
  2145. }
  2146. else if( flVoicePitchScale != 1.f )
  2147. {
  2148. params.pitch *= flVoicePitchScale;
  2149. }
  2150. }
  2151. }
  2152. #endif
  2153. }
  2154. const char* CHLClient::TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName )
  2155. {
  2156. if ( !GameRules() )
  2157. return pchEffectName;
  2158. return GameRules()->TranslateEffectForVisionFilter( pchEffectType, pchEffectName );
  2159. }
  2160. bool CHLClient::DisconnectAttempt( void )
  2161. {
  2162. bool bRet = false;
  2163. #if defined( TF_CLIENT_DLL )
  2164. bRet = HandleDisconnectAttempt();
  2165. #endif
  2166. return bRet;
  2167. }
  2168. bool CHLClient::IsConnectedUserInfoChangeAllowed( IConVar *pCvar )
  2169. {
  2170. return GameRules() ? GameRules()->IsConnectedUserInfoChangeAllowed( NULL ) : true;
  2171. }
  2172. #ifndef NO_STEAM
  2173. CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex )
  2174. {
  2175. player_info_t pi;
  2176. if ( steamapicontext && steamapicontext->SteamUtils() )
  2177. {
  2178. if ( engine->GetPlayerInfo( iPlayerIndex, &pi ) )
  2179. {
  2180. if ( pi.friendsID )
  2181. {
  2182. return CSteamID( pi.friendsID, 1, GetUniverse(), k_EAccountTypeIndividual );
  2183. }
  2184. }
  2185. }
  2186. return CSteamID();
  2187. }
  2188. #endif