- Added ForceChangeLevel and Map History to nextmap api
- Changed base plugins to use new api - Added sm_maphistory command to nextmap.sp --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402413
This commit is contained in:
		
							parent
							
								
									8126aa6bb8
								
							
						
					
					
						commit
						c75d607a00
					
				
							
								
								
									
										135
									
								
								core/NextMap.cpp
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								core/NextMap.cpp
									
									
									
									
									
								
							| @ -33,13 +33,26 @@ | |||||||
| #include "Logger.h" | #include "Logger.h" | ||||||
| #include "sourcemm_api.h" | #include "sourcemm_api.h" | ||||||
| #include "sm_stringutil.h" | #include "sm_stringutil.h" | ||||||
|  | #include "sourcehook.h" | ||||||
|  | #include "sm_srvcmds.h" | ||||||
| 
 | 
 | ||||||
| NextMapManager g_NextMap; | NextMapManager g_NextMap; | ||||||
| 
 | 
 | ||||||
| SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *); | SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *); | ||||||
| 
 | 
 | ||||||
|  | #if defined ORANGEBOX_BUILD | ||||||
|  | SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); | ||||||
|  | #else | ||||||
|  | extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); | ||||||
|  | extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | ConCommand *changeLevelCmd = NULL; | ||||||
|  | 
 | ||||||
| ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY); | ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY); | ||||||
| 
 | 
 | ||||||
|  | bool g_forcedChange = false; | ||||||
|  | 
 | ||||||
