You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.2 KiB
211 lines
5.2 KiB
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
|
#include "cbase.h"
|
|
#include "game_timescale_shared.h"
|
|
#include "usermessages.h"
|
|
|
|
#ifdef CLIENT_DLL
|
|
#include "c_user_message_register.h"
|
|
#endif
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
CGameTimescale g_GameTimescale;
|
|
CGameTimescale* GameTimescale() { return &g_GameTimescale; }
|
|
|
|
CGameTimescale::CGameTimescale( void ) : CAutoGameSystemPerFrame( "CGameTimescale" )
|
|
{
|
|
m_flStartBlendRealtime = 0.0f;
|
|
}
|
|
|
|
CGameTimescale::~CGameTimescale()
|
|
{
|
|
}
|
|
|
|
|
|
bool CGameTimescale::Init()
|
|
{
|
|
ResetTimescale();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CGameTimescale::Shutdown()
|
|
{
|
|
ResetTimescale();
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
void CGameTimescale::Update( float frametime )
|
|
{
|
|
UpdateTimescale();
|
|
}
|
|
#else
|
|
void CGameTimescale::FrameUpdatePostEntityThink()
|
|
{
|
|
UpdateTimescale();
|
|
}
|
|
#endif
|
|
|
|
void CGameTimescale::LevelInitPostEntity()
|
|
{
|
|
ResetTimescale();
|
|
}
|
|
|
|
void CGameTimescale::LevelShutdownPostEntity()
|
|
{
|
|
ResetTimescale();
|
|
}
|
|
|
|
void CGameTimescale::SetCurrentTimescale( float flTimescale )
|
|
{
|
|
if ( m_flCurrentTimescale == flTimescale && m_flCurrentTimescale == engine->GetTimescale() )
|
|
return;
|
|
|
|
// No ramp in/out, just set it!
|
|
m_flDesiredTimescale = flTimescale;
|
|
m_flCurrentTimescale = m_flDesiredTimescale;
|
|
|
|
m_flDurationRealTimeSeconds = 0.0f;
|
|
m_nInterpolatorType = INTERPOLATOR_LINEAR;
|
|
|
|
m_flStartBlendTime = 0.0f;
|
|
m_flStartBlendRealtime = 0.0f;
|
|
|
|
#ifndef CLIENT_DLL
|
|
engine->SetTimescale( m_flCurrentTimescale );
|
|
|
|
// Pass the change info to the client so it can do prediction
|
|
CReliableBroadcastRecipientFilter filter;
|
|
CCSUsrMsg_CurrentTimescale msg;
|
|
msg.set_cur_timescale( m_flCurrentTimescale );
|
|
SendUserMessage( filter, CS_UM_CurrentTimescale, msg );
|
|
#endif
|
|
}
|
|
|
|
void CGameTimescale::SetDesiredTimescaleAtTime( float flDesiredTimescale, float flDurationRealTimeSeconds /*= 0.0f*/, Interpolators_e nInterpolatorType /*= INTERPOLATOR_LINEAR*/, float flStartBlendTime /*= 0.0f*/ )
|
|
{
|
|
SetDesiredTimescale( flDesiredTimescale, flDurationRealTimeSeconds, nInterpolatorType, MAX( 0.0f, flStartBlendTime - gpGlobals->curtime ) );
|
|
}
|
|
|
|
void CGameTimescale::SetDesiredTimescale( float flDesiredTimescale, float flDurationRealTimeSeconds /*= 0.0f*/, Interpolators_e nInterpolatorType /*= INTERPOLATOR_LINEAR*/, float flDelayRealtime /*= 0.0f*/ )
|
|
{
|
|
if ( m_flDesiredTimescale == flDesiredTimescale )
|
|
return;
|
|
|
|
m_flDesiredTimescale = flDesiredTimescale;
|
|
m_flDurationRealTimeSeconds = flDurationRealTimeSeconds;
|
|
m_nInterpolatorType = nInterpolatorType;
|
|
|
|
m_flStartBlendTime = gpGlobals->curtime + flDelayRealtime * m_flCurrentTimescale;
|
|
|
|
if ( gpGlobals->curtime >= m_flStartBlendTime )
|
|
{
|
|
m_flStartBlendRealtime = gpGlobals->realtime;
|
|
}
|
|
else
|
|
{
|
|
m_flStartBlendRealtime = 0.0f;
|
|
}
|
|
|
|
m_flStartTimescale = m_flCurrentTimescale;
|
|
|
|
#ifndef CLIENT_DLL
|
|
// Pass the change info to the client so it can do prediction
|
|
CReliableBroadcastRecipientFilter filter;
|
|
CCSUsrMsg_DesiredTimescale msg;
|
|
msg.set_desired_timescale( m_flDesiredTimescale );
|
|
msg.set_duration_realtime_sec( m_flDurationRealTimeSeconds );
|
|
msg.set_interpolator_type( m_nInterpolatorType );
|
|
msg.set_start_blend_time( m_flStartBlendTime );
|
|
SendUserMessage( filter, CS_UM_DesiredTimescale, msg );
|
|
#endif
|
|
}
|
|
|
|
|
|
void CGameTimescale::UpdateTimescale( void )
|
|
{
|
|
if ( engine->IsPaused() )
|
|
return;
|
|
|
|
if ( m_flCurrentTimescale != m_flDesiredTimescale )
|
|
{
|
|
if ( gpGlobals->curtime >= m_flStartBlendTime )
|
|
{
|
|
if ( m_flStartBlendRealtime == 0.0f )
|
|
{
|
|
m_flStartBlendRealtime = gpGlobals->realtime;
|
|
}
|
|
|
|
float flInterp = 1.0f;
|
|
|
|
if ( m_flDurationRealTimeSeconds > 0.0f )
|
|
{
|
|
flInterp = MIN( 1.0f, ( gpGlobals->realtime - m_flStartBlendRealtime ) / m_flDurationRealTimeSeconds );
|
|
}
|
|
|
|
switch ( m_nInterpolatorType )
|
|
{
|
|
case INTERPOLATOR_ACCEL:
|
|
flInterp = Bias( flInterp, 0.25f );
|
|
break;
|
|
|
|
case INTERPOLATOR_DEACCEL:
|
|
flInterp = Bias( flInterp, 0.75f );
|
|
break;
|
|
|
|
case INTERPOLATOR_EASE_IN_OUT:
|
|
flInterp = Gain( flInterp, 0.75f );
|
|
break;
|
|
}
|
|
|
|
m_flCurrentTimescale = m_flStartTimescale * ( 1.0f - flInterp ) + m_flDesiredTimescale * flInterp;
|
|
}
|
|
}
|
|
|
|
if ( m_flCurrentTimescale != engine->GetTimescale() )
|
|
{
|
|
engine->SetTimescale( m_flCurrentTimescale );
|
|
}
|
|
}
|
|
|
|
void CGameTimescale::ResetTimescale( void )
|
|
{
|
|
m_flDesiredTimescale = 1.0f;
|
|
m_flCurrentTimescale = 1.0f;
|
|
|
|
m_flDurationRealTimeSeconds = 0.0f;
|
|
m_nInterpolatorType = INTERPOLATOR_LINEAR;
|
|
|
|
m_flStartBlendTime = 0.0f;
|
|
m_flStartBlendRealtime = 0.0f;
|
|
|
|
engine->SetTimescale( 1.0f );
|
|
}
|
|
|
|
|
|
#ifdef CLIENT_DLL
|
|
|
|
bool __MsgFunc_CurrentTimescale( const CCSUsrMsg_CurrentTimescale &msg )
|
|
{
|
|
GameTimescale()->SetCurrentTimescale( msg.cur_timescale() );
|
|
|
|
return true;
|
|
}
|
|
USER_MESSAGE_REGISTER( CurrentTimescale );
|
|
|
|
bool __MsgFunc_DesiredTimescale( const CCSUsrMsg_DesiredTimescale &msg )
|
|
{
|
|
float flDesiredTimescale = msg.desired_timescale();
|
|
float flDurationRealTimeSeconds = msg.duration_realtime_sec();
|
|
CGameTimescale::Interpolators_e nInterpolatorType = static_cast< CGameTimescale::Interpolators_e >( msg.interpolator_type() );
|
|
float flStartBlendTime = msg.start_blend_time();
|
|
|
|
GameTimescale()->SetDesiredTimescaleAtTime( flDesiredTimescale, flDurationRealTimeSeconds, nInterpolatorType, flStartBlendTime );
|
|
|
|
return true;
|
|
}
|
|
USER_MESSAGE_REGISTER( DesiredTimescale );
|
|
|
|
#endif //#ifdef CLIENT_DLL
|