plugins/nextmap.sp
changeset 1175 3472591d95eb
child 1180 90bfcf192ffd
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/plugins/nextmap.sp	Thu Jul 26 22:41:13 2007 +0000
     1.3 @@ -0,0 +1,299 @@
     1.4 +/**
     1.5 + * nextmap.sp
     1.6 + * Adds sm_nextmap Cvar for changing map, and nextmap chat trigger
     1.7 + * This file is part of SourceMod, Copyright (C) 2004-2007 AlliedModders LLC
     1.8 + *
     1.9 + * This program is free software; you can redistribute it and/or
    1.10 + * modify it under the terms of the GNU General Public License
    1.11 + * as published by the Free Software Foundation; either version 2
    1.12 + * of the License, or (at your option) any later version.
    1.13 + *
    1.14 + * This program is distributed in the hope that it will be useful,
    1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.17 + * GNU General Public License for more details.
    1.18 + * 
    1.19 + * You should have received a copy of the GNU General Public License
    1.20 + * along with this program; if not, write to the Free Software
    1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1.22 + *
    1.23 + * Version: $Id$
    1.24 + */
    1.25 + 
    1.26 +#include <sourcemod>
    1.27 + 
    1.28 +#pragma semicolon 1
    1.29 + 
    1.30 +public Plugin:myinfo = 
    1.31 +{
    1.32 +	name = "Nextmap",
    1.33 +	author = "AlliedModders LLC",
    1.34 +	description = "Provides nextmap and sm_nextmap",
    1.35 +	version = SOURCEMOD_VERSION,
    1.36 +	url = "http://www.sourcemod.net/"
    1.37 +};
    1.38 +
    1.39 +new bool:g_IntermissionCalled;
    1.40 +new UserMsg:g_VGUIMenu;
    1.41 + 
    1.42 +new Handle:g_Cvar_Chattime;
    1.43 +new Handle:g_Cvar_Nextmap;
    1.44 +new Handle:g_Cvar_Mapcycle;
    1.45 +
    1.46 +new g_MapPos = -1;
    1.47 +new Handle:g_MapList = INVALID_HANDLE;
    1.48 +
    1.49 +#if 0
    1.50 +new bool:g_INS = false;
    1.51 +#endif
    1.52 + 
    1.53 +public OnPluginStart()
    1.54 +{
    1.55 +	LoadTranslations("plugin.nextmap");
    1.56 +	
    1.57 +	g_VGUIMenu = GetUserMessageId("VGUIMenu");
    1.58 +	if (g_VGUIMenu == INVALID_MESSAGE_ID)
    1.59 +	{
    1.60 +		LogMessage("FATAL: Cannot find VGUIMenu user message id. Nextmap not loaded.");
    1.61 +		return;	
    1.62 +	}
    1.63 +	
    1.64 +	g_Cvar_Chattime = FindConVar("mp_chattime");
    1.65 +	g_Cvar_Mapcycle = FindConVar("mapcyclefile");
    1.66 +	
    1.67 +	g_MapList = CreateArray(32);
    1.68 +	
    1.69 +	decl String:mapCycle[64];
    1.70 +	GetConVarString(g_Cvar_Mapcycle, mapCycle, 64);
    1.71 +	if (LoadMaps(mapCycle) == 0)
    1.72 +	{
    1.73 +		LogMessage("FATAL: Cannot load map cycle. Nextmap not loaded.");
    1.74 +		return;
    1.75 +	}	
    1.76 +	
    1.77 +	HookUserMessage(g_VGUIMenu, UserMsg_VGUIMenu);
    1.78 +	HookConVarChange(g_Cvar_Mapcycle, ConVarChange_Mapcyclefile);
    1.79 +	
    1.80 +	g_Cvar_Nextmap = CreateConVar("sm_nextmap", "", "Sets the Next Map", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY);
    1.81 +	
    1.82 +	RegConsoleCmd("say", Command_Say);
    1.83 +	RegConsoleCmd("say_team", Command_Say);
    1.84 +	
    1.85 +	#if 0
    1.86 +	decl String:modname[64];
    1.87 +	GetGameFolderName(modname, sizeof(modname));
    1.88 +	
    1.89 +	if (strcmp(modname, "ins") == 0)
    1.90 +	{
    1.91 +		RegConsoleCmd("say2", Command_SayChat);
    1.92 +		g_INS = true;
    1.93 +	}
    1.94 +	#endif
    1.95 +	
    1.96 +	RegConsoleCmd("nextmap", Command_Nextmap);
    1.97 +	RegConsoleCmd("listmaps", Command_List);
    1.98 +	
    1.99 +	/* Set to the current map so OnMapStart() will know what to do */
   1.100 +	decl String:currentMap[64];
   1.101 +	GetCurrentMap(currentMap, 64);
   1.102 +	SetConVarString(g_Cvar_Nextmap, currentMap);
   1.103 +}
   1.104 + 
   1.105 +public OnMapStart()
   1.106 +{
   1.107 +	decl String:lastMap[64], String:currentMap[64];
   1.108 +	GetConVarString(g_Cvar_Nextmap, lastMap, 64);
   1.109 +	GetCurrentMap(currentMap, 64);
   1.110 +	
   1.111 +	// 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
   1.112 +	// some other plugin/command), we don't want to scramble the map cycle. Or for example, admin switches to a custom map
   1.113 +	// not in mapcyclefile. So we keep it set to the last expected nextmap. - ferret
   1.114 +	if (strcmp(lastMap, currentMap) == 0)
   1.115 +	{
   1.116 +		FindAndSetNextMap();
   1.117 +	}
   1.118 +}
   1.119 + 
   1.120 +public OnMapEnd()
   1.121 +{
   1.122 +	g_IntermissionCalled = false;
   1.123 +}
   1.124 + 
   1.125 +public ConVarChange_Mapcyclefile(Handle:convar, const String:oldValue[], const String:newValue[])
   1.126 +{
   1.127 +	if (strcmp(oldValue, newValue, false) != 0)
   1.128 +	{
   1.129 +		LoadMaps(newValue);
   1.130 +	}
   1.131 +}
   1.132 + 
   1.133 +public Action:Command_Say(client, args)
   1.134 +{
   1.135 +	decl String:text[192];
   1.136 +	GetCmdArgString(text, sizeof(text));
   1.137 +	
   1.138 +	new startidx;
   1.139 +	if (text[strlen(text)-1] == '"')
   1.140 +	{
   1.141 +		text[strlen(text)-1] = '\0';
   1.142 +		startidx = 1;
   1.143 +	}
   1.144 +	
   1.145 +	#if 0
   1.146 +	if (g_INS)
   1.147 +	{
   1.148 +		startidx += 4;
   1.149 +	}
   1.150 +	#endif
   1.151 +	
   1.152 +	decl String:message[8];
   1.153 +	BreakString(text[startidx], message, sizeof(message));
   1.154 +	
   1.155 +	if (strcmp(message, "nextmap", false) == 0)
   1.156 +	{
   1.157 +		return Command_Nextmap(client, args);
   1.158 +	}
   1.159 +	
   1.160 +	return Plugin_Continue;	
   1.161 +}
   1.162 + 
   1.163 +public Action:Command_Nextmap(client, args) 
   1.164 +{
   1.165 +	decl String:map[32];
   1.166 +	GetConVarString(g_Cvar_Nextmap, map, sizeof(map));
   1.167 +	
   1.168 +	PrintToChatAll("%t", "Next Map", map);
   1.169 +	
   1.170 +	return Plugin_Continue;
   1.171 +}
   1.172 + 
   1.173 +public Action:UserMsg_VGUIMenu(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init)
   1.174 +{
   1.175 +	if (g_IntermissionCalled)
   1.176 +	{
   1.177 +		return Plugin_Handled;
   1.178 +	}
   1.179 +	
   1.180 +	decl String:type[15];
   1.181 +	BfReadString(bf, type, sizeof(type));
   1.182 + 
   1.183 +	if (BfReadByte(bf) == 1 && BfReadByte(bf) == 0 && (strcmp(type, "scores", false) == 0))
   1.184 +	{
   1.185 +		g_IntermissionCalled = true;
   1.186 +		
   1.187 +		decl String:map[32];
   1.188 +		new Float:fChatTime = GetConVarFloat(g_Cvar_Chattime);
   1.189 +		
   1.190 +		GetConVarString(g_Cvar_Nextmap, map, sizeof(map));
   1.191 +		
   1.192 +		if (fChatTime < 2.0)
   1.193 +			SetConVarFloat(g_Cvar_Chattime, 2.0);
   1.194 +		
   1.195 +		new Handle:dp;
   1.196 +		CreateDataTimer(fChatTime - 1.0, Timer_ChangeMap, dp);
   1.197 +		WritePackString(dp, map);
   1.198 +	}
   1.199 +	
   1.200 +	return Plugin_Handled;
   1.201 +}
   1.202 + 
   1.203 +public Action:Timer_ChangeMap(Handle:timer, Handle:dp)
   1.204 +{
   1.205 +	new String:map[32];
   1.206 +	
   1.207 +	ResetPack(dp);
   1.208 +	ReadPackString(dp, map, sizeof(map));
   1.209 + 
   1.210 +	InsertServerCommand("changelevel \"%s\"", map);
   1.211 +	ServerExecute();
   1.212 +	
   1.213 +	LogMessage("Nextmap changed map to \"%s\"", map);
   1.214 +	
   1.215 +	return Plugin_Stop;
   1.216 +}
   1.217 + 
   1.218 +public Action:Command_List(client, args) 
   1.219 +{
   1.220 +	PrintToConsole(client, "Map Cycle:");
   1.221 +	
   1.222 +	new mapCount = GetArraySize(g_MapList);
   1.223 +	decl String:mapName[32];
   1.224 +	for (new i = 0; i < mapCount; i++)
   1.225 +	{
   1.226 +		GetArrayString(g_MapList, i, mapName, sizeof(mapName));
   1.227 +		PrintToConsole(client, "%s", mapName);
   1.228 +	}
   1.229 + 
   1.230 +	return Plugin_Handled;
   1.231 +}
   1.232 + 
   1.233 +LoadMaps(const String:path[])
   1.234 +{
   1.235 +	if (!FileExists(path))
   1.236 +	{
   1.237 +		return 0;
   1.238 +	}
   1.239 + 
   1.240 +	new Handle:file = OpenFile(path, "r");
   1.241 +	
   1.242 +	if (file == INVALID_HANDLE)
   1.243 +	{
   1.244 +		LogError("[SM] Could not open file: %s", path);
   1.245 +		return 0;
   1.246 +	}
   1.247 +	
   1.248 +	ClearArray(g_MapList);
   1.249 +	g_MapPos = -1;
   1.250 +	
   1.251 +	decl String:buffer[255];
   1.252 +	while (!IsEndOfFile(file) && ReadFileLine(file, buffer, sizeof(buffer)))
   1.253 +	{
   1.254 +		TrimString(buffer);
   1.255 +		if (buffer[0] == '\0' || buffer[0] == ';')
   1.256 +		{
   1.257 +			continue;
   1.258 +		}
   1.259 +		
   1.260 +		if (IsMapValid(buffer))
   1.261 +		{
   1.262 +			PushArrayString(g_MapList, buffer);
   1.263 +		}
   1.264 +	}
   1.265 +	
   1.266 +	CloseHandle(file);
   1.267 +
   1.268 +	return GetArraySize(g_MapList);
   1.269 +}
   1.270 + 
   1.271 +FindAndSetNextMap()
   1.272 +{
   1.273 +	new mapCount = GetArraySize(g_MapList);
   1.274 +	decl String:mapName[32];
   1.275 +	
   1.276 +	if (g_MapPos == -1)
   1.277 +	{
   1.278 +		decl String:current[64];
   1.279 +		GetCurrentMap(current, 64);
   1.280 +		
   1.281 +
   1.282 +		for (new i = 0; i < mapCount; i++)
   1.283 +		{
   1.284 +			GetArrayString(g_MapList, i, mapName, sizeof(mapName));
   1.285 +			if (strcmp(current, mapName, false) == 0)
   1.286 +			{
   1.287 +				g_MapPos = i;
   1.288 +				break;
   1.289 +			}
   1.290 +		}
   1.291 +		
   1.292 +		if (g_MapPos == -1)
   1.293 +			g_MapPos = 0;
   1.294 +	}
   1.295 +	
   1.296 +	g_MapPos++;
   1.297 +	if (g_MapPos >= mapCount)
   1.298 +		g_MapPos = 0;	
   1.299 + 
   1.300 + 	GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName));
   1.301 +	SetConVarString(g_Cvar_Nextmap, mapName);
   1.302 +}
   1.303 \ No newline at end of file