diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/cdll_client_int.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/cdll_client_int.cpp')
| -rw-r--r-- | mp/src/game/client/cdll_client_int.cpp | 5280 |
1 files changed, 2640 insertions, 2640 deletions
diff --git a/mp/src/game/client/cdll_client_int.cpp b/mp/src/game/client/cdll_client_int.cpp index 4e856c95..0f40f2d3 100644 --- a/mp/src/game/client/cdll_client_int.cpp +++ b/mp/src/game/client/cdll_client_int.cpp @@ -1,2640 +1,2640 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//===========================================================================//
-#include "cbase.h"
-#include <crtmemdebug.h>
-#include "vgui_int.h"
-#include "clientmode.h"
-#include "iinput.h"
-#include "iviewrender.h"
-#include "ivieweffects.h"
-#include "ivmodemanager.h"
-#include "prediction.h"
-#include "clientsideeffects.h"
-#include "particlemgr.h"
-#include "steam/steam_api.h"
-#include "initializer.h"
-#include "smoke_fog_overlay.h"
-#include "view.h"
-#include "ienginevgui.h"
-#include "iefx.h"
-#include "enginesprite.h"
-#include "networkstringtable_clientdll.h"
-#include "voice_status.h"
-#include "filesystem.h"
-#include "c_te_legacytempents.h"
-#include "c_rope.h"
-#include "engine/ishadowmgr.h"
-#include "engine/IStaticPropMgr.h"
-#include "hud_basechat.h"
-#include "hud_crosshair.h"
-#include "view_shared.h"
-#include "env_wind_shared.h"
-#include "detailobjectsystem.h"
-#include "clienteffectprecachesystem.h"
-#include "soundenvelope.h"
-#include "c_basetempentity.h"
-#include "materialsystem/imaterialsystemstub.h"
-#include "VGuiMatSurface/IMatSystemSurface.h"
-#include "materialsystem/imaterialsystemhardwareconfig.h"
-#include "c_soundscape.h"
-#include "engine/ivdebugoverlay.h"
-#include "vguicenterprint.h"
-#include "iviewrender_beams.h"
-#include "tier0/vprof.h"
-#include "engine/IEngineTrace.h"
-#include "engine/ivmodelinfo.h"
-#include "physics.h"
-#include "usermessages.h"
-#include "gamestringpool.h"
-#include "c_user_message_register.h"
-#include "IGameUIFuncs.h"
-#include "saverestoretypes.h"
-#include "saverestore.h"
-#include "physics_saverestore.h"
-#include "igameevents.h"
-#include "datacache/idatacache.h"
-#include "datacache/imdlcache.h"
-#include "kbutton.h"
-#include "tier0/icommandline.h"
-#include "gamerules_register.h"
-#include "vgui_controls/AnimationController.h"
-#include "bitmap/tgawriter.h"
-#include "c_world.h"
-#include "perfvisualbenchmark.h"
-#include "SoundEmitterSystem/isoundemittersystembase.h"
-#include "hud_closecaption.h"
-#include "colorcorrectionmgr.h"
-#include "physpropclientside.h"
-#include "panelmetaclassmgr.h"
-#include "c_vguiscreen.h"
-#include "imessagechars.h"
-#include "game/client/IGameClientExports.h"
-#include "client_factorylist.h"
-#include "ragdoll_shared.h"
-#include "rendertexture.h"
-#include "view_scene.h"
-#include "iclientmode.h"
-#include "con_nprint.h"
-#include "inputsystem/iinputsystem.h"
-#include "appframework/IAppSystemGroup.h"
-#include "scenefilecache/ISceneFileCache.h"
-#include "tier2/tier2dm.h"
-#include "tier3/tier3.h"
-#include "ihudlcd.h"
-#include "toolframework_client.h"
-#include "hltvcamera.h"
-#if defined( REPLAY_ENABLED )
-#include "replay/replaycamera.h"
-#include "replay/replay_ragdoll.h"
-#include "qlimits.h"
-#include "replay/replay.h"
-#include "replay/ireplaysystem.h"
-#include "replay/iclientreplay.h"
-#include "replay/ienginereplay.h"
-#include "replay/ireplaymanager.h"
-#include "replay/ireplayscreenshotmanager.h"
-#include "replay/iclientreplaycontext.h"
-#include "replay/vgui/replayconfirmquitdlg.h"
-#include "replay/vgui/replaybrowsermainpanel.h"
-#include "replay/vgui/replayinputpanel.h"
-#include "replay/vgui/replayperformanceeditor.h"
-#endif
-#include "vgui/ILocalize.h"
-#include "vgui/IVGui.h"
-#include "ixboxsystem.h"
-#include "ipresence.h"
-#include "engine/imatchmaking.h"
-#include "cdll_bounded_cvars.h"
-#include "matsys_controls/matsyscontrols.h"
-#include "gamestats.h"
-#include "particle_parse.h"
-#if defined( TF_CLIENT_DLL )
-#include "rtime.h"
-#include "tf_hud_disconnect_prompt.h"
-#include "../engine/audio/public/sound.h"
-#include "tf_shared_content_manager.h"
-#endif
-#include "clientsteamcontext.h"
-#include "renamed_recvtable_compat.h"
-#include "mouthinfo.h"
-#include "headtrack/isourcevirtualreality.h"
-#include "client_virtualreality.h"
-#include "mumble.h"
-
-// NVNT includes
-#include "hud_macros.h"
-#include "haptics/ihaptics.h"
-#include "haptics/haptic_utils.h"
-#include "haptics/haptic_msgs.h"
-
-#if defined( TF_CLIENT_DLL )
-#include "abuse_report.h"
-#endif
-
-#ifdef USES_ECON_ITEMS
-#include "econ_item_system.h"
-#endif // USES_ECON_ITEMS
-
-#if defined( TF_CLIENT_DLL )
-#include "econ/tool_items/custom_texture_cache.h"
-#endif
-
-#ifdef WORKSHOP_IMPORT_ENABLED
-#include "fbxsystem/fbxsystem.h"
-#endif
-
-extern vgui::IInputInternal *g_InputInternal;
-const char *COM_GetModDirectory(); // return the mod dir (rather than the complete -game param, which can be a path)
-
-//=============================================================================
-// HPE_BEGIN
-// [dwenger] Necessary for stats display
-//=============================================================================
-
-#include "achievements_and_stats_interface.h"
-
-//=============================================================================
-// HPE_END
-//=============================================================================
-
-
-#ifdef PORTAL
-#include "PortalRender.h"
-#endif
-
-#ifdef SIXENSE
-#include "sixense/in_sixense.h"
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-extern IClientMode *GetClientModeNormal();
-
-// IF YOU ADD AN INTERFACE, EXTERN IT IN THE HEADER FILE.
-IVEngineClient *engine = NULL;
-IVModelRender *modelrender = NULL;
-IVEfx *effects = NULL;
-IVRenderView *render = NULL;
-IVDebugOverlay *debugoverlay = NULL;
-IMaterialSystemStub *materials_stub = NULL;
-IDataCache *datacache = NULL;
-IVModelInfoClient *modelinfo = NULL;
-IEngineVGui *enginevgui = NULL;
-INetworkStringTableContainer *networkstringtable = NULL;
-ISpatialPartition* partition = NULL;
-IFileSystem *filesystem = NULL;
-IShadowMgr *shadowmgr = NULL;
-IStaticPropMgrClient *staticpropmgr = NULL;
-IEngineSound *enginesound = NULL;
-IUniformRandomStream *random = NULL;
-static CGaussianRandomStream s_GaussianRandomStream;
-CGaussianRandomStream *randomgaussian = &s_GaussianRandomStream;
-ISharedGameRules *sharedgamerules = NULL;
-IEngineTrace *enginetrace = NULL;
-IGameUIFuncs *gameuifuncs = NULL;
-IGameEventManager2 *gameeventmanager = NULL;
-ISoundEmitterSystemBase *soundemitterbase = NULL;
-IInputSystem *inputsystem = NULL;
-ISceneFileCache *scenefilecache = NULL;
-IXboxSystem *xboxsystem = NULL; // Xbox 360 only
-IMatchmaking *matchmaking = NULL;
-IUploadGameStats *gamestatsuploader = NULL;
-IClientReplayContext *g_pClientReplayContext = NULL;
-#if defined( REPLAY_ENABLED )
-IReplayManager *g_pReplayManager = NULL;
-IReplayMovieManager *g_pReplayMovieManager = NULL;
-IReplayScreenshotManager *g_pReplayScreenshotManager = NULL;
-IReplayPerformanceManager *g_pReplayPerformanceManager = NULL;
-IReplayPerformanceController *g_pReplayPerformanceController = NULL;
-IEngineReplay *g_pEngineReplay = NULL;
-IEngineClientReplay *g_pEngineClientReplay = NULL;
-IReplaySystem *g_pReplay = NULL;
-#endif
-
-IHaptics* haptics = NULL;// NVNT haptics system interface singleton
-
-//=============================================================================
-// HPE_BEGIN
-// [dwenger] Necessary for stats display
-//=============================================================================
-
-AchievementsAndStatsInterface* g_pAchievementsAndStatsInterface = NULL;
-
-//=============================================================================
-// HPE_END
-//=============================================================================
-
-IGameSystem *SoundEmitterSystem();
-IGameSystem *ToolFrameworkClientSystem();
-
-// Engine player info, no game related infos here
-BEGIN_BYTESWAP_DATADESC( player_info_s )
- DEFINE_ARRAY( name, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ),
- DEFINE_FIELD( userID, FIELD_INTEGER ),
- DEFINE_ARRAY( guid, FIELD_CHARACTER, SIGNED_GUID_LEN + 1 ),
- DEFINE_FIELD( friendsID, FIELD_INTEGER ),
- DEFINE_ARRAY( friendsName, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ),
- DEFINE_FIELD( fakeplayer, FIELD_BOOLEAN ),
- DEFINE_FIELD( ishltv, FIELD_BOOLEAN ),
-#if defined( REPLAY_ENABLED )
- DEFINE_FIELD( isreplay, FIELD_BOOLEAN ),
-#endif
- DEFINE_ARRAY( customFiles, FIELD_INTEGER, MAX_CUSTOM_FILES ),
- DEFINE_FIELD( filesDownloaded, FIELD_INTEGER ),
-END_BYTESWAP_DATADESC()
-
-static bool g_bRequestCacheUsedMaterials = false;
-void RequestCacheUsedMaterials()
-{
- g_bRequestCacheUsedMaterials = true;
-}
-
-void ProcessCacheUsedMaterials()
-{
- if ( !g_bRequestCacheUsedMaterials )
- return;
-
- g_bRequestCacheUsedMaterials = false;
- if ( materials )
- {
- materials->CacheUsedMaterials();
- }
-}
-
-// String tables
-INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
-INetworkStringTable *g_StringTableEffectDispatch = NULL;
-INetworkStringTable *g_StringTableVguiScreen = NULL;
-INetworkStringTable *g_pStringTableMaterials = NULL;
-INetworkStringTable *g_pStringTableInfoPanel = NULL;
-INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL;
-INetworkStringTable *g_pStringTableServerMapCycle = NULL;
-
-#ifdef TF_CLIENT_DLL
-INetworkStringTable *g_pStringTableServerPopFiles = NULL;
-INetworkStringTable *g_pStringTableServerMapCycleMvM = NULL;
-#endif
-
-static CGlobalVarsBase dummyvars( true );
-// So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer.
-// Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine
-CGlobalVarsBase *gpGlobals = &dummyvars;
-class CHudChat;
-class CViewRender;
-extern CViewRender g_DefaultViewRender;
-
-extern void StopAllRumbleEffects( void );
-
-static C_BaseEntityClassList *s_pClassLists = NULL;
-C_BaseEntityClassList::C_BaseEntityClassList()
-{
- m_pNextClassList = s_pClassLists;
- s_pClassLists = this;
-}
-C_BaseEntityClassList::~C_BaseEntityClassList()
-{
-}
-
-// Any entities that want an OnDataChanged during simulation register for it here.
-class CDataChangedEvent
-{
-public:
- CDataChangedEvent() {}
- CDataChangedEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
- {
- m_pEntity = ent;
- m_UpdateType = updateType;
- m_pStoredEvent = pStoredEvent;
- }
-
- IClientNetworkable *m_pEntity;
- DataUpdateType_t m_UpdateType;
- int *m_pStoredEvent;
-};
-
-ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler();
-ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler();
-
-CUtlLinkedList<CDataChangedEvent, unsigned short> g_DataChangedEvents;
-ClientFrameStage_t g_CurFrameStage = FRAME_UNDEFINED;
-
-
-class IMoveHelper;
-
-void DispatchHudText( const char *pszName );
-
-static ConVar s_CV_ShowParticleCounts("showparticlecounts", "0", 0, "Display number of particles drawn per frame");
-static ConVar s_cl_team("cl_team", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default team when joining a game");
-static ConVar s_cl_class("cl_class", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default class when joining a game");
-
-// Physics system
-bool g_bLevelInitialized;
-bool g_bTextMode = false;
-class IClientPurchaseInterfaceV2 *g_pClientPurchaseInterface = (class IClientPurchaseInterfaceV2 *)(&g_bTextMode + 156);
-
-static ConVar *g_pcv_ThreadMode = NULL;
-
-//-----------------------------------------------------------------------------
-// Purpose: interface for gameui to modify voice bans
-//-----------------------------------------------------------------------------
-class CGameClientExports : public IGameClientExports
-{
-public:
- // ingame voice manipulation
- bool IsPlayerGameVoiceMuted(int playerIndex)
- {
- return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex);
- }
-
- void MutePlayerGameVoice(int playerIndex)
- {
- GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true);
- }
-
- void UnmutePlayerGameVoice(int playerIndex)
- {
- GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false);
- }
-
- void OnGameUIActivated( void )
- {
- IGameEvent *event = gameeventmanager->CreateEvent( "gameui_activated" );
- if ( event )
- {
- gameeventmanager->FireEventClientSide( event );
- }
- }
-
- void OnGameUIHidden( void )
- {
- IGameEvent *event = gameeventmanager->CreateEvent( "gameui_hidden" );
- if ( event )
- {
- gameeventmanager->FireEventClientSide( event );
- }
- }
-
- //=============================================================================
- // HPE_BEGIN
- // [dwenger] Necessary for stats display
- //=============================================================================
-
- void CreateAchievementsPanel( vgui::Panel* pParent )
- {
- if (g_pAchievementsAndStatsInterface)
- {
- g_pAchievementsAndStatsInterface->CreatePanel( pParent );
- }
- }
-
- void DisplayAchievementPanel()
- {
- if (g_pAchievementsAndStatsInterface)
- {
- g_pAchievementsAndStatsInterface->DisplayPanel();
- }
- }
-
- void ShutdownAchievementPanel()
- {
- if (g_pAchievementsAndStatsInterface)
- {
- g_pAchievementsAndStatsInterface->ReleasePanel();
- }
- }
-
- int GetAchievementsPanelMinWidth( void ) const
- {
- if ( g_pAchievementsAndStatsInterface )
- {
- return g_pAchievementsAndStatsInterface->GetAchievementsPanelMinWidth();
- }
-
- return 0;
- }
-
- //=============================================================================
- // HPE_END
- //=============================================================================
-
- const char *GetHolidayString()
- {
- return UTIL_GetActiveHolidayString();
- }
-};
-
-EXPOSE_SINGLE_INTERFACE( CGameClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION );
-
-class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems
-{
-public:
- CClientDLLSharedAppSystems()
- {
- AddAppSystem( "soundemittersystem" DLL_EXT_STRING, SOUNDEMITTERSYSTEM_INTERFACE_VERSION );
- AddAppSystem( "scenefilecache" DLL_EXT_STRING, SCENE_FILE_CACHE_INTERFACE_VERSION );
- }
-
- virtual int Count()
- {
- return m_Systems.Count();
- }
- virtual char const *GetDllName( int idx )
- {
- return m_Systems[ idx ].m_pModuleName;
- }
- virtual char const *GetInterfaceName( int idx )
- {
- return m_Systems[ idx ].m_pInterfaceName;
- }
-private:
- void AddAppSystem( char const *moduleName, char const *interfaceName )
- {
- AppSystemInfo_t sys;
- sys.m_pModuleName = moduleName;
- sys.m_pInterfaceName = interfaceName;
- m_Systems.AddToTail( sys );
- }
-
- CUtlVector< AppSystemInfo_t > m_Systems;
-};
-
-EXPOSE_SINGLE_INTERFACE( CClientDLLSharedAppSystems, IClientDLLSharedAppSystems, CLIENT_DLL_SHARED_APPSYSTEMS );
-
-
-//-----------------------------------------------------------------------------
-// Helper interface for voice.
-//-----------------------------------------------------------------------------
-class CHLVoiceStatusHelper : public IVoiceStatusHelper
-{
-public:
- virtual void GetPlayerTextColor(int entindex, int color[3])
- {
- color[0] = color[1] = color[2] = 128;
- }
-
- virtual void UpdateCursorState()
- {
- }
-
- virtual bool CanShowSpeakerLabels()
- {
- return true;
- }
-};
-static CHLVoiceStatusHelper g_VoiceStatusHelper;
-
-//-----------------------------------------------------------------------------
-// Code to display which entities are having their bones setup each frame.
-//-----------------------------------------------------------------------------
-
-ConVar cl_ShowBoneSetupEnts( "cl_ShowBoneSetupEnts", "0", 0, "Show which entities are having their bones setup each frame." );
-
-class CBoneSetupEnt
-{
-public:
- char m_ModelName[128];
- int m_Index;
- int m_Count;
-};
-
-bool BoneSetupCompare( const CBoneSetupEnt &a, const CBoneSetupEnt &b )
-{
- return a.m_Index < b.m_Index;
-}
-
-CUtlRBTree<CBoneSetupEnt> g_BoneSetupEnts( BoneSetupCompare );
-
-
-void TrackBoneSetupEnt( C_BaseAnimating *pEnt )
-{
-#ifdef _DEBUG
- if ( IsRetail() )
- return;
-
- if ( !cl_ShowBoneSetupEnts.GetInt() )
- return;
-
- CBoneSetupEnt ent;
- ent.m_Index = pEnt->entindex();
- unsigned short i = g_BoneSetupEnts.Find( ent );
- if ( i == g_BoneSetupEnts.InvalidIndex() )
- {
- Q_strncpy( ent.m_ModelName, modelinfo->GetModelName( pEnt->GetModel() ), sizeof( ent.m_ModelName ) );
- ent.m_Count = 1;
- g_BoneSetupEnts.Insert( ent );
- }
- else
- {
- g_BoneSetupEnts[i].m_Count++;
- }
-#endif
-}
-
-void DisplayBoneSetupEnts()
-{
-#ifdef _DEBUG
- if ( IsRetail() )
- return;
-
- if ( !cl_ShowBoneSetupEnts.GetInt() )
- return;
-
- unsigned short i;
- int nElements = 0;
- for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
- ++nElements;
-
- engine->Con_NPrintf( 0, "%d bone setup ents (name/count/entindex) ------------", nElements );
-
- con_nprint_s printInfo;
- printInfo.time_to_live = -1;
- printInfo.fixed_width_font = true;
- printInfo.color[0] = printInfo.color[1] = printInfo.color[2] = 1;
-
- printInfo.index = 2;
- for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) )
- {
- CBoneSetupEnt *pEnt = &g_BoneSetupEnts[i];
-
- if ( pEnt->m_Count >= 3 )
- {
- printInfo.color[0] = 1;
- printInfo.color[1] = printInfo.color[2] = 0;
- }
- else if ( pEnt->m_Count == 2 )
- {
- printInfo.color[0] = (float)200 / 255;
- printInfo.color[1] = (float)220 / 255;
- printInfo.color[2] = 0;
- }
- else
- {
- printInfo.color[0] = printInfo.color[0] = printInfo.color[0] = 1;
- }
- engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index );
- printInfo.index++;
- }
-
- g_BoneSetupEnts.RemoveAll();
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: engine to client .dll interface
-//-----------------------------------------------------------------------------
-class CHLClient : public IBaseClientDLL
-{
-public:
- CHLClient();
-
- virtual int Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals );
-
- virtual void PostInit();
- virtual void Shutdown( void );
-
- virtual bool ReplayInit( CreateInterfaceFn fnReplayFactory );
- virtual bool ReplayPostInit();
-
- virtual void LevelInitPreEntity( const char *pMapName );
- virtual void LevelInitPostEntity();
- virtual void LevelShutdown( void );
-
- virtual ClientClass *GetAllClasses( void );
-
- virtual int HudVidInit( void );
- virtual void HudProcessInput( bool bActive );
- virtual void HudUpdate( bool bActive );
- virtual void HudReset( void );
- virtual void HudText( const char * message );
-
- // Mouse Input Interfaces
- virtual void IN_ActivateMouse( void );
- virtual void IN_DeactivateMouse( void );
- virtual void IN_Accumulate( void );
- virtual void IN_ClearStates( void );
- virtual bool IN_IsKeyDown( const char *name, bool& isdown );
- virtual void IN_OnMouseWheeled( int nDelta );
- // Raw signal
- virtual int IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding );
- virtual void IN_SetSampleTime( float frametime );
- // Create movement command
- virtual void CreateMove ( int sequence_number, float input_sample_frametime, bool active );
- virtual void ExtraMouseSample( float frametime, bool active );
- virtual bool WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand );
- virtual void EncodeUserCmdToBuffer( bf_write& buf, int slot );
- virtual void DecodeUserCmdFromBuffer( bf_read& buf, int slot );
-
-
- virtual void View_Render( vrect_t *rect );
- virtual void RenderView( const CViewSetup &view, int nClearFlags, int whatToDraw );
- virtual void View_Fade( ScreenFade_t *pSF );
-
- virtual void SetCrosshairAngle( const QAngle& angle );
-
- virtual void InitSprite( CEngineSprite *pSprite, const char *loadname );
- virtual void ShutdownSprite( CEngineSprite *pSprite );
-
- virtual int GetSpriteSize( void ) const;
-
- virtual void VoiceStatus( int entindex, qboolean bTalking );
-
- virtual void InstallStringTableCallback( const char *tableName );
-
- virtual void FrameStageNotify( ClientFrameStage_t curStage );
-
- virtual bool DispatchUserMessage( int msg_type, bf_read &msg_data );
-
- // Save/restore system hooks
- virtual CSaveRestoreData *SaveInit( int size );
- virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
- virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int );
- virtual void PreSave( CSaveRestoreData * );
- virtual void Save( CSaveRestoreData * );
- virtual void WriteSaveHeaders( CSaveRestoreData * );
- virtual void ReadRestoreHeaders( CSaveRestoreData * );
- virtual void Restore( CSaveRestoreData *, bool );
- virtual void DispatchOnRestore();
- virtual void WriteSaveGameScreenshot( const char *pFilename );
-
- // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
- // the appropriate close caption if running with closecaption = 1
- virtual void EmitSentenceCloseCaption( char const *tokenstream );
- virtual void EmitCloseCaption( char const *captionname, float duration );
-
- virtual CStandardRecvProxies* GetStandardRecvProxies();
-
- virtual bool CanRecordDemo( char *errorMsg, int length ) const;
-
- virtual void OnDemoRecordStart( char const* pDemoBaseName );
- virtual void OnDemoRecordStop();
- virtual void OnDemoPlaybackStart( char const* pDemoBaseName );
- virtual void OnDemoPlaybackStop();
-
- virtual bool ShouldDrawDropdownConsole();
-
- // Get client screen dimensions
- virtual int GetScreenWidth();
- virtual int GetScreenHeight();
-
- // save game screenshot writing
- virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, bool bWriteVTF/*=false*/ );
-
- // Gets the location of the player viewpoint
- virtual bool GetPlayerView( CViewSetup &playerView );
-
- // Matchmaking
- virtual void SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties );
- virtual uint GetPresenceID( const char *pIDName );
- virtual const char *GetPropertyIdString( const uint id );
- virtual void GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes );
- virtual void StartStatsReporting( HANDLE handle, bool bArbitrated );
-
- virtual void InvalidateMdlCache();
-
- virtual void ReloadFilesInList( IFileList *pFilesToReload );
-
- // Let the client handle UI toggle - if this function returns false, the UI will toggle, otherwise it will not.
- virtual bool HandleUiToggle();
-
- // Allow the console to be shown?
- virtual bool ShouldAllowConsole();
-
- // Get renamed recv tables
- virtual CRenamedRecvTableInfo *GetRenamedRecvTableInfos();
-
- // Get the mouthinfo for the sound being played inside UI panels
- virtual CMouthInfo *GetClientUIMouthInfo();
-
- // Notify the client that a file has been received from the game server
- virtual void FileReceived( const char * fileName, unsigned int transferID );
-
- virtual const char* TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName );
-
- virtual void ClientAdjustStartSoundParams( struct StartSoundParams_t& params );
-
- // Returns true if the disconnect command has been handled by the client
- virtual bool DisconnectAttempt( void );
-public:
- void PrecacheMaterial( const char *pMaterialName );
-
- virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar );
-
-private:
- void UncacheAllMaterials( );
- void ResetStringTablePointers();
-
- CUtlVector< IMaterial * > m_CachedMaterials;
-};
-
-
-CHLClient gHLClient;
-IBaseClientDLL *clientdll = &gHLClient;
-
-EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLClient, IBaseClientDLL, CLIENT_DLL_INTERFACE_VERSION, gHLClient );
-
-
-//-----------------------------------------------------------------------------
-// Precaches a material
-//-----------------------------------------------------------------------------
-void PrecacheMaterial( const char *pMaterialName )
-{
- gHLClient.PrecacheMaterial( pMaterialName );
-}
-
-//-----------------------------------------------------------------------------
-// Converts a previously precached material into an index
-//-----------------------------------------------------------------------------
-int GetMaterialIndex( const char *pMaterialName )
-{
- if (pMaterialName)
- {
- int nIndex = g_pStringTableMaterials->FindStringIndex( pMaterialName );
- Assert( nIndex >= 0 );
- if (nIndex >= 0)
- return nIndex;
- }
-
- // This is the invalid string index
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Converts precached material indices into strings
-//-----------------------------------------------------------------------------
-const char *GetMaterialNameFromIndex( int nIndex )
-{
- if (nIndex != (g_pStringTableMaterials->GetMaxStrings() - 1))
- {
- return g_pStringTableMaterials->GetString( nIndex );
- }
- else
- {
- return NULL;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Precaches a particle system
-//-----------------------------------------------------------------------------
-void PrecacheParticleSystem( const char *pParticleSystemName )
-{
- g_pStringTableParticleEffectNames->AddString( false, pParticleSystemName );
- g_pParticleSystemMgr->PrecacheParticleSystem( pParticleSystemName );
-}
-
-
-//-----------------------------------------------------------------------------
-// Converts a previously precached particle system into an index
-//-----------------------------------------------------------------------------
-int GetParticleSystemIndex( const char *pParticleSystemName )
-{
- if ( pParticleSystemName )
- {
- int nIndex = g_pStringTableParticleEffectNames->FindStringIndex( pParticleSystemName );
- if ( nIndex != INVALID_STRING_INDEX )
- return nIndex;
- DevWarning("Client: Missing precache for particle system \"%s\"!\n", pParticleSystemName );
- }
-
- // This is the invalid string index
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Converts precached particle system indices into strings
-//-----------------------------------------------------------------------------
-const char *GetParticleSystemNameFromIndex( int nIndex )
-{
- if ( nIndex < g_pStringTableParticleEffectNames->GetMaxStrings() )
- return g_pStringTableParticleEffectNames->GetString( nIndex );
- return "error";
-}
-
-//-----------------------------------------------------------------------------
-// Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode)
-//-----------------------------------------------------------------------------
-bool IsEngineThreaded()
-{
- if ( g_pcv_ThreadMode )
- {
- return g_pcv_ThreadMode->GetBool();
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-
-CHLClient::CHLClient()
-{
- // Kinda bogus, but the logic in the engine is too convoluted to put it there
- g_bLevelInitialized = false;
-}
-
-
-extern IGameSystem *ViewportClientSystem();
-
-
-//-----------------------------------------------------------------------------
-ISourceVirtualReality *g_pSourceVR = NULL;
-
-// Purpose: Called when the DLL is first loaded.
-// Input : engineFactory -
-// Output : int
-//-----------------------------------------------------------------------------
-int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals )
-{
- InitCRTMemDebug();
- MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
-
-
-#ifdef SIXENSE
- g_pSixenseInput = new SixenseInput;
-#endif
-
- // Hook up global variables
- gpGlobals = pGlobals;
-
- ConnectTier1Libraries( &appSystemFactory, 1 );
- ConnectTier2Libraries( &appSystemFactory, 1 );
- ConnectTier3Libraries( &appSystemFactory, 1 );
-
-#ifndef NO_STEAM
- ClientSteamContext().Activate();
-#endif
-
- // We aren't happy unless we get all of our interfaces.
- // please don't collapse this into one monolithic boolean expression (impossible to debug)
- if ( (engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (effects = (IVEfx *)appSystemFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (enginetrace = (IEngineTrace *)appSystemFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL )) == NULL )
- return false;
- if ( (render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( !mdlcache )
- return false;
- if ( (modelinfo = (IVModelInfoClient *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( (enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) == NULL )
- return false;
- if ( (networkstringtable = (INetworkStringTableContainer *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLECLIENT,NULL)) == NULL )
- return false;
- if ( (partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) == NULL )
- return false;
- if ( (shadowmgr = (IShadowMgr *)appSystemFactory(ENGINE_SHADOWMGR_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (staticpropmgr = (IStaticPropMgrClient *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_CLIENT, NULL)) == NULL )
- return false;
- if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) == NULL )
- return false;
- if ( (gameeventmanager = (IGameEventManager2 *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2,NULL)) == NULL )
- return false;
- if ( (soundemitterbase = (ISoundEmitterSystemBase *)appSystemFactory(SOUNDEMITTERSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL )
- return false;
- if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( IsX360() && (xboxsystem = (IXboxSystem *)appSystemFactory( XBOXSYSTEM_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( IsX360() && (matchmaking = (IMatchmaking *)appSystemFactory( VENGINE_MATCHMAKING_VERSION, NULL )) == NULL )
- return false;
-#ifndef _XBOX
- if ( ( gamestatsuploader = (IUploadGameStats *)appSystemFactory( INTERFACEVERSION_UPLOADGAMESTATS, NULL )) == NULL )
- return false;
-#endif
-
-#if defined( REPLAY_ENABLED )
- if ( IsPC() && (g_pEngineReplay = (IEngineReplay *)appSystemFactory( ENGINE_REPLAY_INTERFACE_VERSION, NULL )) == NULL )
- return false;
- if ( IsPC() && (g_pEngineClientReplay = (IEngineClientReplay *)appSystemFactory( ENGINE_REPLAY_CLIENT_INTERFACE_VERSION, NULL )) == NULL )
- return false;
-#endif
-
- if (!g_pMatSystemSurface)
- return false;
-
-#ifdef WORKSHOP_IMPORT_ENABLED
- if ( !ConnectDataModel( appSystemFactory ) )
- return false;
- if ( InitDataModel() != INIT_OK )
- return false;
- InitFbx();
-#endif
-
- // it's ok if this is NULL. That just means the headtrack.dll wasn't found
- g_pSourceVR = (ISourceVirtualReality *)appSystemFactory(SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION, NULL);
-
- factorylist_t factories;
- factories.appSystemFactory = appSystemFactory;
- factories.physicsFactory = physicsFactory;
- FactoryList_Store( factories );
-
- // Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully
- if ( !soundemitterbase->Connect( appSystemFactory ) )
- {
- return false;
- }
-
- if ( CommandLine()->FindParm( "-textmode" ) )
- g_bTextMode = true;
-
- if ( CommandLine()->FindParm( "-makedevshots" ) )
- g_MakingDevShots = true;
-
- // Not fatal if the material system stub isn't around.
- materials_stub = (IMaterialSystemStub*)appSystemFactory( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION, NULL );
-
- if( !g_pMaterialSystemHardwareConfig )
- return false;
-
- // Hook up the gaussian random number generator
- s_GaussianRandomStream.AttachToStream( random );
-
- // Initialize the console variables.
- ConVar_Register( FCVAR_CLIENTDLL );
-
- g_pcv_ThreadMode = g_pCVar->FindVar( "host_thread_mode" );
-
- // If we are in VR mode do some initial setup work
- if( UseVR() )
- {
- int nViewportWidth, nViewportHeight;
-
- g_pSourceVR->GetViewportBounds( ISourceVirtualReality::VREye_Left, NULL, NULL, &nViewportWidth, &nViewportHeight );
- vgui::surface()->SetFullscreenViewport( 0, 0, nViewportWidth, nViewportHeight );
-
- vgui::ivgui()->SetVRMode( true );
- }
-
- if (!Initializer::InitializeAllObjects())
- return false;
-
- if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials))
- return false;
-
-
- if (!VGui_Startup( appSystemFactory ))
- return false;
-
- vgui::VGui_InitMatSysInterfacesList( "ClientDLL", &appSystemFactory, 1 );
-
- // Add the client systems.
-
- // Client Leaf System has to be initialized first, since DetailObjectSystem uses it
- IGameSystem::Add( GameStringSystem() );
- IGameSystem::Add( SoundEmitterSystem() );
- IGameSystem::Add( ToolFrameworkClientSystem() );
- IGameSystem::Add( ClientLeafSystem() );
- IGameSystem::Add( DetailObjectSystem() );
- IGameSystem::Add( ViewportClientSystem() );
- IGameSystem::Add( ClientEffectPrecacheSystem() );
- IGameSystem::Add( g_pClientShadowMgr );
- IGameSystem::Add( g_pColorCorrectionMgr ); // NOTE: This must happen prior to ClientThinkList (color correction is updated there)
- IGameSystem::Add( ClientThinkList() );
- IGameSystem::Add( ClientSoundscapeSystem() );
- IGameSystem::Add( PerfVisualBenchmark() );
- IGameSystem::Add( MumbleSystem() );
-
- #if defined( TF_CLIENT_DLL )
- IGameSystem::Add( CustomTextureToolCacheGameSystem() );
- IGameSystem::Add( TFSharedContentManager() );
- #endif
-
-#if defined( TF_CLIENT_DLL )
- if ( g_AbuseReportMgr != NULL )
- {
- IGameSystem::Add( g_AbuseReportMgr );
- }
-#endif
-
-#if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST )
- IGameSystem::Add( GetPredictionCopyTester() );
-#endif
-
- modemanager->Init( );
-
- g_pClientMode->InitViewport();
-
- gHUD.Init();
-
- g_pClientMode->Init();
-
- if ( !IGameSystem::InitAllSystems() )
- return false;
-
- g_pClientMode->Enable();
-
- if ( !view )
- {
- view = ( IViewRender * )&g_DefaultViewRender;
- }
-
- view->Init();
- vieweffects->Init();
-
- C_BaseTempEntity::PrecacheTempEnts();
-
- input->Init_All();
-
- VGui_CreateGlobalPanels();
-
- InitSmokeFogOverlay();
-
- // Register user messages..
- CUserMessageRegister::RegisterAll();
-
- ClientVoiceMgr_Init();
-
- // Embed voice status icons inside chat element
- {
- vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL );
- GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent );
- }
-
- if ( !PhysicsDLLInit( physicsFactory ) )
- return false;
-
- g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() );
- g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );
- g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() );
-
- ClientWorldFactoryInit();
-
- C_BaseAnimating::InitBoneSetupThreadPool();
-
-#if defined( WIN32 ) && !defined( _X360 )
- // NVNT connect haptics sytem
- ConnectHaptics(appSystemFactory);
-#endif
-#ifndef _X360
- HookHapticMessages(); // Always hook the messages
-#endif
- return true;
-}
-
-bool CHLClient::ReplayInit( CreateInterfaceFn fnReplayFactory )
-{
-#if defined( REPLAY_ENABLED )
- if ( !IsPC() )
- return false;
- if ( (g_pReplay = (IReplaySystem *)fnReplayFactory( REPLAY_INTERFACE_VERSION, NULL ) ) == NULL )
- return false;
- if ( (g_pClientReplayContext = g_pReplay->CL_GetContext()) == NULL )
- return false;
-
- return true;
-#else
- return false;
-#endif
-}
-
-bool CHLClient::ReplayPostInit()
-{
-#if defined( REPLAY_ENABLED )
- if ( ( g_pReplayManager = g_pClientReplayContext->GetReplayManager() ) == NULL )
- return false;
- if ( ( g_pReplayScreenshotManager = g_pClientReplayContext->GetScreenshotManager() ) == NULL )
- return false;
- if ( ( g_pReplayPerformanceManager = g_pClientReplayContext->GetPerformanceManager() ) == NULL )
- return false;
- if ( ( g_pReplayPerformanceController = g_pClientReplayContext->GetPerformanceController() ) == NULL )
- return false;
- if ( ( g_pReplayMovieManager = g_pClientReplayContext->GetMovieManager() ) == NULL )
- return false;
- return true;
-#else
- return false;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called after client & server DLL are loaded and all systems initialized
-//-----------------------------------------------------------------------------
-void CHLClient::PostInit()
-{
- IGameSystem::PostInitAllSystems();
-
-#ifdef SIXENSE
- // allow sixnese input to perform post-init operations
- g_pSixenseInput->PostInit();
-#endif
-
- // If we are in VR mode execute headtrack.cfg in PostInit so all the convars will
- // already be set up
- if( UseVR() )
- {
- // general all-game stuff
- engine->ExecuteClientCmd( "exec headtrack\\headtrack.cfg" );
-
- // game specific VR config
- CUtlString sCmd;
- sCmd.Format( "exec headtrack_%s.cfg", COM_GetModDirectory() );
- engine->ExecuteClientCmd( sCmd.Get() );
-
- engine->ExecuteClientCmd( "vr_start_tracking" );
-
- vgui::surface()->SetSoftwareCursor( true );
-#if defined(POSIX)
- ConVarRef m_rawinput( "m_rawinput" );
- m_rawinput.SetValue( 1 );
-
- ConVarRef mat_vsync( "mat_vsync" );
- mat_vsync.SetValue( 0 );
-#endif
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called when the client .dll is being dismissed
-//-----------------------------------------------------------------------------
-void CHLClient::Shutdown( void )
-{
- if (g_pAchievementsAndStatsInterface)
- {
- g_pAchievementsAndStatsInterface->ReleasePanel();
- }
-
-#ifdef SIXENSE
- g_pSixenseInput->Shutdown();
- delete g_pSixenseInput;
- g_pSixenseInput = NULL;
-#endif
-
- C_BaseAnimating::ShutdownBoneSetupThreadPool();
- ClientWorldFactoryShutdown();
-
- g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() );
- g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() );
- g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() );
-
- ClientVoiceMgr_Shutdown();
-
- Initializer::FreeAllObjects();
-
- g_pClientMode->Disable();
- g_pClientMode->Shutdown();
-
- input->Shutdown_All();
- C_BaseTempEntity::ClearDynamicTempEnts();
- TermSmokeFogOverlay();
- view->Shutdown();
- g_pParticleSystemMgr->UncacheAllParticleSystems();
- UncacheAllMaterials();
-
- IGameSystem::ShutdownAllSystems();
-
- gHUD.Shutdown();
- VGui_Shutdown();
-
- ParticleMgr()->Term();
-
- ClearKeyValuesCache();
-
-#ifndef NO_STEAM
- ClientSteamContext().Shutdown();
-#endif
-
-#ifdef WORKSHOP_IMPORT_ENABLED
- ShutdownDataModel();
- DisconnectDataModel();
- ShutdownFbx();
-#endif
-
- // This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
-// DisconnectTier3Libraries( );
- DisconnectTier2Libraries( );
- ConVar_Unregister();
- DisconnectTier1Libraries( );
-
- gameeventmanager = NULL;
-
-#if defined( WIN32 ) && !defined( _X360 )
- // NVNT Disconnect haptics system
- DisconnectHaptics();
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Called when the game initializes
-// and whenever the vid_mode is changed
-// so the HUD can reinitialize itself.
-// Output : int
-//-----------------------------------------------------------------------------
-int CHLClient::HudVidInit( void )
-{
- gHUD.VidInit();
-
- GetClientVoiceMgr()->VidInit();
-
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-// Method used to allow the client to filter input messages before the
-// move record is transmitted to the server
-//-----------------------------------------------------------------------------
-void CHLClient::HudProcessInput( bool bActive )
-{
- g_pClientMode->ProcessInput( bActive );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called when shared data gets changed, allows dll to modify data
-// Input : bActive -
-//-----------------------------------------------------------------------------
-void CHLClient::HudUpdate( bool bActive )
-{
- float frametime = gpGlobals->frametime;
-
-#if defined( TF_CLIENT_DLL )
- CRTime::UpdateRealTime();
-#endif
-
- GetClientVoiceMgr()->Frame( frametime );
-
- gHUD.UpdateHud( bActive );
-
- {
- C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
- IGameSystem::UpdateAllSystems( frametime );
- }
-
- // run vgui animations
- vgui::GetAnimationController()->UpdateAnimations( engine->Time() );
-
- hudlcd->SetGlobalStat( "(time_int)", VarArgs( "%d", (int)gpGlobals->curtime ) );
- hudlcd->SetGlobalStat( "(time_float)", VarArgs( "%.2f", gpGlobals->curtime ) );
-
- // I don't think this is necessary any longer, but I will leave it until
- // I can check into this further.
- C_BaseTempEntity::CheckDynamicTempEnts();
-
-#ifdef SIXENSE
- // If we're not connected, update sixense so we can move the mouse cursor when in the menus
- if( !engine->IsConnected() || engine->IsPaused() )
- {
- g_pSixenseInput->SixenseFrame( 0, NULL );
- }
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called to restore to "non"HUD state.
-//-----------------------------------------------------------------------------
-void CHLClient::HudReset( void )
-{
- gHUD.VidInit();
- PhysicsReset();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called to add hud text message
-//-----------------------------------------------------------------------------
-void CHLClient::HudText( const char * message )
-{
- DispatchHudText( message );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CHLClient::ShouldDrawDropdownConsole()
-{
-#if defined( REPLAY_ENABLED )
- extern ConVar hud_freezecamhide;
- extern bool IsTakingAFreezecamScreenshot();
-
- if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() )
- {
- return false;
- }
-#endif
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : ClientClass
-//-----------------------------------------------------------------------------
-ClientClass *CHLClient::GetAllClasses( void )
-{
- return g_pClientClassHead;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHLClient::IN_ActivateMouse( void )
-{
- input->ActivateMouse();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHLClient::IN_DeactivateMouse( void )
-{
- input->DeactivateMouse();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHLClient::IN_Accumulate ( void )
-{
- input->AccumulateMouse();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHLClient::IN_ClearStates ( void )
-{
- input->ClearStates();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Engine can query for particular keys
-// Input : *name -
-//-----------------------------------------------------------------------------
-bool CHLClient::IN_IsKeyDown( const char *name, bool& isdown )
-{
- kbutton_t *key = input->FindKey( name );
- if ( !key )
- {
- return false;
- }
-
- isdown = ( key->state & 1 ) ? true : false;
-
- // Found the key by name
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Engine can issue a key event
-// Input : eventcode -
-// keynum -
-// *pszCurrentBinding -
-void CHLClient::IN_OnMouseWheeled( int nDelta )
-{
-#if defined( REPLAY_ENABLED )
- CReplayPerformanceEditorPanel *pPerfEditor = ReplayUI_GetPerformanceEditor();
- if ( pPerfEditor )
- {
- pPerfEditor->OnInGameMouseWheelEvent( nDelta );
- }
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Engine can issue a key event
-// Input : eventcode -
-// keynum -
-// *pszCurrentBinding -
-// Output : int
-//-----------------------------------------------------------------------------
-int CHLClient::IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding )
-{
- return input->KeyEvent( eventcode, keynum, pszCurrentBinding );
-}
-
-void CHLClient::ExtraMouseSample( float frametime, bool active )
-{
- Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
- Assert( C_BaseEntity::IsAbsQueriesValid() );
-
- C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
-
- MDLCACHE_CRITICAL_SECTION();
- input->ExtraMouseSample( frametime, active );
-}
-
-void CHLClient::IN_SetSampleTime( float frametime )
-{
- input->Joystick_SetSampleTime( frametime );
- input->IN_SetSampleTime( frametime );
-
-#ifdef SIXENSE
- g_pSixenseInput->ResetFrameTime( frametime );
-#endif
-}
-//-----------------------------------------------------------------------------
-// Purpose: Fills in usercmd_s structure based on current view angles and key/controller inputs
-// Input : frametime - timestamp for last frame
-// *cmd - the command to fill in
-// active - whether the user is fully connected to a server
-//-----------------------------------------------------------------------------
-void CHLClient::CreateMove ( int sequence_number, float input_sample_frametime, bool active )
-{
-
- Assert( C_BaseEntity::IsAbsRecomputationsEnabled() );
- Assert( C_BaseEntity::IsAbsQueriesValid() );
-
- C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false );
-
- MDLCACHE_CRITICAL_SECTION();
- input->CreateMove( sequence_number, input_sample_frametime, active );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *buf -
-// from -
-// to -
-//-----------------------------------------------------------------------------
-bool CHLClient::WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand )
-{
- return input->WriteUsercmdDeltaToBuffer( buf, from, to, isnewcommand );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : buf -
-// buffersize -
-// slot -
-//-----------------------------------------------------------------------------
-void CHLClient::EncodeUserCmdToBuffer( bf_write& buf, int slot )
-{
- input->EncodeUserCmdToBuffer( buf, slot );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : buf -
-// buffersize -
-// slot -
-//-----------------------------------------------------------------------------
-void CHLClient::DecodeUserCmdFromBuffer( bf_read& buf, int slot )
-{
- input->DecodeUserCmdFromBuffer( buf, slot );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CHLClient::View_Render( vrect_t *rect )
-{
- VPROF( "View_Render" );
-
- // UNDONE: This gets hit at startup sometimes, investigate - will cause NaNs in calcs inside Render()
- if ( rect->width == 0 || rect->height == 0 )
- return;
-
- view->Render( rect );
- UpdatePerfStats();
-}
-
-
-//-----------------------------------------------------------------------------
-// Gets the location of the player viewpoint
-//-----------------------------------------------------------------------------
-bool CHLClient::GetPlayerView( CViewSetup &playerView )
-{
- playerView = *view->GetPlayerViewSetup();
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Matchmaking
-//-----------------------------------------------------------------------------
-void CHLClient::SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties )
-{
- presence->SetupGameProperties( contexts, properties );
-}
-
-uint CHLClient::GetPresenceID( const char *pIDName )
-{
- return presence->GetPresenceID( pIDName );
-}
-
-const char *CHLClient::GetPropertyIdString( const uint id )
-{
- return presence->GetPropertyIdString( id );
-}
-
-void CHLClient::GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes )
-{
- presence->GetPropertyDisplayString( id, value, pOutput, nBytes );
-}
-
-void CHLClient::StartStatsReporting( HANDLE handle, bool bArbitrated )
-{
- presence->StartStatsReporting( handle, bArbitrated );
-}
-
-//-----------------------------------------------------------------------------
-//
-//-----------------------------------------------------------------------------
-void CHLClient::InvalidateMdlCache()
-{
- C_BaseAnimating *pAnimating;
- for ( C_BaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity(pEntity) )
- {
- pAnimating = dynamic_cast<C_BaseAnimating *>(pEntity);
- if ( pAnimating )
- {
- pAnimating->InvalidateMdlCache();
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pSF -
-//-----------------------------------------------------------------------------
-void CHLClient::View_Fade( ScreenFade_t *pSF )
-{
- if ( pSF != NULL )
- vieweffects->Fade( *pSF );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Per level init
-//-----------------------------------------------------------------------------
-void CHLClient::LevelInitPreEntity( char const* pMapName )
-{
- // HACK: Bogus, but the logic is too complicated in the engine
- if (g_bLevelInitialized)
- return;
- g_bLevelInitialized = true;
-
- input->LevelInit();
-
- vieweffects->LevelInit();
-
- //Tony; loadup per-map manifests.
- ParseParticleEffectsMap( pMapName, true );
-
- // Tell mode manager that map is changing
- modemanager->LevelInit( pMapName );
- ParticleMgr()->LevelInit();
-
- hudlcd->SetGlobalStat( "(mapname)", pMapName );
-
- C_BaseTempEntity::ClearDynamicTempEnts();
- clienteffects->Flush();
- view->LevelInit();
- tempents->LevelInit();
- ResetToneMapping(1.0);
-
- IGameSystem::LevelInitPreEntityAllSystems(pMapName);
-
-#ifdef USES_ECON_ITEMS
- GameItemSchema_t *pItemSchema = ItemSystem()->GetItemSchema();
- if ( pItemSchema )
- {
- pItemSchema->BInitFromDelayedBuffer();
- }
-#endif // USES_ECON_ITEMS
-
- ResetWindspeed();
-
-#if !defined( NO_ENTITY_PREDICTION )
- // don't do prediction if single player!
- // don't set direct because of FCVAR_USERINFO
- if ( gpGlobals->maxClients > 1 )
- {
- if ( !cl_predict->GetInt() )
- {
- engine->ClientCmd( "cl_predict 1" );
- }
- }
- else
- {
- if ( cl_predict->GetInt() )
- {
- engine->ClientCmd( "cl_predict 0" );
- }
- }
-#endif
-
- // Check low violence settings for this map
- g_RagdollLVManager.SetLowViolence( pMapName );
-
- gHUD.LevelInit();
-
-#if defined( REPLAY_ENABLED )
- // Initialize replay ragdoll recorder
- if ( !engine->IsPlayingDemo() )
- {
- CReplayRagdollRecorder::Instance().Init();
- }
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Per level init
-//-----------------------------------------------------------------------------
-void CHLClient::LevelInitPostEntity( )
-{
- IGameSystem::LevelInitPostEntityAllSystems();
- C_PhysPropClientside::RecreateAll();
- internalCenterPrint->Clear();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Reset our global string table pointers
-//-----------------------------------------------------------------------------
-void CHLClient::ResetStringTablePointers()
-{
- g_pStringTableParticleEffectNames = NULL;
- g_StringTableEffectDispatch = NULL;
- g_StringTableVguiScreen = NULL;
- g_pStringTableMaterials = NULL;
- g_pStringTableInfoPanel = NULL;
- g_pStringTableClientSideChoreoScenes = NULL;
- g_pStringTableServerMapCycle = NULL;
-
-#ifdef TF_CLIENT_DLL
- g_pStringTableServerPopFiles = NULL;
- g_pStringTableServerMapCycleMvM = NULL;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Per level de-init
-//-----------------------------------------------------------------------------
-void CHLClient::LevelShutdown( void )
-{
- // HACK: Bogus, but the logic is too complicated in the engine
- if (!g_bLevelInitialized)
- return;
-
- g_bLevelInitialized = false;
-
- // Disable abs recomputations when everything is shutting down
- CBaseEntity::EnableAbsRecomputations( false );
-
- // Level shutdown sequence.
- // First do the pre-entity shutdown of all systems
- IGameSystem::LevelShutdownPreEntityAllSystems();
-
- C_PhysPropClientside::DestroyAll();
-
- modemanager->LevelShutdown();
-
- // Remove temporary entities before removing entities from the client entity list so that the te_* may
- // clean up before hand.
- tempents->LevelShutdown();
-
- // Now release/delete the entities
- cl_entitylist->Release();
-
- C_BaseEntityClassList *pClassList = s_pClassLists;
- while ( pClassList )
- {
- pClassList->LevelShutdown();
- pClassList = pClassList->m_pNextClassList;
- }
-
- // Now do the post-entity shutdown of all systems
- IGameSystem::LevelShutdownPostEntityAllSystems();
-
- view->LevelShutdown();
- beams->ClearBeams();
- ParticleMgr()->RemoveAllEffects();
-
- StopAllRumbleEffects();
-
- gHUD.LevelShutdown();
-
- internalCenterPrint->Clear();
-
- messagechars->Clear();
-
- g_pParticleSystemMgr->UncacheAllParticleSystems();
- UncacheAllMaterials();
-
-#ifdef _XBOX
- ReleaseRenderTargets();
-#endif
-
- // string tables are cleared on disconnect from a server, so reset our global pointers to NULL
- ResetStringTablePointers();
-
-#if defined( REPLAY_ENABLED )
- // Shutdown the ragdoll recorder
- CReplayRagdollRecorder::Instance().Shutdown();
- CReplayRagdollCache::Instance().Shutdown();
-#endif
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Engine received crosshair offset ( autoaim )
-// Input : angle -
-//-----------------------------------------------------------------------------
-void CHLClient::SetCrosshairAngle( const QAngle& angle )
-{
- CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
- if ( crosshair )
- {
- crosshair->SetCrosshairAngle( angle );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Helper to initialize sprite from .spr semaphor
-// Input : *pSprite -
-// *loadname -
-//-----------------------------------------------------------------------------
-void CHLClient::InitSprite( CEngineSprite *pSprite, const char *loadname )
-{
- if ( pSprite )
- {
- pSprite->Init( loadname );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pSprite -
-//-----------------------------------------------------------------------------
-void CHLClient::ShutdownSprite( CEngineSprite *pSprite )
-{
- if ( pSprite )
- {
- pSprite->Shutdown();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Tells engine how much space to allocate for sprite objects
-// Output : int
-//-----------------------------------------------------------------------------
-int CHLClient::GetSpriteSize( void ) const
-{
- return sizeof( CEngineSprite );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : entindex -
-// bTalking -
-//-----------------------------------------------------------------------------
-void CHLClient::VoiceStatus( int entindex, qboolean bTalking )
-{
- GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, !!bTalking );
-}
-
-
-//-----------------------------------------------------------------------------
-// Called when the string table for materials changes
-//-----------------------------------------------------------------------------
-void OnMaterialStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
-{
- // Make sure this puppy is precached
- gHLClient.PrecacheMaterial( newString );
- RequestCacheUsedMaterials();
-}
-
-
-//-----------------------------------------------------------------------------
-// Called when the string table for particle systems changes
-//-----------------------------------------------------------------------------
-void OnParticleSystemStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
-{
- // Make sure this puppy is precached
- g_pParticleSystemMgr->PrecacheParticleSystem( newString );
- RequestCacheUsedMaterials();
-}
-
-
-//-----------------------------------------------------------------------------
-// Called when the string table for VGUI changes
-//-----------------------------------------------------------------------------
-void OnVguiScreenTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
-{
- // Make sure this puppy is precached
- vgui::Panel *pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( newString, 100, NULL, NULL );
- if ( pPanel )
- PanelMetaClassMgr()->DestroyPanelMetaClass( pPanel );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Preload the string on the client (if single player it should already be in the cache from the server!!!)
-// Input : *object -
-// *stringTable -
-// stringNumber -
-// *newString -
-// *newData -
-//-----------------------------------------------------------------------------
-void OnSceneStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData )
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Hook up any callbacks here, the table definition has been parsed but
-// no data has been added yet
-//-----------------------------------------------------------------------------
-void CHLClient::InstallStringTableCallback( const char *tableName )
-{
- // Here, cache off string table IDs
- if (!Q_strcasecmp(tableName, "VguiScreen"))
- {
- // Look up the id
- g_StringTableVguiScreen = networkstringtable->FindTable( tableName );
-
- // When the material list changes, we need to know immediately
- g_StringTableVguiScreen->SetStringChangedCallback( NULL, OnVguiScreenTableChanged );
- }
- else if (!Q_strcasecmp(tableName, "Materials"))
- {
- // Look up the id
- g_pStringTableMaterials = networkstringtable->FindTable( tableName );
-
- // When the material list changes, we need to know immediately
- g_pStringTableMaterials->SetStringChangedCallback( NULL, OnMaterialStringTableChanged );
- }
- else if ( !Q_strcasecmp( tableName, "EffectDispatch" ) )
- {
- g_StringTableEffectDispatch = networkstringtable->FindTable( tableName );
- }
- else if ( !Q_strcasecmp( tableName, "InfoPanel" ) )
- {
- g_pStringTableInfoPanel = networkstringtable->FindTable( tableName );
- }
- else if ( !Q_strcasecmp( tableName, "Scenes" ) )
- {
- g_pStringTableClientSideChoreoScenes = networkstringtable->FindTable( tableName );
- g_pStringTableClientSideChoreoScenes->SetStringChangedCallback( NULL, OnSceneStringTableChanged );
- }
- else if ( !Q_strcasecmp( tableName, "ParticleEffectNames" ) )
- {
- g_pStringTableParticleEffectNames = networkstringtable->FindTable( tableName );
- networkstringtable->SetAllowClientSideAddString( g_pStringTableParticleEffectNames, true );
- // When the particle system list changes, we need to know immediately
- g_pStringTableParticleEffectNames->SetStringChangedCallback( NULL, OnParticleSystemStringTableChanged );
- }
- else if ( !Q_strcasecmp( tableName, "ServerMapCycle" ) )
- {
- g_pStringTableServerMapCycle = networkstringtable->FindTable( tableName );
- }
-#ifdef TF_CLIENT_DLL
- else if ( !Q_strcasecmp( tableName, "ServerPopFiles" ) )
- {
- g_pStringTableServerPopFiles = networkstringtable->FindTable( tableName );
- }
- else if ( !Q_strcasecmp( tableName, "ServerMapCycleMvM" ) )
- {
- g_pStringTableServerMapCycleMvM = networkstringtable->FindTable( tableName );
- }
-#endif
-
- InstallStringTableCallback_GameRules();
-}
-
-
-//-----------------------------------------------------------------------------
-// Material precache
-//-----------------------------------------------------------------------------
-void CHLClient::PrecacheMaterial( const char *pMaterialName )
-{
- Assert( pMaterialName );
-
- int nLen = Q_strlen( pMaterialName );
- char *pTempBuf = (char*)stackalloc( nLen + 1 );
- memcpy( pTempBuf, pMaterialName, nLen + 1 );
- char *pFound = Q_strstr( pTempBuf, ".vmt\0" );
- if ( pFound )
- {
- *pFound = 0;
- }
-
- IMaterial *pMaterial = materials->FindMaterial( pTempBuf, TEXTURE_GROUP_PRECACHED );
- if ( !IsErrorMaterial( pMaterial ) )
- {
- pMaterial->IncrementReferenceCount();
- m_CachedMaterials.AddToTail( pMaterial );
- }
- else
- {
- if (IsOSX())
- {
- printf("\n ##### CHLClient::PrecacheMaterial could not find material %s (%s)", pMaterialName, pTempBuf );
- }
- }
-}
-
-void CHLClient::UncacheAllMaterials( )
-{
- for (int i = m_CachedMaterials.Count(); --i >= 0; )
- {
- m_CachedMaterials[i]->DecrementReferenceCount();
- }
- m_CachedMaterials.RemoveAll();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pszName -
-// iSize -
-// *pbuf -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool CHLClient::DispatchUserMessage( int msg_type, bf_read &msg_data )
-{
- return usermessages->DispatchUserMessage( msg_type, msg_data );
-}
-
-
-void SimulateEntities()
-{
- VPROF_BUDGET("Client SimulateEntities", VPROF_BUDGETGROUP_CLIENT_SIM);
-
- // Service timer events (think functions).
- ClientThinkList()->PerformThinkFunctions();
-
- // TODO: make an ISimulateable interface so C_BaseNetworkables can simulate?
- {
- VPROF_("C_BaseEntity::Simulate", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
- C_BaseEntityIterator iterator;
- C_BaseEntity *pEnt;
- while ( (pEnt = iterator.Next()) != NULL )
- {
- pEnt->Simulate();
- }
- }
-}
-
-
-bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent )
-{
- VPROF( "AddDataChangeEvent" );
-
- Assert( ent );
- // Make sure we don't already have an event queued for this guy.
- if ( *pStoredEvent >= 0 )
- {
- Assert( g_DataChangedEvents[*pStoredEvent].m_pEntity == ent );
-
- // DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED.
- if ( updateType == DATA_UPDATE_CREATED )
- g_DataChangedEvents[*pStoredEvent].m_UpdateType = updateType;
-
- return false;
- }
- else
- {
- *pStoredEvent = g_DataChangedEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) );
- return true;
- }
-}
-
-
-void ClearDataChangedEvent( int iStoredEvent )
-{
- if ( iStoredEvent != -1 )
- g_DataChangedEvents.Remove( iStoredEvent );
-}
-
-
-void ProcessOnDataChangedEvents()
-{
- VPROF_("ProcessOnDataChangedEvents", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
- FOR_EACH_LL( g_DataChangedEvents, i )
- {
- CDataChangedEvent *pEvent = &g_DataChangedEvents[i];
-
- // Reset their stored event identifier.
- *pEvent->m_pStoredEvent = -1;
-
- // Send the event.
- IClientNetworkable *pNetworkable = pEvent->m_pEntity;
- pNetworkable->OnDataChanged( pEvent->m_UpdateType );
- }
-
- g_DataChangedEvents.Purge();
-}
-
-
-void UpdateClientRenderableInPVSStatus()
-{
- // Vis for this view should already be setup at this point.
-
- // For each client-only entity, notify it if it's newly coming into the PVS.
- CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
- FOR_EACH_LL( theList, i )
- {
- CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
-
- if ( pInfo->m_InPVSStatus & INPVS_YES )
- {
- // Ok, this entity already thinks it's in the PVS. No need to notify it.
- // We need to set the INPVS_YES_THISFRAME flag if it's in this frame at all, so we
- // don't tell the entity it's not in the PVS anymore at the end of the frame.
- if ( !( pInfo->m_InPVSStatus & INPVS_THISFRAME ) )
- {
- if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
- {
- pInfo->m_InPVSStatus |= INPVS_THISFRAME;
- }
- }
- }
- else
- {
- // This entity doesn't think it's in the PVS yet. If it is now in the PVS, let it know.
- if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) )
- {
- pInfo->m_InPVSStatus |= ( INPVS_YES | INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
- }
- }
- }
-}
-
-void UpdatePVSNotifiers()
-{
- MDLCACHE_CRITICAL_SECTION();
-
- // At this point, all the entities that were rendered in the previous frame have INPVS_THISFRAME set
- // so we can tell the entities that aren't in the PVS anymore so.
- CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers();
- FOR_EACH_LL( theList, i )
- {
- CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i];
-
- // If this entity thinks it's in the PVS, but it wasn't in the PVS this frame, tell it so.
- if ( pInfo->m_InPVSStatus & INPVS_YES )
- {
- if ( pInfo->m_InPVSStatus & INPVS_THISFRAME )
- {
- if ( pInfo->m_InPVSStatus & INPVS_NEEDSNOTIFY )
- {
- pInfo->m_pNotify->OnPVSStatusChanged( true );
- }
- // Clear it for the next time around.
- pInfo->m_InPVSStatus &= ~( INPVS_THISFRAME | INPVS_NEEDSNOTIFY );
- }
- else
- {
- pInfo->m_InPVSStatus &= ~INPVS_YES;
- pInfo->m_pNotify->OnPVSStatusChanged( false );
- }
- }
- }
-}
-
-
-void OnRenderStart()
-{
- VPROF( "OnRenderStart" );
- MDLCACHE_CRITICAL_SECTION();
- MDLCACHE_COARSE_LOCK();
-
-#ifdef PORTAL
- 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.
-#endif
-
- partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
- C_BaseEntity::SetAbsQueriesValid( false );
-
- Rope_ResetCounters();
-
- // Interpolate server entities and move aiments.
- {
- PREDICTION_TRACKVALUECHANGESCOPE( "interpolation" );
- C_BaseEntity::InterpolateServerEntities();
- }
-
- {
- // vprof node for this bloc of math
- VPROF( "OnRenderStart: dirty bone caches");
- // Invalidate any bone information.
- C_BaseAnimating::InvalidateBoneCaches();
-
- C_BaseEntity::SetAbsQueriesValid( true );
- C_BaseEntity::EnableAbsRecomputations( true );
-
- // Enable access to all model bones except view models.
- // This is necessary for aim-ent computation to occur properly
- C_BaseAnimating::PushAllowBoneAccess( true, false, "OnRenderStart->CViewRender::SetUpView" ); // pops in CViewRender::SetUpView
-
- // FIXME: This needs to be done before the player moves; it forces
- // aiments the player may be attached to to forcibly update their position
- C_BaseEntity::MarkAimEntsDirty();
- }
-
- // Make sure the camera simulation happens before OnRenderStart, where it's used.
- // NOTE: the only thing that happens in CAM_Think is thirdperson related code.
- input->CAM_Think();
-
- // This will place the player + the view models + all parent
- // entities at the correct abs position so that their attachment points
- // are at the correct location
- view->OnRenderStart();
-
- RopeManager()->OnRenderStart();
-
- // This will place all entities in the correct position in world space and in the KD-tree
- C_BaseAnimating::UpdateClientSideAnimations();
-
- partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
-
- // Process OnDataChanged events.
- ProcessOnDataChangedEvents();
-
- // Reset the overlay alpha. Entities can change the state of this in their think functions.
- g_SmokeFogOverlayAlpha = 0;
-
- // This must occur prior to SimulatEntities,
- // which is where the client thinks for c_colorcorrection + c_colorcorrectionvolumes
- // update the color correction weights.
- // FIXME: The place where IGameSystem::Update is called should be in here
- // so we don't have to explicitly call ResetColorCorrectionWeights + SimulateEntities, etc.
- g_pColorCorrectionMgr->ResetColorCorrectionWeights();
-
- // Simulate all the entities.
- SimulateEntities();
- PhysicsSimulate();
-
- C_BaseAnimating::ThreadedBoneSetup();
-
- {
- VPROF_("Client TempEnts", 0, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT);
- // This creates things like temp entities.
- engine->FireEvents();
-
- // Update temp entities
- tempents->Update();
-
- // Update temp ent beams...
- beams->UpdateTempEntBeams();
-
- // Lock the frame from beam additions
- SetBeamCreationAllowed( false );
- }
-
- // Update particle effects (eventually, the effects should use Simulate() instead of having
- // their own update system).
- {
- // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined,
- // to help track down bad math.
- FPExceptionEnabler enableExceptions;
- VPROF_BUDGET( "ParticleMgr()->Simulate", VPROF_BUDGETGROUP_PARTICLE_SIMULATION );
- ParticleMgr()->Simulate( gpGlobals->frametime );
- }
-
- // Now that the view model's position is setup and aiments are marked dirty, update
- // their positions so they're in the leaf system correctly.
- C_BaseEntity::CalcAimEntPositions();
-
- // For entities marked for recording, post bone messages to IToolSystems
- if ( ToolsEnabled() )
- {
- C_BaseEntity::ToolRecordEntities();
- }
-
-#if defined( REPLAY_ENABLED )
- // This will record any ragdolls if Replay mode is enabled on the server
- CReplayRagdollRecorder::Instance().Think();
- CReplayRagdollCache::Instance().Think();
-#endif
-
- // Finally, link all the entities into the leaf system right before rendering.
- C_BaseEntity::AddVisibleEntities();
-}
-
-
-void OnRenderEnd()
-{
- // Disallow access to bones (access is enabled in CViewRender::SetUpView).
- C_BaseAnimating::PopBoneAccess( "CViewRender::SetUpView->OnRenderEnd" );
-
- UpdatePVSNotifiers();
-
- DisplayBoneSetupEnts();
-}
-
-
-
-void CHLClient::FrameStageNotify( ClientFrameStage_t curStage )
-{
- g_CurFrameStage = curStage;
-
- switch( curStage )
- {
- default:
- break;
-
- case FRAME_RENDER_START:
- {
- VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_START" );
-
- // Last thing before rendering, run simulation.
- OnRenderStart();
- }
- break;
-
- case FRAME_RENDER_END:
- {
- VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_END" );
- OnRenderEnd();
-
- PREDICTION_SPEWVALUECHANGES();
- }
- break;
-
- case FRAME_NET_UPDATE_START:
- {
- VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_START" );
- // disabled all recomputations while we update entities
- C_BaseEntity::EnableAbsRecomputations( false );
- C_BaseEntity::SetAbsQueriesValid( false );
- Interpolation_SetLastPacketTimeStamp( engine->GetLastTimeStamp() );
- partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
-
- PREDICTION_STARTTRACKVALUE( "netupdate" );
- }
- break;
- case FRAME_NET_UPDATE_END:
- {
- ProcessCacheUsedMaterials();
-
- // reenable abs recomputation since now all entities have been updated
- C_BaseEntity::EnableAbsRecomputations( true );
- C_BaseEntity::SetAbsQueriesValid( true );
- partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
-
- PREDICTION_ENDTRACKVALUE();
- }
- break;
- case FRAME_NET_UPDATE_POSTDATAUPDATE_START:
- {
- VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START" );
- PREDICTION_STARTTRACKVALUE( "postdataupdate" );
- }
- break;
- case FRAME_NET_UPDATE_POSTDATAUPDATE_END:
- {
- VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END" );
- PREDICTION_ENDTRACKVALUE();
- // Let prediction copy off pristine data
- prediction->PostEntityPacketReceived();
- HLTVCamera()->PostEntityPacketReceived();
-#if defined( REPLAY_ENABLED )
- ReplayCamera()->PostEntityPacketReceived();
-#endif
- }
- break;
- case FRAME_START:
- {
- // Mark the frame as open for client fx additions
- SetFXCreationAllowed( true );
- SetBeamCreationAllowed( true );
- C_BaseEntity::CheckCLInterpChanged();
- }
- break;
- }
-}
-
-CSaveRestoreData *SaveInit( int size );
-
-// Save/restore system hooks
-CSaveRestoreData *CHLClient::SaveInit( int size )
-{
- return ::SaveInit(size);
-}
-
-void CHLClient::SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
-{
- CSave saveHelper( pSaveData );
- saveHelper.WriteFields( pname, pBaseData, pMap, pFields, fieldCount );
-}
-
-void CHLClient::SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount )
-{
- CRestore restoreHelper( pSaveData );
- restoreHelper.ReadFields( pname, pBaseData, pMap, pFields, fieldCount );
-}
-
-void CHLClient::PreSave( CSaveRestoreData *s )
-{
- g_pGameSaveRestoreBlockSet->PreSave( s );
-}
-
-void CHLClient::Save( CSaveRestoreData *s )
-{
- CSave saveHelper( s );
- g_pGameSaveRestoreBlockSet->Save( &saveHelper );
-}
-
-void CHLClient::WriteSaveHeaders( CSaveRestoreData *s )
-{
- CSave saveHelper( s );
- g_pGameSaveRestoreBlockSet->WriteSaveHeaders( &saveHelper );
- g_pGameSaveRestoreBlockSet->PostSave();
-}
-
-void CHLClient::ReadRestoreHeaders( CSaveRestoreData *s )
-{
- CRestore restoreHelper( s );
- g_pGameSaveRestoreBlockSet->PreRestore();
- g_pGameSaveRestoreBlockSet->ReadRestoreHeaders( &restoreHelper );
-}
-
-void CHLClient::Restore( CSaveRestoreData *s, bool b )
-{
- CRestore restore(s);
- g_pGameSaveRestoreBlockSet->Restore( &restore, b );
- g_pGameSaveRestoreBlockSet->PostRestore();
-}
-
-static CUtlVector<EHANDLE> g_RestoredEntities;
-
-void AddRestoredEntity( C_BaseEntity *pEntity )
-{
- if ( !pEntity )
- return;
-
- g_RestoredEntities.AddToTail( EHANDLE(pEntity) );
-}
-
-void CHLClient::DispatchOnRestore()
-{
- for ( int i = 0; i < g_RestoredEntities.Count(); i++ )
- {
- if ( g_RestoredEntities[i] != NULL )
- {
- MDLCACHE_CRITICAL_SECTION();
- g_RestoredEntities[i]->OnRestore();
- }
- }
- g_RestoredEntities.RemoveAll();
-}
-
-void CHLClient::WriteSaveGameScreenshot( const char *pFilename )
-{
- view->WriteSaveGameScreenshot( pFilename );
-}
-
-// Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
-// the appropriate close caption if running with closecaption = 1
-void CHLClient::EmitSentenceCloseCaption( char const *tokenstream )
-{
- extern ConVar closecaption;
-
- if ( !closecaption.GetBool() )
- return;
-
- CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
- if ( hudCloseCaption )
- {
- hudCloseCaption->ProcessSentenceCaptionStream( tokenstream );
- }
-}
-
-
-void CHLClient::EmitCloseCaption( char const *captionname, float duration )
-{
- extern ConVar closecaption;
-
- if ( !closecaption.GetBool() )
- return;
-
- CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
- if ( hudCloseCaption )
- {
- hudCloseCaption->ProcessCaption( captionname, duration );
- }
-}
-
-CStandardRecvProxies* CHLClient::GetStandardRecvProxies()
-{
- return &g_StandardRecvProxies;
-}
-
-bool CHLClient::CanRecordDemo( char *errorMsg, int length ) const
-{
- if ( GetClientModeNormal() )
- {
- return GetClientModeNormal()->CanRecordDemo( errorMsg, length );
- }
-
- return true;
-}
-
-void CHLClient::OnDemoRecordStart( char const* pDemoBaseName )
-{
-}
-
-void CHLClient::OnDemoRecordStop()
-{
-}
-
-void CHLClient::OnDemoPlaybackStart( char const* pDemoBaseName )
-{
-#if defined( REPLAY_ENABLED )
- // Load any ragdoll override frames from disk
- char szRagdollFile[MAX_OSPATH];
- V_snprintf( szRagdollFile, sizeof(szRagdollFile), "%s.dmx", pDemoBaseName );
- CReplayRagdollCache::Instance().Init( szRagdollFile );
-#endif
-}
-
-void CHLClient::OnDemoPlaybackStop()
-{
-#ifdef DEMOPOLISH_ENABLED
- if ( DemoPolish_GetController().m_bInit )
- {
- DemoPolish_GetController().Shutdown();
- }
-#endif
-
-#if defined( REPLAY_ENABLED )
- CReplayRagdollCache::Instance().Shutdown();
-#endif
-}
-
-int CHLClient::GetScreenWidth()
-{
- return ScreenWidth();
-}
-
-int CHLClient::GetScreenHeight()
-{
- return ScreenHeight();
-}
-
-// NEW INTERFACES
-// save game screenshot writing
-void CHLClient::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/,
- bool bWriteVTF/*=false*/ )
-{
- view->WriteSaveGameScreenshotOfSize( pFilename, width, height, bCreatePowerOf2Padded, bWriteVTF );
-}
-
-// See RenderViewInfo_t
-void CHLClient::RenderView( const CViewSetup &setup, int nClearFlags, int whatToDraw )
-{
- VPROF("RenderView");
- view->RenderView( setup, nClearFlags, whatToDraw );
-}
-
-void ReloadSoundEntriesInList( IFileList *pFilesToReload );
-
-//-----------------------------------------------------------------------------
-// For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences.
-//-----------------------------------------------------------------------------
-void CHLClient::ReloadFilesInList( IFileList *pFilesToReload )
-{
- ReloadParticleEffectsInList( pFilesToReload );
- ReloadSoundEntriesInList( pFilesToReload );
-}
-
-bool CHLClient::HandleUiToggle()
-{
-#if defined( REPLAY_ENABLED )
- if ( !g_pEngineReplay || !g_pEngineReplay->IsSupportedModAndPlatform() )
- return false;
-
- CReplayPerformanceEditorPanel *pEditor = ReplayUI_GetPerformanceEditor();
- if ( !pEditor )
- return false;
-
- pEditor->HandleUiToggle();
-
- return true;
-
-#else
- return false;
-#endif
-}
-
-bool CHLClient::ShouldAllowConsole()
-{
- return true;
-}
-
-CRenamedRecvTableInfo *CHLClient::GetRenamedRecvTableInfos()
-{
- return g_pRenamedRecvTableInfoHead;
-}
-
-CMouthInfo g_ClientUIMouth;
-// Get the mouthinfo for the sound being played inside UI panels
-CMouthInfo *CHLClient::GetClientUIMouthInfo()
-{
- return &g_ClientUIMouth;
-}
-
-void CHLClient::FileReceived( const char * fileName, unsigned int transferID )
-{
- if ( g_pGameRules )
- {
- g_pGameRules->OnFileReceived( fileName, transferID );
- }
-}
-
-void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params )
-{
-#ifdef TF_CLIENT_DLL
- CBaseEntity *pEntity = ClientEntityList().GetEnt( params.soundsource );
-
- // A player speaking
- if ( params.entchannel == CHAN_VOICE && GameRules() && pEntity && pEntity->IsPlayer() )
- {
- // Use high-pitched voices for other players if the local player has an item that allows them to hear it (Pyro Goggles)
- if ( !GameRules()->IsLocalPlayer( params.soundsource ) && IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
- {
- params.pitch *= 1.3f;
- }
- // Halloween voice futzery?
- else
- {
- float flHeadScale = 1.f;
- CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flHeadScale, head_scale );
-
- int iHalloweenVoiceSpell = 0;
- CALL_ATTRIB_HOOK_INT_ON_OTHER( pEntity, iHalloweenVoiceSpell, halloween_voice_modulation );
- if ( iHalloweenVoiceSpell > 0 )
- {
- params.pitch *= 0.8f;
- }
- else if( flHeadScale != 1.f )
- {
- // Big head, deep voice
- if( flHeadScale > 1.f )
- {
- params.pitch *= 0.8f;
- }
- else // Small head, high voice
- {
- params.pitch *= 1.3f;
- }
- }
- }
- }
-#endif
-}
-
-const char* CHLClient::TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName )
-{
- if ( !GameRules() )
- return pchEffectName;
-
- return GameRules()->TranslateEffectForVisionFilter( pchEffectType, pchEffectName );
-}
-
-bool CHLClient::DisconnectAttempt( void )
-{
- bool bRet = false;
-
-#if defined( TF_CLIENT_DLL )
- bRet = HandleDisconnectAttempt();
-#endif
-
- return bRet;
-}
-
-bool CHLClient::IsConnectedUserInfoChangeAllowed( IConVar *pCvar )
-{
- return GameRules() ? GameRules()->IsConnectedUserInfoChangeAllowed( NULL ) : true;
-}
-
-#ifndef NO_STEAM
-
-CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex )
-{
- player_info_t pi;
- if ( steamapicontext && steamapicontext->SteamUtils() )
- {
- if ( engine->GetPlayerInfo( iPlayerIndex, &pi ) )
- {
- if ( pi.friendsID )
- {
- return CSteamID( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual );
- }
- }
- }
- return CSteamID();
-}
-
-#endif
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// +#include "cbase.h" +#include <crtmemdebug.h> +#include "vgui_int.h" +#include "clientmode.h" +#include "iinput.h" +#include "iviewrender.h" +#include "ivieweffects.h" +#include "ivmodemanager.h" +#include "prediction.h" +#include "clientsideeffects.h" +#include "particlemgr.h" +#include "steam/steam_api.h" +#include "initializer.h" +#include "smoke_fog_overlay.h" +#include "view.h" +#include "ienginevgui.h" +#include "iefx.h" +#include "enginesprite.h" +#include "networkstringtable_clientdll.h" +#include "voice_status.h" +#include "filesystem.h" +#include "c_te_legacytempents.h" +#include "c_rope.h" +#include "engine/ishadowmgr.h" +#include "engine/IStaticPropMgr.h" +#include "hud_basechat.h" +#include "hud_crosshair.h" +#include "view_shared.h" +#include "env_wind_shared.h" +#include "detailobjectsystem.h" +#include "clienteffectprecachesystem.h" +#include "soundenvelope.h" +#include "c_basetempentity.h" +#include "materialsystem/imaterialsystemstub.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "materialsystem/imaterialsystemhardwareconfig.h" +#include "c_soundscape.h" +#include "engine/ivdebugoverlay.h" +#include "vguicenterprint.h" +#include "iviewrender_beams.h" +#include "tier0/vprof.h" +#include "engine/IEngineTrace.h" +#include "engine/ivmodelinfo.h" +#include "physics.h" +#include "usermessages.h" +#include "gamestringpool.h" +#include "c_user_message_register.h" +#include "IGameUIFuncs.h" +#include "saverestoretypes.h" +#include "saverestore.h" +#include "physics_saverestore.h" +#include "igameevents.h" +#include "datacache/idatacache.h" +#include "datacache/imdlcache.h" +#include "kbutton.h" +#include "tier0/icommandline.h" +#include "gamerules_register.h" +#include "vgui_controls/AnimationController.h" +#include "bitmap/tgawriter.h" +#include "c_world.h" +#include "perfvisualbenchmark.h" +#include "SoundEmitterSystem/isoundemittersystembase.h" +#include "hud_closecaption.h" +#include "colorcorrectionmgr.h" +#include "physpropclientside.h" +#include "panelmetaclassmgr.h" +#include "c_vguiscreen.h" +#include "imessagechars.h" +#include "game/client/IGameClientExports.h" +#include "client_factorylist.h" +#include "ragdoll_shared.h" +#include "rendertexture.h" +#include "view_scene.h" +#include "iclientmode.h" +#include "con_nprint.h" +#include "inputsystem/iinputsystem.h" +#include "appframework/IAppSystemGroup.h" +#include "scenefilecache/ISceneFileCache.h" +#include "tier2/tier2dm.h" +#include "tier3/tier3.h" +#include "ihudlcd.h" +#include "toolframework_client.h" +#include "hltvcamera.h" +#if defined( REPLAY_ENABLED ) +#include "replay/replaycamera.h" +#include "replay/replay_ragdoll.h" +#include "qlimits.h" +#include "replay/replay.h" +#include "replay/ireplaysystem.h" +#include "replay/iclientreplay.h" +#include "replay/ienginereplay.h" +#include "replay/ireplaymanager.h" +#include "replay/ireplayscreenshotmanager.h" +#include "replay/iclientreplaycontext.h" +#include "replay/vgui/replayconfirmquitdlg.h" +#include "replay/vgui/replaybrowsermainpanel.h" +#include "replay/vgui/replayinputpanel.h" +#include "replay/vgui/replayperformanceeditor.h" +#endif +#include "vgui/ILocalize.h" +#include "vgui/IVGui.h" +#include "ixboxsystem.h" +#include "ipresence.h" +#include "engine/imatchmaking.h" +#include "cdll_bounded_cvars.h" +#include "matsys_controls/matsyscontrols.h" +#include "gamestats.h" +#include "particle_parse.h" +#if defined( TF_CLIENT_DLL ) +#include "rtime.h" +#include "tf_hud_disconnect_prompt.h" +#include "../engine/audio/public/sound.h" +#include "tf_shared_content_manager.h" +#endif +#include "clientsteamcontext.h" +#include "renamed_recvtable_compat.h" +#include "mouthinfo.h" +#include "headtrack/isourcevirtualreality.h" +#include "client_virtualreality.h" +#include "mumble.h" + +// NVNT includes +#include "hud_macros.h" +#include "haptics/ihaptics.h" +#include "haptics/haptic_utils.h" +#include "haptics/haptic_msgs.h" + +#if defined( TF_CLIENT_DLL ) +#include "abuse_report.h" +#endif + +#ifdef USES_ECON_ITEMS +#include "econ_item_system.h" +#endif // USES_ECON_ITEMS + +#if defined( TF_CLIENT_DLL ) +#include "econ/tool_items/custom_texture_cache.h" +#endif + +#ifdef WORKSHOP_IMPORT_ENABLED +#include "fbxsystem/fbxsystem.h" +#endif + +extern vgui::IInputInternal *g_InputInternal; +const char *COM_GetModDirectory(); // return the mod dir (rather than the complete -game param, which can be a path) + +//============================================================================= +// HPE_BEGIN +// [dwenger] Necessary for stats display +//============================================================================= + +#include "achievements_and_stats_interface.h" + +//============================================================================= +// HPE_END +//============================================================================= + + +#ifdef PORTAL +#include "PortalRender.h" +#endif + +#ifdef SIXENSE +#include "sixense/in_sixense.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +extern IClientMode *GetClientModeNormal(); + +// IF YOU ADD AN INTERFACE, EXTERN IT IN THE HEADER FILE. +IVEngineClient *engine = NULL; +IVModelRender *modelrender = NULL; +IVEfx *effects = NULL; +IVRenderView *render = NULL; +IVDebugOverlay *debugoverlay = NULL; +IMaterialSystemStub *materials_stub = NULL; +IDataCache *datacache = NULL; +IVModelInfoClient *modelinfo = NULL; +IEngineVGui *enginevgui = NULL; +INetworkStringTableContainer *networkstringtable = NULL; +ISpatialPartition* partition = NULL; +IFileSystem *filesystem = NULL; +IShadowMgr *shadowmgr = NULL; +IStaticPropMgrClient *staticpropmgr = NULL; +IEngineSound *enginesound = NULL; +IUniformRandomStream *random = NULL; +static CGaussianRandomStream s_GaussianRandomStream; +CGaussianRandomStream *randomgaussian = &s_GaussianRandomStream; +ISharedGameRules *sharedgamerules = NULL; +IEngineTrace *enginetrace = NULL; +IGameUIFuncs *gameuifuncs = NULL; +IGameEventManager2 *gameeventmanager = NULL; +ISoundEmitterSystemBase *soundemitterbase = NULL; +IInputSystem *inputsystem = NULL; +ISceneFileCache *scenefilecache = NULL; +IXboxSystem *xboxsystem = NULL; // Xbox 360 only +IMatchmaking *matchmaking = NULL; +IUploadGameStats *gamestatsuploader = NULL; +IClientReplayContext *g_pClientReplayContext = NULL; +#if defined( REPLAY_ENABLED ) +IReplayManager *g_pReplayManager = NULL; +IReplayMovieManager *g_pReplayMovieManager = NULL; +IReplayScreenshotManager *g_pReplayScreenshotManager = NULL; +IReplayPerformanceManager *g_pReplayPerformanceManager = NULL; +IReplayPerformanceController *g_pReplayPerformanceController = NULL; +IEngineReplay *g_pEngineReplay = NULL; +IEngineClientReplay *g_pEngineClientReplay = NULL; +IReplaySystem *g_pReplay = NULL; +#endif + +IHaptics* haptics = NULL;// NVNT haptics system interface singleton + +//============================================================================= +// HPE_BEGIN +// [dwenger] Necessary for stats display +//============================================================================= + +AchievementsAndStatsInterface* g_pAchievementsAndStatsInterface = NULL; + +//============================================================================= +// HPE_END +//============================================================================= + +IGameSystem *SoundEmitterSystem(); +IGameSystem *ToolFrameworkClientSystem(); + +// Engine player info, no game related infos here +BEGIN_BYTESWAP_DATADESC( player_info_s ) + DEFINE_ARRAY( name, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ), + DEFINE_FIELD( userID, FIELD_INTEGER ), + DEFINE_ARRAY( guid, FIELD_CHARACTER, SIGNED_GUID_LEN + 1 ), + DEFINE_FIELD( friendsID, FIELD_INTEGER ), + DEFINE_ARRAY( friendsName, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ), + DEFINE_FIELD( fakeplayer, FIELD_BOOLEAN ), + DEFINE_FIELD( ishltv, FIELD_BOOLEAN ), +#if defined( REPLAY_ENABLED ) + DEFINE_FIELD( isreplay, FIELD_BOOLEAN ), +#endif + DEFINE_ARRAY( customFiles, FIELD_INTEGER, MAX_CUSTOM_FILES ), + DEFINE_FIELD( filesDownloaded, FIELD_INTEGER ), +END_BYTESWAP_DATADESC() + +static bool g_bRequestCacheUsedMaterials = false; +void RequestCacheUsedMaterials() +{ + g_bRequestCacheUsedMaterials = true; +} + +void ProcessCacheUsedMaterials() +{ + if ( !g_bRequestCacheUsedMaterials ) + return; + + g_bRequestCacheUsedMaterials = false; + if ( materials ) + { + materials->CacheUsedMaterials(); + } +} + +// String tables +INetworkStringTable *g_pStringTableParticleEffectNames = NULL; +INetworkStringTable *g_StringTableEffectDispatch = NULL; +INetworkStringTable *g_StringTableVguiScreen = NULL; +INetworkStringTable *g_pStringTableMaterials = NULL; +INetworkStringTable *g_pStringTableInfoPanel = NULL; +INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL; +INetworkStringTable *g_pStringTableServerMapCycle = NULL; + +#ifdef TF_CLIENT_DLL +INetworkStringTable *g_pStringTableServerPopFiles = NULL; +INetworkStringTable *g_pStringTableServerMapCycleMvM = NULL; +#endif + +static CGlobalVarsBase dummyvars( true ); +// So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer. +// Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine +CGlobalVarsBase *gpGlobals = &dummyvars; +class CHudChat; +class CViewRender; +extern CViewRender g_DefaultViewRender; + +extern void StopAllRumbleEffects( void ); + +static C_BaseEntityClassList *s_pClassLists = NULL; +C_BaseEntityClassList::C_BaseEntityClassList() +{ + m_pNextClassList = s_pClassLists; + s_pClassLists = this; +} +C_BaseEntityClassList::~C_BaseEntityClassList() +{ +} + +// Any entities that want an OnDataChanged during simulation register for it here. +class CDataChangedEvent +{ +public: + CDataChangedEvent() {} + CDataChangedEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent ) + { + m_pEntity = ent; + m_UpdateType = updateType; + m_pStoredEvent = pStoredEvent; + } + + IClientNetworkable *m_pEntity; + DataUpdateType_t m_UpdateType; + int *m_pStoredEvent; +}; + +ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler(); +ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler(); + +CUtlLinkedList<CDataChangedEvent, unsigned short> g_DataChangedEvents; +ClientFrameStage_t g_CurFrameStage = FRAME_UNDEFINED; + + +class IMoveHelper; + +void DispatchHudText( const char *pszName ); + +static ConVar s_CV_ShowParticleCounts("showparticlecounts", "0", 0, "Display number of particles drawn per frame"); +static ConVar s_cl_team("cl_team", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default team when joining a game"); +static ConVar s_cl_class("cl_class", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "Default class when joining a game"); + +// Physics system +bool g_bLevelInitialized; +bool g_bTextMode = false; +class IClientPurchaseInterfaceV2 *g_pClientPurchaseInterface = (class IClientPurchaseInterfaceV2 *)(&g_bTextMode + 156); + +static ConVar *g_pcv_ThreadMode = NULL; + +//----------------------------------------------------------------------------- +// Purpose: interface for gameui to modify voice bans +//----------------------------------------------------------------------------- +class CGameClientExports : public IGameClientExports +{ +public: + // ingame voice manipulation + bool IsPlayerGameVoiceMuted(int playerIndex) + { + return GetClientVoiceMgr()->IsPlayerBlocked(playerIndex); + } + + void MutePlayerGameVoice(int playerIndex) + { + GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, true); + } + + void UnmutePlayerGameVoice(int playerIndex) + { + GetClientVoiceMgr()->SetPlayerBlockedState(playerIndex, false); + } + + void OnGameUIActivated( void ) + { + IGameEvent *event = gameeventmanager->CreateEvent( "gameui_activated" ); + if ( event ) + { + gameeventmanager->FireEventClientSide( event ); + } + } + + void OnGameUIHidden( void ) + { + IGameEvent *event = gameeventmanager->CreateEvent( "gameui_hidden" ); + if ( event ) + { + gameeventmanager->FireEventClientSide( event ); + } + } + + //============================================================================= + // HPE_BEGIN + // [dwenger] Necessary for stats display + //============================================================================= + + void CreateAchievementsPanel( vgui::Panel* pParent ) + { + if (g_pAchievementsAndStatsInterface) + { + g_pAchievementsAndStatsInterface->CreatePanel( pParent ); + } + } + + void DisplayAchievementPanel() + { + if (g_pAchievementsAndStatsInterface) + { + g_pAchievementsAndStatsInterface->DisplayPanel(); + } + } + + void ShutdownAchievementPanel() + { + if (g_pAchievementsAndStatsInterface) + { + g_pAchievementsAndStatsInterface->ReleasePanel(); + } + } + + int GetAchievementsPanelMinWidth( void ) const + { + if ( g_pAchievementsAndStatsInterface ) + { + return g_pAchievementsAndStatsInterface->GetAchievementsPanelMinWidth(); + } + + return 0; + } + + //============================================================================= + // HPE_END + //============================================================================= + + const char *GetHolidayString() + { + return UTIL_GetActiveHolidayString(); + } +}; + +EXPOSE_SINGLE_INTERFACE( CGameClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION ); + +class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems +{ +public: + CClientDLLSharedAppSystems() + { + AddAppSystem( "soundemittersystem" DLL_EXT_STRING, SOUNDEMITTERSYSTEM_INTERFACE_VERSION ); + AddAppSystem( "scenefilecache" DLL_EXT_STRING, SCENE_FILE_CACHE_INTERFACE_VERSION ); + } + + virtual int Count() + { + return m_Systems.Count(); + } + virtual char const *GetDllName( int idx ) + { + return m_Systems[ idx ].m_pModuleName; + } + virtual char const *GetInterfaceName( int idx ) + { + return m_Systems[ idx ].m_pInterfaceName; + } +private: + void AddAppSystem( char const *moduleName, char const *interfaceName ) + { + AppSystemInfo_t sys; + sys.m_pModuleName = moduleName; + sys.m_pInterfaceName = interfaceName; + m_Systems.AddToTail( sys ); + } + + CUtlVector< AppSystemInfo_t > m_Systems; +}; + +EXPOSE_SINGLE_INTERFACE( CClientDLLSharedAppSystems, IClientDLLSharedAppSystems, CLIENT_DLL_SHARED_APPSYSTEMS ); + + +//----------------------------------------------------------------------------- +// Helper interface for voice. +//----------------------------------------------------------------------------- +class CHLVoiceStatusHelper : public IVoiceStatusHelper +{ +public: + virtual void GetPlayerTextColor(int entindex, int color[3]) + { + color[0] = color[1] = color[2] = 128; + } + + virtual void UpdateCursorState() + { + } + + virtual bool CanShowSpeakerLabels() + { + return true; + } +}; +static CHLVoiceStatusHelper g_VoiceStatusHelper; + +//----------------------------------------------------------------------------- +// Code to display which entities are having their bones setup each frame. +//----------------------------------------------------------------------------- + +ConVar cl_ShowBoneSetupEnts( "cl_ShowBoneSetupEnts", "0", 0, "Show which entities are having their bones setup each frame." ); + +class CBoneSetupEnt +{ +public: + char m_ModelName[128]; + int m_Index; + int m_Count; +}; + +bool BoneSetupCompare( const CBoneSetupEnt &a, const CBoneSetupEnt &b ) +{ + return a.m_Index < b.m_Index; +} + +CUtlRBTree<CBoneSetupEnt> g_BoneSetupEnts( BoneSetupCompare ); + + +void TrackBoneSetupEnt( C_BaseAnimating *pEnt ) +{ +#ifdef _DEBUG + if ( IsRetail() ) + return; + + if ( !cl_ShowBoneSetupEnts.GetInt() ) + return; + + CBoneSetupEnt ent; + ent.m_Index = pEnt->entindex(); + unsigned short i = g_BoneSetupEnts.Find( ent ); + if ( i == g_BoneSetupEnts.InvalidIndex() ) + { + Q_strncpy( ent.m_ModelName, modelinfo->GetModelName( pEnt->GetModel() ), sizeof( ent.m_ModelName ) ); + ent.m_Count = 1; + g_BoneSetupEnts.Insert( ent ); + } + else + { + g_BoneSetupEnts[i].m_Count++; + } +#endif +} + +void DisplayBoneSetupEnts() +{ +#ifdef _DEBUG + if ( IsRetail() ) + return; + + if ( !cl_ShowBoneSetupEnts.GetInt() ) + return; + + unsigned short i; + int nElements = 0; + for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) ) + ++nElements; + + engine->Con_NPrintf( 0, "%d bone setup ents (name/count/entindex) ------------", nElements ); + + con_nprint_s printInfo; + printInfo.time_to_live = -1; + printInfo.fixed_width_font = true; + printInfo.color[0] = printInfo.color[1] = printInfo.color[2] = 1; + + printInfo.index = 2; + for ( i=g_BoneSetupEnts.FirstInorder(); i != g_BoneSetupEnts.LastInorder(); i=g_BoneSetupEnts.NextInorder( i ) ) + { + CBoneSetupEnt *pEnt = &g_BoneSetupEnts[i]; + + if ( pEnt->m_Count >= 3 ) + { + printInfo.color[0] = 1; + printInfo.color[1] = printInfo.color[2] = 0; + } + else if ( pEnt->m_Count == 2 ) + { + printInfo.color[0] = (float)200 / 255; + printInfo.color[1] = (float)220 / 255; + printInfo.color[2] = 0; + } + else + { + printInfo.color[0] = printInfo.color[0] = printInfo.color[0] = 1; + } + engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index ); + printInfo.index++; + } + + g_BoneSetupEnts.RemoveAll(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: engine to client .dll interface +//----------------------------------------------------------------------------- +class CHLClient : public IBaseClientDLL +{ +public: + CHLClient(); + + virtual int Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals ); + + virtual void PostInit(); + virtual void Shutdown( void ); + + virtual bool ReplayInit( CreateInterfaceFn fnReplayFactory ); + virtual bool ReplayPostInit(); + + virtual void LevelInitPreEntity( const char *pMapName ); + virtual void LevelInitPostEntity(); + virtual void LevelShutdown( void ); + + virtual ClientClass *GetAllClasses( void ); + + virtual int HudVidInit( void ); + virtual void HudProcessInput( bool bActive ); + virtual void HudUpdate( bool bActive ); + virtual void HudReset( void ); + virtual void HudText( const char * message ); + + // Mouse Input Interfaces + virtual void IN_ActivateMouse( void ); + virtual void IN_DeactivateMouse( void ); + virtual void IN_Accumulate( void ); + virtual void IN_ClearStates( void ); + virtual bool IN_IsKeyDown( const char *name, bool& isdown ); + virtual void IN_OnMouseWheeled( int nDelta ); + // Raw signal + virtual int IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding ); + virtual void IN_SetSampleTime( float frametime ); + // Create movement command + virtual void CreateMove ( int sequence_number, float input_sample_frametime, bool active ); + virtual void ExtraMouseSample( float frametime, bool active ); + virtual bool WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand ); + virtual void EncodeUserCmdToBuffer( bf_write& buf, int slot ); + virtual void DecodeUserCmdFromBuffer( bf_read& buf, int slot ); + + + virtual void View_Render( vrect_t *rect ); + virtual void RenderView( const CViewSetup &view, int nClearFlags, int whatToDraw ); + virtual void View_Fade( ScreenFade_t *pSF ); + + virtual void SetCrosshairAngle( const QAngle& angle ); + + virtual void InitSprite( CEngineSprite *pSprite, const char *loadname ); + virtual void ShutdownSprite( CEngineSprite *pSprite ); + + virtual int GetSpriteSize( void ) const; + + virtual void VoiceStatus( int entindex, qboolean bTalking ); + + virtual void InstallStringTableCallback( const char *tableName ); + + virtual void FrameStageNotify( ClientFrameStage_t curStage ); + + virtual bool DispatchUserMessage( int msg_type, bf_read &msg_data ); + + // Save/restore system hooks + virtual CSaveRestoreData *SaveInit( int size ); + virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ); + virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ); + virtual void PreSave( CSaveRestoreData * ); + virtual void Save( CSaveRestoreData * ); + virtual void WriteSaveHeaders( CSaveRestoreData * ); + virtual void ReadRestoreHeaders( CSaveRestoreData * ); + virtual void Restore( CSaveRestoreData *, bool ); + virtual void DispatchOnRestore(); + virtual void WriteSaveGameScreenshot( const char *pFilename ); + + // Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit + // the appropriate close caption if running with closecaption = 1 + virtual void EmitSentenceCloseCaption( char const *tokenstream ); + virtual void EmitCloseCaption( char const *captionname, float duration ); + + virtual CStandardRecvProxies* GetStandardRecvProxies(); + + virtual bool CanRecordDemo( char *errorMsg, int length ) const; + + virtual void OnDemoRecordStart( char const* pDemoBaseName ); + virtual void OnDemoRecordStop(); + virtual void OnDemoPlaybackStart( char const* pDemoBaseName ); + virtual void OnDemoPlaybackStop(); + + virtual bool ShouldDrawDropdownConsole(); + + // Get client screen dimensions + virtual int GetScreenWidth(); + virtual int GetScreenHeight(); + + // save game screenshot writing + virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, bool bWriteVTF/*=false*/ ); + + // Gets the location of the player viewpoint + virtual bool GetPlayerView( CViewSetup &playerView ); + + // Matchmaking + virtual void SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties ); + virtual uint GetPresenceID( const char *pIDName ); + virtual const char *GetPropertyIdString( const uint id ); + virtual void GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes ); + virtual void StartStatsReporting( HANDLE handle, bool bArbitrated ); + + virtual void InvalidateMdlCache(); + + virtual void ReloadFilesInList( IFileList *pFilesToReload ); + + // Let the client handle UI toggle - if this function returns false, the UI will toggle, otherwise it will not. + virtual bool HandleUiToggle(); + + // Allow the console to be shown? + virtual bool ShouldAllowConsole(); + + // Get renamed recv tables + virtual CRenamedRecvTableInfo *GetRenamedRecvTableInfos(); + + // Get the mouthinfo for the sound being played inside UI panels + virtual CMouthInfo *GetClientUIMouthInfo(); + + // Notify the client that a file has been received from the game server + virtual void FileReceived( const char * fileName, unsigned int transferID ); + + virtual const char* TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName ); + + virtual void ClientAdjustStartSoundParams( struct StartSoundParams_t& params ); + + // Returns true if the disconnect command has been handled by the client + virtual bool DisconnectAttempt( void ); +public: + void PrecacheMaterial( const char *pMaterialName ); + + virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar ); + +private: + void UncacheAllMaterials( ); + void ResetStringTablePointers(); + + CUtlVector< IMaterial * > m_CachedMaterials; +}; + + +CHLClient gHLClient; +IBaseClientDLL *clientdll = &gHLClient; + +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLClient, IBaseClientDLL, CLIENT_DLL_INTERFACE_VERSION, gHLClient ); + + +//----------------------------------------------------------------------------- +// Precaches a material +//----------------------------------------------------------------------------- +void PrecacheMaterial( const char *pMaterialName ) +{ + gHLClient.PrecacheMaterial( pMaterialName ); +} + +//----------------------------------------------------------------------------- +// Converts a previously precached material into an index +//----------------------------------------------------------------------------- +int GetMaterialIndex( const char *pMaterialName ) +{ + if (pMaterialName) + { + int nIndex = g_pStringTableMaterials->FindStringIndex( pMaterialName ); + Assert( nIndex >= 0 ); + if (nIndex >= 0) + return nIndex; + } + + // This is the invalid string index + return 0; +} + +//----------------------------------------------------------------------------- +// Converts precached material indices into strings +//----------------------------------------------------------------------------- +const char *GetMaterialNameFromIndex( int nIndex ) +{ + if (nIndex != (g_pStringTableMaterials->GetMaxStrings() - 1)) + { + return g_pStringTableMaterials->GetString( nIndex ); + } + else + { + return NULL; + } +} + + +//----------------------------------------------------------------------------- +// Precaches a particle system +//----------------------------------------------------------------------------- +void PrecacheParticleSystem( const char *pParticleSystemName ) +{ + g_pStringTableParticleEffectNames->AddString( false, pParticleSystemName ); + g_pParticleSystemMgr->PrecacheParticleSystem( pParticleSystemName ); +} + + +//----------------------------------------------------------------------------- +// Converts a previously precached particle system into an index +//----------------------------------------------------------------------------- +int GetParticleSystemIndex( const char *pParticleSystemName ) +{ + if ( pParticleSystemName ) + { + int nIndex = g_pStringTableParticleEffectNames->FindStringIndex( pParticleSystemName ); + if ( nIndex != INVALID_STRING_INDEX ) + return nIndex; + DevWarning("Client: Missing precache for particle system \"%s\"!\n", pParticleSystemName ); + } + + // This is the invalid string index + return 0; +} + +//----------------------------------------------------------------------------- +// Converts precached particle system indices into strings +//----------------------------------------------------------------------------- +const char *GetParticleSystemNameFromIndex( int nIndex ) +{ + if ( nIndex < g_pStringTableParticleEffectNames->GetMaxStrings() ) + return g_pStringTableParticleEffectNames->GetString( nIndex ); + return "error"; +} + +//----------------------------------------------------------------------------- +// Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode) +//----------------------------------------------------------------------------- +bool IsEngineThreaded() +{ + if ( g_pcv_ThreadMode ) + { + return g_pcv_ThreadMode->GetBool(); + } + return false; +} + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- + +CHLClient::CHLClient() +{ + // Kinda bogus, but the logic in the engine is too convoluted to put it there + g_bLevelInitialized = false; +} + + +extern IGameSystem *ViewportClientSystem(); + + +//----------------------------------------------------------------------------- +ISourceVirtualReality *g_pSourceVR = NULL; + +// Purpose: Called when the DLL is first loaded. +// Input : engineFactory - +// Output : int +//----------------------------------------------------------------------------- +int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CGlobalVarsBase *pGlobals ) +{ + InitCRTMemDebug(); + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); + + +#ifdef SIXENSE + g_pSixenseInput = new SixenseInput; +#endif + + // Hook up global variables + gpGlobals = pGlobals; + + ConnectTier1Libraries( &appSystemFactory, 1 ); + ConnectTier2Libraries( &appSystemFactory, 1 ); + ConnectTier3Libraries( &appSystemFactory, 1 ); + +#ifndef NO_STEAM + ClientSteamContext().Activate(); +#endif + + // We aren't happy unless we get all of our interfaces. + // please don't collapse this into one monolithic boolean expression (impossible to debug) + if ( (engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (effects = (IVEfx *)appSystemFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (enginetrace = (IEngineTrace *)appSystemFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL )) == NULL ) + return false; + if ( (render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( !mdlcache ) + return false; + if ( (modelinfo = (IVModelInfoClient *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) == NULL ) + return false; + if ( (networkstringtable = (INetworkStringTableContainer *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLECLIENT,NULL)) == NULL ) + return false; + if ( (partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) == NULL ) + return false; + if ( (shadowmgr = (IShadowMgr *)appSystemFactory(ENGINE_SHADOWMGR_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (staticpropmgr = (IStaticPropMgrClient *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_CLIENT, NULL)) == NULL ) + return false; + if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) == NULL ) + return false; + if ( (gameeventmanager = (IGameEventManager2 *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2,NULL)) == NULL ) + return false; + if ( (soundemitterbase = (ISoundEmitterSystemBase *)appSystemFactory(SOUNDEMITTERSYSTEM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( IsX360() && (xboxsystem = (IXboxSystem *)appSystemFactory( XBOXSYSTEM_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( IsX360() && (matchmaking = (IMatchmaking *)appSystemFactory( VENGINE_MATCHMAKING_VERSION, NULL )) == NULL ) + return false; +#ifndef _XBOX + if ( ( gamestatsuploader = (IUploadGameStats *)appSystemFactory( INTERFACEVERSION_UPLOADGAMESTATS, NULL )) == NULL ) + return false; +#endif + +#if defined( REPLAY_ENABLED ) + if ( IsPC() && (g_pEngineReplay = (IEngineReplay *)appSystemFactory( ENGINE_REPLAY_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( IsPC() && (g_pEngineClientReplay = (IEngineClientReplay *)appSystemFactory( ENGINE_REPLAY_CLIENT_INTERFACE_VERSION, NULL )) == NULL ) + return false; +#endif + + if (!g_pMatSystemSurface) + return false; + +#ifdef WORKSHOP_IMPORT_ENABLED + if ( !ConnectDataModel( appSystemFactory ) ) + return false; + if ( InitDataModel() != INIT_OK ) + return false; + InitFbx(); +#endif + + // it's ok if this is NULL. That just means the headtrack.dll wasn't found + g_pSourceVR = (ISourceVirtualReality *)appSystemFactory(SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION, NULL); + + factorylist_t factories; + factories.appSystemFactory = appSystemFactory; + factories.physicsFactory = physicsFactory; + FactoryList_Store( factories ); + + // Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully + if ( !soundemitterbase->Connect( appSystemFactory ) ) + { + return false; + } + + if ( CommandLine()->FindParm( "-textmode" ) ) + g_bTextMode = true; + + if ( CommandLine()->FindParm( "-makedevshots" ) ) + g_MakingDevShots = true; + + // Not fatal if the material system stub isn't around. + materials_stub = (IMaterialSystemStub*)appSystemFactory( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION, NULL ); + + if( !g_pMaterialSystemHardwareConfig ) + return false; + + // Hook up the gaussian random number generator + s_GaussianRandomStream.AttachToStream( random ); + + // Initialize the console variables. + ConVar_Register( FCVAR_CLIENTDLL ); + + g_pcv_ThreadMode = g_pCVar->FindVar( "host_thread_mode" ); + + // If we are in VR mode do some initial setup work + if( UseVR() ) + { + int nViewportWidth, nViewportHeight; + + g_pSourceVR->GetViewportBounds( ISourceVirtualReality::VREye_Left, NULL, NULL, &nViewportWidth, &nViewportHeight ); + vgui::surface()->SetFullscreenViewport( 0, 0, nViewportWidth, nViewportHeight ); + + vgui::ivgui()->SetVRMode( true ); + } + + if (!Initializer::InitializeAllObjects()) + return false; + + if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials)) + return false; + + + if (!VGui_Startup( appSystemFactory )) + return false; + + vgui::VGui_InitMatSysInterfacesList( "ClientDLL", &appSystemFactory, 1 ); + + // Add the client systems. + + // Client Leaf System has to be initialized first, since DetailObjectSystem uses it + IGameSystem::Add( GameStringSystem() ); + IGameSystem::Add( SoundEmitterSystem() ); + IGameSystem::Add( ToolFrameworkClientSystem() ); + IGameSystem::Add( ClientLeafSystem() ); + IGameSystem::Add( DetailObjectSystem() ); + IGameSystem::Add( ViewportClientSystem() ); + IGameSystem::Add( ClientEffectPrecacheSystem() ); + IGameSystem::Add( g_pClientShadowMgr ); + IGameSystem::Add( g_pColorCorrectionMgr ); // NOTE: This must happen prior to ClientThinkList (color correction is updated there) + IGameSystem::Add( ClientThinkList() ); + IGameSystem::Add( ClientSoundscapeSystem() ); + IGameSystem::Add( PerfVisualBenchmark() ); + IGameSystem::Add( MumbleSystem() ); + + #if defined( TF_CLIENT_DLL ) + IGameSystem::Add( CustomTextureToolCacheGameSystem() ); + IGameSystem::Add( TFSharedContentManager() ); + #endif + +#if defined( TF_CLIENT_DLL ) + if ( g_AbuseReportMgr != NULL ) + { + IGameSystem::Add( g_AbuseReportMgr ); + } +#endif + +#if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST ) + IGameSystem::Add( GetPredictionCopyTester() ); +#endif + + modemanager->Init( ); + + g_pClientMode->InitViewport(); + + gHUD.Init(); + + g_pClientMode->Init(); + + if ( !IGameSystem::InitAllSystems() ) + return false; + + g_pClientMode->Enable(); + + if ( !view ) + { + view = ( IViewRender * )&g_DefaultViewRender; + } + + view->Init(); + vieweffects->Init(); + + C_BaseTempEntity::PrecacheTempEnts(); + + input->Init_All(); + + VGui_CreateGlobalPanels(); + + InitSmokeFogOverlay(); + + // Register user messages.. + CUserMessageRegister::RegisterAll(); + + ClientVoiceMgr_Init(); + + // Embed voice status icons inside chat element + { + vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL ); + GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent ); + } + + if ( !PhysicsDLLInit( physicsFactory ) ) + return false; + + g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() ); + g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() ); + g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() ); + + ClientWorldFactoryInit(); + + C_BaseAnimating::InitBoneSetupThreadPool(); + +#if defined( WIN32 ) && !defined( _X360 ) + // NVNT connect haptics sytem + ConnectHaptics(appSystemFactory); +#endif +#ifndef _X360 + HookHapticMessages(); // Always hook the messages +#endif + return true; +} + +bool CHLClient::ReplayInit( CreateInterfaceFn fnReplayFactory ) +{ +#if defined( REPLAY_ENABLED ) + if ( !IsPC() ) + return false; + if ( (g_pReplay = (IReplaySystem *)fnReplayFactory( REPLAY_INTERFACE_VERSION, NULL ) ) == NULL ) + return false; + if ( (g_pClientReplayContext = g_pReplay->CL_GetContext()) == NULL ) + return false; + + return true; +#else + return false; +#endif +} + +bool CHLClient::ReplayPostInit() +{ +#if defined( REPLAY_ENABLED ) + if ( ( g_pReplayManager = g_pClientReplayContext->GetReplayManager() ) == NULL ) + return false; + if ( ( g_pReplayScreenshotManager = g_pClientReplayContext->GetScreenshotManager() ) == NULL ) + return false; + if ( ( g_pReplayPerformanceManager = g_pClientReplayContext->GetPerformanceManager() ) == NULL ) + return false; + if ( ( g_pReplayPerformanceController = g_pClientReplayContext->GetPerformanceController() ) == NULL ) + return false; + if ( ( g_pReplayMovieManager = g_pClientReplayContext->GetMovieManager() ) == NULL ) + return false; + return true; +#else + return false; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Called after client & server DLL are loaded and all systems initialized +//----------------------------------------------------------------------------- +void CHLClient::PostInit() +{ + IGameSystem::PostInitAllSystems(); + +#ifdef SIXENSE + // allow sixnese input to perform post-init operations + g_pSixenseInput->PostInit(); +#endif + + // If we are in VR mode execute headtrack.cfg in PostInit so all the convars will + // already be set up + if( UseVR() ) + { + // general all-game stuff + engine->ExecuteClientCmd( "exec headtrack\\headtrack.cfg" ); + + // game specific VR config + CUtlString sCmd; + sCmd.Format( "exec headtrack_%s.cfg", COM_GetModDirectory() ); + engine->ExecuteClientCmd( sCmd.Get() ); + + engine->ExecuteClientCmd( "vr_start_tracking" ); + + vgui::surface()->SetSoftwareCursor( true ); +#if defined(POSIX) + ConVarRef m_rawinput( "m_rawinput" ); + m_rawinput.SetValue( 1 ); + + ConVarRef mat_vsync( "mat_vsync" ); + mat_vsync.SetValue( 0 ); +#endif + } +} + +//----------------------------------------------------------------------------- +// Purpose: Called when the client .dll is being dismissed +//----------------------------------------------------------------------------- +void CHLClient::Shutdown( void ) +{ + if (g_pAchievementsAndStatsInterface) + { + g_pAchievementsAndStatsInterface->ReleasePanel(); + } + +#ifdef SIXENSE + g_pSixenseInput->Shutdown(); + delete g_pSixenseInput; + g_pSixenseInput = NULL; +#endif + + C_BaseAnimating::ShutdownBoneSetupThreadPool(); + ClientWorldFactoryShutdown(); + + g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() ); + g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() ); + g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() ); + + ClientVoiceMgr_Shutdown(); + + Initializer::FreeAllObjects(); + + g_pClientMode->Disable(); + g_pClientMode->Shutdown(); + + input->Shutdown_All(); + C_BaseTempEntity::ClearDynamicTempEnts(); + TermSmokeFogOverlay(); + view->Shutdown(); + g_pParticleSystemMgr->UncacheAllParticleSystems(); + UncacheAllMaterials(); + + IGameSystem::ShutdownAllSystems(); + + gHUD.Shutdown(); + VGui_Shutdown(); + + ParticleMgr()->Term(); + + ClearKeyValuesCache(); + +#ifndef NO_STEAM + ClientSteamContext().Shutdown(); +#endif + +#ifdef WORKSHOP_IMPORT_ENABLED + ShutdownDataModel(); + DisconnectDataModel(); + ShutdownFbx(); +#endif + + // This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it +// DisconnectTier3Libraries( ); + DisconnectTier2Libraries( ); + ConVar_Unregister(); + DisconnectTier1Libraries( ); + + gameeventmanager = NULL; + +#if defined( WIN32 ) && !defined( _X360 ) + // NVNT Disconnect haptics system + DisconnectHaptics(); +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Called when the game initializes +// and whenever the vid_mode is changed +// so the HUD can reinitialize itself. +// Output : int +//----------------------------------------------------------------------------- +int CHLClient::HudVidInit( void ) +{ + gHUD.VidInit(); + + GetClientVoiceMgr()->VidInit(); + + return 1; +} + +//----------------------------------------------------------------------------- +// Method used to allow the client to filter input messages before the +// move record is transmitted to the server +//----------------------------------------------------------------------------- +void CHLClient::HudProcessInput( bool bActive ) +{ + g_pClientMode->ProcessInput( bActive ); +} + +//----------------------------------------------------------------------------- +// Purpose: Called when shared data gets changed, allows dll to modify data +// Input : bActive - +//----------------------------------------------------------------------------- +void CHLClient::HudUpdate( bool bActive ) +{ + float frametime = gpGlobals->frametime; + +#if defined( TF_CLIENT_DLL ) + CRTime::UpdateRealTime(); +#endif + + GetClientVoiceMgr()->Frame( frametime ); + + gHUD.UpdateHud( bActive ); + + { + C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false ); + IGameSystem::UpdateAllSystems( frametime ); + } + + // run vgui animations + vgui::GetAnimationController()->UpdateAnimations( engine->Time() ); + + hudlcd->SetGlobalStat( "(time_int)", VarArgs( "%d", (int)gpGlobals->curtime ) ); + hudlcd->SetGlobalStat( "(time_float)", VarArgs( "%.2f", gpGlobals->curtime ) ); + + // I don't think this is necessary any longer, but I will leave it until + // I can check into this further. + C_BaseTempEntity::CheckDynamicTempEnts(); + +#ifdef SIXENSE + // If we're not connected, update sixense so we can move the mouse cursor when in the menus + if( !engine->IsConnected() || engine->IsPaused() ) + { + g_pSixenseInput->SixenseFrame( 0, NULL ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Called to restore to "non"HUD state. +//----------------------------------------------------------------------------- +void CHLClient::HudReset( void ) +{ + gHUD.VidInit(); + PhysicsReset(); +} + +//----------------------------------------------------------------------------- +// Purpose: Called to add hud text message +//----------------------------------------------------------------------------- +void CHLClient::HudText( const char * message ) +{ + DispatchHudText( message ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CHLClient::ShouldDrawDropdownConsole() +{ +#if defined( REPLAY_ENABLED ) + extern ConVar hud_freezecamhide; + extern bool IsTakingAFreezecamScreenshot(); + + if ( hud_freezecamhide.GetBool() && IsTakingAFreezecamScreenshot() ) + { + return false; + } +#endif + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : ClientClass +//----------------------------------------------------------------------------- +ClientClass *CHLClient::GetAllClasses( void ) +{ + return g_pClientClassHead; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHLClient::IN_ActivateMouse( void ) +{ + input->ActivateMouse(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHLClient::IN_DeactivateMouse( void ) +{ + input->DeactivateMouse(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHLClient::IN_Accumulate ( void ) +{ + input->AccumulateMouse(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHLClient::IN_ClearStates ( void ) +{ + input->ClearStates(); +} + +//----------------------------------------------------------------------------- +// Purpose: Engine can query for particular keys +// Input : *name - +//----------------------------------------------------------------------------- +bool CHLClient::IN_IsKeyDown( const char *name, bool& isdown ) +{ + kbutton_t *key = input->FindKey( name ); + if ( !key ) + { + return false; + } + + isdown = ( key->state & 1 ) ? true : false; + + // Found the key by name + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Engine can issue a key event +// Input : eventcode - +// keynum - +// *pszCurrentBinding - +void CHLClient::IN_OnMouseWheeled( int nDelta ) +{ +#if defined( REPLAY_ENABLED ) + CReplayPerformanceEditorPanel *pPerfEditor = ReplayUI_GetPerformanceEditor(); + if ( pPerfEditor ) + { + pPerfEditor->OnInGameMouseWheelEvent( nDelta ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Engine can issue a key event +// Input : eventcode - +// keynum - +// *pszCurrentBinding - +// Output : int +//----------------------------------------------------------------------------- +int CHLClient::IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding ) +{ + return input->KeyEvent( eventcode, keynum, pszCurrentBinding ); +} + +void CHLClient::ExtraMouseSample( float frametime, bool active ) +{ + Assert( C_BaseEntity::IsAbsRecomputationsEnabled() ); + Assert( C_BaseEntity::IsAbsQueriesValid() ); + + C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false ); + + MDLCACHE_CRITICAL_SECTION(); + input->ExtraMouseSample( frametime, active ); +} + +void CHLClient::IN_SetSampleTime( float frametime ) +{ + input->Joystick_SetSampleTime( frametime ); + input->IN_SetSampleTime( frametime ); + +#ifdef SIXENSE + g_pSixenseInput->ResetFrameTime( frametime ); +#endif +} +//----------------------------------------------------------------------------- +// Purpose: Fills in usercmd_s structure based on current view angles and key/controller inputs +// Input : frametime - timestamp for last frame +// *cmd - the command to fill in +// active - whether the user is fully connected to a server +//----------------------------------------------------------------------------- +void CHLClient::CreateMove ( int sequence_number, float input_sample_frametime, bool active ) +{ + + Assert( C_BaseEntity::IsAbsRecomputationsEnabled() ); + Assert( C_BaseEntity::IsAbsQueriesValid() ); + + C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false ); + + MDLCACHE_CRITICAL_SECTION(); + input->CreateMove( sequence_number, input_sample_frametime, active ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *buf - +// from - +// to - +//----------------------------------------------------------------------------- +bool CHLClient::WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand ) +{ + return input->WriteUsercmdDeltaToBuffer( buf, from, to, isnewcommand ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : buf - +// buffersize - +// slot - +//----------------------------------------------------------------------------- +void CHLClient::EncodeUserCmdToBuffer( bf_write& buf, int slot ) +{ + input->EncodeUserCmdToBuffer( buf, slot ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : buf - +// buffersize - +// slot - +//----------------------------------------------------------------------------- +void CHLClient::DecodeUserCmdFromBuffer( bf_read& buf, int slot ) +{ + input->DecodeUserCmdFromBuffer( buf, slot ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHLClient::View_Render( vrect_t *rect ) +{ + VPROF( "View_Render" ); + + // UNDONE: This gets hit at startup sometimes, investigate - will cause NaNs in calcs inside Render() + if ( rect->width == 0 || rect->height == 0 ) + return; + + view->Render( rect ); + UpdatePerfStats(); +} + + +//----------------------------------------------------------------------------- +// Gets the location of the player viewpoint +//----------------------------------------------------------------------------- +bool CHLClient::GetPlayerView( CViewSetup &playerView ) +{ + playerView = *view->GetPlayerViewSetup(); + return true; +} + +//----------------------------------------------------------------------------- +// Matchmaking +//----------------------------------------------------------------------------- +void CHLClient::SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties ) +{ + presence->SetupGameProperties( contexts, properties ); +} + +uint CHLClient::GetPresenceID( const char *pIDName ) +{ + return presence->GetPresenceID( pIDName ); +} + +const char *CHLClient::GetPropertyIdString( const uint id ) +{ + return presence->GetPropertyIdString( id ); +} + +void CHLClient::GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes ) +{ + presence->GetPropertyDisplayString( id, value, pOutput, nBytes ); +} + +void CHLClient::StartStatsReporting( HANDLE handle, bool bArbitrated ) +{ + presence->StartStatsReporting( handle, bArbitrated ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CHLClient::InvalidateMdlCache() +{ + C_BaseAnimating *pAnimating; + for ( C_BaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity(pEntity) ) + { + pAnimating = dynamic_cast<C_BaseAnimating *>(pEntity); + if ( pAnimating ) + { + pAnimating->InvalidateMdlCache(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSF - +//----------------------------------------------------------------------------- +void CHLClient::View_Fade( ScreenFade_t *pSF ) +{ + if ( pSF != NULL ) + vieweffects->Fade( *pSF ); +} + +//----------------------------------------------------------------------------- +// Purpose: Per level init +//----------------------------------------------------------------------------- +void CHLClient::LevelInitPreEntity( char const* pMapName ) +{ + // HACK: Bogus, but the logic is too complicated in the engine + if (g_bLevelInitialized) + return; + g_bLevelInitialized = true; + + input->LevelInit(); + + vieweffects->LevelInit(); + + //Tony; loadup per-map manifests. + ParseParticleEffectsMap( pMapName, true ); + + // Tell mode manager that map is changing + modemanager->LevelInit( pMapName ); + ParticleMgr()->LevelInit(); + + hudlcd->SetGlobalStat( "(mapname)", pMapName ); + + C_BaseTempEntity::ClearDynamicTempEnts(); + clienteffects->Flush(); + view->LevelInit(); + tempents->LevelInit(); + ResetToneMapping(1.0); + + IGameSystem::LevelInitPreEntityAllSystems(pMapName); + +#ifdef USES_ECON_ITEMS + GameItemSchema_t *pItemSchema = ItemSystem()->GetItemSchema(); + if ( pItemSchema ) + { + pItemSchema->BInitFromDelayedBuffer(); + } +#endif // USES_ECON_ITEMS + + ResetWindspeed(); + +#if !defined( NO_ENTITY_PREDICTION ) + // don't do prediction if single player! + // don't set direct because of FCVAR_USERINFO + if ( gpGlobals->maxClients > 1 ) + { + if ( !cl_predict->GetInt() ) + { + engine->ClientCmd( "cl_predict 1" ); + } + } + else + { + if ( cl_predict->GetInt() ) + { + engine->ClientCmd( "cl_predict 0" ); + } + } +#endif + + // Check low violence settings for this map + g_RagdollLVManager.SetLowViolence( pMapName ); + + gHUD.LevelInit(); + +#if defined( REPLAY_ENABLED ) + // Initialize replay ragdoll recorder + if ( !engine->IsPlayingDemo() ) + { + CReplayRagdollRecorder::Instance().Init(); + } +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: Per level init +//----------------------------------------------------------------------------- +void CHLClient::LevelInitPostEntity( ) +{ + IGameSystem::LevelInitPostEntityAllSystems(); + C_PhysPropClientside::RecreateAll(); + internalCenterPrint->Clear(); +} + +//----------------------------------------------------------------------------- +// Purpose: Reset our global string table pointers +//----------------------------------------------------------------------------- +void CHLClient::ResetStringTablePointers() +{ + g_pStringTableParticleEffectNames = NULL; + g_StringTableEffectDispatch = NULL; + g_StringTableVguiScreen = NULL; + g_pStringTableMaterials = NULL; + g_pStringTableInfoPanel = NULL; + g_pStringTableClientSideChoreoScenes = NULL; + g_pStringTableServerMapCycle = NULL; + +#ifdef TF_CLIENT_DLL + g_pStringTableServerPopFiles = NULL; + g_pStringTableServerMapCycleMvM = NULL; +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Per level de-init +//----------------------------------------------------------------------------- +void CHLClient::LevelShutdown( void ) +{ + // HACK: Bogus, but the logic is too complicated in the engine + if (!g_bLevelInitialized) + return; + + g_bLevelInitialized = false; + + // Disable abs recomputations when everything is shutting down + CBaseEntity::EnableAbsRecomputations( false ); + + // Level shutdown sequence. + // First do the pre-entity shutdown of all systems + IGameSystem::LevelShutdownPreEntityAllSystems(); + + C_PhysPropClientside::DestroyAll(); + + modemanager->LevelShutdown(); + + // Remove temporary entities before removing entities from the client entity list so that the te_* may + // clean up before hand. + tempents->LevelShutdown(); + + // Now release/delete the entities + cl_entitylist->Release(); + + C_BaseEntityClassList *pClassList = s_pClassLists; + while ( pClassList ) + { + pClassList->LevelShutdown(); + pClassList = pClassList->m_pNextClassList; + } + + // Now do the post-entity shutdown of all systems + IGameSystem::LevelShutdownPostEntityAllSystems(); + + view->LevelShutdown(); + beams->ClearBeams(); + ParticleMgr()->RemoveAllEffects(); + + StopAllRumbleEffects(); + + gHUD.LevelShutdown(); + + internalCenterPrint->Clear(); + + messagechars->Clear(); + + g_pParticleSystemMgr->UncacheAllParticleSystems(); + UncacheAllMaterials(); + +#ifdef _XBOX + ReleaseRenderTargets(); +#endif + + // string tables are cleared on disconnect from a server, so reset our global pointers to NULL + ResetStringTablePointers(); + +#if defined( REPLAY_ENABLED ) + // Shutdown the ragdoll recorder + CReplayRagdollRecorder::Instance().Shutdown(); + CReplayRagdollCache::Instance().Shutdown(); +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: Engine received crosshair offset ( autoaim ) +// Input : angle - +//----------------------------------------------------------------------------- +void CHLClient::SetCrosshairAngle( const QAngle& angle ) +{ + CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair ); + if ( crosshair ) + { + crosshair->SetCrosshairAngle( angle ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Helper to initialize sprite from .spr semaphor +// Input : *pSprite - +// *loadname - +//----------------------------------------------------------------------------- +void CHLClient::InitSprite( CEngineSprite *pSprite, const char *loadname ) +{ + if ( pSprite ) + { + pSprite->Init( loadname ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pSprite - +//----------------------------------------------------------------------------- +void CHLClient::ShutdownSprite( CEngineSprite *pSprite ) +{ + if ( pSprite ) + { + pSprite->Shutdown(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Tells engine how much space to allocate for sprite objects +// Output : int +//----------------------------------------------------------------------------- +int CHLClient::GetSpriteSize( void ) const +{ + return sizeof( CEngineSprite ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : entindex - +// bTalking - +//----------------------------------------------------------------------------- +void CHLClient::VoiceStatus( int entindex, qboolean bTalking ) +{ + GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, !!bTalking ); +} + + +//----------------------------------------------------------------------------- +// Called when the string table for materials changes +//----------------------------------------------------------------------------- +void OnMaterialStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData ) +{ + // Make sure this puppy is precached + gHLClient.PrecacheMaterial( newString ); + RequestCacheUsedMaterials(); +} + + +//----------------------------------------------------------------------------- +// Called when the string table for particle systems changes +//----------------------------------------------------------------------------- +void OnParticleSystemStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData ) +{ + // Make sure this puppy is precached + g_pParticleSystemMgr->PrecacheParticleSystem( newString ); + RequestCacheUsedMaterials(); +} + + +//----------------------------------------------------------------------------- +// Called when the string table for VGUI changes +//----------------------------------------------------------------------------- +void OnVguiScreenTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData ) +{ + // Make sure this puppy is precached + vgui::Panel *pPanel = PanelMetaClassMgr()->CreatePanelMetaClass( newString, 100, NULL, NULL ); + if ( pPanel ) + PanelMetaClassMgr()->DestroyPanelMetaClass( pPanel ); +} + +//----------------------------------------------------------------------------- +// Purpose: Preload the string on the client (if single player it should already be in the cache from the server!!!) +// Input : *object - +// *stringTable - +// stringNumber - +// *newString - +// *newData - +//----------------------------------------------------------------------------- +void OnSceneStringTableChanged( void *object, INetworkStringTable *stringTable, int stringNumber, const char *newString, void const *newData ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: Hook up any callbacks here, the table definition has been parsed but +// no data has been added yet +//----------------------------------------------------------------------------- +void CHLClient::InstallStringTableCallback( const char *tableName ) +{ + // Here, cache off string table IDs + if (!Q_strcasecmp(tableName, "VguiScreen")) + { + // Look up the id + g_StringTableVguiScreen = networkstringtable->FindTable( tableName ); + + // When the material list changes, we need to know immediately + g_StringTableVguiScreen->SetStringChangedCallback( NULL, OnVguiScreenTableChanged ); + } + else if (!Q_strcasecmp(tableName, "Materials")) + { + // Look up the id + g_pStringTableMaterials = networkstringtable->FindTable( tableName ); + + // When the material list changes, we need to know immediately + g_pStringTableMaterials->SetStringChangedCallback( NULL, OnMaterialStringTableChanged ); + } + else if ( !Q_strcasecmp( tableName, "EffectDispatch" ) ) + { + g_StringTableEffectDispatch = networkstringtable->FindTable( tableName ); + } + else if ( !Q_strcasecmp( tableName, "InfoPanel" ) ) + { + g_pStringTableInfoPanel = networkstringtable->FindTable( tableName ); + } + else if ( !Q_strcasecmp( tableName, "Scenes" ) ) + { + g_pStringTableClientSideChoreoScenes = networkstringtable->FindTable( tableName ); + g_pStringTableClientSideChoreoScenes->SetStringChangedCallback( NULL, OnSceneStringTableChanged ); + } + else if ( !Q_strcasecmp( tableName, "ParticleEffectNames" ) ) + { + g_pStringTableParticleEffectNames = networkstringtable->FindTable( tableName ); + networkstringtable->SetAllowClientSideAddString( g_pStringTableParticleEffectNames, true ); + // When the particle system list changes, we need to know immediately + g_pStringTableParticleEffectNames->SetStringChangedCallback( NULL, OnParticleSystemStringTableChanged ); + } + else if ( !Q_strcasecmp( tableName, "ServerMapCycle" ) ) + { + g_pStringTableServerMapCycle = networkstringtable->FindTable( tableName ); + } +#ifdef TF_CLIENT_DLL + else if ( !Q_strcasecmp( tableName, "ServerPopFiles" ) ) + { + g_pStringTableServerPopFiles = networkstringtable->FindTable( tableName ); + } + else if ( !Q_strcasecmp( tableName, "ServerMapCycleMvM" ) ) + { + g_pStringTableServerMapCycleMvM = networkstringtable->FindTable( tableName ); + } +#endif + + InstallStringTableCallback_GameRules(); +} + + +//----------------------------------------------------------------------------- +// Material precache +//----------------------------------------------------------------------------- +void CHLClient::PrecacheMaterial( const char *pMaterialName ) +{ + Assert( pMaterialName ); + + int nLen = Q_strlen( pMaterialName ); + char *pTempBuf = (char*)stackalloc( nLen + 1 ); + memcpy( pTempBuf, pMaterialName, nLen + 1 ); + char *pFound = Q_strstr( pTempBuf, ".vmt\0" ); + if ( pFound ) + { + *pFound = 0; + } + + IMaterial *pMaterial = materials->FindMaterial( pTempBuf, TEXTURE_GROUP_PRECACHED ); + if ( !IsErrorMaterial( pMaterial ) ) + { + pMaterial->IncrementReferenceCount(); + m_CachedMaterials.AddToTail( pMaterial ); + } + else + { + if (IsOSX()) + { + printf("\n ##### CHLClient::PrecacheMaterial could not find material %s (%s)", pMaterialName, pTempBuf ); + } + } +} + +void CHLClient::UncacheAllMaterials( ) +{ + for (int i = m_CachedMaterials.Count(); --i >= 0; ) + { + m_CachedMaterials[i]->DecrementReferenceCount(); + } + m_CachedMaterials.RemoveAll(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pszName - +// iSize - +// *pbuf - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CHLClient::DispatchUserMessage( int msg_type, bf_read &msg_data ) +{ + return usermessages->DispatchUserMessage( msg_type, msg_data ); +} + + +void SimulateEntities() +{ + VPROF_BUDGET("Client SimulateEntities", VPROF_BUDGETGROUP_CLIENT_SIM); + + // Service timer events (think functions). + ClientThinkList()->PerformThinkFunctions(); + + // TODO: make an ISimulateable interface so C_BaseNetworkables can simulate? + { + VPROF_("C_BaseEntity::Simulate", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); + C_BaseEntityIterator iterator; + C_BaseEntity *pEnt; + while ( (pEnt = iterator.Next()) != NULL ) + { + pEnt->Simulate(); + } + } +} + + +bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent ) +{ + VPROF( "AddDataChangeEvent" ); + + Assert( ent ); + // Make sure we don't already have an event queued for this guy. + if ( *pStoredEvent >= 0 ) + { + Assert( g_DataChangedEvents[*pStoredEvent].m_pEntity == ent ); + + // DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED. + if ( updateType == DATA_UPDATE_CREATED ) + g_DataChangedEvents[*pStoredEvent].m_UpdateType = updateType; + + return false; + } + else + { + *pStoredEvent = g_DataChangedEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) ); + return true; + } +} + + +void ClearDataChangedEvent( int iStoredEvent ) +{ + if ( iStoredEvent != -1 ) + g_DataChangedEvents.Remove( iStoredEvent ); +} + + +void ProcessOnDataChangedEvents() +{ + VPROF_("ProcessOnDataChangedEvents", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); + FOR_EACH_LL( g_DataChangedEvents, i ) + { + CDataChangedEvent *pEvent = &g_DataChangedEvents[i]; + + // Reset their stored event identifier. + *pEvent->m_pStoredEvent = -1; + + // Send the event. + IClientNetworkable *pNetworkable = pEvent->m_pEntity; + pNetworkable->OnDataChanged( pEvent->m_UpdateType ); + } + + g_DataChangedEvents.Purge(); +} + + +void UpdateClientRenderableInPVSStatus() +{ + // Vis for this view should already be setup at this point. + + // For each client-only entity, notify it if it's newly coming into the PVS. + CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers(); + FOR_EACH_LL( theList, i ) + { + CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i]; + + if ( pInfo->m_InPVSStatus & INPVS_YES ) + { + // Ok, this entity already thinks it's in the PVS. No need to notify it. + // We need to set the INPVS_YES_THISFRAME flag if it's in this frame at all, so we + // don't tell the entity it's not in the PVS anymore at the end of the frame. + if ( !( pInfo->m_InPVSStatus & INPVS_THISFRAME ) ) + { + if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) ) + { + pInfo->m_InPVSStatus |= INPVS_THISFRAME; + } + } + } + else + { + // This entity doesn't think it's in the PVS yet. If it is now in the PVS, let it know. + if ( g_pClientLeafSystem->IsRenderableInPVS( pInfo->m_pRenderable ) ) + { + pInfo->m_InPVSStatus |= ( INPVS_YES | INPVS_THISFRAME | INPVS_NEEDSNOTIFY ); + } + } + } +} + +void UpdatePVSNotifiers() +{ + MDLCACHE_CRITICAL_SECTION(); + + // At this point, all the entities that were rendered in the previous frame have INPVS_THISFRAME set + // so we can tell the entities that aren't in the PVS anymore so. + CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short> &theList = ClientEntityList().GetPVSNotifiers(); + FOR_EACH_LL( theList, i ) + { + CClientEntityList::CPVSNotifyInfo *pInfo = &theList[i]; + + // If this entity thinks it's in the PVS, but it wasn't in the PVS this frame, tell it so. + if ( pInfo->m_InPVSStatus & INPVS_YES ) + { + if ( pInfo->m_InPVSStatus & INPVS_THISFRAME ) + { + if ( pInfo->m_InPVSStatus & INPVS_NEEDSNOTIFY ) + { + pInfo->m_pNotify->OnPVSStatusChanged( true ); + } + // Clear it for the next time around. + pInfo->m_InPVSStatus &= ~( INPVS_THISFRAME | INPVS_NEEDSNOTIFY ); + } + else + { + pInfo->m_InPVSStatus &= ~INPVS_YES; + pInfo->m_pNotify->OnPVSStatusChanged( false ); + } + } + } +} + + +void OnRenderStart() +{ + VPROF( "OnRenderStart" ); + MDLCACHE_CRITICAL_SECTION(); + MDLCACHE_COARSE_LOCK(); + +#ifdef PORTAL + 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. +#endif + + partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true ); + C_BaseEntity::SetAbsQueriesValid( false ); + + Rope_ResetCounters(); + + // Interpolate server entities and move aiments. + { + PREDICTION_TRACKVALUECHANGESCOPE( "interpolation" ); + C_BaseEntity::InterpolateServerEntities(); + } + + { + // vprof node for this bloc of math + VPROF( "OnRenderStart: dirty bone caches"); + // Invalidate any bone information. + C_BaseAnimating::InvalidateBoneCaches(); + + C_BaseEntity::SetAbsQueriesValid( true ); + C_BaseEntity::EnableAbsRecomputations( true ); + + // Enable access to all model bones except view models. + // This is necessary for aim-ent computation to occur properly + C_BaseAnimating::PushAllowBoneAccess( true, false, "OnRenderStart->CViewRender::SetUpView" ); // pops in CViewRender::SetUpView + + // FIXME: This needs to be done before the player moves; it forces + // aiments the player may be attached to to forcibly update their position + C_BaseEntity::MarkAimEntsDirty(); + } + + // Make sure the camera simulation happens before OnRenderStart, where it's used. + // NOTE: the only thing that happens in CAM_Think is thirdperson related code. + input->CAM_Think(); + + // This will place the player + the view models + all parent + // entities at the correct abs position so that their attachment points + // are at the correct location + view->OnRenderStart(); + + RopeManager()->OnRenderStart(); + + // This will place all entities in the correct position in world space and in the KD-tree + C_BaseAnimating::UpdateClientSideAnimations(); + + partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false ); + + // Process OnDataChanged events. + ProcessOnDataChangedEvents(); + + // Reset the overlay alpha. Entities can change the state of this in their think functions. + g_SmokeFogOverlayAlpha = 0; + + // This must occur prior to SimulatEntities, + // which is where the client thinks for c_colorcorrection + c_colorcorrectionvolumes + // update the color correction weights. + // FIXME: The place where IGameSystem::Update is called should be in here + // so we don't have to explicitly call ResetColorCorrectionWeights + SimulateEntities, etc. + g_pColorCorrectionMgr->ResetColorCorrectionWeights(); + + // Simulate all the entities. + SimulateEntities(); + PhysicsSimulate(); + + C_BaseAnimating::ThreadedBoneSetup(); + + { + VPROF_("Client TempEnts", 0, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); + // This creates things like temp entities. + engine->FireEvents(); + + // Update temp entities + tempents->Update(); + + // Update temp ent beams... + beams->UpdateTempEntBeams(); + + // Lock the frame from beam additions + SetBeamCreationAllowed( false ); + } + + // Update particle effects (eventually, the effects should use Simulate() instead of having + // their own update system). + { + // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined, + // to help track down bad math. + FPExceptionEnabler enableExceptions; + VPROF_BUDGET( "ParticleMgr()->Simulate", VPROF_BUDGETGROUP_PARTICLE_SIMULATION ); + ParticleMgr()->Simulate( gpGlobals->frametime ); + } + + // Now that the view model's position is setup and aiments are marked dirty, update + // their positions so they're in the leaf system correctly. + C_BaseEntity::CalcAimEntPositions(); + + // For entities marked for recording, post bone messages to IToolSystems + if ( ToolsEnabled() ) + { + C_BaseEntity::ToolRecordEntities(); + } + +#if defined( REPLAY_ENABLED ) + // This will record any ragdolls if Replay mode is enabled on the server + CReplayRagdollRecorder::Instance().Think(); + CReplayRagdollCache::Instance().Think(); +#endif + + // Finally, link all the entities into the leaf system right before rendering. + C_BaseEntity::AddVisibleEntities(); +} + + +void OnRenderEnd() +{ + // Disallow access to bones (access is enabled in CViewRender::SetUpView). + C_BaseAnimating::PopBoneAccess( "CViewRender::SetUpView->OnRenderEnd" ); + + UpdatePVSNotifiers(); + + DisplayBoneSetupEnts(); +} + + + +void CHLClient::FrameStageNotify( ClientFrameStage_t curStage ) +{ + g_CurFrameStage = curStage; + + switch( curStage ) + { + default: + break; + + case FRAME_RENDER_START: + { + VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_START" ); + + // Last thing before rendering, run simulation. + OnRenderStart(); + } + break; + + case FRAME_RENDER_END: + { + VPROF( "CHLClient::FrameStageNotify FRAME_RENDER_END" ); + OnRenderEnd(); + + PREDICTION_SPEWVALUECHANGES(); + } + break; + + case FRAME_NET_UPDATE_START: + { + VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_START" ); + // disabled all recomputations while we update entities + C_BaseEntity::EnableAbsRecomputations( false ); + C_BaseEntity::SetAbsQueriesValid( false ); + Interpolation_SetLastPacketTimeStamp( engine->GetLastTimeStamp() ); + partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true ); + + PREDICTION_STARTTRACKVALUE( "netupdate" ); + } + break; + case FRAME_NET_UPDATE_END: + { + ProcessCacheUsedMaterials(); + + // reenable abs recomputation since now all entities have been updated + C_BaseEntity::EnableAbsRecomputations( true ); + C_BaseEntity::SetAbsQueriesValid( true ); + partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false ); + + PREDICTION_ENDTRACKVALUE(); + } + break; + case FRAME_NET_UPDATE_POSTDATAUPDATE_START: + { + VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START" ); + PREDICTION_STARTTRACKVALUE( "postdataupdate" ); + } + break; + case FRAME_NET_UPDATE_POSTDATAUPDATE_END: + { + VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END" ); + PREDICTION_ENDTRACKVALUE(); + // Let prediction copy off pristine data + prediction->PostEntityPacketReceived(); + HLTVCamera()->PostEntityPacketReceived(); +#if defined( REPLAY_ENABLED ) + ReplayCamera()->PostEntityPacketReceived(); +#endif + } + break; + case FRAME_START: + { + // Mark the frame as open for client fx additions + SetFXCreationAllowed( true ); + SetBeamCreationAllowed( true ); + C_BaseEntity::CheckCLInterpChanged(); + } + break; + } +} + +CSaveRestoreData *SaveInit( int size ); + +// Save/restore system hooks +CSaveRestoreData *CHLClient::SaveInit( int size ) +{ + return ::SaveInit(size); +} + +void CHLClient::SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ) +{ + CSave saveHelper( pSaveData ); + saveHelper.WriteFields( pname, pBaseData, pMap, pFields, fieldCount ); +} + +void CHLClient::SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ) +{ + CRestore restoreHelper( pSaveData ); + restoreHelper.ReadFields( pname, pBaseData, pMap, pFields, fieldCount ); +} + +void CHLClient::PreSave( CSaveRestoreData *s ) +{ + g_pGameSaveRestoreBlockSet->PreSave( s ); +} + +void CHLClient::Save( CSaveRestoreData *s ) +{ + CSave saveHelper( s ); + g_pGameSaveRestoreBlockSet->Save( &saveHelper ); +} + +void CHLClient::WriteSaveHeaders( CSaveRestoreData *s ) +{ + CSave saveHelper( s ); + g_pGameSaveRestoreBlockSet->WriteSaveHeaders( &saveHelper ); + g_pGameSaveRestoreBlockSet->PostSave(); +} + +void CHLClient::ReadRestoreHeaders( CSaveRestoreData *s ) +{ + CRestore restoreHelper( s ); + g_pGameSaveRestoreBlockSet->PreRestore(); + g_pGameSaveRestoreBlockSet->ReadRestoreHeaders( &restoreHelper ); +} + +void CHLClient::Restore( CSaveRestoreData *s, bool b ) +{ + CRestore restore(s); + g_pGameSaveRestoreBlockSet->Restore( &restore, b ); + g_pGameSaveRestoreBlockSet->PostRestore(); +} + +static CUtlVector<EHANDLE> g_RestoredEntities; + +void AddRestoredEntity( C_BaseEntity *pEntity ) +{ + if ( !pEntity ) + return; + + g_RestoredEntities.AddToTail( EHANDLE(pEntity) ); +} + +void CHLClient::DispatchOnRestore() +{ + for ( int i = 0; i < g_RestoredEntities.Count(); i++ ) + { + if ( g_RestoredEntities[i] != NULL ) + { + MDLCACHE_CRITICAL_SECTION(); + g_RestoredEntities[i]->OnRestore(); + } + } + g_RestoredEntities.RemoveAll(); +} + +void CHLClient::WriteSaveGameScreenshot( const char *pFilename ) +{ + view->WriteSaveGameScreenshot( pFilename ); +} + +// Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit +// the appropriate close caption if running with closecaption = 1 +void CHLClient::EmitSentenceCloseCaption( char const *tokenstream ) +{ + extern ConVar closecaption; + + if ( !closecaption.GetBool() ) + return; + + CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption ); + if ( hudCloseCaption ) + { + hudCloseCaption->ProcessSentenceCaptionStream( tokenstream ); + } +} + + +void CHLClient::EmitCloseCaption( char const *captionname, float duration ) +{ + extern ConVar closecaption; + + if ( !closecaption.GetBool() ) + return; + + CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption ); + if ( hudCloseCaption ) + { + hudCloseCaption->ProcessCaption( captionname, duration ); + } +} + +CStandardRecvProxies* CHLClient::GetStandardRecvProxies() +{ + return &g_StandardRecvProxies; +} + +bool CHLClient::CanRecordDemo( char *errorMsg, int length ) const +{ + if ( GetClientModeNormal() ) + { + return GetClientModeNormal()->CanRecordDemo( errorMsg, length ); + } + + return true; +} + +void CHLClient::OnDemoRecordStart( char const* pDemoBaseName ) +{ +} + +void CHLClient::OnDemoRecordStop() +{ +} + +void CHLClient::OnDemoPlaybackStart( char const* pDemoBaseName ) +{ +#if defined( REPLAY_ENABLED ) + // Load any ragdoll override frames from disk + char szRagdollFile[MAX_OSPATH]; + V_snprintf( szRagdollFile, sizeof(szRagdollFile), "%s.dmx", pDemoBaseName ); + CReplayRagdollCache::Instance().Init( szRagdollFile ); +#endif +} + +void CHLClient::OnDemoPlaybackStop() +{ +#ifdef DEMOPOLISH_ENABLED + if ( DemoPolish_GetController().m_bInit ) + { + DemoPolish_GetController().Shutdown(); + } +#endif + +#if defined( REPLAY_ENABLED ) + CReplayRagdollCache::Instance().Shutdown(); +#endif +} + +int CHLClient::GetScreenWidth() +{ + return ScreenWidth(); +} + +int CHLClient::GetScreenHeight() +{ + return ScreenHeight(); +} + +// NEW INTERFACES +// save game screenshot writing +void CHLClient::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, + bool bWriteVTF/*=false*/ ) +{ + view->WriteSaveGameScreenshotOfSize( pFilename, width, height, bCreatePowerOf2Padded, bWriteVTF ); +} + +// See RenderViewInfo_t +void CHLClient::RenderView( const CViewSetup &setup, int nClearFlags, int whatToDraw ) +{ + VPROF("RenderView"); + view->RenderView( setup, nClearFlags, whatToDraw ); +} + +void ReloadSoundEntriesInList( IFileList *pFilesToReload ); + +//----------------------------------------------------------------------------- +// For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences. +//----------------------------------------------------------------------------- +void CHLClient::ReloadFilesInList( IFileList *pFilesToReload ) +{ + ReloadParticleEffectsInList( pFilesToReload ); + ReloadSoundEntriesInList( pFilesToReload ); +} + +bool CHLClient::HandleUiToggle() +{ +#if defined( REPLAY_ENABLED ) + if ( !g_pEngineReplay || !g_pEngineReplay->IsSupportedModAndPlatform() ) + return false; + + CReplayPerformanceEditorPanel *pEditor = ReplayUI_GetPerformanceEditor(); + if ( !pEditor ) + return false; + + pEditor->HandleUiToggle(); + + return true; + +#else + return false; +#endif +} + +bool CHLClient::ShouldAllowConsole() +{ + return true; +} + +CRenamedRecvTableInfo *CHLClient::GetRenamedRecvTableInfos() +{ + return g_pRenamedRecvTableInfoHead; +} + +CMouthInfo g_ClientUIMouth; +// Get the mouthinfo for the sound being played inside UI panels +CMouthInfo *CHLClient::GetClientUIMouthInfo() +{ + return &g_ClientUIMouth; +} + +void CHLClient::FileReceived( const char * fileName, unsigned int transferID ) +{ + if ( g_pGameRules ) + { + g_pGameRules->OnFileReceived( fileName, transferID ); + } +} + +void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params ) +{ +#ifdef TF_CLIENT_DLL + CBaseEntity *pEntity = ClientEntityList().GetEnt( params.soundsource ); + + // A player speaking + if ( params.entchannel == CHAN_VOICE && GameRules() && pEntity && pEntity->IsPlayer() ) + { + // Use high-pitched voices for other players if the local player has an item that allows them to hear it (Pyro Goggles) + if ( !GameRules()->IsLocalPlayer( params.soundsource ) && IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) ) + { + params.pitch *= 1.3f; + } + // Halloween voice futzery? + else + { + float flHeadScale = 1.f; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flHeadScale, head_scale ); + + int iHalloweenVoiceSpell = 0; + CALL_ATTRIB_HOOK_INT_ON_OTHER( pEntity, iHalloweenVoiceSpell, halloween_voice_modulation ); + if ( iHalloweenVoiceSpell > 0 ) + { + params.pitch *= 0.8f; + } + else if( flHeadScale != 1.f ) + { + // Big head, deep voice + if( flHeadScale > 1.f ) + { + params.pitch *= 0.8f; + } + else // Small head, high voice + { + params.pitch *= 1.3f; + } + } + } + } +#endif +} + +const char* CHLClient::TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName ) +{ + if ( !GameRules() ) + return pchEffectName; + + return GameRules()->TranslateEffectForVisionFilter( pchEffectType, pchEffectName ); +} + +bool CHLClient::DisconnectAttempt( void ) +{ + bool bRet = false; + +#if defined( TF_CLIENT_DLL ) + bRet = HandleDisconnectAttempt(); +#endif + + return bRet; +} + +bool CHLClient::IsConnectedUserInfoChangeAllowed( IConVar *pCvar ) +{ + return GameRules() ? GameRules()->IsConnectedUserInfoChangeAllowed( NULL ) : true; +} + +#ifndef NO_STEAM + +CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex ) +{ + player_info_t pi; + if ( steamapicontext && steamapicontext->SteamUtils() ) + { + if ( engine->GetPlayerInfo( iPlayerIndex, &pi ) ) + { + if ( pi.friendsID ) + { + return CSteamID( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual ); + } + } + } + return CSteamID(); +} + +#endif |