ds@1952: /** ds@1952: * vim: set ts=4 : ds@1952: * ============================================================================= ds@1952: * SourceMod Nextmap Plugin ds@1952: * Adds sm_nextmap cvar for changing map and nextmap chat trigger. ds@1952: * ds@1952: * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. ds@1952: * ============================================================================= ds@1952: * ds@1952: * This program is free software; you can redistribute it and/or modify it under ds@1952: * the terms of the GNU General Public License, version 3.0, as published by the ds@1952: * Free Software Foundation. ds@1952: * ds@1952: * This program is distributed in the hope that it will be useful, but WITHOUT ds@1952: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ds@1952: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ds@1952: * details. ds@1952: * ds@1952: * You should have received a copy of the GNU General Public License along with ds@1952: * this program. If not, see . ds@1952: * ds@1952: * As a special exception, AlliedModders LLC gives you permission to link the ds@1952: * code of this program (as well as its derivative works) to "Half-Life 2," the ds@1952: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software ds@1952: * by the Valve Corporation. You must obey the GNU General Public License in ds@1952: * all respects for all other code used. Additionally, AlliedModders LLC grants ds@1952: * this exception to all derivative works. AlliedModders LLC defines further ds@1952: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), ds@1952: * or . ds@1952: * ds@1952: * Version: $Id$ ds@1952: */ ds@1952: ds@1952: #pragma semicolon 1 ds@1952: ds@1952: #include pred@2077: #include "include/nextmap.inc" pred@2077: ds@1952: public Plugin:myinfo = ds@1952: { ds@1952: name = "Nextmap", ds@1952: author = "AlliedModders LLC", ds@1952: description = "Provides nextmap and sm_nextmap", ds@1952: version = SOURCEMOD_VERSION, ds@1952: url = "http://www.sourcemod.net/" ds@1952: }; ds@1952: ds@1952: ds@1952: new g_MapPos = -1; ds@1952: new Handle:g_MapList = INVALID_HANDLE; ds@1952: new g_MapListSerial = -1; pred@2203: pred@2203: new g_CurrentMapStartTime; ds@1952: ds@1952: public OnPluginStart() ds@1952: { ds@1952: LoadTranslations("common.phrases"); ds@1952: LoadTranslations("nextmap.phrases"); ds@1952: ds@1952: g_MapList = CreateArray(32); ds@1952: ds@1952: RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap "); pred@2203: RegAdminCmd("sm_maphistory", Command_MapHistory, ADMFLAG_CHANGEMAP, "Shows the most recent maps played"); ds@1952: RegConsoleCmd("listmaps", Command_List); ds@1952: ds@1952: // Set to the current map so OnMapStart() will know what to do ds@1952: decl String:currentMap[64]; ds@1952: GetCurrentMap(currentMap, 64); pred@2077: SetNextMap(currentMap); ds@1952: } pred@2203: pred@2203: public OnMapStart() pred@2203: { pred@2203: g_CurrentMapStartTime = GetTime(); pred@2203: } ds@1952: ds@1952: public OnConfigsExecuted() ds@1952: { ds@1952: decl String:lastMap[64], String:currentMap[64]; pred@2077: GetNextMap(lastMap, sizeof(lastMap)); ds@1952: GetCurrentMap(currentMap, 64); ds@1952: ds@1952: // Why am I doing this? If we switched to a new map, but it wasn't what we expected (Due to sm_map, sm_votemap, or ds@1952: // some other plugin/command), we don't want to scramble the map cycle. Or for example, admin switches to a custom map ds@1952: // not in mapcyclefile. So we keep it set to the last expected nextmap. - ferret ds@1952: if (strcmp(lastMap, currentMap) == 0) ds@1952: { ds@1952: FindAndSetNextMap(); ds@1952: } ds@1952: } ds@1952: ds@1952: public Action:Command_SetNextmap(client, args) ds@1952: { ds@1952: if (args < 1) ds@1952: { ds@1952: ReplyToCommand(client, "[SM] Usage: sm_setnextmap "); ds@1952: return Plugin_Handled; ds@1952: } ds@1952: ds@1952: decl String:map[64]; ds@1952: GetCmdArg(1, map, sizeof(map)); ds@1952: ds@1952: if (!IsMapValid(map)) ds@1952: { ds@1952: ReplyToCommand(client, "[SM] %t", "Map was not found", map); ds@1952: return Plugin_Handled; ds@1952: } ds@1952: pred@2077: ShowActivity(client, "%t", "Changed Next Map", map); pred@2077: LogMessage("\"%L\" changed nextmap to \"%s\"", client, map); ds@1952: pred@2077: SetNextMap(map); ds@1952: ds@1952: return Plugin_Handled; ds@1952: } ds@1952: ds@1952: public Action:Command_List(client, args) ds@1952: { ds@1952: PrintToConsole(client, "Map Cycle:"); ds@1952: ds@1952: new mapCount = GetArraySize(g_MapList); ds@1952: decl String:mapName[32]; ds@1952: for (new i = 0; i < mapCount; i++) ds@1952: { ds@1952: GetArrayString(g_MapList, i, mapName, sizeof(mapName)); ds@1952: PrintToConsole(client, "%s", mapName); ds@1952: } ds@1952: ds@1952: return Plugin_Handled; ds@1952: } pred@2206: ds@1952: FindAndSetNextMap() ds@1952: { ds@1952: if (ReadMapList(g_MapList, ds@1952: g_MapListSerial, ds@1952: "mapcyclefile", ds@1952: MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT) ds@1952: == INVALID_HANDLE) ds@1952: { ds@1952: if (g_MapListSerial == -1) ds@1952: { ds@1952: LogError("FATAL: Cannot load map cycle. Nextmap not loaded."); ds@1952: SetFailState("Mapcycle Not Found"); ds@1952: } ds@1952: } ds@1952: ds@1952: new mapCount = GetArraySize(g_MapList); ds@1952: decl String:mapName[32]; ds@1952: ds@1952: if (g_MapPos == -1) ds@1952: { ds@1952: decl String:current[64]; ds@1952: GetCurrentMap(current, 64); ds@1952: ds@1952: for (new i = 0; i < mapCount; i++) ds@1952: { ds@1952: GetArrayString(g_MapList, i, mapName, sizeof(mapName)); ds@1952: if (strcmp(current, mapName, false) == 0) ds@1952: { ds@1952: g_MapPos = i; ds@1952: break; ds@1952: } ds@1952: } ds@1952: ds@1952: if (g_MapPos == -1) ds@1952: g_MapPos = 0; ds@1952: } ds@1952: ds@1952: g_MapPos++; ds@1952: if (g_MapPos >= mapCount) ds@1952: g_MapPos = 0; ds@1952: ds@1952: GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName)); pred@2077: SetNextMap(mapName); ds@1952: } pred@2203: pred@2203: public Action:Command_MapHistory(client, args) pred@2203: { pred@2203: new mapCount = GetMapHistorySize(); pred@2203: pred@2203: decl String:mapName[32]; pred@2203: decl String:changeReason[100]; pred@2203: decl String:timeString[100]; pred@2203: decl String:playedTime[100]; pred@2203: new startTime; pred@2203: pred@2203: new lastMapStartTime = g_CurrentMapStartTime; pred@2203: pred@2203: PrintToConsole(client, "Map History:\n"); pred@2203: PrintToConsole(client, "Map : Started : Played Time : Reason for ending"); pred@2203: pred@2203: GetCurrentMap(mapName, sizeof(mapName)); pred@2203: PrintToConsole(client, "%02i. %s (Current Map)", 0, mapName); pred@2203: pred@2203: for (new i=0; i 0) pred@2203: { pred@2203: Format(buffer, maxlen, "%id %ih %im", days, hours, (seconds >= 30) ? minutes+1 : minutes); pred@2203: } pred@2203: else if (hours > 0) pred@2203: { pred@2203: Format(buffer, maxlen, "%ih %im", hours, (seconds >= 30) ? minutes+1 : minutes); pred@2203: } pred@2203: else if (minutes > 0) pred@2203: { pred@2203: Format(buffer, maxlen, "%im", (seconds >= 30) ? minutes+1 : minutes); pred@2203: } pred@2203: else pred@2203: { pred@2203: Format(buffer, maxlen, "%is", seconds); pred@2203: } pred@2203: }