diff --git a/core/CTimerSys.cpp b/core/CTimerSys.cpp
new file mode 100644
index 00000000..166b54ed
--- /dev/null
+++ b/core/CTimerSys.cpp
@@ -0,0 +1,199 @@
+/**
+* vim: set ts=4 :
+* ===============================================================
+* SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
+* ===============================================================
+*
+* This file is not open source and may not be copied without explicit
+* written permission of AlliedModders LLC.  This file may not be redistributed 
+* in whole or significant part.
+* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
+*
+* Version: $Id$
+*/
+
+#include "CTimerSys.h"
+
+CTimerSystem g_Timers;
+
+void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags)
+{
+	m_Listener = pCallbacks;
+	m_Interval = fInterval;
+	m_ToExec = fToExec;
+	m_pData = pData;
+	m_Flags = flags;
+	m_InExec = false;
+	m_KillMe = false;
+}
+
+void CTimerSystem::OnSourceModAllInitialized()
+{
+	g_ShareSys.AddInterface(NULL, this);
+}
+
+void CTimerSystem::RunFrame()
+{
+	ITimer *pTimer;
+	TimerIter iter;
+
+	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); )
+	{
+		pTimer = (*iter);
+		if (gpGlobals->curtime >= pTimer->m_ToExec)
+		{
+			pTimer->m_InExec = true;
+			pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
+			if (pTimer->m_KillMe)
+			{
+				pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
+			}
+			iter = m_SingleTimers.erase(iter);
+			m_FreeTimers.push(pTimer);
+		} else {
+			break;
+		}
+	}
+
+	ResultType res;
+	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); )
+	{
+		pTimer = (*iter);
+		if (gpGlobals->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 = m_LoopTimers.erase(iter);
+				m_FreeTimers.push(pTimer);
+				continue;
+			}
+			pTimer->m_InExec = false;
+			pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
+		}
+		iter++;
+	}
+
+	m_LastExecTime = gpGlobals->curtime;
+}
+
+ITimer *CTimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags)
+{
+	ITimer *pTimer;
+	TimerIter iter;
+	float to_exec = gpGlobals->curtime + fInterval;
+
+	if (m_FreeTimers.empty())
+	{
+		pTimer = new ITimer;
+	} else {
+		pTimer = m_FreeTimers.front();
+		m_FreeTimers.pop();
+	}
+
+	pTimer->Initialize(pCallbacks, fInterval, to_exec, pData, flags);
+
+	if (flags & TIMER_FLAG_REPEAT)
+	{
+		m_LoopTimers.push_back(pTimer);
+		goto return_timer;
+	}
+
+	if (m_SingleTimers.size() >= 1)
+	{
+		iter = --m_SingleTimers.end();
+		if ((*iter)->m_ToExec <= to_exec)
+		{
+			goto 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;
+		}
+	}
+
+insert_end:
+	m_SingleTimers.push_back(pTimer);
+
+return_timer:
+	return pTimer;
+}
+
+void CTimerSystem::FireTimerOnce(ITimer *pTimer, bool delayExec)
+{
+	ResultType res;
+
+	if (pTimer->m_InExec)
+	{
+		return;
+	}
+
+	pTimer->m_InExec = true;
+	res = pTimer->m_Listener->OnTimer(pTimer, pTimer->m_pData);
+
+	if (!(pTimer->m_Flags & TIMER_FLAG_REPEAT))
+	{
+		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
+		m_SingleTimers.remove(pTimer);
+		m_FreeTimers.push(pTimer);
+	} else {
+		if (delayExec && (res != Pl_Stop) && !pTimer->m_KillMe)
+		{
+			pTimer->m_ToExec = gpGlobals->curtime + pTimer->m_Interval;
+			pTimer->m_InExec = false;
+			return;
+		}
+		pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
+		m_LoopTimers.remove(pTimer);
+		m_FreeTimers.push(pTimer);
+	}
+}
+
+void CTimerSystem::KillTimer(ITimer *pTimer)
+{
+	TimerList *pList;
+
+	if (pTimer->m_KillMe)
+	{
+		return;
+	}
+
+	if (pTimer->m_InExec)
+	{
+		pTimer->m_KillMe = true;
+		return;
+	}
+
+	pTimer->m_InExec = true; /* The timer it's not really executed but this check needs to be done */
+	pTimer->m_Listener->OnTimerEnd(pTimer, pTimer->m_pData);
+
+	pList = (pTimer->m_Flags & TIMER_FLAG_REPEAT) ? &m_LoopTimers : &m_SingleTimers;
+
+	pList->remove(pTimer);
+	m_FreeTimers.push(pTimer);
+}
+
+void CTimerSystem::MapChange()
+{
+	ITimer *pTimer;
+	TimerIter iter;
+
+	for (iter=m_SingleTimers.begin(); iter!=m_SingleTimers.end(); iter++)
+	{
+		pTimer = (*iter);
+		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
+	}
+
+	for (iter=m_LoopTimers.begin(); iter!=m_LoopTimers.end(); iter++)
+	{
+		pTimer = (*iter);
+		pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + gpGlobals->curtime;
+	}
+}
diff --git a/core/CTimerSys.h b/core/CTimerSys.h
new file mode 100644
index 00000000..520a33f1
--- /dev/null
+++ b/core/CTimerSys.h
@@ -0,0 +1,65 @@
+/**
+* vim: set ts=4 :
+* ===============================================================
+* SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
+* ===============================================================
+*
+* This file is not open source and may not be copied without explicit
+* written permission of AlliedModders LLC.  This file may not be redistributed 
+* in whole or significant part.
+* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
+*
+* Version: $Id$
+*/
+
+#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
+#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
+
+#include "ShareSys.h"
+#include <ITimerSystem.h>
+#include <sh_stack.h>
+#include <sh_list.h>
+#include "sourcemm_api.h"
+
+using namespace SourceHook;
+using namespace SourceMod;
+
+typedef List<ITimer *> TimerList;
+typedef List<ITimer *>::iterator TimerIter;
+
+class SourceMod::ITimer
+{
+public:
+	void Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags);
+	ITimedEvent *m_Listener;
+	void *m_pData;
+	float m_Interval;
+	float m_ToExec;
+	int m_Flags;
+	bool m_InExec;
+	bool m_KillMe;
+};
+
+class CTimerSystem : 
+	public ITimerSystem,
+	public SMGlobalClass
+{
+public: //SMGlobalClass
+	void OnSourceModAllInitialized();
+public: //ITimerSystem
+	ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags);
+	void KillTimer(ITimer *pTimer);
+	void FireTimerOnce(ITimer *pTimer, bool delayExec=false);
+public:
+	void RunFrame();
+	void MapChange();
+private:
+	List<ITimer *> m_SingleTimers;
+	List<ITimer *> m_LoopTimers;
+	CStack<ITimer *> m_FreeTimers;
+	float m_LastExecTime;
+};
+
+extern CTimerSystem g_Timers;
+
+#endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_
diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj
index 5ee357db..76298884 100644
--- a/core/msvc8/sourcemod_mm.vcproj
+++ b/core/msvc8/sourcemod_mm.vcproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8.00"
+	Version="8,00"
 	Name="sourcemod_mm"
 	ProjectGUID="{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
 	RootNamespace="sourcemod_mm"
