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)