overhaul of the map timer idea -- function is now an interface, and the timer flag is removed
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401420
This commit is contained in:
parent
aec2160e84
commit
6206027476
@ -35,9 +35,13 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
|
|
||||||
|
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
|
||||||
|
|
||||||
TimerSystem g_Timers;
|
TimerSystem g_Timers;
|
||||||
float g_fUniversalTime = 0.0f;
|
float g_fUniversalTime = 0.0f;
|
||||||
|
float g_fMapStartTime = 0.0f;
|
||||||
const float *g_pUniversalTime = &g_fUniversalTime;
|
const float *g_pUniversalTime = &g_fUniversalTime;
|
||||||
|
ConVar *mp_timelimit = NULL;
|
||||||
|
|
||||||
ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds");
|
ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds");
|
||||||
|
|
||||||
@ -56,6 +60,84 @@ time_t GetAdjustedTime(time_t *buf)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DefaultMapTimer :
|
||||||
|
public IMapTimer,
|
||||||
|
public SMGlobalClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DefaultMapTimer()
|
||||||
|
{
|
||||||
|
m_bInUse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMapTimeLimit()
|
||||||
|
{
|
||||||
|
return mp_timelimit->GetInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMapTimerStatus(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled && !m_bInUse)
|
||||||
|
{
|
||||||
|
Enable();
|
||||||
|
}
|
||||||
|
else if (!enabled && m_bInUse)
|
||||||
|
{
|
||||||
|
Disable();
|
||||||
|
}
|
||||||
|
m_bInUse = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetMapTimeLeft(int *time_left)
|
||||||
|
{
|
||||||
|
if (GetMapTimeLimit() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*time_left = (int)((g_fMapStartTime + mp_timelimit->GetInt() * 60.0f) - g_fUniversalTime);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtendMapTimeLimit(int extra_time)
|
||||||
|
{
|
||||||
|
extra_time /= 60;
|
||||||
|
|
||||||
|
if (extra_time == 0)
|
||||||
|
{
|
||||||
|
mp_timelimit->SetValue(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_timelimit->SetValue(mp_timelimit->GetInt() + extra_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalChangeCallback(ConVar *pVar, const char *old_value)
|
||||||
|
{
|
||||||
|
if (pVar != mp_timelimit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_Timers.MapTimeLimitExtended(atoi(old_value) * 60, pVar->GetInt() * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Enable()
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallback, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disable()
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallback, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_bInUse;
|
||||||
|
} s_DefaultMapTimer;
|
||||||
|
|
||||||
void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
|
void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
|
||||||
{
|
{
|
||||||
m_Listener = pCallbacks;
|
m_Listener = pCallbacks;
|
||||||
@ -69,7 +151,7 @@ void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec,
|
|||||||
|
|
||||||
TimerSystem::TimerSystem()
|
TimerSystem::TimerSystem()
|
||||||
{
|
{
|
||||||
m_fnTimeLeft = NULL;
|
m_pMapTimer = NULL;
|
||||||
m_bHasMapTickedYet = false;
|
m_bHasMapTickedYet = false;
|
||||||
m_fLastTickedTime = 0.0f;
|
m_fLastTickedTime = 0.0f;
|
||||||
m_LastExecTime = 0.0f;
|
m_LastExecTime = 0.0f;
|
||||||
@ -91,8 +173,19 @@ void TimerSystem::OnSourceModAllInitialized()
|
|||||||
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TimerSystem::OnSourceModGameInitialized()
|
||||||
|
{
|
||||||
|
mp_timelimit = icvar->FindVar("mp_timelimit");
|
||||||
|
|
||||||
|
if (m_pMapTimer == NULL && mp_timelimit != NULL)
|
||||||
|
{
|
||||||
|
SetMapTimer(&s_DefaultMapTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TimerSystem::OnSourceModShutdown()
|
void TimerSystem::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
|
SetMapTimer(NULL);
|
||||||
g_Forwards.ReleaseForward(m_pOnGameFrame);
|
g_Forwards.ReleaseForward(m_pOnGameFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +211,11 @@ void TimerSystem::GameFrame(bool simulating)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_fLastTickedTime = gpGlobals->curtime;
|
m_fLastTickedTime = gpGlobals->curtime;
|
||||||
m_bHasMapTickedYet = true;
|
if (!m_bHasMapTickedYet)
|
||||||
|
{
|
||||||
|
g_fMapStartTime = g_fUniversalTime;
|
||||||
|
m_bHasMapTickedYet = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_fUniversalTime - m_LastExecTime >= 0.1)
|
if (g_fUniversalTime - m_LastExecTime >= 0.1)
|
||||||
{
|
{
|
||||||
@ -154,25 +251,6 @@ void TimerSystem::RunFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fnTimeLeft != NULL && m_MapEndTimers.size())
|
|
||||||
{
|
|
||||||
float time_left = m_fnTimeLeft();
|
|
||||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end();)
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
if ((*iter)->m_Interval < time_left)
|
|
||||||
{
|
|
||||||
pTimer->m_InExec = true;
|
|
||||||
pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
|
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
|
||||||
iter = m_MapEndTimers.erase(iter);
|
|
||||||
m_FreeTimers.push(pTimer);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultType res;
|
ResultType res;
|
||||||
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
|
for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
|
||||||
{
|
{
|
||||||
@ -203,12 +281,6 @@ ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void
|
|||||||
TimerIter iter;
|
TimerIter iter;
|
||||||
float to_exec = GetSimulatedTime() + fInterval;
|
float to_exec = GetSimulatedTime() + fInterval;
|
||||||
|
|
||||||
if ((flags & TIMER_FLAG_BEFORE_MAP_END)
|
|
||||||
&& m_fnTimeLeft == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_FreeTimers.empty())
|
if (m_FreeTimers.empty())
|
||||||
{
|
{
|
||||||
pTimer = new ITimer;
|
pTimer = new ITimer;
|
||||||
@ -225,40 +297,26 @@ ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void
|
|||||||
goto return_timer;
|
goto return_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & TIMER_FLAG_BEFORE_MAP_END)
|
if (m_SingleTimers.size() >= 1)
|
||||||
{
|
{
|
||||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
|
iter = --m_SingleTimers.end();
|
||||||
|
if ((*iter)->m_ToExec <= to_exec)
|
||||||
{
|
{
|
||||||
if (fInterval >= (*iter)->m_Interval)
|
goto normal_insert_end;
|
||||||
{
|
|
||||||
m_MapEndTimers.insert(iter, pTimer);
|
|
||||||
goto return_timer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_MapEndTimers.push_back(pTimer);
|
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
||||||
} else {
|
{
|
||||||
if (m_SingleTimers.size() >= 1)
|
if ((*iter)->m_ToExec >= to_exec)
|
||||||
{
|
{
|
||||||
iter = --m_SingleTimers.end();
|
m_SingleTimers.insert(iter, pTimer);
|
||||||
if ((*iter)->m_ToExec <= to_exec)
|
goto return_timer;
|
||||||
{
|
|
||||||
goto normal_insert_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
if ((*iter)->m_ToExec >= to_exec)
|
|
||||||
{
|
|
||||||
m_SingleTimers.insert(iter, pTimer);
|
|
||||||
goto return_timer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
normal_insert_end:
|
normal_insert_end:
|
||||||
m_SingleTimers.push_back(pTimer);
|
m_SingleTimers.push_back(pTimer);
|
||||||
}
|
|
||||||
|
|
||||||
return_timer:
|
return_timer:
|
||||||
return pTimer;
|
return pTimer;
|
||||||
@ -279,12 +337,7 @@ void TimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
|
|||||||
if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
|
if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
|
||||||
{
|
{
|
||||||
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
|
||||||
if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END)
|
m_SingleTimers.remove(pTimer);
|
||||||
{
|
|
||||||
m_MapEndTimers.remove(pTimer);
|
|
||||||
} else {
|
|
||||||
m_SingleTimers.remove(pTimer);
|
|
||||||
}
|
|
||||||
m_FreeTimers.push(pTimer);
|
m_FreeTimers.push(pTimer);
|
||||||
} else {
|
} else {
|
||||||
if ((res != Pl_Stop) && !pTimer->m_KillMe)
|
if ((res != Pl_Stop) && !pTimer->m_KillMe)
|
||||||
@ -321,8 +374,6 @@ void TimerSystem::KillTimer(ITimer *pTimer)
|
|||||||
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
if (pTimer->m_Flags & TIMER_FLAG_REPEAT)
|
||||||
{
|
{
|
||||||
m_LoopTimers.remove(pTimer);
|
m_LoopTimers.remove(pTimer);
|
||||||
} else if (pTimer->m_Flags & TIMER_FLAG_BEFORE_MAP_END) {
|
|
||||||
m_MapEndTimers.remove(pTimer);
|
|
||||||
} else {
|
} else {
|
||||||
m_SingleTimers.remove(pTimer);
|
m_SingleTimers.remove(pTimer);
|
||||||
}
|
}
|
||||||
@ -354,15 +405,6 @@ void TimerSystem::MapChange(bool real_mapchange)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (real_mapchange)
|
|
||||||
{
|
|
||||||
for (iter=m_MapEndTimers.begin(); iter!=m_MapEndTimers.end(); iter++)
|
|
||||||
{
|
|
||||||
pTimer = (*iter);
|
|
||||||
s_tokill.push(pTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!s_tokill.empty())
|
while (!s_tokill.empty())
|
||||||
{
|
{
|
||||||
KillTimer(s_tokill.front());
|
KillTimer(s_tokill.front());
|
||||||
@ -370,10 +412,34 @@ void TimerSystem::MapChange(bool real_mapchange)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SM_TIMELEFT_FUNCTION TimerSystem::SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn)
|
IMapTimer *TimerSystem::SetMapTimer(IMapTimer *pTimer)
|
||||||
{
|
{
|
||||||
SM_TIMELEFT_FUNCTION old = m_fnTimeLeft;
|
IMapTimer *old = m_pMapTimer;
|
||||||
m_fnTimeLeft = fn;
|
|
||||||
|
m_pMapTimer = pTimer;
|
||||||
|
|
||||||
|
if (m_pMapTimer)
|
||||||
|
{
|
||||||
|
m_pMapTimer->SetMapTimerStatus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
{
|
||||||
|
old->SetMapTimerStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMapTimer *TimerSystem::GetMapTimer()
|
||||||
|
{
|
||||||
|
return m_pMapTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerSystem::MapTimeLimitExtended(int old_limit, int new_limit)
|
||||||
|
{
|
||||||
|
if (old_limit == new_limit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -68,23 +68,25 @@ public: //SMGlobalClass
|
|||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
void OnSourceModLevelChange(const char *mapName);
|
||||||
void OnSourceModLevelEnd();
|
void OnSourceModLevelEnd();
|
||||||
|
void OnSourceModGameInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
public: //ITimerSystem
|
public: //ITimerSystem
|
||||||
ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
|
ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
|
||||||
void KillTimer(ITimer *pTimer);
|
void KillTimer(ITimer *pTimer);
|
||||||
void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
|
void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
|
||||||
SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn);
|
void MapTimeLimitExtended(int old_limit, int new_limit);
|
||||||
|
IMapTimer *SetMapTimer(IMapTimer *pTimer);
|
||||||
public:
|
public:
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
void MapChange(bool real_mapchange);
|
void MapChange(bool real_mapchange);
|
||||||
void GameFrame(bool simulating);
|
void GameFrame(bool simulating);
|
||||||
|
IMapTimer *GetMapTimer();
|
||||||
private:
|
private:
|
||||||
List<ITimer *> m_SingleTimers;
|
List<ITimer *> m_SingleTimers;
|
||||||
List<ITimer *> m_LoopTimers;
|
List<ITimer *> m_LoopTimers;
|
||||||
List<ITimer *> m_MapEndTimers;
|
|
||||||
CStack<ITimer *> m_FreeTimers;
|
CStack<ITimer *> m_FreeTimers;
|
||||||
float m_LastExecTime;
|
float m_LastExecTime;
|
||||||
SM_TIMELEFT_FUNCTION m_fnTimeLeft;
|
IMapTimer *m_pMapTimer;
|
||||||
|
|
||||||
/* This is stuff for our manual ticking escapades. */
|
/* This is stuff for our manual ticking escapades. */
|
||||||
bool m_bHasMapTickedYet; /** Has the map ticked yet? */
|
bool m_bHasMapTickedYet; /** Has the map ticked yet? */
|
||||||
|
@ -48,7 +48,47 @@ namespace SourceMod
|
|||||||
{
|
{
|
||||||
class ITimer;
|
class ITimer;
|
||||||
|
|
||||||
typedef float (*SM_TIMELEFT_FUNCTION)();
|
/**
|
||||||
|
* @brief Interface for map timers.
|
||||||
|
*/
|
||||||
|
class IMapTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Returns the current map time limit in seconds.
|
||||||
|
*
|
||||||
|
* @return Time limit, in seconds, or
|
||||||
|
* 0 if there is no limit.
|
||||||
|
*/
|
||||||
|
virtual int GetMapTimeLimit() =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns how much time is left in the map.
|
||||||
|
*
|
||||||
|
* @param time_left Pointer to store time, in seconds.
|
||||||
|
* @return True if there is a time limit, false
|
||||||
|
* if the time limit is 0.
|
||||||
|
*/
|
||||||
|
virtual bool GetMapTimeLeft(int *time_left) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the map limit (either positively or negatively) in seconds.
|
||||||
|
*
|
||||||
|
* @param extra_time Time to extend map by. If 0, the map will
|
||||||
|
* be set to have no time limit.
|
||||||
|
*/
|
||||||
|
virtual void ExtendMapTimeLimit(int extra_time) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells the map timer whether it is being used or not.
|
||||||
|
*
|
||||||
|
* Map timers are automatically enabled when they are set, and
|
||||||
|
* automatically disabled if being un-set.
|
||||||
|
*
|
||||||
|
* @param enabled True if enabling, false if disabling.
|
||||||
|
*/
|
||||||
|
virtual void SetMapTimerStatus(bool enabled) =0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Event callbacks for when a timer is executed.
|
* @brief Event callbacks for when a timer is executed.
|
||||||
@ -76,10 +116,6 @@ 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_BEFORE_MAP_END (1<<2) /**< Timer will fire <interval> seconds before map end.
|
|
||||||
This flag is cannot be used with REPEAT,
|
|
||||||
and TIMER_FLAG_NO_MAPCHANGE is implied.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ITimerSystem : public SMInterface
|
class ITimerSystem : public SMInterface
|
||||||
{
|
{
|
||||||
@ -130,12 +166,22 @@ namespace SourceMod
|
|||||||
virtual void FireTimerOnce(ITimer *pTimer, bool delayExec=false) =0;
|
virtual void FireTimerOnce(ITimer *pTimer, bool delayExec=false) =0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the function which is used to find the time left in the map.
|
* @brief Sets the interface for dealing with map time limits.
|
||||||
*
|
*
|
||||||
* @param fn Function that returns the time left in seconds.
|
* @param pMapTimer Map timer interface pointer.
|
||||||
* @return The previous SM_TIMELEFT_FUNCTION pointer.
|
* @return Old pointer.
|
||||||
*/
|
*/
|
||||||
virtual SM_TIMELEFT_FUNCTION SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn) =0;
|
virtual IMapTimer *SetMapTimer(IMapTimer *pTimer) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Notifies the timer that the map timelimit has been extended.
|
||||||
|
*
|
||||||
|
* A time limit of 0 implies that there is no limit.
|
||||||
|
*
|
||||||
|
* @param old_limit Old limit, in seconds.
|
||||||
|
* @param new_limit New limit, in seconds.
|
||||||
|
*/
|
||||||
|
virtual void MapTimeLimitExtended(int old_limit, int new_limit) =0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user