| void NextMapManager::OnSourceModAllInitialized_Post() | void NextMapManager::OnSourceModAllInitialized_Post() | ||||||
| { | { | ||||||
| #if defined ORANGEBOX_BUILD | #if defined ORANGEBOX_BUILD | ||||||
| @ -47,6 +60,30 @@ void NextMapManager::OnSourceModAllInitialized_Post() | |||||||
| #else | #else | ||||||
| 	SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false); | 	SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false); | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | 	ConCommandBase *pBase = icvar->GetCommands(); | ||||||
|  | 	ConCommand *pCmd = NULL; | ||||||
|  | 	while (pBase) | ||||||
|  | 	{ | ||||||
|  | 		if (strcmp(pBase->GetName(), "changelevel") == 0) | ||||||
|  | 		{ | ||||||
|  | 			/* Don't want to return convar with same name */ | ||||||
|  | 			if (!pBase->IsCommand()) | ||||||
|  | 			{ | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			pCmd = (ConCommand *)pBase; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		pBase = const_cast<ConCommandBase *>(pBase->GetNext()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (pCmd != NULL) | ||||||
|  | 	{ | ||||||
|  | 		SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false); | ||||||
|  | 		changeLevelCmd = pCmd; | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void NextMapManager::OnSourceModShutdown() | void NextMapManager::OnSourceModShutdown() | ||||||
| @ -56,6 +93,20 @@ void NextMapManager::OnSourceModShutdown() | |||||||
| #else | #else | ||||||
| 	SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false); | 	SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false); | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
|  | 	if (changeLevelCmd != NULL) | ||||||
|  | 	{ | ||||||
|  | 		SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, changeLevelCmd, CmdChangeLevelCallback, false); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SourceHook::List<MapChangeData *>::iterator iter; | ||||||
|  | 	iter = m_mapHistory.begin(); | ||||||
|  | 
 | ||||||
|  | 	while (iter != m_mapHistory.end()) | ||||||
|  | 	{ | ||||||
|  | 		delete (MapChangeData *)*iter; | ||||||
|  | 		iter = m_mapHistory.erase(iter); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const char *NextMapManager::GetNextMap() | const char *NextMapManager::GetNextMap() | ||||||
| @ -77,6 +128,12 @@ bool NextMapManager::SetNextMap(const char *map) | |||||||
| 
 | 
 | ||||||
| void NextMapManager::HookChangeLevel(const char *map, const char *unknown) | void NextMapManager::HookChangeLevel(const char *map, const char *unknown) | ||||||
| { | { | ||||||
|  | 	if (g_forcedChange) | ||||||
|  | 	{ | ||||||
|  | 		g_Logger.LogMessage("[SM] Changed map to \"%s\"", map); | ||||||
|  | 		RETURN_META(MRES_IGNORED); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	const char *newmap = sm_nextmap.GetString(); | 	const char *newmap = sm_nextmap.GetString(); | ||||||
| 
 | 
 | ||||||
| 	if (newmap[0] == 0 || !engine->IsMapValid(newmap)) | 	if (newmap[0] == 0 || !engine->IsMapValid(newmap)) | ||||||
| @ -86,5 +143,83 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown) | |||||||
| 
 | 
 | ||||||
| 	g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap); | 	g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap); | ||||||
| 
 | 
 | ||||||
|  | 	UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap); | ||||||
|  | 	UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); | ||||||
|  | 
 | ||||||
| 	RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown)); | 	RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown)); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void NextMapManager::OnSourceModLevelChange( const char *mapName ) | ||||||
|  | { | ||||||
|  | 	/* Skip the first 'mapchange' when the server starts up */ | ||||||
|  | 	if (m_tempChangeInfo.startTime != 0) | ||||||
|  | 	{ | ||||||
|  | 		if (strcmp(mapName, m_tempChangeInfo.m_mapName) == 0) | ||||||
|  | 		{ | ||||||
|  | 			/* The map change was as we expected */ | ||||||
|  | 			m_mapHistory.push_back(new MapChangeData(lastMap, m_tempChangeInfo.m_changeReason, m_tempChangeInfo.startTime)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			/* Something intercepted the mapchange */ | ||||||
|  | 			char newReason[255]; | ||||||
|  | 			UTIL_Format(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason); | ||||||
|  | 			m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* TODO: Should this be customizable? */ | ||||||
|  | 		if (m_mapHistory.size() > 20) | ||||||
|  | 		{ | ||||||
|  | 			SourceHook::List<MapChangeData *>::iterator iter; | ||||||
|  | 			iter = m_mapHistory.begin(); | ||||||
|  | 
 | ||||||
|  | 			delete (MapChangeData *)*iter; | ||||||
|  | 
 | ||||||
|  | 			m_mapHistory.erase(iter); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m_tempChangeInfo.m_mapName[0] ='\0'; | ||||||
|  | 	m_tempChangeInfo.m_changeReason[0] = '\0'; | ||||||
|  | 	m_tempChangeInfo.startTime = time(NULL); | ||||||
|  | 	UTIL_Format(lastMap, sizeof(lastMap), mapName); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason ) | ||||||
|  | { | ||||||
|  | 	/* Store the mapname and reason */ | ||||||
|  | 	UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName); | ||||||
|  | 	UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason); | ||||||
|  | 
 | ||||||
|  | 	/* Change level and skip our hook */ | ||||||
|  | 	g_forcedChange = true; | ||||||
|  | 	engine->ChangeLevel(mapName, NULL); | ||||||
|  | 	g_forcedChange = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NextMapManager::NextMapManager() | ||||||
|  | { | ||||||
|  | 	m_tempChangeInfo = MapChangeData(); | ||||||
|  | 	m_mapHistory = SourceHook::List<MapChangeData *>(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if defined ORANGEBOX_BUILD | ||||||
|  | void CmdChangeLevelCallback(const CCommand &command) | ||||||
|  | { | ||||||
|  | #else | ||||||
|  | void CmdChangeLevelCallback() | ||||||
|  | { | ||||||
|  | 	CCommand command; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	if (command.ArgC() < 2) | ||||||
|  | 	{ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0') | ||||||
|  | 	{ | ||||||
|  | 		UTIL_Format(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1)); | ||||||
|  | 		UTIL_Format(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -34,17 +34,58 @@ | |||||||
| 
 | 
 | ||||||
| #include "sm_globals.h" | #include "sm_globals.h" | ||||||
| #include "eiface.h" | #include "eiface.h" | ||||||
|  | #include "sh_list.h" | ||||||
|  | #include "sm_stringutil.h" | ||||||
|  | 
 | ||||||
|  | struct MapChangeData | ||||||
|  | { | ||||||
|  | 	MapChangeData(const char *mapName, const char *changeReason, time_t time) | ||||||
|  | 	{ | ||||||
|  | 		UTIL_Format(m_mapName, sizeof(m_mapName), mapName); | ||||||
|  | 		UTIL_Format(m_changeReason, sizeof(m_changeReason), changeReason); | ||||||
|  | 		startTime = time; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	MapChangeData() | ||||||
|  | 	{ | ||||||
|  | 		m_mapName[0] = '\0'; | ||||||
|  | 		m_changeReason[0] = '\0'; | ||||||
|  | 		startTime = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char m_mapName[32]; | ||||||
|  | 	char m_changeReason[100]; | ||||||
|  | 	time_t startTime; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| class NextMapManager : public SMGlobalClass | class NextMapManager : public SMGlobalClass | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | 	NextMapManager(); | ||||||
|  | 
 | ||||||
|  | #if defined ORANGEBOX_BUILD | ||||||
|  | 	friend void CmdChangeLevelCallback(const CCommand &command); | ||||||
|  | #else | ||||||
|  | 	friend void CmdChangeLevelCallback(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 	void OnSourceModAllInitialized_Post(); | 	void OnSourceModAllInitialized_Post(); | ||||||
| 	void OnSourceModShutdown(); | 	void OnSourceModShutdown(); | ||||||
|  | 	void OnSourceModLevelChange(const char *mapName); | ||||||
| 
 | 
 | ||||||
| 	const char *GetNextMap(); | 	const char *GetNextMap(); | ||||||
| 	bool SetNextMap(const char *map); | 	bool SetNextMap(const char *map); | ||||||
| 
 | 
 | ||||||
|  | 	void ForceChangeLevel(const char *mapName, const char* changeReason); | ||||||
|  | 
 | ||||||
| 	void HookChangeLevel(const char *map, const char *unknown); | 	void HookChangeLevel(const char *map, const char *unknown); | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	SourceHook::List<MapChangeData *> m_mapHistory; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	MapChangeData m_tempChangeInfo; | ||||||
|  | 	char lastMap[32]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern NextMapManager g_NextMap; | extern NextMapManager g_NextMap; | ||||||
|  | |||||||
| @ -54,10 +54,58 @@ static cell_t sm_SetNextMap(IPluginContext *pCtx, const cell_t *params) | |||||||
| 	return g_NextMap.SetNextMap(map); | 	return g_NextMap.SetNextMap(map); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static cell_t sm_ForceChangeLevel(IPluginContext *pCtx, const cell_t *params) | ||||||
|  | { | ||||||
|  | 	char *map; | ||||||
|  | 	char *changeReason; | ||||||
|  | 
 | ||||||
|  | 	pCtx->LocalToString(params[1], &map); | ||||||
|  | 	pCtx->LocalToString(params[2], &changeReason); | ||||||
|  | 
 | ||||||
|  | 	g_NextMap.ForceChangeLevel(map, changeReason); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static cell_t sm_GetMapHistorySize(IPluginContext *pCtx, const cell_t *params) | ||||||
|  | { | ||||||
|  | 	return g_NextMap.m_mapHistory.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static cell_t sm_GetMapHistory(IPluginContext *pCtx, const cell_t *params) | ||||||
|  | { | ||||||
|  | 	if (params[1] < 0 || params[1] >= (int)g_NextMap.m_mapHistory.size()) | ||||||
|  | 	{ | ||||||
|  | 		return pCtx->ThrowNativeError("Invalid Map History Index"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SourceHook::List<MapChangeData *>::iterator iter; | ||||||
|  | 	iter = g_NextMap.m_mapHistory.end(); | ||||||
|  | 	iter--; | ||||||
|  | 
 | ||||||
|  | 	for (int i=0; i<params[1]; i++) | ||||||
|  | 	{ | ||||||
|  | 		iter--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	MapChangeData *data = (MapChangeData *)*iter; | ||||||
|  | 
 | ||||||
|  | 	pCtx->StringToLocal(params[2], params[3], data->m_mapName); | ||||||
|  | 	pCtx->StringToLocal(params[4], params[5], data->m_changeReason); | ||||||
|  | 
 | ||||||
|  | 	cell_t *startTime; | ||||||
|  | 	pCtx->LocalToPhysAddr(params[6], &startTime); | ||||||
|  | 	*startTime = data->startTime; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| REGISTER_NATIVES(nextmapnatives) | REGISTER_NATIVES(nextmapnatives) | ||||||
| { | { | ||||||
| 	{"GetNextMap",		sm_GetNextMap}, | 	{"GetNextMap",			sm_GetNextMap}, | ||||||
| 	{"SetNextMap",		sm_SetNextMap}, | 	{"SetNextMap",			sm_SetNextMap}, | ||||||
| 	{NULL,						NULL}, | 	{"ForceChangeLevel",	sm_ForceChangeLevel}, | ||||||
|  | 	{"GetMapHistorySize",	sm_GetMapHistorySize}, | ||||||
|  | 	{"GetMapHistory",		sm_GetMapHistory}, | ||||||
|  | 	{NULL,					NULL}, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -109,7 +109,7 @@ public Action:Timer_ChangeMap(Handle:timer, Handle:dp) | |||||||
| 	ResetPack(dp); | 	ResetPack(dp); | ||||||
| 	ReadPackString(dp, map, sizeof(map)); | 	ReadPackString(dp, map, sizeof(map)); | ||||||
| 
 | 
 | ||||||
| 	ServerCommand("changelevel \"%s\"", map); | 	ForceChangeLevel(map, "sm_map Command"); | ||||||
| 
 | 
 | ||||||
| 	return Plugin_Stop; | 	return Plugin_Stop; | ||||||
| } | } | ||||||
|  | |||||||
| @ -54,9 +54,9 @@ new Handle:g_Cvar_WinLimit = INVALID_HANDLE; | |||||||
| new Handle:g_Cvar_FragLimit = INVALID_HANDLE; | new Handle:g_Cvar_FragLimit = INVALID_HANDLE; | ||||||
| new Handle:g_Cvar_MaxRounds = INVALID_HANDLE; | new Handle:g_Cvar_MaxRounds = INVALID_HANDLE; | ||||||
| 
 | 
 | ||||||
| #define TIMELEFT_ALL_ALWAYS		0 | #define TIMELEFT_ALL_ALWAYS		0		/* Print to all players */ | ||||||
| #define TIMELEFT_ALL_MAYBE		1 | #define TIMELEFT_ALL_MAYBE		1		/* Print to all players if sm_trigger_show allows */ | ||||||
| #define TIMELEFT_ONE			2 | #define TIMELEFT_ONE			2		/* Print to a single player */ | ||||||
| 
 | 
 | ||||||
| public OnPluginStart() | public OnPluginStart() | ||||||
| { | { | ||||||
|  | |||||||
| @ -424,7 +424,7 @@ public Action:Timer_ChangeMap(Handle:timer, Handle:dp) | |||||||
| 	ResetPack(dp); | 	ResetPack(dp); | ||||||
| 	ReadPackString(dp, mapname, sizeof(mapname)); | 	ReadPackString(dp, mapname, sizeof(mapname)); | ||||||
| 	 | 	 | ||||||
| 	ServerCommand("changelevel \"%s\"", mapname); | 	ForceChangeLevel(mapname, "sm_votemap Result"); | ||||||
| 	 | 	 | ||||||
| 	return Plugin_Stop; | 	return Plugin_Stop; | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,3 +52,33 @@ native bool:SetNextMap(const String:map[]); | |||||||
|  * @return			True if a Map was found and copied, false if no nextmap is set (map will be unchanged). |  * @return			True if a Map was found and copied, false if no nextmap is set (map will be unchanged). | ||||||
|  */ |  */ | ||||||
| native bool:GetNextMap(String:map[], maxlen); | native bool:GetNextMap(String:map[], maxlen); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Changes the current map and records the reason for the change with maphistory | ||||||
|  |  * | ||||||
|  |  * @param map		Map to change to. | ||||||
|  |  * @param reason	Reason for change. | ||||||
|  |  * @noreturn | ||||||
|  |  */ | ||||||
|  | native ForceChangeLevel(const String:map[], const String:reason[]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Gets the current number of maps in the map history | ||||||
|  |  * | ||||||
|  |  * @return			Number of maps. | ||||||
|  |  */ | ||||||
|  | native GetMapHistorySize(); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Retrieves a map from the map history list. | ||||||
|  |  *  | ||||||
|  |  * @param item			Item number. Must be 0 or greater and less than GetMapHistorySize(). | ||||||
|  |  * @param map			Buffer to store the map name. | ||||||
|  |  * @param mapLen		Length of map buffer. | ||||||
|  |  * @param reason		Buffer to store the change reason. | ||||||
|  |  * @param reasonLen		Length of the reason buffer. | ||||||
|  |  * @param startTime		Time the map started. | ||||||
|  |  * @noreturn | ||||||
|  |  * @error				Invalid item number.	 | ||||||
|  |  */ | ||||||
|  | native GetMapHistory(item, String:map[], mapLen, String:reason[], reasonLen, &startTime); | ||||||
| @ -771,7 +771,7 @@ public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp) | |||||||
| 		ReadPackString(dp, map, sizeof(map));		 | 		ReadPackString(dp, map, sizeof(map));		 | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	ServerCommand("changelevel \"%s\"", map); | 	ForceChangeLevel(map, "Map Vote"); | ||||||
| 	 | 	 | ||||||
| 	return Plugin_Stop; | 	return Plugin_Stop; | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,6 +52,8 @@ new g_MapPos = -1; | |||||||
| new Handle:g_MapList = INVALID_HANDLE; | new Handle:g_MapList = INVALID_HANDLE; | ||||||
| new g_MapListSerial = -1; | new g_MapListSerial = -1; | ||||||
| 
 | 
 | ||||||
|  | new g_CurrentMapStartTime; | ||||||
|  |   | ||||||
| public OnPluginStart() | public OnPluginStart() | ||||||
| { | { | ||||||
| 	LoadTranslations("common.phrases"); | 	LoadTranslations("common.phrases"); | ||||||
| @ -65,6 +67,7 @@ public OnPluginStart() | |||||||
| 	RegConsoleCmd("nextmap", Command_Nextmap); | 	RegConsoleCmd("nextmap", Command_Nextmap); | ||||||
| 
 | 
 | ||||||
| 	RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>"); | 	RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>"); | ||||||
|  | 	RegAdminCmd("sm_maphistory", Command_MapHistory, ADMFLAG_CHANGEMAP, "Shows the most recent maps played"); | ||||||
| 	RegConsoleCmd("listmaps", Command_List); | 	RegConsoleCmd("listmaps", Command_List); | ||||||
| 
 | 
 | ||||||
| 	// Set to the current map so OnMapStart() will know what to do | 	// Set to the current map so OnMapStart() will know what to do | ||||||
| @ -73,6 +76,11 @@ public OnPluginStart() | |||||||
| 	SetNextMap(currentMap); | 	SetNextMap(currentMap); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | public OnMapStart() | ||||||
|  | { | ||||||
|  | 	g_CurrentMapStartTime = GetTime(); | ||||||
|  | } | ||||||
|  |   | ||||||
| public OnConfigsExecuted() | public OnConfigsExecuted() | ||||||
| { | { | ||||||
| 	decl String:lastMap[64], String:currentMap[64]; | 	decl String:lastMap[64], String:currentMap[64]; | ||||||
| @ -228,3 +236,59 @@ FindAndSetNextMap() | |||||||
|  	GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName)); |  	GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName)); | ||||||
| 	SetNextMap(mapName); | 	SetNextMap(mapName); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | public Action:Command_MapHistory(client, args) | ||||||
|  | { | ||||||
|  | 	new mapCount = GetMapHistorySize(); | ||||||
|  | 	 | ||||||
|  | 	decl String:mapName[32]; | ||||||
|  | 	decl String:changeReason[100]; | ||||||
|  | 	decl String:timeString[100]; | ||||||
|  | 	decl String:playedTime[100]; | ||||||
|  | 	new startTime; | ||||||
|  | 	 | ||||||
|  | 	new lastMapStartTime = g_CurrentMapStartTime; | ||||||
|  | 	 | ||||||
|  | 	PrintToConsole(client, "Map History:\n"); | ||||||
|  | 	PrintToConsole(client, "Map : Started : Played Time : Reason for ending"); | ||||||
|  | 	 | ||||||
|  | 	GetCurrentMap(mapName, sizeof(mapName)); | ||||||
|  | 	PrintToConsole(client, "%02i. %s (Current Map)", 0, mapName); | ||||||
|  | 	 | ||||||
|  | 	for (new i=0; i<mapCount; i++) | ||||||
|  | 	{ | ||||||
|  | 		GetMapHistory(i, mapName, sizeof(mapName), changeReason, sizeof(changeReason), startTime); | ||||||
|  | 
 | ||||||
|  | 		FormatTimeDuration(timeString, sizeof(timeString), GetTime() - startTime); | ||||||
|  | 		FormatTimeDuration(playedTime, sizeof(playedTime), lastMapStartTime - startTime); | ||||||
|  | 		 | ||||||
|  | 		PrintToConsole(client, "%02i. %s : %s ago : %s : %s", i+1, mapName, timeString, playedTime, changeReason); | ||||||
|  | 		 | ||||||
|  | 		lastMapStartTime = startTime; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FormatTimeDuration(String:buffer[], maxlen, time) | ||||||
|  | { | ||||||
|  | 	new	days = time / 86400; | ||||||
|  | 	new	hours = (time / 3600) % 24; | ||||||
|  | 	new	minutes = (time / 60) % 60; | ||||||
|  | 	new	seconds =  time % 60; | ||||||
|  | 	 | ||||||
|  | 	if (days > 0) | ||||||
|  | 	{ | ||||||
|  | 		Format(buffer, maxlen, "%id %ih %im", days, hours, (seconds >= 30) ? minutes+1 : minutes); | ||||||
|  | 	} | ||||||
|  | 	else if (hours > 0) | ||||||
|  | 	{ | ||||||
|  | 		Format(buffer, maxlen, "%ih %im", hours, (seconds >= 30) ? minutes+1 : minutes);		 | ||||||
|  | 	} | ||||||
|  | 	else if (minutes > 0) | ||||||
|  | 	{ | ||||||
|  | 		Format(buffer, maxlen, "%im", (seconds >= 30) ? minutes+1 : minutes);		 | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		Format(buffer, maxlen, "%is", seconds);		 | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -298,7 +298,7 @@ public Action:Timer_ChangeMap(Handle:hTimer) | |||||||
| 	new String:map[65]; | 	new String:map[65]; | ||||||
| 	if (GetNextMap(map, sizeof(map))) | 	if (GetNextMap(map, sizeof(map))) | ||||||
| 	{	 | 	{	 | ||||||
| 		ServerCommand("changelevel \"%s\"", map); | 		ForceChangeLevel(map, "RTV after mapvote"); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	return Plugin_Stop; | 	return Plugin_Stop; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user