@@ -219,6 +219,10 @@
 				RelativePath="..\CTextParsers.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\CTimerSys.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\CTranslator.cpp"
 				>
@@ -313,6 +317,10 @@
 				RelativePath="..\CTextParsers.h"
 				>
 			</File>
+			<File
+				RelativePath="..\CTimerSys.h"
+				>
+			</File>
 			<File
 				RelativePath="..\CTranslator.h"
 				>
@@ -421,6 +429,10 @@
 				RelativePath="..\..\public\ITextParsers.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\public\ITimerSystem.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\public\IUserMessages.h"
 				>
diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp
index 950793d1..4271d6d3 100644
--- a/core/sourcemod.cpp
+++ b/core/sourcemod.cpp
@@ -26,6 +26,7 @@
 #include "CPlayerManager.h"
 #include "CTranslator.h"
 #include "ForwardSys.h"
+#include "CTimerSys.h"
 
 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
 SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
@@ -193,6 +194,7 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
 	g_LastAuthCheck = 0.0f;
 
 	g_Logger.MapChange(pMapName);
+	g_Timers.MapChange();
 
 	/* Refresh language stuff */
 	char path[PLATFORM_MAX_PATH];
@@ -221,7 +223,7 @@ void SourceModBase::GameFrame(bool simulating)
 	 * precious CPU cycles.
 	 */
 	float curtime = gpGlobals->curtime;
-	if (curtime - g_LastTime > 0.1f)
+	if (curtime - g_LastTime >= 0.1f)
 	{
 		if (m_CheckingAuth
 			&& (gpGlobals->curtime - g_LastAuthCheck > 0.7f))
@@ -229,9 +231,11 @@ void SourceModBase::GameFrame(bool simulating)
 			g_LastAuthCheck = gpGlobals->curtime;
 			g_Players.RunAuthChecks();
 		}
+
+		g_Timers.RunFrame();
 		g_LastTime = curtime;
 	}
-	
+
 	if (g_pOnGameFrame && g_pOnGameFrame->GetFunctionCount())
 	{
 		g_pOnGameFrame->Execute(NULL);
diff --git a/public/ITimerSystem.h b/public/ITimerSystem.h
index 2291087f..23d19353 100644
--- a/public/ITimerSystem.h
+++ b/public/ITimerSystem.h
@@ -20,11 +20,10 @@
 #define _INCLUDE_SOURCEMOD_TIMER_SYSTEM_H_
 
 #include <IShareSys.h>
+#include <IForwardSys.h>
 
-//:TODO: this is a placeholder and not yet implemented
-//remove these lines and uncomment once we're done!
-//#define SMINTERFACE_TIMERSYS_NAME		"ITimerSys"
-//#define SMINTERFACE_TIMERSYS_VERSION	1
+#define SMINTERFACE_TIMERSYS_NAME		"ITimerSys"
+#define SMINTERFACE_TIMERSYS_VERSION	1
 
 namespace SourceMod
 {
@@ -41,9 +40,7 @@ namespace SourceMod
 		 *
 		 * @param pTimer		Pointer to the timer instance.
 		 * @param pData			Private pointer passed from host.
-		 * @return				Pl_Handle to stop timer, Pl_Continue to continue.
-		 *						Passing Pl_Continue when a timer's repeat count
-		 *						has been exhausted will not extend it.
+		 * @return				Pl_Stop to stop timer, Pl_Continue to continue.
 		 */
 		virtual ResultType OnTimer(ITimer *pTimer, void *pData) =0;
 
@@ -53,7 +50,7 @@ namespace SourceMod
 		 * @param pTimer		Pointer to the timer instance.
 		 * @param pData			Private data pointer passed from host.
 		 */
-		virtual void OnTimerEnd() =0;
+		virtual void OnTimerEnd(ITimer *pTimer, void *pData) =0;
 	};
 
 	#define TIMER_FLAG_REPEAT		(1<<0)