aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/view_effects.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/view_effects.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/view_effects.cpp')
-rw-r--r--mp/src/game/client/view_effects.cpp1590
1 files changed, 795 insertions, 795 deletions
diff --git a/mp/src/game/client/view_effects.cpp b/mp/src/game/client/view_effects.cpp
index 44a4dffd..41cf27d4 100644
--- a/mp/src/game/client/view_effects.cpp
+++ b/mp/src/game/client/view_effects.cpp
@@ -1,795 +1,795 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-#include "cbase.h"
-#include "ivieweffects.h"
-#include "shake.h"
-#include "hud_macros.h"
-#include "isaverestore.h"
-#include "view_shared.h"
-#include "iviewrender.h"
-#include "viewrender.h"
-#include "con_nprint.h"
-#include "saverestoretypes.h"
-#include "c_rumble.h"
-// NVNT haptics interface system
-#include "haptics/ihaptics.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-extern IntroData_t *g_pIntroData;
-
-
-// Arbitrary limit so that bad entity logic on the server can't consume tons of memory on the client.
-#define MAX_SHAKES 32
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Screen fade variables
-//-----------------------------------------------------------------------------
-struct screenfade_t
-{
- float Speed; // How fast to fade (tics / second) (+ fade in, - fade out)
- float End; // When the fading hits maximum
- float Reset; // When to reset to not fading (for fadeout and hold)
- byte r, g, b, alpha; // Fade color
- int Flags; // Fading flags
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-BEGIN_SIMPLE_DATADESC( screenfade_t )
- DEFINE_FIELD( Speed, FIELD_FLOAT ),
- DEFINE_FIELD( End, FIELD_TIME ),
- DEFINE_FIELD( Reset, FIELD_TIME ),
- DEFINE_FIELD( r, FIELD_CHARACTER ),
- DEFINE_FIELD( g, FIELD_CHARACTER ),
- DEFINE_FIELD( b, FIELD_CHARACTER ),
- DEFINE_FIELD( alpha, FIELD_CHARACTER ),
- DEFINE_FIELD( Flags, FIELD_INTEGER ),
-END_DATADESC()
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Screen shake variables
-//-----------------------------------------------------------------------------
-struct screenshake_t
-{
- float endtime;
- float duration;
- float amplitude;
- float frequency;
- float nextShake;
- Vector offset;
- float angle;
- int command;
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-BEGIN_SIMPLE_DATADESC( screenshake_t )
- DEFINE_FIELD( endtime, FIELD_TIME ),
- DEFINE_FIELD( duration, FIELD_FLOAT ),
- DEFINE_FIELD( amplitude, FIELD_FLOAT ),
- DEFINE_FIELD( frequency, FIELD_FLOAT ),
- DEFINE_FIELD( nextShake, FIELD_TIME ),
- DEFINE_FIELD( offset, FIELD_VECTOR ),
- DEFINE_FIELD( angle, FIELD_FLOAT ),
-END_DATADESC()
-
-
-void CC_Shake_Stop();
-//-----------------------------------------------------------------------------
-// Purpose: Implements the view effects interface for the client .dll
-//-----------------------------------------------------------------------------
-class CViewEffects : public IViewEffects
-{
-public:
-
- ~CViewEffects()
- {
- ClearAllFades();
- }
-
- virtual void Init( void );
- virtual void LevelInit( void );
- virtual void GetFadeParams( byte *r, byte *g, byte *b, byte *a, bool *blend );
- virtual void CalcShake( void );
- virtual void ApplyShake( Vector& origin, QAngle& angles, float factor );
-
- virtual void Shake( ScreenShake_t &data );
- virtual void Fade( ScreenFade_t &data );
- virtual void ClearPermanentFades( void );
- virtual void FadeCalculate( void );
- virtual void ClearAllFades( void );
-
- // Save / Restore
- virtual void Save( ISave *pSave );
- virtual void Restore( IRestore *pRestore, bool fCreatePlayers );
-
-private:
-
- void ClearAllShakes();
- screenshake_t *FindLongestShake();
-
- CUtlVector<screenfade_t *> m_FadeList;
-
- CUtlVector<screenshake_t *> m_ShakeList;
- Vector m_vecShakeAppliedOffset;
- float m_flShakeAppliedAngle;
-
- int m_FadeColorRGBA[4];
- bool m_bModulate;
-
- friend void CC_Shake_Stop();
-};
-
-static CViewEffects g_ViewEffects;
-IViewEffects *vieweffects = ( IViewEffects * )&g_ViewEffects;
-
-// Callback function to call at end of screen m_Fade.
-static int s_nCallbackParameter;
-static void ( *s_pfnFadeDoneCallback )( int parm1 );
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pszName -
-// iSize -
-// *pbuf -
-// Output : static int
-//-----------------------------------------------------------------------------
-void __MsgFunc_Shake( bf_read &msg )
-{
- ScreenShake_t shake;
-
- shake.command = msg.ReadByte();
- shake.amplitude = msg.ReadFloat();
- shake.frequency = msg.ReadFloat();
- shake.duration = msg.ReadFloat();
-
- g_ViewEffects.Shake( shake );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pszName -
-// iSize -
-// *pbuf -
-// Output : static int
-//-----------------------------------------------------------------------------
-void __MsgFunc_Fade( bf_read &msg )
-{
- ScreenFade_t fade;
-
- fade.duration = msg.ReadShort(); // fade lasts this long
- fade.holdTime = msg.ReadShort(); // fade lasts this long
- fade.fadeFlags = msg.ReadShort(); // fade type (in / out)
- fade.r = msg.ReadByte(); // fade red
- fade.g = msg.ReadByte(); // fade green
- fade.b = msg.ReadByte(); // fade blue
- fade.a = msg.ReadByte(); // fade blue
-
- g_ViewEffects.Fade( fade );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CViewEffects::Init( void )
-{
- HOOK_MESSAGE( Shake );
- HOOK_MESSAGE( Fade );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CViewEffects::LevelInit( void )
-{
- ClearAllShakes();
- ClearAllFades();
-}
-
-
-static ConVar shake_show( "shake_show", "0", 0, "Displays a list of the active screen shakes." );
-static ConCommand shake_stop("shake_stop", CC_Shake_Stop, "Stops all active screen shakes.\n", FCVAR_CHEAT );
-
-//-----------------------------------------------------------------------------
-// Purpose: Stops all active screen shakes.
-//-----------------------------------------------------------------------------
-void CC_Shake_Stop()
-{
- g_ViewEffects.ClearAllShakes();
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Apply noise to the eye position.
-// UNDONE: Feedback a bit of this into the view model position. It shakes too much
-//-----------------------------------------------------------------------------
-void CViewEffects::CalcShake( void )
-{
- float fraction, freq;
-
- // We'll accumulate the aggregate shake for this frame into these data members.
- m_vecShakeAppliedOffset.Init(0, 0, 0);
- m_flShakeAppliedAngle = 0;
- float flRumbleAngle = 0;
-
- // NVNT - haptic shake effect amplitude
- float hapticShakeAmp = 0;
-
- bool bShow = shake_show.GetBool();
-
- int nShakeCount = m_ShakeList.Count();
-
- for ( int nShake = nShakeCount - 1; nShake >= 0; nShake-- )
- {
- screenshake_t *pShake = m_ShakeList.Element( nShake );
-
- if ( pShake->endtime == 0 )
- {
- // Shouldn't be any such shakes in the list.
- Assert( false );
- continue;
- }
-
- if ( ( gpGlobals->curtime > pShake->endtime ) ||
- pShake->duration <= 0 ||
- pShake->amplitude <= 0 ||
- pShake->frequency <= 0 )
- {
- // Retire this shake.
- delete m_ShakeList.Element( nShake );
- m_ShakeList.FastRemove( nShake );
- continue;
- }
-
- if ( bShow )
- {
- con_nprint_t np;
- np.time_to_live = 2.0f;
- np.fixed_width_font = true;
- np.color[0] = 1.0;
- np.color[1] = 0.8;
- np.color[2] = 0.1;
- np.index = nShake + 2;
-
- engine->Con_NXPrintf( &np, "%02d: dur(%8.2f) amp(%8.2f) freq(%8.2f)", nShake + 1, (double)pShake->duration, (double)pShake->amplitude, (double)pShake->frequency );
- }
-
- if ( gpGlobals->curtime > pShake->nextShake )
- {
- // Higher frequency means we recalc the extents more often and perturb the display again
- pShake->nextShake = gpGlobals->curtime + (1.0f / pShake->frequency);
-
- // Compute random shake extents (the shake will settle down from this)
- for (int i = 0; i < 3; i++ )
- {
- pShake->offset[i] = random->RandomFloat( -pShake->amplitude, pShake->amplitude );
- }
-
- pShake->angle = random->RandomFloat( -pShake->amplitude*0.25, pShake->amplitude*0.25 );
- }
-
- // Ramp down amplitude over duration (fraction goes from 1 to 0 linearly with slope 1/duration)
- fraction = ( pShake->endtime - gpGlobals->curtime ) / pShake->duration;
-
- // Ramp up frequency over duration
- if ( fraction )
- {
- freq = (pShake->frequency / fraction);
- }
- else
- {
- freq = 0;
- }
-
- // square fraction to approach zero more quickly
- fraction *= fraction;
-
- // Sine wave that slowly settles to zero
- float angle = gpGlobals->curtime * freq;
- if ( angle > 1e8 )
- {
- angle = 1e8;
- }
- fraction = fraction * sin( angle );
-
- if( pShake->command != SHAKE_START_NORUMBLE )
- {
- // As long as this isn't a NO RUMBLE effect, then accumulate rumble
- flRumbleAngle += pShake->angle * fraction;
- }
-
- if( pShake->command != SHAKE_START_RUMBLEONLY )
- {
- // As long as this isn't a RUMBLE ONLY effect, then accumulate screen shake
-
- // Add to view origin
- m_vecShakeAppliedOffset += pShake->offset * fraction;
-
- // Add to roll
- m_flShakeAppliedAngle += pShake->angle * fraction;
- }
-
- // Drop amplitude a bit, less for higher frequency shakes
- pShake->amplitude -= pShake->amplitude * ( gpGlobals->frametime / (pShake->duration * pShake->frequency) );
- // NVNT - update our amplitude.
- hapticShakeAmp += pShake->amplitude*fraction;
- }
- // NVNT - apply our screen shake update
- if ( haptics )
- haptics->SetShake(hapticShakeAmp,1);
-
- // Feed this to the rumble system!
- UpdateScreenShakeRumble( flRumbleAngle );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Apply the current screen shake to this origin/angles. Factor is the amount to apply
-// This is so you can blend in part of the shake
-// Input : origin -
-// angles -
-// factor -
-//-----------------------------------------------------------------------------
-void CViewEffects::ApplyShake( Vector& origin, QAngle& angles, float factor )
-{
- VectorMA( origin, factor, m_vecShakeAppliedOffset, origin );
- angles.z += m_flShakeAppliedAngle * factor;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Zeros out all active screen shakes.
-//-----------------------------------------------------------------------------
-void CViewEffects::ClearAllShakes()
-{
- int nShakeCount = m_ShakeList.Count();
- for ( int i = 0; i < nShakeCount; i++ )
- {
- delete m_ShakeList.Element( i );
- }
-
- m_ShakeList.Purge();
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the shake with the longest duration. This is the shake we
-// use anytime we get an amplitude or frequency command, because the
-// most likely case is that we're modifying a shake with a long
-// duration rather than a brief shake caused by an explosion, etc.
-//-----------------------------------------------------------------------------
-screenshake_t *CViewEffects::FindLongestShake()
-{
- screenshake_t *pLongestShake = NULL;
-
- int nShakeCount = m_ShakeList.Count();
- for ( int i = 0; i < nShakeCount; i++ )
- {
- screenshake_t *pShake = m_ShakeList.Element( i );
- if ( pShake && ( !pLongestShake || ( pShake->duration > pLongestShake->duration ) ) )
- {
- pLongestShake = pShake;
- }
- }
-
- return pLongestShake;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Message hook to parse ScreenShake messages
-// Input : pszName -
-// iSize -
-// pbuf -
-// Output :
-//-----------------------------------------------------------------------------
-void CViewEffects::Shake( ScreenShake_t &data )
-{
- if ( ( data.command == SHAKE_START || data.command == SHAKE_START_RUMBLEONLY ) && ( m_ShakeList.Count() < MAX_SHAKES ) )
- {
- screenshake_t *pNewShake = new screenshake_t;
-
- pNewShake->amplitude = data.amplitude;
- pNewShake->frequency = data.frequency;
- pNewShake->duration = data.duration;
- pNewShake->nextShake = 0;
- pNewShake->endtime = gpGlobals->curtime + data.duration;
- pNewShake->command = data.command;
-
- m_ShakeList.AddToTail( pNewShake );
- }
- else if ( data.command == SHAKE_STOP)
- {
- ClearAllShakes();
- }
- else if ( data.command == SHAKE_AMPLITUDE )
- {
- // Look for the most likely shake to modify.
- screenshake_t *pShake = FindLongestShake();
- if ( pShake )
- {
- pShake->amplitude = data.amplitude;
- }
- }
- else if ( data.command == SHAKE_FREQUENCY )
- {
- // Look for the most likely shake to modify.
- screenshake_t *pShake = FindLongestShake();
- if ( pShake )
- {
- pShake->frequency = data.frequency;
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Message hook to parse ScreenFade messages
-// Input : *pszName -
-// iSize -
-// *pbuf -
-// Output : int
-//-----------------------------------------------------------------------------
-void CViewEffects::Fade( ScreenFade_t &data )
-{
- // Create a new fade and append it to the list
- screenfade_t *pNewFade = new screenfade_t;
- pNewFade->End = data.duration * (1.0f/(float)(1<<SCREENFADE_FRACBITS));
- pNewFade->Reset = data.holdTime * (1.0f/(float)(1<<SCREENFADE_FRACBITS));
- pNewFade->r = data.r;
- pNewFade->g = data.g;
- pNewFade->b = data.b;
- pNewFade->alpha = data.a;
- pNewFade->Flags = data.fadeFlags;
- pNewFade->Speed = 0;
-
- // Calc fade speed
- if ( data.duration > 0 )
- {
- if ( data.fadeFlags & FFADE_OUT )
- {
- if ( pNewFade->End )
- {
- pNewFade->Speed = -(float)pNewFade->alpha / pNewFade->End;
- }
-
- pNewFade->End += gpGlobals->curtime;
- pNewFade->Reset += pNewFade->End;
- }
- else
- {
- if ( pNewFade->End )
- {
- pNewFade->Speed = (float)pNewFade->alpha / pNewFade->End;
- }
-
- pNewFade->Reset += gpGlobals->curtime;
- pNewFade->End += pNewFade->Reset;
- }
- }
-
- if ( data.fadeFlags & FFADE_PURGE )
- {
- ClearAllFades();
- }
-
- m_FadeList.AddToTail( pNewFade );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Compute the overall color & alpha of the fades
-//-----------------------------------------------------------------------------
-void CViewEffects::FadeCalculate( void )
-{
- // Cycle through all fades and remove any that have finished (work backwards)
- int i;
- int iSize = m_FadeList.Size();
- for (i = iSize-1; i >= 0; i-- )
- {
- screenfade_t *pFade = m_FadeList[i];
-
- // Keep pushing reset time out indefinitely
- if ( pFade->Flags & FFADE_STAYOUT )
- {
- pFade->Reset = gpGlobals->curtime + 0.1;
- }
-
- // All done?
- if ( ( gpGlobals->curtime > pFade->Reset ) && ( gpGlobals->curtime > pFade->End ) )
- {
- // User passed in a callback function, call it now
- if ( s_pfnFadeDoneCallback )
- {
- s_pfnFadeDoneCallback( s_nCallbackParameter );
- s_pfnFadeDoneCallback = NULL;
- s_nCallbackParameter = 0;
- }
-
- // Remove this Fade from the list
- m_FadeList.FindAndRemove( pFade );
- delete pFade;
- }
- }
-
- m_bModulate = false;
- m_FadeColorRGBA[0] = m_FadeColorRGBA[1] = m_FadeColorRGBA[2] = m_FadeColorRGBA[3] = 0;
-
- // Cycle through all fades in the list and calculate the overall color/alpha
- for ( i = 0; i < m_FadeList.Size(); i++ )
- {
- screenfade_t *pFade = m_FadeList[i];
-
- // Color
- m_FadeColorRGBA[0] += pFade->r;
- m_FadeColorRGBA[1] += pFade->g;
- m_FadeColorRGBA[2] += pFade->b;
-
- // Fading...
- int iFadeAlpha;
- if ( pFade->Flags & (FFADE_OUT|FFADE_IN) )
- {
- iFadeAlpha = pFade->Speed * ( pFade->End - gpGlobals->curtime );
- if ( pFade->Flags & FFADE_OUT )
- {
- iFadeAlpha += pFade->alpha;
- }
- iFadeAlpha = MIN( iFadeAlpha, pFade->alpha );
- iFadeAlpha = MAX( 0, iFadeAlpha );
- }
- else
- {
- iFadeAlpha = pFade->alpha;
- }
-
- // Use highest alpha
- if ( iFadeAlpha > m_FadeColorRGBA[3] )
- {
- m_FadeColorRGBA[3] = iFadeAlpha;
- }
-
- // Modulate?
- if ( pFade->Flags & FFADE_MODULATE )
- {
- m_bModulate = true;
- }
- }
-
- // Divide colors
- if ( m_FadeList.Size() )
- {
- m_FadeColorRGBA[0] /= m_FadeList.Size();
- m_FadeColorRGBA[1] /= m_FadeList.Size();
- m_FadeColorRGBA[2] /= m_FadeList.Size();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Clear only the permanent fades in our fade list
-//-----------------------------------------------------------------------------
-void CViewEffects::ClearPermanentFades( void )
-{
- int iSize = m_FadeList.Size();
- for (int i = iSize-1; i >= 0; i-- )
- {
- screenfade_t *pFade = m_FadeList[i];
-
- if ( pFade->Flags & FFADE_STAYOUT )
- {
- // Destroy this fade
- m_FadeList.FindAndRemove( pFade );
- delete pFade;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Purge & delete all fades in the queue
-//-----------------------------------------------------------------------------
-void CViewEffects::ClearAllFades( void )
-{
- int iSize = m_FadeList.Size();
- for (int i = iSize-1; i >= 0; i-- )
- {
- delete m_FadeList[i];
- }
- m_FadeList.Purge();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : context - Which call to Render is this ( CViewSetup::context )
-// *r -
-// *g -
-// *b -
-// *a -
-// *blend -
-//-----------------------------------------------------------------------------
-void CViewEffects::GetFadeParams( byte *r, byte *g, byte *b, byte *a, bool *blend )
-{
- // If the intro is overriding our fade, use that instead
- if ( g_pIntroData && g_pIntroData->m_flCurrentFadeColor[3] )
- {
- *r = g_pIntroData->m_flCurrentFadeColor[0];
- *g = g_pIntroData->m_flCurrentFadeColor[1];
- *b = g_pIntroData->m_flCurrentFadeColor[2];
- *a = g_pIntroData->m_flCurrentFadeColor[3];
- *blend = false;
- return;
- }
-
- FadeCalculate();
-
- *r = m_FadeColorRGBA[0];
- *g = m_FadeColorRGBA[1];
- *b = m_FadeColorRGBA[2];
- *a = m_FadeColorRGBA[3];
- *blend = m_bModulate;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pSave -
-//-----------------------------------------------------------------------------
-void CViewEffects::Save( ISave *pSave )
-{
- // Save the view fades
- int iCount = m_FadeList.Count();
- pSave->WriteInt( &iCount );
- for ( int i = 0; i < iCount; i++ )
- {
- pSave->StartBlock();
- pSave->WriteAll( m_FadeList[i] );
- pSave->EndBlock();
- }
-
- // Save the view shakes
- iCount = m_ShakeList.Count();
- pSave->WriteInt( &iCount );
- for ( int i = 0; i < iCount; i++ )
- {
- pSave->StartBlock();
- pSave->WriteAll( m_ShakeList[i] );
- pSave->EndBlock();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pRestore -
-// fCreatePlayers -
-//-----------------------------------------------------------------------------
-void CViewEffects::Restore( IRestore *pRestore, bool fCreatePlayers )
-{
- CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo();
-
- // View effects is a singleton so we only need to restore it once,
- // from the level that we are going into.
- if( !pSaveData->levelInfo.fUseLandmark )
- {
- ClearAllFades();
- ClearAllShakes();
-
- // Read in the view fades
- int iCount = pRestore->ReadInt();
- for ( int i = 0; i < iCount; i++ )
- {
- screenfade_t *pNewFade = new screenfade_t;
-
- pRestore->StartBlock();
- pRestore->ReadAll( pNewFade );
- pRestore->EndBlock();
-
- m_FadeList.AddToTail( pNewFade );
- }
-
- // Read in the view shakes
- iCount = pRestore->ReadInt();
- for ( int i = 0; i < iCount; i++ )
- {
- screenshake_t *pNewShake = new screenshake_t;
-
- pRestore->StartBlock();
- pRestore->ReadAll( pNewShake );
- pRestore->EndBlock();
-
- m_ShakeList.AddToTail( pNewShake );
- }
- }
-}
-
-//====================================================================================================
-// CLIENTSIDE VIEW EFFECTS SAVE/RESTORE
-//====================================================================================================
-static short VIEWEFFECTS_SAVE_RESTORE_VERSION = 2;
-
-class CViewEffectsSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
-{
- struct QueuedItem_t;
-public:
- CViewEffectsSaveRestoreBlockHandler()
- {
- }
-
- const char *GetBlockName()
- {
- return "ViewEffects";
- }
-
- //---------------------------------
-
- virtual void PreSave( CSaveRestoreData * )
- {
- }
-
- //---------------------------------
-
- virtual void Save( ISave *pSave )
- {
- vieweffects->Save( pSave );
- }
-
- //---------------------------------
-
- virtual void WriteSaveHeaders( ISave *pSave )
- {
- pSave->WriteShort( &VIEWEFFECTS_SAVE_RESTORE_VERSION );
- }
-
- //---------------------------------
-
- virtual void PostSave()
- {
- }
-
- //---------------------------------
-
- virtual void PreRestore()
- {
- }
-
- //---------------------------------
-
- virtual void ReadRestoreHeaders( IRestore *pRestore )
- {
- // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
- short version = pRestore->ReadShort();
- m_bDoLoad = ( version == VIEWEFFECTS_SAVE_RESTORE_VERSION );
- }
-
- //---------------------------------
-
- virtual void Restore( IRestore *pRestore, bool fCreatePlayers )
- {
- if ( m_bDoLoad )
- {
- vieweffects->Restore( pRestore, fCreatePlayers );
- }
- }
-
- //---------------------------------
-
- virtual void PostRestore()
- {
- }
-
-private:
- bool m_bDoLoad;
-};
-
-//-----------------------------------------------------------------------------
-
-CViewEffectsSaveRestoreBlockHandler g_ViewEffectsSaveRestoreBlockHandler;
-
-ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler()
-{
- return &g_ViewEffectsSaveRestoreBlockHandler;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "ivieweffects.h"
+#include "shake.h"
+#include "hud_macros.h"
+#include "isaverestore.h"
+#include "view_shared.h"
+#include "iviewrender.h"
+#include "viewrender.h"
+#include "con_nprint.h"
+#include "saverestoretypes.h"
+#include "c_rumble.h"
+// NVNT haptics interface system
+#include "haptics/ihaptics.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern IntroData_t *g_pIntroData;
+
+
+// Arbitrary limit so that bad entity logic on the server can't consume tons of memory on the client.
+#define MAX_SHAKES 32
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Screen fade variables
+//-----------------------------------------------------------------------------
+struct screenfade_t
+{
+ float Speed; // How fast to fade (tics / second) (+ fade in, - fade out)
+ float End; // When the fading hits maximum
+ float Reset; // When to reset to not fading (for fadeout and hold)
+ byte r, g, b, alpha; // Fade color
+ int Flags; // Fading flags
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+BEGIN_SIMPLE_DATADESC( screenfade_t )
+ DEFINE_FIELD( Speed, FIELD_FLOAT ),
+ DEFINE_FIELD( End, FIELD_TIME ),
+ DEFINE_FIELD( Reset, FIELD_TIME ),
+ DEFINE_FIELD( r, FIELD_CHARACTER ),
+ DEFINE_FIELD( g, FIELD_CHARACTER ),
+ DEFINE_FIELD( b, FIELD_CHARACTER ),
+ DEFINE_FIELD( alpha, FIELD_CHARACTER ),
+ DEFINE_FIELD( Flags, FIELD_INTEGER ),
+END_DATADESC()
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Screen shake variables
+//-----------------------------------------------------------------------------
+struct screenshake_t
+{
+ float endtime;
+ float duration;
+ float amplitude;
+ float frequency;
+ float nextShake;
+ Vector offset;
+ float angle;
+ int command;
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+BEGIN_SIMPLE_DATADESC( screenshake_t )
+ DEFINE_FIELD( endtime, FIELD_TIME ),
+ DEFINE_FIELD( duration, FIELD_FLOAT ),
+ DEFINE_FIELD( amplitude, FIELD_FLOAT ),
+ DEFINE_FIELD( frequency, FIELD_FLOAT ),
+ DEFINE_FIELD( nextShake, FIELD_TIME ),
+ DEFINE_FIELD( offset, FIELD_VECTOR ),
+ DEFINE_FIELD( angle, FIELD_FLOAT ),
+END_DATADESC()
+
+
+void CC_Shake_Stop();
+//-----------------------------------------------------------------------------
+// Purpose: Implements the view effects interface for the client .dll
+//-----------------------------------------------------------------------------
+class CViewEffects : public IViewEffects
+{
+public:
+
+ ~CViewEffects()
+ {
+ ClearAllFades();
+ }
+
+ virtual void Init( void );
+ virtual void LevelInit( void );
+ virtual void GetFadeParams( byte *r, byte *g, byte *b, byte *a, bool *blend );
+ virtual void CalcShake( void );
+ virtual void ApplyShake( Vector& origin, QAngle& angles, float factor );
+
+ virtual void Shake( ScreenShake_t &data );
+ virtual void Fade( ScreenFade_t &data );
+ virtual void ClearPermanentFades( void );
+ virtual void FadeCalculate( void );
+ virtual void ClearAllFades( void );
+
+ // Save / Restore
+ virtual void Save( ISave *pSave );
+ virtual void Restore( IRestore *pRestore, bool fCreatePlayers );
+
+private:
+
+ void ClearAllShakes();
+ screenshake_t *FindLongestShake();
+
+ CUtlVector<screenfade_t *> m_FadeList;
+
+ CUtlVector<screenshake_t *> m_ShakeList;
+ Vector m_vecShakeAppliedOffset;
+ float m_flShakeAppliedAngle;
+
+ int m_FadeColorRGBA[4];
+ bool m_bModulate;
+
+ friend void CC_Shake_Stop();
+};
+
+static CViewEffects g_ViewEffects;
+IViewEffects *vieweffects = ( IViewEffects * )&g_ViewEffects;
+
+// Callback function to call at end of screen m_Fade.
+static int s_nCallbackParameter;
+static void ( *s_pfnFadeDoneCallback )( int parm1 );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pszName -
+// iSize -
+// *pbuf -
+// Output : static int
+//-----------------------------------------------------------------------------
+void __MsgFunc_Shake( bf_read &msg )
+{
+ ScreenShake_t shake;
+
+ shake.command = msg.ReadByte();
+ shake.amplitude = msg.ReadFloat();
+ shake.frequency = msg.ReadFloat();
+ shake.duration = msg.ReadFloat();
+
+ g_ViewEffects.Shake( shake );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pszName -
+// iSize -
+// *pbuf -
+// Output : static int
+//-----------------------------------------------------------------------------
+void __MsgFunc_Fade( bf_read &msg )
+{
+ ScreenFade_t fade;
+
+ fade.duration = msg.ReadShort(); // fade lasts this long
+ fade.holdTime = msg.ReadShort(); // fade lasts this long
+ fade.fadeFlags = msg.ReadShort(); // fade type (in / out)
+ fade.r = msg.ReadByte(); // fade red
+ fade.g = msg.ReadByte(); // fade green
+ fade.b = msg.ReadByte(); // fade blue
+ fade.a = msg.ReadByte(); // fade blue
+
+ g_ViewEffects.Fade( fade );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CViewEffects::Init( void )
+{
+ HOOK_MESSAGE( Shake );
+ HOOK_MESSAGE( Fade );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CViewEffects::LevelInit( void )
+{
+ ClearAllShakes();
+ ClearAllFades();
+}
+
+
+static ConVar shake_show( "shake_show", "0", 0, "Displays a list of the active screen shakes." );
+static ConCommand shake_stop("shake_stop", CC_Shake_Stop, "Stops all active screen shakes.\n", FCVAR_CHEAT );
+
+//-----------------------------------------------------------------------------
+// Purpose: Stops all active screen shakes.
+//-----------------------------------------------------------------------------
+void CC_Shake_Stop()
+{
+ g_ViewEffects.ClearAllShakes();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Apply noise to the eye position.
+// UNDONE: Feedback a bit of this into the view model position. It shakes too much
+//-----------------------------------------------------------------------------
+void CViewEffects::CalcShake( void )
+{
+ float fraction, freq;
+
+ // We'll accumulate the aggregate shake for this frame into these data members.
+ m_vecShakeAppliedOffset.Init(0, 0, 0);
+ m_flShakeAppliedAngle = 0;
+ float flRumbleAngle = 0;
+
+ // NVNT - haptic shake effect amplitude
+ float hapticShakeAmp = 0;
+
+ bool bShow = shake_show.GetBool();
+
+ int nShakeCount = m_ShakeList.Count();
+
+ for ( int nShake = nShakeCount - 1; nShake >= 0; nShake-- )
+ {
+ screenshake_t *pShake = m_ShakeList.Element( nShake );
+
+ if ( pShake->endtime == 0 )
+ {
+ // Shouldn't be any such shakes in the list.
+ Assert( false );
+ continue;
+ }
+
+ if ( ( gpGlobals->curtime > pShake->endtime ) ||
+ pShake->duration <= 0 ||
+ pShake->amplitude <= 0 ||
+ pShake->frequency <= 0 )
+ {
+ // Retire this shake.
+ delete m_ShakeList.Element( nShake );
+ m_ShakeList.FastRemove( nShake );
+ continue;
+ }
+
+ if ( bShow )
+ {
+ con_nprint_t np;
+ np.time_to_live = 2.0f;
+ np.fixed_width_font = true;
+ np.color[0] = 1.0;
+ np.color[1] = 0.8;
+ np.color[2] = 0.1;
+ np.index = nShake + 2;
+
+ engine->Con_NXPrintf( &np, "%02d: dur(%8.2f) amp(%8.2f) freq(%8.2f)", nShake + 1, (double)pShake->duration, (double)pShake->amplitude, (double)pShake->frequency );
+ }
+
+ if ( gpGlobals->curtime > pShake->nextShake )
+ {
+ // Higher frequency means we recalc the extents more often and perturb the display again
+ pShake->nextShake = gpGlobals->curtime + (1.0f / pShake->frequency);
+
+ // Compute random shake extents (the shake will settle down from this)
+ for (int i = 0; i < 3; i++ )
+ {
+ pShake->offset[i] = random->RandomFloat( -pShake->amplitude, pShake->amplitude );
+ }
+
+ pShake->angle = random->RandomFloat( -pShake->amplitude*0.25, pShake->amplitude*0.25 );
+ }
+
+ // Ramp down amplitude over duration (fraction goes from 1 to 0 linearly with slope 1/duration)
+ fraction = ( pShake->endtime - gpGlobals->curtime ) / pShake->duration;
+
+ // Ramp up frequency over duration
+ if ( fraction )
+ {
+ freq = (pShake->frequency / fraction);
+ }
+ else
+ {
+ freq = 0;
+ }
+
+ // square fraction to approach zero more quickly
+ fraction *= fraction;
+
+ // Sine wave that slowly settles to zero
+ float angle = gpGlobals->curtime * freq;
+ if ( angle > 1e8 )
+ {
+ angle = 1e8;
+ }
+ fraction = fraction * sin( angle );
+
+ if( pShake->command != SHAKE_START_NORUMBLE )
+ {
+ // As long as this isn't a NO RUMBLE effect, then accumulate rumble
+ flRumbleAngle += pShake->angle * fraction;
+ }
+
+ if( pShake->command != SHAKE_START_RUMBLEONLY )
+ {
+ // As long as this isn't a RUMBLE ONLY effect, then accumulate screen shake
+
+ // Add to view origin
+ m_vecShakeAppliedOffset += pShake->offset * fraction;
+
+ // Add to roll
+ m_flShakeAppliedAngle += pShake->angle * fraction;
+ }
+
+ // Drop amplitude a bit, less for higher frequency shakes
+ pShake->amplitude -= pShake->amplitude * ( gpGlobals->frametime / (pShake->duration * pShake->frequency) );
+ // NVNT - update our amplitude.
+ hapticShakeAmp += pShake->amplitude*fraction;
+ }
+ // NVNT - apply our screen shake update
+ if ( haptics )
+ haptics->SetShake(hapticShakeAmp,1);
+
+ // Feed this to the rumble system!
+ UpdateScreenShakeRumble( flRumbleAngle );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Apply the current screen shake to this origin/angles. Factor is the amount to apply
+// This is so you can blend in part of the shake
+// Input : origin -
+// angles -
+// factor -
+//-----------------------------------------------------------------------------
+void CViewEffects::ApplyShake( Vector& origin, QAngle& angles, float factor )
+{
+ VectorMA( origin, factor, m_vecShakeAppliedOffset, origin );
+ angles.z += m_flShakeAppliedAngle * factor;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Zeros out all active screen shakes.
+//-----------------------------------------------------------------------------
+void CViewEffects::ClearAllShakes()
+{
+ int nShakeCount = m_ShakeList.Count();
+ for ( int i = 0; i < nShakeCount; i++ )
+ {
+ delete m_ShakeList.Element( i );
+ }
+
+ m_ShakeList.Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the shake with the longest duration. This is the shake we
+// use anytime we get an amplitude or frequency command, because the
+// most likely case is that we're modifying a shake with a long
+// duration rather than a brief shake caused by an explosion, etc.
+//-----------------------------------------------------------------------------
+screenshake_t *CViewEffects::FindLongestShake()
+{
+ screenshake_t *pLongestShake = NULL;
+
+ int nShakeCount = m_ShakeList.Count();
+ for ( int i = 0; i < nShakeCount; i++ )
+ {
+ screenshake_t *pShake = m_ShakeList.Element( i );
+ if ( pShake && ( !pLongestShake || ( pShake->duration > pLongestShake->duration ) ) )
+ {
+ pLongestShake = pShake;
+ }
+ }
+
+ return pLongestShake;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Message hook to parse ScreenShake messages
+// Input : pszName -
+// iSize -
+// pbuf -
+// Output :
+//-----------------------------------------------------------------------------
+void CViewEffects::Shake( ScreenShake_t &data )
+{
+ if ( ( data.command == SHAKE_START || data.command == SHAKE_START_RUMBLEONLY ) && ( m_ShakeList.Count() < MAX_SHAKES ) )
+ {
+ screenshake_t *pNewShake = new screenshake_t;
+
+ pNewShake->amplitude = data.amplitude;
+ pNewShake->frequency = data.frequency;
+ pNewShake->duration = data.duration;
+ pNewShake->nextShake = 0;
+ pNewShake->endtime = gpGlobals->curtime + data.duration;
+ pNewShake->command = data.command;
+
+ m_ShakeList.AddToTail( pNewShake );
+ }
+ else if ( data.command == SHAKE_STOP)
+ {
+ ClearAllShakes();
+ }
+ else if ( data.command == SHAKE_AMPLITUDE )
+ {
+ // Look for the most likely shake to modify.
+ screenshake_t *pShake = FindLongestShake();
+ if ( pShake )
+ {
+ pShake->amplitude = data.amplitude;
+ }
+ }
+ else if ( data.command == SHAKE_FREQUENCY )
+ {
+ // Look for the most likely shake to modify.
+ screenshake_t *pShake = FindLongestShake();
+ if ( pShake )
+ {
+ pShake->frequency = data.frequency;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Message hook to parse ScreenFade messages
+// Input : *pszName -
+// iSize -
+// *pbuf -
+// Output : int
+//-----------------------------------------------------------------------------
+void CViewEffects::Fade( ScreenFade_t &data )
+{
+ // Create a new fade and append it to the list
+ screenfade_t *pNewFade = new screenfade_t;
+ pNewFade->End = data.duration * (1.0f/(float)(1<<SCREENFADE_FRACBITS));
+ pNewFade->Reset = data.holdTime * (1.0f/(float)(1<<SCREENFADE_FRACBITS));
+ pNewFade->r = data.r;
+ pNewFade->g = data.g;
+ pNewFade->b = data.b;
+ pNewFade->alpha = data.a;
+ pNewFade->Flags = data.fadeFlags;
+ pNewFade->Speed = 0;
+
+ // Calc fade speed
+ if ( data.duration > 0 )
+ {
+ if ( data.fadeFlags & FFADE_OUT )
+ {
+ if ( pNewFade->End )
+ {
+ pNewFade->Speed = -(float)pNewFade->alpha / pNewFade->End;
+ }
+
+ pNewFade->End += gpGlobals->curtime;
+ pNewFade->Reset += pNewFade->End;
+ }
+ else
+ {
+ if ( pNewFade->End )
+ {
+ pNewFade->Speed = (float)pNewFade->alpha / pNewFade->End;
+ }
+
+ pNewFade->Reset += gpGlobals->curtime;
+ pNewFade->End += pNewFade->Reset;
+ }
+ }
+
+ if ( data.fadeFlags & FFADE_PURGE )
+ {
+ ClearAllFades();
+ }
+
+ m_FadeList.AddToTail( pNewFade );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Compute the overall color & alpha of the fades
+//-----------------------------------------------------------------------------
+void CViewEffects::FadeCalculate( void )
+{
+ // Cycle through all fades and remove any that have finished (work backwards)
+ int i;
+ int iSize = m_FadeList.Size();
+ for (i = iSize-1; i >= 0; i-- )
+ {
+ screenfade_t *pFade = m_FadeList[i];
+
+ // Keep pushing reset time out indefinitely
+ if ( pFade->Flags & FFADE_STAYOUT )
+ {
+ pFade->Reset = gpGlobals->curtime + 0.1;
+ }
+
+ // All done?
+ if ( ( gpGlobals->curtime > pFade->Reset ) && ( gpGlobals->curtime > pFade->End ) )
+ {
+ // User passed in a callback function, call it now
+ if ( s_pfnFadeDoneCallback )
+ {
+ s_pfnFadeDoneCallback( s_nCallbackParameter );
+ s_pfnFadeDoneCallback = NULL;
+ s_nCallbackParameter = 0;
+ }
+
+ // Remove this Fade from the list
+ m_FadeList.FindAndRemove( pFade );
+ delete pFade;
+ }
+ }
+
+ m_bModulate = false;
+ m_FadeColorRGBA[0] = m_FadeColorRGBA[1] = m_FadeColorRGBA[2] = m_FadeColorRGBA[3] = 0;
+
+ // Cycle through all fades in the list and calculate the overall color/alpha
+ for ( i = 0; i < m_FadeList.Size(); i++ )
+ {
+ screenfade_t *pFade = m_FadeList[i];
+
+ // Color
+ m_FadeColorRGBA[0] += pFade->r;
+ m_FadeColorRGBA[1] += pFade->g;
+ m_FadeColorRGBA[2] += pFade->b;
+
+ // Fading...
+ int iFadeAlpha;
+ if ( pFade->Flags & (FFADE_OUT|FFADE_IN) )
+ {
+ iFadeAlpha = pFade->Speed * ( pFade->End - gpGlobals->curtime );
+ if ( pFade->Flags & FFADE_OUT )
+ {
+ iFadeAlpha += pFade->alpha;
+ }
+ iFadeAlpha = MIN( iFadeAlpha, pFade->alpha );
+ iFadeAlpha = MAX( 0, iFadeAlpha );
+ }
+ else
+ {
+ iFadeAlpha = pFade->alpha;
+ }
+
+ // Use highest alpha
+ if ( iFadeAlpha > m_FadeColorRGBA[3] )
+ {
+ m_FadeColorRGBA[3] = iFadeAlpha;
+ }
+
+ // Modulate?
+ if ( pFade->Flags & FFADE_MODULATE )
+ {
+ m_bModulate = true;
+ }
+ }
+
+ // Divide colors
+ if ( m_FadeList.Size() )
+ {
+ m_FadeColorRGBA[0] /= m_FadeList.Size();
+ m_FadeColorRGBA[1] /= m_FadeList.Size();
+ m_FadeColorRGBA[2] /= m_FadeList.Size();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Clear only the permanent fades in our fade list
+//-----------------------------------------------------------------------------
+void CViewEffects::ClearPermanentFades( void )
+{
+ int iSize = m_FadeList.Size();
+ for (int i = iSize-1; i >= 0; i-- )
+ {
+ screenfade_t *pFade = m_FadeList[i];
+
+ if ( pFade->Flags & FFADE_STAYOUT )
+ {
+ // Destroy this fade
+ m_FadeList.FindAndRemove( pFade );
+ delete pFade;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Purge & delete all fades in the queue
+//-----------------------------------------------------------------------------
+void CViewEffects::ClearAllFades( void )
+{
+ int iSize = m_FadeList.Size();
+ for (int i = iSize-1; i >= 0; i-- )
+ {
+ delete m_FadeList[i];
+ }
+ m_FadeList.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : context - Which call to Render is this ( CViewSetup::context )
+// *r -
+// *g -
+// *b -
+// *a -
+// *blend -
+//-----------------------------------------------------------------------------
+void CViewEffects::GetFadeParams( byte *r, byte *g, byte *b, byte *a, bool *blend )
+{
+ // If the intro is overriding our fade, use that instead
+ if ( g_pIntroData && g_pIntroData->m_flCurrentFadeColor[3] )
+ {
+ *r = g_pIntroData->m_flCurrentFadeColor[0];
+ *g = g_pIntroData->m_flCurrentFadeColor[1];
+ *b = g_pIntroData->m_flCurrentFadeColor[2];
+ *a = g_pIntroData->m_flCurrentFadeColor[3];
+ *blend = false;
+ return;
+ }
+
+ FadeCalculate();
+
+ *r = m_FadeColorRGBA[0];
+ *g = m_FadeColorRGBA[1];
+ *b = m_FadeColorRGBA[2];
+ *a = m_FadeColorRGBA[3];
+ *blend = m_bModulate;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pSave -
+//-----------------------------------------------------------------------------
+void CViewEffects::Save( ISave *pSave )
+{
+ // Save the view fades
+ int iCount = m_FadeList.Count();
+ pSave->WriteInt( &iCount );
+ for ( int i = 0; i < iCount; i++ )
+ {
+ pSave->StartBlock();
+ pSave->WriteAll( m_FadeList[i] );
+ pSave->EndBlock();
+ }
+
+ // Save the view shakes
+ iCount = m_ShakeList.Count();
+ pSave->WriteInt( &iCount );
+ for ( int i = 0; i < iCount; i++ )
+ {
+ pSave->StartBlock();
+ pSave->WriteAll( m_ShakeList[i] );
+ pSave->EndBlock();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pRestore -
+// fCreatePlayers -
+//-----------------------------------------------------------------------------
+void CViewEffects::Restore( IRestore *pRestore, bool fCreatePlayers )
+{
+ CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo();
+
+ // View effects is a singleton so we only need to restore it once,
+ // from the level that we are going into.
+ if( !pSaveData->levelInfo.fUseLandmark )
+ {
+ ClearAllFades();
+ ClearAllShakes();
+
+ // Read in the view fades
+ int iCount = pRestore->ReadInt();
+ for ( int i = 0; i < iCount; i++ )
+ {
+ screenfade_t *pNewFade = new screenfade_t;
+
+ pRestore->StartBlock();
+ pRestore->ReadAll( pNewFade );
+ pRestore->EndBlock();
+
+ m_FadeList.AddToTail( pNewFade );
+ }
+
+ // Read in the view shakes
+ iCount = pRestore->ReadInt();
+ for ( int i = 0; i < iCount; i++ )
+ {
+ screenshake_t *pNewShake = new screenshake_t;
+
+ pRestore->StartBlock();
+ pRestore->ReadAll( pNewShake );
+ pRestore->EndBlock();
+
+ m_ShakeList.AddToTail( pNewShake );
+ }
+ }
+}
+
+//====================================================================================================
+// CLIENTSIDE VIEW EFFECTS SAVE/RESTORE
+//====================================================================================================
+static short VIEWEFFECTS_SAVE_RESTORE_VERSION = 2;
+
+class CViewEffectsSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
+{
+ struct QueuedItem_t;
+public:
+ CViewEffectsSaveRestoreBlockHandler()
+ {
+ }
+
+ const char *GetBlockName()
+ {
+ return "ViewEffects";
+ }
+
+ //---------------------------------
+
+ virtual void PreSave( CSaveRestoreData * )
+ {
+ }
+
+ //---------------------------------
+
+ virtual void Save( ISave *pSave )
+ {
+ vieweffects->Save( pSave );
+ }
+
+ //---------------------------------
+
+ virtual void WriteSaveHeaders( ISave *pSave )
+ {
+ pSave->WriteShort( &VIEWEFFECTS_SAVE_RESTORE_VERSION );
+ }
+
+ //---------------------------------
+
+ virtual void PostSave()
+ {
+ }
+
+ //---------------------------------
+
+ virtual void PreRestore()
+ {
+ }
+
+ //---------------------------------
+
+ virtual void ReadRestoreHeaders( IRestore *pRestore )
+ {
+ // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
+ short version = pRestore->ReadShort();
+ m_bDoLoad = ( version == VIEWEFFECTS_SAVE_RESTORE_VERSION );
+ }
+
+ //---------------------------------
+
+ virtual void Restore( IRestore *pRestore, bool fCreatePlayers )
+ {
+ if ( m_bDoLoad )
+ {
+ vieweffects->Restore( pRestore, fCreatePlayers );
+ }
+ }
+
+ //---------------------------------
+
+ virtual void PostRestore()
+ {
+ }
+
+private:
+ bool m_bDoLoad;
+};
+
+//-----------------------------------------------------------------------------
+
+CViewEffectsSaveRestoreBlockHandler g_ViewEffectsSaveRestoreBlockHandler;
+
+ISaveRestoreBlockHandler *GetViewEffectsRestoreBlockHandler()
+{
+ return &g_ViewEffectsSaveRestoreBlockHandler;
+}