core/TimerSys.cpp
changeset 1662 a5a5bf128cd7
parent 1541 e46ad208b9b4
child 1714 f1da232f6ca4
     1.1 --- a/core/TimerSys.cpp	Wed Oct 31 06:58:03 2007 +0000
     1.2 +++ b/core/TimerSys.cpp	Fri Nov 02 20:38:37 2007 +0000
     1.3 @@ -35,6 +35,8 @@
     1.4  #include "sourcemm_api.h"
     1.5  #include "frame_hooks.h"
     1.6  
     1.7 +#define TIMER_MIN_ACCURACY		0.1
     1.8 +
     1.9  #if !defined ORANGEBOX_BUILD
    1.10  #define CallGlobalChangeCallbacks	CallGlobalChangeCallback
    1.11  #endif
    1.12 @@ -48,6 +50,7 @@
    1.13  TimerSystem g_Timers;
    1.14  float g_fUniversalTime = 0.0f;
    1.15  float g_fGameStartTime = 0.0f;	/* Game game start time, non-universal */
    1.16 +float g_fTimerThink = 0.0f;		/* Timer's next think time */
    1.17  const float *g_pUniversalTime = &g_fUniversalTime;
    1.18  ConVar *mp_timelimit = NULL;
    1.19  int g_TimeLeftMode = 0;
    1.20 @@ -149,6 +152,25 @@
    1.21  	bool m_bInUse;
    1.22  } s_DefaultMapTimer;
    1.23  
    1.24 +/**
    1.25 + * If the ticking process has run amok (should be impossible), we 
    1.26 + * take care of this by "skipping" the in-between time, to prevent 
    1.27 + * a bazillion times from firing on accident.  This has the result  
    1.28 + * that a drastic jump in time will continue acting normally.  Users 
    1.29 + * may not expect this, but... I think it is the best solution.
    1.30 + */
    1.31 +inline float CalcNextThink(float last, float interval)
    1.32 +{
    1.33 +	if (g_fUniversalTime - last - interval <= TIMER_MIN_ACCURACY)
    1.34 +	{
    1.35 +		return last + interval;
    1.36 +	}
    1.37 +	else
    1.38 +	{
    1.39 +		return g_fUniversalTime + interval;
    1.40 +	}
    1.41 +}
    1.42 +
    1.43  void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
    1.44  {
    1.45  	m_Listener = pCallbacks;
    1.46 @@ -166,7 +188,6 @@
    1.47  	m_bHasMapTickedYet = false;
    1.48  	m_bHasMapSimulatedYet = false;
    1.49  	m_fLastTickedTime = 0.0f;
    1.50 -	m_LastExecTime = 0.0f;
    1.51  }
    1.52  
    1.53  TimerSystem::~TimerSystem()
    1.54 @@ -233,9 +254,11 @@
    1.55  	m_fLastTickedTime = gpGlobals->curtime;
    1.56  	m_bHasMapTickedYet = true;
    1.57  
    1.58 -	if (g_fUniversalTime - m_LastExecTime >= 0.1)
    1.59 +	if (g_fUniversalTime >= g_fTimerThink)
    1.60  	{
    1.61  		RunFrame();
    1.62 +
    1.63 +		g_fTimerThink = CalcNextThink(g_fTimerThink, TIMER_MIN_ACCURACY);
    1.64  	}
    1.65  
    1.66  	RunFrameHooks();
    1.67 @@ -262,7 +285,9 @@
    1.68  			pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    1.69  			iter = m_SingleTimers.erase(iter);
    1.70  			m_FreeTimers.push(pTimer);
    1.71 -		} else {
    1.72 +		} 
    1.73 +		else 
    1.74 +		{
    1.75  			break;
    1.76  		}
    1.77  	}
    1.78 @@ -283,12 +308,10 @@
    1.79  				continue;
    1.80  			}
    1.81  			pTimer->m_InExec = false;
    1.82 -			pTimer->m_ToExec = curtime + pTimer->m_Interval;
    1.83 +			pTimer->m_ToExec = CalcNextThink(pTimer->m_ToExec, pTimer->m_Interval);
    1.84  		}
    1.85  		iter++;
    1.86  	}
    1.87 -
    1.88 -	m_LastExecTime = curtime;
    1.89  }
    1.90  
    1.91  ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
    1.92 @@ -355,7 +378,9 @@
    1.93  		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
    1.94  		m_SingleTimers.remove(pTimer);
    1.95  		m_FreeTimers.push(pTimer);
    1.96 -	} else {
    1.97 +	} 
    1.98 +	else 
    1.99 +	{
   1.100  		if ((res != Pl_Stop) && !pTimer->m_KillMe)
   1.101  		{
   1.102  			if (delayExec)