mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-06 18:08:36 +00:00
Merge cde98e9d9c into 1819f491b5
This commit is contained in:
commit
fca288c922
@ -36,12 +36,12 @@
|
|||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
#include "logic_bridge.h"
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
#define TIMER_MIN_ACCURACY 0.1
|
#define TIMER_MIN_ACCURACY 0.1
|
||||||
|
|
||||||
TimerSystem g_Timers;
|
TimerSystem g_Timers;
|
||||||
double g_fUniversalTime = 0.0f;
|
double g_fUniversalTime = 0.0f;
|
||||||
float g_fGameStartTime = 0.0f; /* Game game start time, non-universal */
|
float g_fGameStartTime = 0.0f; /* Game game start time, non-universal */
|
||||||
double g_fTimerThink = 0.0f; /* Timer's next think time */
|
double g_fTimerThink = 0.0f; /* Timer's next think time */
|
||||||
const double *g_pUniversalTime = &g_fUniversalTime;
|
const double *g_pUniversalTime = &g_fUniversalTime;
|
||||||
ConVar *mp_timelimit = NULL;
|
ConVar *mp_timelimit = NULL;
|
||||||
int g_TimeLeftMode = 0;
|
int g_TimeLeftMode = 0;
|
||||||
@ -144,9 +144,10 @@ private:
|
|||||||
* that a drastic jump in time will continue acting normally. Users
|
* that a drastic jump in time will continue acting normally. Users
|
||||||
* may not expect this, but... I think it is the best solution.
|
* may not expect this, but... I think it is the best solution.
|
||||||
*/
|
*/
|
||||||
inline double CalcNextThink(double last, float interval)
|
inline double CalcNextThink(double last, float interval, bool useTickInterval = false)
|
||||||
{
|
{
|
||||||
if (g_fUniversalTime - last - interval <= TIMER_MIN_ACCURACY)
|
const float intervalAccuracy = useTickInterval ? gpGlobals->interval_per_tick : TIMER_MIN_ACCURACY;
|
||||||
|
if (g_fUniversalTime - last - interval <= intervalAccuracy)
|
||||||
{
|
{
|
||||||
return last + interval;
|
return last + interval;
|
||||||
}
|
}
|
||||||
@ -234,10 +235,11 @@ void TimerSystem::GameFrame(bool simulating)
|
|||||||
m_fLastTickedTime = gpGlobals->curtime;
|
m_fLastTickedTime = gpGlobals->curtime;
|
||||||
m_bHasMapTickedYet = true;
|
m_bHasMapTickedYet = true;
|
||||||
|
|
||||||
if (g_fUniversalTime >= g_fTimerThink)
|
const bool timerThink = g_fUniversalTime >= g_fTimerThink;
|
||||||
{
|
RunFrame(timerThink);
|
||||||
RunFrame();
|
|
||||||
|
|
||||||
|
if (timerThink)
|
||||||
|
{
|
||||||
g_fTimerThink = CalcNextThink(g_fTimerThink, TIMER_MIN_ACCURACY);
|
g_fTimerThink = CalcNextThink(g_fTimerThink, TIMER_MIN_ACCURACY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,12 +251,40 @@ void TimerSystem::GameFrame(bool simulating)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerSystem::RunFrame()
|
void TimerSystem::ProcessRepeatTimers(double curtime, List<ITimer*>& timerList, bool isHighSpeed)
|
||||||
{
|
{
|
||||||
ITimer *pTimer;
|
ITimer *pTimer;
|
||||||
TimerIter iter;
|
TimerIter iter;
|
||||||
|
|
||||||
double curtime = GetSimulatedTime();
|
ResultType res;
|
||||||
|
for (iter=timerList.begin(); iter!=timerList.end(); )
|
||||||
|
{
|
||||||
|
pTimer = (*iter);
|
||||||
|
if (curtime >= pTimer->m_ToExec)
|
||||||
|
{
|
||||||
|
pTimer->m_InExec = true;
|
||||||
|
res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
||||||
|
if (pTimer->m_KillMe || (res == Pl_Stop))
|
||||||
|
{
|
||||||
|
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||||
|
iter = timerList.erase(iter);
|
||||||
|
m_FreeTimers.push(pTimer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pTimer->m_InExec = false;
|
||||||
|
pTimer->m_ToExec = CalcNextThink(pTimer->m_ToExec, pTimer->m_Interval, isHighSpeed);
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerSystem::RunFrame(bool timerThink)
|
||||||
|
{
|
||||||
|
const double curtime = GetSimulatedTime();
|
||||||
|
|
||||||
|
//// One-off timers
|
||||||
|
ITimer *pTimer;
|
||||||
|
TimerIter iter;
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
|
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
|
||||||
{
|
{
|
||||||
pTimer = (*iter);
|
pTimer = (*iter);
|
||||||
@ -272,26 +302,15 @@ void TimerSystem::RunFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultType res;
|
//// Repeating timers
|
||||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
|
// Most repeating timers do not need to be updated every frame
|
||||||
{
|
if (timerThink)
|
||||||
pTimer = (*iter);
|
{
|
||||||
if (curtime >= pTimer->m_ToExec)
|
ProcessRepeatTimers(curtime, m_LowSpeedLoopTimers, false);
|
||||||
{
|
}
|
||||||
pTimer->m_InExec = true;
|
|
||||||
res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
// High speed repeating timers will always update
|
||||||
if (pTimer->m_KillMe || (res == Pl_Stop))
|
ProcessRepeatTimers(curtime, m_HighSpeedLoopTimers, true);
|
||||||
{
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
iter = m_LoopTimers.erase(iter);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pTimer->m_InExec = false;
|
|
||||||
pTimer->m_ToExec = CalcNextThink(pTimer->m_ToExec, pTimer->m_Interval);
|
|
||||||
}
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
|
ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
|
||||||
@ -312,7 +331,8 @@ ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void
|
|||||||
|
|
||||||
if (flags & TIMER_FLAG_REPEAT)
|
if (flags & TIMER_FLAG_REPEAT)
|
||||||
{
|
{
|
||||||
m_LoopTimers.push_back(pTimer);
|
List<ITimer*>& timerList = pTimer->m_Flags & TIMER_FLAG_TICK_PRECISE ? m_HighSpeedLoopTimers : m_LowSpeedLoopTimers;
|
||||||
|
timerList.push_back(pTimer);
|
||||||
goto return_timer;
|
goto return_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,8 +390,10 @@ void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
|
|||||||
pTimer->m_InExec = false;
|
pTimer->m_InExec = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<ITimer*>& timerList = pTimer->m_Flags & TIMER_FLAG_TICK_PRECISE ? m_HighSpeedLoopTimers : m_LowSpeedLoopTimers;
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||||
m_LoopTimers.remove(pTimer);
|
timerList.remove(pTimer);
|
||||||
m_FreeTimers.push(pTimer);
|
m_FreeTimers.push(pTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,12 +411,13 @@ void TimerSystem::KillTimer(ITimer *pTimer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
|
pTimer->m_InExec = true; /* The timer is not really executed but this check needs to be done */
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||||
|
|
||||||
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
||||||
{
|
{
|
||||||
m_LoopTimers.remove(pTimer);
|
List<ITimer*>& timerList = pTimer->m_Flags & TIMER_FLAG_TICK_PRECISE ? m_HighSpeedLoopTimers : m_LowSpeedLoopTimers;
|
||||||
|
timerList.remove(pTimer);
|
||||||
} else {
|
} else {
|
||||||
m_SingleTimers.remove(pTimer);
|
m_SingleTimers.remove(pTimer);
|
||||||
}
|
}
|
||||||
@ -405,26 +428,20 @@ void TimerSystem::KillTimer(ITimer *pTimer)
|
|||||||
CStack<ITimer *> s_tokill;
|
CStack<ITimer *> s_tokill;
|
||||||
void TimerSystem::RemoveMapChangeTimers()
|
void TimerSystem::RemoveMapChangeTimers()
|
||||||
{
|
{
|
||||||
ITimer *pTimer;
|
const auto KillMapchangeTimers = [](List<ITimer*>& timerList) {
|
||||||
TimerIter iter;
|
for (ITimer* pTimer : timerList)
|
||||||
|
{
|
||||||
|
if (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE)
|
||||||
|
{
|
||||||
|
s_tokill.push(pTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
KillMapchangeTimers(m_SingleTimers);
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE)
|
|
||||||
{
|
|
||||||
s_tokill.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
|
KillMapchangeTimers(m_LowSpeedLoopTimers);
|
||||||
{
|
KillMapchangeTimers(m_HighSpeedLoopTimers);
|
||||||
pTimer = (*iter);
|
|
||||||
if (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE)
|
|
||||||
{
|
|
||||||
s_tokill.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!s_tokill.empty())
|
while (!s_tokill.empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@ -41,7 +41,6 @@
|
|||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
typedef List<ITimer *> TimerList;
|
|
||||||
typedef List<ITimer *>::iterator TimerIter;
|
typedef List<ITimer *>::iterator TimerIter;
|
||||||
|
|
||||||
class SourceMod::ITimer
|
class SourceMod::ITimer
|
||||||
@ -80,12 +79,15 @@ public: //ITimerSystem
|
|||||||
bool GetMapTimeLeft(float *pTime);
|
bool GetMapTimeLeft(float *pTime);
|
||||||
IMapTimer *GetMapTimer();
|
IMapTimer *GetMapTimer();
|
||||||
public:
|
public:
|
||||||
void RunFrame();
|
void RunFrame(bool timerThink);
|
||||||
void RemoveMapChangeTimers();
|
void RemoveMapChangeTimers();
|
||||||
void GameFrame(bool simulating);
|
void GameFrame(bool simulating);
|
||||||
private:
|
private:
|
||||||
List<ITimer *> m_SingleTimers;
|
void ProcessRepeatTimers(double curtime, List<ITimer*>& timerList, bool isHighSpeed);
|
||||||
List<ITimer *> m_LoopTimers;
|
private:
|
||||||
|
List<ITimer*> m_SingleTimers;
|
||||||
|
List<ITimer*> m_LowSpeedLoopTimers;
|
||||||
|
List<ITimer*> m_HighSpeedLoopTimers;
|
||||||
CStack<ITimer *> m_FreeTimers;
|
CStack<ITimer *> m_FreeTimers;
|
||||||
IMapTimer *m_pMapTimer;
|
IMapTimer *m_pMapTimer;
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#define TIMER_REPEAT (1<<0) /**< Timer will repeat until it returns Plugin_Stop */
|
#define TIMER_REPEAT (1<<0) /**< Timer will repeat until it returns Plugin_Stop */
|
||||||
#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
|
#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
|
||||||
|
#define TIMER_FLAG_TICK_PRECISE (1<<2) /**< Timer will have tick level time precision */
|
||||||
#define TIMER_HNDL_CLOSE (1<<9) /**< Deprecated define, replaced by below */
|
#define TIMER_HNDL_CLOSE (1<<9) /**< Deprecated define, replaced by below */
|
||||||
#define TIMER_DATA_HNDL_CLOSE (1<<9) /**< Timer will automatically call CloseHandle() on its data when finished */
|
#define TIMER_DATA_HNDL_CLOSE (1<<9) /**< Timer will automatically call CloseHandle() on its data when finished */
|
||||||
|
|
||||||
|
|||||||
@ -107,6 +107,7 @@ namespace SourceMod
|
|||||||
|
|
||||||
#define TIMER_FLAG_REPEAT (1<<0) /**< Timer will repeat until stopped */
|
#define TIMER_FLAG_REPEAT (1<<0) /**< Timer will repeat until stopped */
|
||||||
#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
|
#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
|
||||||
|
#define TIMER_FLAG_TICK_PRECISE (1<<2) /**< Timer will have tick level time precision */
|
||||||
|
|
||||||
class ITimerSystem : public SMInterface
|
class ITimerSystem : public SMInterface
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user