//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // // $NoKeywords: $ //===========================================================================// #include "cbase.h" #include <crtmemdebug.h> #include "vgui_int.h" #include "clientmode.h" #include "cdll_convar.h" #include "iinput.h" #include "iviewrender.h" #include "ivieweffects.h" #include "ivmodemanager.h" #include "prediction.h" #include "clientsideeffects.h" #include "particlemgr.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 "vstdlib/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 "physpropclientside.h" #include "panelmetaclassmgr.h" #include "c_vguiscreen.h" #include "imessagechars.h" #include "cl_dll/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 "materialsystem/icolorcorrection.h" #include "inputsystem/iinputsystem.h" #include "appframework/IAppSystemGroup.h" #include "scenefilecache/ISceneFileCache.h" #include "tier2/tier2.h" #include "avi/iavi.h" #include "hltvcamera.h" // 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; IMDLCache *mdlcache = 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; IMatSystemSurface *g_pMatSystemSurface = NULL; ISharedGameRules *sharedgamerules = NULL; IEngineTrace *enginetrace = NULL; IGameUIFuncs *gameuifuncs = NULL; IGameEventManager2 *gameeventmanager = NULL; ISoundEmitterSystemBase *soundemitterbase = NULL; IInputSystem *inputsystem = NULL; ISceneFileCache *scenefilecache = NULL; IAvi *avi = NULL; IGameSystem *SoundEmitterSystem(); IGameSystem *ToolFrameworkClientSystem(); 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_StringTableEffectDispatch = NULL; INetworkStringTable *g_StringTableVguiScreen = NULL; INetworkStringTable *g_pStringTableMaterials = NULL; INetworkStringTable *g_pStringTableInfoPanel = NULL; INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL; 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"); // Console variable accessor. static CDLL_ConVarAccessor g_ConVarAccessor; // Physics system bool g_bLevelInitialized; bool g_bTextMode = false; //----------------------------------------------------------------------------- // 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); } }; EXPOSE_SINGLE_INTERFACE( CGameClientExports, IGameClientExports, GAMECLIENTEXPORTS_INTERFACE_VERSION ); class CClientDLLSharedAppSystems : public IClientDLLSharedAppSystems { public: CClientDLLSharedAppSystems() { AddAppSystem( "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION ); AddAppSystem( "scenefilecache.dll", 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. //----------------------------------------------------------------------------- #ifndef _XBOX 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; #endif //----------------------------------------------------------------------------- // 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 Shutdown( void ); 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_MouseEvent( int mstate, bool down ); virtual void IN_Accumulate( void ); virtual void IN_ClearStates( void ); virtual bool IN_IsKeyDown( const char *name, bool& isdown ); // Raw signal virtual int IN_KeyEvent( int eventcode, int keynum, const char *pszCurrentBinding ); // 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, bool drawViewmodel ); 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; // save game screenshot writing virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height ); // See RenderViewInfo_t virtual void RenderViewEx( const CViewSetup &view, int nClearFlags, int whatToDraw ); // Gets the location of the player viewpoint virtual bool GetPlayerView( CViewSetup &playerView ); public: void PrecacheMaterial( const char *pMaterialName ); private: void UncacheAllMaterials( ); 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; } } //----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- CHLClient::CHLClient() { // Kinda bogus, but the logic in the engine is too convoluted to put it there g_bLevelInitialized = false; } extern IGameSystem *ViewportClientSystem(); //----------------------------------------------------------------------------- // 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 ); // Hook up global variables gpGlobals = pGlobals; ConnectTier1Libraries( &appSystemFactory, 1 ); ConnectTier2Libraries( &appSystemFactory, 1 ); // 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 = (IMDLCache*)appSystemFactory(MDLCACHE_INTERFACE_VERSION, NULL )) == NULL ) 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 ( IsPC() && !colorcorrection ) return false; if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL ) return false; if ( (avi = (IAvi *)appSystemFactory(AVI_INTERFACE_VERSION, NULL)) == NULL ) return false; if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL ) return false; 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; #ifndef _XBOX // Not fatal if the material system stub isn't around. materials_stub = (IMaterialSystemStub*)appSystemFactory( MATERIAL_SYSTEM_STUB_INTERFACE_VERSION, NULL ); #endif if( !g_pMaterialSystemHardwareConfig ) return false; // Hook up the gaussian random number generator s_GaussianRandomStream.AttachToStream( random ); // Initialize the console variables. ConCommandBaseMgr::OneTimeInit(&g_ConVarAccessor); if (!Initializer::InitializeAllObjects()) return false; if (!ParticleMgr()->Init(MAX_TOTAL_PARTICLES, materials)) return false; if (!VGui_Startup( appSystemFactory )) return false; g_pMatSystemSurface = (IMatSystemSurface*)vgui::surface()->QueryInterface( MAT_SYSTEM_SURFACE_INTERFACE_VERSION ); if (!g_pMatSystemSurface) return false; // Add the client systems. // Client Leaf System has to be initialized first, since DetailObjectSystem uses it IGameSystem::Add( GameStringSystem() ); IGameSystem::Add( SoundEmitterSystem() ); if ( ToolsEnabled() ) { IGameSystem::Add( ToolFrameworkClientSystem() ); } IGameSystem::Add( ClientLeafSystem() ); IGameSystem::Add( DetailObjectSystem() ); IGameSystem::Add( ViewportClientSystem() ); IGameSystem::Add( ClientEffectPrecacheSystem() ); IGameSystem::Add( g_pClientShadowMgr ); IGameSystem::Add( ClientThinkList() ); IGameSystem::Add( ClientSoundscapeSystem() ); IGameSystem::Add( PerfVisualBenchmark() ); #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(); #ifndef _XBOX ClientVoiceMgr_Init(); // Embed voice status icons inside chat element { vgui::VPANEL parent = enginevgui->GetPanel( PANEL_CLIENTDLL ); GetClientVoiceMgr()->Init( &g_VoiceStatusHelper, parent ); } #endif if ( !PhysicsDLLInit( physicsFactory ) ) return false; g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() ); g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() ); g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() ); ClientWorldFactoryInit(); return true; } //----------------------------------------------------------------------------- // Purpose: Called when the client .dll is being dismissed //----------------------------------------------------------------------------- void CHLClient::Shutdown( void ) { ClientWorldFactoryShutdown(); g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() ); g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() ); g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() ); #ifndef _XBOX ClientVoiceMgr_Shutdown(); #endif Initializer::FreeAllObjects(); g_pClientMode->Disable(); g_pClientMode->Shutdown(); input->Shutdown_All(); C_BaseTempEntity::ClearDynamicTempEnts(); TermSmokeFogOverlay(); view->Shutdown(); UncacheAllMaterials(); IGameSystem::ShutdownAllSystems(); gHUD.Shutdown(); VGui_Shutdown(); ClearKeyValuesCache(); g_pMatSystemSurface = NULL; DisconnectTier2Libraries( ); DisconnectTier1Libraries( ); } //----------------------------------------------------------------------------- // 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(); #ifndef _XBOX GetClientVoiceMgr()->VidInit(); #endif 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; #ifndef _XBOX GetClientVoiceMgr()->Frame( frametime ); #endif gHUD.UpdateHud( bActive ); C_BaseAnimating::AllowBoneAccess( true, false ); IGameSystem::UpdateAllSystems( frametime ); C_BaseAnimating::AllowBoneAccess( false, false ); // run vgui animations vgui::GetAnimationController()->UpdateAnimations( engine->Time() ); // I don't think this is necessary any longer, but I will leave it until // I can check into this further. C_BaseTempEntity::CheckDynamicTempEnts(); } //----------------------------------------------------------------------------- // 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: // Output : ClientClass //----------------------------------------------------------------------------- ClientClass *CHLClient::GetAllClasses( void ) { return g_pClientClassHead; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHLClient::IN_ActivateMouse( void ) { #ifndef _XBOX input->ActivateMouse(); #endif } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHLClient::IN_DeactivateMouse( void ) { #ifndef _XBOX input->DeactivateMouse(); #endif } //----------------------------------------------------------------------------- // Purpose: // Input : mstate - //----------------------------------------------------------------------------- void CHLClient::IN_MouseEvent ( int mstate, bool down ) { #ifndef _XBOX input->MouseEvent( mstate, down ); #endif } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHLClient::IN_Accumulate ( void ) { #ifndef _XBOX input->AccumulateMouse(); #endif } //----------------------------------------------------------------------------- // 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 - // Output : int //----------------------------------------------------------------------------- int CHLClient::IN_KeyEvent( int eventcode, int 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::AllowBoneAccess( true, false ); MDLCACHE_CRITICAL_SECTION(); input->ExtraMouseSample( frametime, active ); C_BaseAnimating::AllowBoneAccess( false, false ); } //----------------------------------------------------------------------------- // 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::AllowBoneAccess( true, false ); MDLCACHE_CRITICAL_SECTION(); input->CreateMove( sequence_number, input_sample_frametime, active ); C_BaseAnimating::AllowBoneAccess( false, false ); } //----------------------------------------------------------------------------- // 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 ); } //----------------------------------------------------------------------------- // Gets the location of the player viewpoint //----------------------------------------------------------------------------- bool CHLClient::GetPlayerView( CViewSetup &playerView ) { playerView = *view->GetPlayerViewSetup(); return true; } //----------------------------------------------------------------------------- // 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(); // Tell mode manager that map is changing modemanager->LevelInit( pMapName ); C_BaseTempEntity::ClearDynamicTempEnts(); clienteffects->Flush(); view->LevelInit(); tempents->LevelInit(); ResetToneMapping(1.0); IGameSystem::LevelInitPreEntityAllSystems(pMapName); 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) && !engine->IsHLTV() ) { if ( !cl_predict.GetBool() ) { engine->ClientCmd( "cl_predict 1" ); } } else { if ( cl_predict.GetBool() ) { engine->ClientCmd( "cl_predict 0" ); } } #endif // Check low violence settings for this map g_RagdollLVManager.SetLowViolence( pMapName ); gHUD.LevelInit(); } //----------------------------------------------------------------------------- // Purpose: Per level init //----------------------------------------------------------------------------- void CHLClient::LevelInitPostEntity( ) { IGameSystem::LevelInitPostEntityAllSystems(); C_PhysPropClientside::RecreateAll(); internalCenterPrint->Clear(); } //----------------------------------------------------------------------------- // 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(); // 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(); tempents->LevelShutdown(); beams->ClearBeams(); ParticleMgr()->RemoveAllEffects(); StopAllRumbleEffects(); gHUD.LevelShutdown(); internalCenterPrint->Clear(); #ifndef _XBOX messagechars->Clear(); #endif UncacheAllMaterials(); #ifdef _XBOX ReleaseRenderTargets(); #endif } //----------------------------------------------------------------------------- // Purpose: Engine can directly ask to render a view ( timerefresh and envmap creation, e.g. ) // Input : &vs - // drawViewmodel - //----------------------------------------------------------------------------- void CHLClient::RenderView( const CViewSetup &vs, int nClearFlags, bool drawViewmodel ) { view->RenderView( vs, nClearFlags, drawViewmodel ); } //----------------------------------------------------------------------------- // 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 ) { #ifndef _XBOX GetClientVoiceMgr()->UpdateSpeakerStatus( entindex, !!bTalking ); #endif } //----------------------------------------------------------------------------- // 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 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 ) { scenefilecache->FindOrAddScene( newString ); } //----------------------------------------------------------------------------- // 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 ); } 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 ); } } 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() { input->CAM_Think(); // Service timer events (think functions). ClientThinkList()->PerformThinkFunctions(); // TODO: make an ISimulateable interface so C_BaseNetworkables can simulate? C_BaseEntityIterator iterator; C_BaseEntity *pEnt; while ( (pEnt = iterator.Next()) != NULL ) { pEnt->Simulate(); } } bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent ) { 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() { 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 UpdatePVSNotifiers() { // 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 ) { // Clear it for the next time around. pInfo->m_InPVSStatus &= ~INPVS_THISFRAME; } else { pInfo->m_InPVSStatus &= ~INPVS_YES; pInfo->m_pNotify->OnPVSStatusChanged( false ); } } } } void OnRenderStart() { VPROF( "OnRenderStart" ); MDLCACHE_CRITICAL_SECTION(); partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true ); C_BaseEntity::SetAbsQueriesValid( false ); Rope_ResetCounters(); // Interpolate server entities and move aiments. C_BaseEntity::InterpolateServerEntities(); // 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::AllowBoneAccess( true, false ); // 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(); // 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(); // 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; // Simulate all the entities. SimulateEntities(); PhysicsSimulate(); // 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). { VPROF_BUDGET( "ParticleMgr()->Update", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); 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(); // 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::AllowBoneAccess( false, false ); 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(); } 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 ); } 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 ); } break; case FRAME_NET_UPDATE_POSTDATAUPDATE_START: { VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_START" ); } break; case FRAME_NET_UPDATE_POSTDATAUPDATE_END: { VPROF( "CHLClient::FrameStageNotify FRAME_NET_UPDATE_POSTDATAUPDATE_END" ); // Let prediction copy off pristine data prediction->PostEntityPacketReceived(); HLTVCamera()->PostEntityPacketReceived(); } break; case FRAME_START: { // Mark the frame as open for client fx additions SetFXCreationAllowed( true ); SetBeamCreationAllowed( true ); } 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; } // NEW INTERFACES // save game screenshot writing void CHLClient::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height ) { view->WriteSaveGameScreenshotOfSize( pFilename, width, height ); } // See RenderViewInfo_t void CHLClient::RenderViewEx( const CViewSetup &setup, int nClearFlags, int whatToDraw ) { VPROF("RenderViewEx"); view->RenderViewEx( setup, nClearFlags, whatToDraw ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 5821 | Knut Wikstrom |
Added Valve Source code. This is NOT to be commited to other than new code from Valve. |