1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/plugins/include/helpers.inc Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,294 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
1.8 + * =============================================================================
1.9 + *
1.10 + * This file is part of the SourceMod/SourcePawn SDK.
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify it under
1.13 + * the terms of the GNU General Public License, version 3.0, as published by the
1.14 + * Free Software Foundation.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 + * details.
1.20 + *
1.21 + * You should have received a copy of the GNU General Public License along with
1.22 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.23 + *
1.24 + * As a special exception, AlliedModders LLC gives you permission to link the
1.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.27 + * by the Valve Corporation. You must obey the GNU General Public License in
1.28 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.29 + * this exception to all derivative works. AlliedModders LLC defines further
1.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.31 + * or <http://www.sourcemod.net/license.php>.
1.32 + *
1.33 + * Version: $Id$
1.34 + */
1.35 +
1.36 +#if defined _helpers_included
1.37 + #endinput
1.38 +#endif
1.39 +#define _helpers_included
1.40 +
1.41 +/**
1.42 + * Formats a user's info as log text. This is usually not needed because
1.43 + * %L can be used to auto-format client information into a string.
1.44 + *
1.45 + * @param client Client index.
1.46 + * @param buffer Buffer for text.
1.47 + * @param maxlength Maximum length of text.
1.48 + */
1.49 +stock FormatUserLogText(client, String:buffer[], maxlength)
1.50 +{
1.51 + decl String:auth[32];
1.52 + decl String:name[40];
1.53 +
1.54 + new userid = GetClientUserId(client);
1.55 + if (!GetClientAuthString(client, auth, sizeof(auth)))
1.56 + {
1.57 + strcopy(auth, sizeof(auth), "UNKNOWN");
1.58 + }
1.59 + if (!GetClientName(client, name, sizeof(name)))
1.60 + {
1.61 + strcopy(name, sizeof(name), "UNKNOWN");
1.62 + }
1.63 +
1.64 + /** Currently, no team stuff ... */
1.65 +
1.66 + Format(buffer, maxlength, "\"%s<%d><%s><>\"", name, userid, auth);
1.67 +}
1.68 +
1.69 +/**
1.70 + * Returns plugin handle from plugin filename.
1.71 + *
1.72 + * @param filename Filename of the plugin to search for.
1.73 + * @return Handle to plugin if found, INVALID_HANDLE otherwise.
1.74 + */
1.75 +stock Handle:FindPluginByFile(const String:filename[])
1.76 +{
1.77 + decl String:buffer[256];
1.78 +
1.79 + new Handle:iter = GetPluginIterator();
1.80 + new Handle:pl;
1.81 +
1.82 + while (MorePlugins(iter))
1.83 + {
1.84 + pl = ReadPlugin(iter);
1.85 +
1.86 + GetPluginFilename(pl, buffer, sizeof(buffer));
1.87 + if (strcmp(buffer, filename, false) == 0)
1.88 + {
1.89 + CloseHandle(iter);
1.90 + return pl;
1.91 + }
1.92 + }
1.93 +
1.94 + CloseHandle(iter);
1.95 +
1.96 + return INVALID_HANDLE;
1.97 +}
1.98 +
1.99 +/**
1.100 + * @deprecated Use FindTarget() or ProcessTargetString().
1.101 + */
1.102 +#pragma deprecated Use FindTarget() or ProcessTargetString()
1.103 +stock SearchForClients(const String:pattern[], clients[], maxClients)
1.104 +{
1.105 + new maxclients = GetMaxClients();
1.106 + new total = 0;
1.107 +
1.108 + if (maxClients == 0)
1.109 + {
1.110 + return 0;
1.111 + }
1.112 +
1.113 + if (pattern[0] == '#')
1.114 + {
1.115 + new input = StringToInt(pattern[1]);
1.116 + if (!input)
1.117 + {
1.118 + decl String:name[65]
1.119 + for (new i=1; i<=maxclients; i++)
1.120 + {
1.121 + if (!IsClientInGame(i))
1.122 + {
1.123 + continue;
1.124 + }
1.125 + GetClientName(i, name, sizeof(name));
1.126 + if (strcmp(name, pattern, false) == 0)
1.127 + {
1.128 + clients[0] = i;
1.129 + return 1;
1.130 + }
1.131 + }
1.132 + } else {
1.133 + new client = GetClientOfUserId(input);
1.134 + if (client)
1.135 + {
1.136 + clients[0] = client;
1.137 + return 1;
1.138 + }
1.139 + }
1.140 + }
1.141 +
1.142 + decl String:name[65]
1.143 + for (new i=1; i<=maxclients; i++)
1.144 + {
1.145 + if (!IsClientInGame(i))
1.146 + {
1.147 + continue;
1.148 + }
1.149 + GetClientName(i, name, sizeof(name));
1.150 + if (StrContains(name, pattern, false) != -1)
1.151 + {
1.152 + clients[total++] = i;
1.153 + if (total >= maxClients)
1.154 + {
1.155 + break;
1.156 + }
1.157 + }
1.158 + }
1.159 +
1.160 + return total;
1.161 +}
1.162 +
1.163 +/**
1.164 + * Wraps ProcessTargetString() and handles producing error messages for
1.165 + * bad targets.
1.166 + *
1.167 + * @param client Client who issued command
1.168 + * @param target Client's target argument
1.169 + * @param nobots Optional. Set to true if bots should NOT be targetted
1.170 + * @param immunity Optional. Set to false to ignore target immunity.
1.171 + * @return Index of target client, or -1 on error.
1.172 + */
1.173 +stock FindTarget(client, const String:target[], bool:nobots = false, bool:immunity = true)
1.174 +{
1.175 + decl String:target_name[MAX_TARGET_LENGTH];
1.176 + decl target_list[1], target_count, bool:tn_is_ml;
1.177 +
1.178 + new flags = COMMAND_FILTER_NO_MULTI;
1.179 + if (nobots)
1.180 + {
1.181 + flags |= COMMAND_FILTER_NO_BOTS;
1.182 + }
1.183 + if (!immunity)
1.184 + {
1.185 + flags |= COMMAND_FILTER_NO_IMMUNITY;
1.186 + }
1.187 +
1.188 + if ((target_count = ProcessTargetString(
1.189 + target,
1.190 + client,
1.191 + target_list,
1.192 + 1,
1.193 + flags,
1.194 + target_name,
1.195 + sizeof(target_name),
1.196 + tn_is_ml)) > 0)
1.197 + {
1.198 + return target_list[0];
1.199 + }
1.200 + else
1.201 + {
1.202 + ReplyToTargetError(client, target_count);
1.203 + return -1;
1.204 + }
1.205 +}
1.206 +
1.207 +/**
1.208 + * This function is no longer supported. It has been replaced with ReadMapList(),
1.209 + * which uses a more unified caching and configuration mechanism. This function also
1.210 + * has a bug where if the cvar contents changes, the fileTime change won't be recognized.
1.211 + *
1.212 + * Loads a specified array with maps. The maps will be either loaded from mapcyclefile, or if supplied
1.213 + * a cvar containing a file name. If the file in the cvar is bad, it will use mapcyclefile. The fileTime
1.214 + * parameter is used to store a timestamp of the file. If specified, the file will only be reloaded if it
1.215 + * has changed.
1.216 + *
1.217 + * @param array Valid array handle, should be created with CreateArray(33) or larger.
1.218 + * @param fileTime Variable containing the "last changed" time of the file. Used to avoid needless reloading.
1.219 + * @param fileCvar CVAR set to the file to be loaded. Optional.
1.220 + * @return Number of maps loaded or 0 if in error.
1.221 + */
1.222 +#pragma deprecated Use ReadMapList() instead.
1.223 + stock LoadMaps(Handle:array, &fileTime = 0, Handle:fileCvar = INVALID_HANDLE)
1.224 + {
1.225 + decl String:mapPath[256], String:mapFile[64];
1.226 + new bool:fileFound = false;
1.227 +
1.228 + if (fileCvar != INVALID_HANDLE)
1.229 + {
1.230 + GetConVarString(fileCvar, mapFile, 64);
1.231 + BuildPath(Path_SM, mapPath, sizeof(mapPath), mapFile);
1.232 + fileFound = FileExists(mapPath);
1.233 + }
1.234 +
1.235 + if (!fileFound)
1.236 + {
1.237 + new Handle:mapCycleFile = FindConVar("mapcyclefile");
1.238 + GetConVarString(mapCycleFile, mapPath, sizeof(mapPath));
1.239 + fileFound = FileExists(mapPath);
1.240 + }
1.241 +
1.242 + if (!fileFound)
1.243 + {
1.244 + LogError("Failed to find a file to load maps from. No maps loaded.");
1.245 + ClearArray(array);
1.246 +
1.247 + return 0;
1.248 + }
1.249 +
1.250 + // If the file hasn't changed, there's no reason to reload
1.251 + // all of the maps.
1.252 + new newTime = GetFileTime(mapPath, FileTime_LastChange);
1.253 + if (fileTime == newTime)
1.254 + {
1.255 + return GetArraySize(array);
1.256 + }
1.257 +
1.258 + fileTime = newTime;
1.259 +
1.260 + ClearArray(array);
1.261 +
1.262 + new Handle:file = OpenFile(mapPath, "rt");
1.263 + if (file == INVALID_HANDLE)
1.264 + {
1.265 + LogError("Could not open file: %s", mapPath);
1.266 +
1.267 + return 0;
1.268 + }
1.269 +
1.270 + LogMessage("Loading maps from file: %s", mapPath);
1.271 +
1.272 + decl String:buffer[64], len;
1.273 + while (!IsEndOfFile(file) && ReadFileLine(file, buffer, sizeof(buffer)))
1.274 + {
1.275 + TrimString(buffer);
1.276 +
1.277 + if ((len = StrContains(buffer, ".bsp", false)) != -1)
1.278 + {
1.279 + buffer[len] = '\0';
1.280 + }
1.281 +
1.282 + if (buffer[0] == '\0' || !IsValidConVarChar(buffer[0]) || !IsMapValid(buffer))
1.283 + {
1.284 + continue;
1.285 + }
1.286 +
1.287 + if (FindStringInArray(array, buffer) != -1)
1.288 + {
1.289 + continue;
1.290 + }
1.291 +
1.292 + PushArrayString(array, buffer);
1.293 + }
1.294 +
1.295 + CloseHandle(file);
1.296 + return GetArraySize(array);
1.297 +}