merged branch-1.1.0 back into trunk

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401960
This commit is contained in:
David Anderson
2008-03-26 03:52:37 +00:00
parent 3bcd296d99
commit c5af41d983
52 changed files with 8062 additions and 39 deletions
+18 -5
View File
@@ -45,6 +45,8 @@ public Plugin:myinfo =
url = "http://www.sourcemod.net/"
};
new g_maxPlayers;
/* Forwards */
new Handle:hOnAdminMenuReady = INVALID_HANDLE;
new Handle:hOnAdminMenuCreated = INVALID_HANDLE;
@@ -57,6 +59,8 @@ new TopMenuObject:obj_playercmds = INVALID_TOPMENUOBJECT;
new TopMenuObject:obj_servercmds = INVALID_TOPMENUOBJECT;
new TopMenuObject:obj_votingcmds = INVALID_TOPMENUOBJECT;
#include "adminmenu/dynamicmenu.sp"
public bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max)
{
CreateNative("GetAdminTopMenu", __GetAdminTopMenu);
@@ -91,27 +95,36 @@ public OnConfigsExecuted()
}
}
public OnMapStart()
{
g_maxPlayers = GetMaxClients();
ParseConfigs();
}
public OnAllPluginsLoaded()
{
hAdminMenu = CreateTopMenu(CategoryHandler);
hAdminMenu = CreateTopMenu(DefaultCategoryHandler);
obj_playercmds = AddToTopMenu(hAdminMenu,
"PlayerCommands",
TopMenuObject_Category,
CategoryHandler,
DefaultCategoryHandler,
INVALID_TOPMENUOBJECT);
obj_servercmds = AddToTopMenu(hAdminMenu,
"ServerCommands",
TopMenuObject_Category,
CategoryHandler,
DefaultCategoryHandler,
INVALID_TOPMENUOBJECT);
obj_votingcmds = AddToTopMenu(hAdminMenu,
"VotingCommands",
TopMenuObject_Category,
CategoryHandler,
DefaultCategoryHandler,
INVALID_TOPMENUOBJECT);
BuildDynamicMenu();
Call_StartForward(hOnAdminMenuCreated);
Call_PushCell(hAdminMenu);
@@ -122,7 +135,7 @@ public OnAllPluginsLoaded()
Call_Finish();
}
public CategoryHandler(Handle:topmenu,
public DefaultCategoryHandler(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
+520
View File
@@ -0,0 +1,520 @@
#define NAME_LENGTH 32
#define CMD_LENGTH 255
#define ARRAY_STRING_LENGTH 32
new Handle:g_kvMenu;
enum GroupCommands
{
Handle:groupListName,
Handle:groupListCommand
};
new g_groupList[GroupCommands];
new g_groupCount;
new Handle:g_configParser = INVALID_HANDLE;
enum Places
{
Place_Category,
Place_Item,
Place_ReplaceNum
};
new String:g_command[MAXPLAYERS+1][CMD_LENGTH];
new g_currentPlace[MAXPLAYERS+1][Places];
/**
* What to put in the 'info' menu field (for PlayerList and Player_Team menus only)
*/
enum PlayerMethod
{
ClientId, /** Client id number ( 1 - Maxplayers) */
UserId, /** Client userid */
Name, /** Client Name */
SteamId, /** Client Steamid */
IpAddress, /** Client's Ip Address */
UserId2 /** Userid (not prefixed with #) */
};
BuildDynamicMenu()
{
if (g_kvMenu != INVALID_HANDLE)
{
CloseHandle(g_kvMenu);
}
g_kvMenu = CreateKeyValues("Commands");
new String:file[256];
BuildPath(Path_SM, file, 255, "configs/dynamicmenu/menu.ini");
FileToKeyValues(g_kvMenu, file);
new String:name[NAME_LENGTH];
new String:buffer[NAME_LENGTH];
if (!KvGotoFirstSubKey(g_kvMenu))
{
return;
}
decl String:admin[30];
new TopMenuObject:categoryId;
new catId;
new id;
do
{
KvGetSectionName(g_kvMenu, buffer, sizeof(buffer));
KvGetString(g_kvMenu, "admin", admin, sizeof(admin),"sm_admin");
if ((categoryId =FindTopMenuCategory(hAdminMenu, buffer)) == INVALID_TOPMENUOBJECT)
{
categoryId = AddToTopMenu(hAdminMenu,
buffer,
TopMenuObject_Category,
DynamicMenuCategoryHandler,
INVALID_TOPMENUOBJECT,
admin,
ADMFLAG_GENERIC,
name);
}
if (!KvGetSectionSymbol(g_kvMenu, catId))
{
LogError("Key Id not found for section: %s", buffer);
break;
}
if (!KvGotoFirstSubKey(g_kvMenu))
{
return;
}
do
{
KvGetSectionName(g_kvMenu, buffer, sizeof(buffer));
KvGetString(g_kvMenu, "admin", admin, sizeof(admin),"");
if (admin[0] == '\0')
{
//No 'admin' keyvalue was found
//Use the first argument of the 'cmd' string instead
decl String:temp[64];
KvGetString(g_kvMenu, "cmd", temp, sizeof(temp),"");
BreakString(temp, admin, sizeof(admin));
}
if (!KvGetSectionSymbol(g_kvMenu, id))
{
LogError("Key Id not found for section: %s");
break;
}
decl String:keyId[64];
Format(keyId, sizeof(keyId), "%i %i", catId, id);
AddToTopMenu(hAdminMenu,
buffer,
TopMenuObject_Item,
DynamicMenuItemHandler,
categoryId,
admin,
ADMFLAG_GENERIC,
keyId);
} while (KvGotoNextKey(g_kvMenu));
KvGoBack(g_kvMenu);
} while (KvGotoNextKey(g_kvMenu));
KvRewind(g_kvMenu);
}
ParseConfigs()
{
if (g_configParser == INVALID_HANDLE)
{
g_configParser = SMC_CreateParser();
}
SMC_SetReaders(g_configParser, NewSection, KeyValue, EndSection);
if (g_groupList[groupListName] != INVALID_HANDLE)
{
CloseHandle(g_groupList[groupListName]);
}
if (g_groupList[groupListCommand] != INVALID_HANDLE)
{
CloseHandle(g_groupList[groupListCommand]);
}
g_groupList[groupListName] = CreateArray(ARRAY_STRING_LENGTH);
g_groupList[groupListCommand] = CreateArray(ARRAY_STRING_LENGTH);
decl String:configPath[256];
BuildPath(Path_SM, configPath, sizeof(configPath), "configs/dynamicmenu/adminmenu_grouping.txt");
if (!FileExists(configPath))
{
LogError("Unable to locate admin menu groups file, no groups loaded.");
return;
}
new line;
new SMCError:err = SMC_ParseFile(g_configParser, configPath, line);
if (err != SMCError_Okay)
{
decl String:error[256];
SMC_GetErrorString(err, error, sizeof(error));
LogError("Could not parse file (line %d, file \"%s\"):", line, configPath);
LogError("Parser encountered error: %s", error);
}
return;
}
public SMCResult:NewSection(Handle:smc, const String:name[], bool:opt_quotes)
{
}
public SMCResult:KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes)
{
PushArrayString(g_groupList[groupListName], key);
PushArrayString(g_groupList[groupListCommand], value);
}
public SMCResult:EndSection(Handle:smc)
{
g_groupCount = GetArraySize(g_groupList[groupListName]);
}
public DynamicMenuCategoryHandler(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength)
{
if ((action == TopMenuAction_DisplayTitle) || (action == TopMenuAction_DisplayOption))
{
GetTopMenuObjName(topmenu, object_id, buffer, maxlength);
}
}
public DynamicMenuItemHandler(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength)
{
if (action == TopMenuAction_DisplayOption)
{
GetTopMenuObjName(topmenu, object_id, buffer, maxlength);
}
else if (action == TopMenuAction_SelectOption)
{
new String:keyId[64];
new String:catId[64];
GetTopMenuInfoString(topmenu, object_id, keyId, sizeof(keyId));
new start = BreakString(keyId, catId, sizeof(catId));
new id = StringToInt(keyId[start]);
new category = StringToInt(catId);
KvJumpToKeySymbol(g_kvMenu, category);
KvJumpToKeySymbol(g_kvMenu, id);
KvGetString(g_kvMenu, "cmd", g_command[param], sizeof(g_command[]),"");
KvRewind(g_kvMenu);
g_currentPlace[param][Place_Category] = category;
g_currentPlace[param][Place_Item] = id;
ParamCheck(param);
}
}
public ParamCheck(client)
{
new String:buffer[6];
new String:buffer2[6];
KvJumpToKeySymbol(g_kvMenu, g_currentPlace[client][Place_Category]);
KvJumpToKeySymbol(g_kvMenu, g_currentPlace[client][Place_Item]);
new String:type[NAME_LENGTH];
if (g_currentPlace[client][Place_ReplaceNum] < 1)
{
g_currentPlace[client][Place_ReplaceNum] = 1;
}
Format(buffer, 5, "#%i", g_currentPlace[client][Place_ReplaceNum]);
Format(buffer2, 5, "@%i", g_currentPlace[client][Place_ReplaceNum]);
if (StrContains(g_command[client], buffer) != -1 || StrContains(g_command[client], buffer2) != -1)
{
//user has a parameter to fill. lets do it.
KvJumpToKey(g_kvMenu, buffer[1]); // Jump to current param
KvGetString(g_kvMenu, "type", type, sizeof(type),"list");
PrintToChatAll("Checking param %s - type %s", buffer[1], type);
new Handle:itemMenu = CreateMenu(Menu_Selection);
new String:title[NAME_LENGTH];
if (strncmp(type,"group",5)==0 && g_groupCount)
{
decl String:nameBuffer[ARRAY_STRING_LENGTH];
decl String:commandBuffer[ARRAY_STRING_LENGTH];
for (new i = 0; i<g_groupCount; i++)
{
GetArrayString(g_groupList[groupListName], i, nameBuffer, sizeof(nameBuffer));
GetArrayString(g_groupList[groupListCommand], i, commandBuffer, sizeof(commandBuffer));
AddMenuItem(itemMenu, commandBuffer, nameBuffer);
}
}
if (strncmp(type,"mapcycle",8) == 0)
{
decl String:path[200];
KvGetString(g_kvMenu, "path", path, sizeof(path),"mapcycle.txt");
new Handle:file = OpenFile(path, "rt");
new String:readData[128];
if(file != INVALID_HANDLE)
{
while(!IsEndOfFile(file) && ReadFileLine(file, readData, sizeof(readData)))
{
TrimString(readData);
if (IsMapValid(readData))
{
AddMenuItem(itemMenu, readData, readData);
}
}
}
}
else if (StrContains(type, "player") != -1)
{
PrintToChatAll("Building Player List");
new PlayerMethod:playermethod;
new String:method[NAME_LENGTH];
KvGetString(g_kvMenu, "method", method, sizeof(method),"name");
if (strncmp(method,"clientid",8)==0)
{
playermethod = ClientId;
}
else if (strncmp(method,"steamid",7)==0)
{
playermethod = SteamId;
}
else if (strncmp(method,"userid2",7)==0)
{
playermethod = UserId2;
}
else if (strncmp(method,"userid",6)==0)
{
playermethod = UserId;
}
else if (strncmp(method,"ip",2)==0)
{
playermethod = IpAddress;
}
else
{
playermethod = Name;
}
new String:nameBuffer[32];
new String:infoBuffer[32];
new String:temp[4];
//loop through players. Add name as text and name/userid/steamid as info
for (new i=1; i<=g_maxPlayers; i++)
{
if (IsClientInGame(i))
{
GetClientName(i, nameBuffer, 31);
switch (playermethod)
{
case UserId:
{
new userid = GetClientUserId(i);
Format(infoBuffer, sizeof(infoBuffer), "#%i", userid);
AddMenuItem(itemMenu, infoBuffer, nameBuffer);
}
case UserId2:
{
new userid = GetClientUserId(i);
Format(infoBuffer, sizeof(infoBuffer), "%i", userid);
AddMenuItem(itemMenu, infoBuffer, nameBuffer);
}
case SteamId:
{
GetClientAuthString(i, infoBuffer, sizeof(infoBuffer));
AddMenuItem(itemMenu, infoBuffer, nameBuffer);
}
case IpAddress:
{
GetClientIP(i, infoBuffer, sizeof(infoBuffer));
AddMenuItem(itemMenu, infoBuffer, nameBuffer);
}
case Name:
{
AddMenuItem(itemMenu, nameBuffer, nameBuffer);
}
default: //assume client id
{
Format(temp,3,"%i",i);
AddMenuItem(itemMenu, temp, nameBuffer);
}
}
}
}
}
else if (strncmp(type,"onoff",5) == 0)
{
AddMenuItem(itemMenu, "1", "On");
AddMenuItem(itemMenu, "0", "Off");
}
else
{
//list menu
PrintToChatAll("Building List Menu");
new String:temp[6];
new String:value[64];
new String:text[64];
new i=1;
new bool:more = true;
new String:admin[NAME_LENGTH];
do
{
// load the i and i. options from kv and make a menu from them (i* = required admin level to view)
Format(temp,3,"%i",i);
KvGetString(g_kvMenu, temp, value, sizeof(value), "");
Format(temp,5,"%i.",i);
KvGetString(g_kvMenu, temp, text, sizeof(text), value);
Format(temp,5,"%i*",i);
KvGetString(g_kvMenu, temp, admin, sizeof(admin),"");
if (value[0]=='\0')
{
more = false;
}
else if (CheckCommandAccess(client, admin, 0))
{
AddMenuItem(itemMenu, value, text);
}
i++;
} while (more);
}
KvGetString(g_kvMenu, "title", title, sizeof(title),"Choose an Option");
SetMenuTitle(itemMenu, title);
DisplayMenu(itemMenu, client, MENU_TIME_FOREVER);
}
else
{
//nothing else need to be done. Run teh command.
new String:execute[7];
KvGetString(g_kvMenu, "execute", execute, sizeof(execute), "player");
DisplayTopMenu(hAdminMenu, client, TopMenuPosition_LastCategory);
if (execute[0]=='p') // assume 'player' type execute option
{
FakeClientCommand(client, g_command[client]);
}
else // assume 'server' type execute option
{
InsertServerCommand(g_command[client]);
ServerExecute();
}
g_command[client][0] = '\0';
g_currentPlace[client][Place_ReplaceNum] = 1;
}
KvRewind(g_kvMenu);
}
public Menu_Selection(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
if (action == MenuAction_Select)
{
new String:info[NAME_LENGTH];
/* Get item info */
new bool:found = GetMenuItem(menu, param2, info, sizeof(info));
if (!found)
{
return;
}
new String:buffer[6];
new String:infobuffer[NAME_LENGTH+2];
Format(infobuffer, sizeof(infobuffer), "\"%s\"", info);
Format(buffer, 5, "#%i", g_currentPlace[param1][Place_ReplaceNum]);
ReplaceString(g_command[param1], sizeof(g_command[]), buffer, infobuffer);
//replace #num with the selected option (quoted)
Format(buffer, 5, "@%i", g_currentPlace[param1][Place_ReplaceNum]);
ReplaceString(g_command[param1], sizeof(g_command[]), buffer, info);
//replace @num with the selected option (unquoted)
// Increment the parameter counter.
g_currentPlace[param1][Place_ReplaceNum]++;
ParamCheck(param1);
}
if (action == MenuAction_Cancel && param2 == MenuCancel_Exit)
{
//client exited we should go back to submenu i think
DisplayTopMenu(hAdminMenu, param1, TopMenuPosition_LastCategory);
}
}
+141
View File
@@ -0,0 +1,141 @@
#if defined _regex_included
#endinput
#endif
#define _regex_included
/**
* @section Flags for compiling regex expressions. These come directly from the
* pcre library and can be used in MatchRegex and CompileRegex.
*/
#define PCRE_CASELESS 0x00000001 /* Ignore Case */
#define PCRE_MULTILINE 0x00000002 /* Multilines (affects ^ and $ so that they match the start/end of a line rather than matching the start/end of the string). */
#define PCRE_DOTALL 0x00000004 /* Single line (affects . so that it matches any character, even new line characters). */
#define PCRE_EXTENDED 0x00000008 /* Pattern extension (ignore whitespace and # comments). */
#define PCRE_UNGREEDY 0x00000200 /* Invert greediness of quantifiers */
#define PCRE_UTF8 0x00000800 /* Use UTF-8 Chars */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) */
/**
* Regex expression error codes.
*/
enum RegexError
{
REGEX_ERROR_NONE = 0, /* No error */
REGEX_ERROR_NOMATCH = -1, /* No match was found */
REGEX_ERROR_NULL = -2,
REGEX_ERROR_BADOPTION = -3,
REGEX_ERROR_BADMAGIC = -4,
REGEX_ERROR_UNKNOWN_OPCODE = -5,
REGEX_ERROR_NOMEMORY = -6,
REGEX_ERROR_NOSUBSTRING = -7,
REGEX_ERROR_MATCHLIMIT = -8,
REGEX_ERROR_CALLOUT = -9, /* Never used by PCRE itself */
REGEX_ERROR_BADUTF8 = -10,
REGEX_ERROR_BADUTF8_OFFSET = -11,
REGEX_ERROR_PARTIAL = -12,
REGEX_ERROR_BADPARTIAL = -13,
REGEX_ERROR_INTERNAL = -14,
REGEX_ERROR_BADCOUNT = -15,
REGEX_ERROR_DFA_UITEM = -16,
REGEX_ERROR_DFA_UCOND = -17,
REGEX_ERROR_DFA_UMLIMIT = -18,
REGEX_ERROR_DFA_WSSIZE = -19,
REGEX_ERROR_DFA_RECURSE = -20,
REGEX_ERROR_RECURSIONLIMIT = -21,
REGEX_ERROR_NULLWSLIMIT = -22, /* No longer actually used */
REGEX_ERROR_BADNEWLINE = -23
}
/**
* Precompile a regular expression. Use this if you intend on using the
* same expression multiple times. Pass the regex handle returned here to
* MatchRegex to check for matches.
*
* @param pattern The regular expression pattern.
* @param flags General flags for the regular expression.
* @param error Error message encountered, if applicable.
* @param maxLen Maximum string length of the error buffer.
* @param errcode Regex type error code encountered, if applicable.
* @return Valid regex handle on success, INVALID_HANDLE on failure.
*/
native Handle:CompileRegex(const String:pattern[], flags = 0, String:error[]="", maxLen = 0, &RegexError:errcode = REGEX_ERROR_NONE);
/**
* Matches a string against a pre-compiled regular expression pattern.
*
* @param str The string to check.
* @param regex Regex Handle from CompileRegex()
* @param ret Error code, if applicable.
* @return Number of substrings found or -1 on failure.
*
* @note Use the regex handle passed to this function to extract
* matches with GetRegexSubString().
*/
native MatchRegex(Handle:regex, const String:str[], &RegexError:ret = REGEX_ERROR_NONE);
/**
* Returns a matched substring from a regex handle.
* Substring ids start at 0 and end at substrings-1, where substrings is the number returned
* by MatchRegex
*
* @param regex The regex handle to extract data from.
* @param str_id The index of the expression to get - starts at 0, and ends at substrings - 1.
* @param buffer The buffer to set to the matching substring.
* @param maxLen The maximum string length of the buffer.
* @return True if a substring was found, False on fail/error
*/
native bool:GetRegexSubString(Handle:regex, str_id, String:buffer[], maxlen);
/**
* Matches a string against a regular expression pattern.
*
* @note If you intend on using the same regular expression pattern
* multiple times, consider using CompileRegex and MatchRegex
* instead of making this function reparse the expression each time.
*
* @param str The string to check.
* @param pattern The regular expression pattern.
* @param flags General flags for the regular expression.
* @param error Error message, if applicable.
* @param maxLen Maximum length of the error buffer.
* @return Number of substrings found or -1 on failure.
*/
stock SimpleRegexMatch(const String:str[], const String:pattern[], flags = 0, String:error[]="", maxLen = 0)
{
new Handle:regex = CompileRegex(pattern, flags, error, maxLen);
if (regex == INVALID_HANDLE)
{
return -1;
}
new substrings = MatchRegex(regex, str);
CloseHandle(regex);
return substrings;
}
/**
* @endsection
*/
/**
* Do not edit below this line!
*/
public Extension:__ext_regex =
{
name = "Regex Extension",
file = "regex.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};
+362
View File
@@ -0,0 +1,362 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Management Plugin
* Provides all map related functionality, including map changing, map voting,
* and nextmap.
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#pragma semicolon 1
#include <sourcemod>
public Plugin:myinfo =
{
name = "Map Manager",
author = "AlliedModders LLC",
description = "Map Management",
version = SOURCEMOD_VERSION,
url = "http://www.sourcemod.net/"
};
#include "mapmanagement/globals.sp"
#include "mapmanagement/commands.sp"
#include "mapmanagement/events.sp"
#include "mapmanagement/functions.sp"
#include "mapmanagement/menus.sp"
#include "mapmanagement/timers.sp"
#include "mapmanagement/votes.sp"
public OnPluginStart()
{
LoadTranslations("mapmanager.phrases");
// Prepare nextmap functionality.
g_VGUIMenu = GetUserMessageId("VGUIMenu");
if (g_VGUIMenu == INVALID_MESSAGE_ID)
{
LogError("FATAL: Cannot find VGUIMenu user message id. MapManager crippled.");
g_NextMapEnabled = false;
}
HookUserMessage(g_VGUIMenu, UserMsg_VGUIMenu);
// Create all of the arrays, sized for a 64 character string.
new arraySize = ByteCountToCells(64);
g_MapCycle = CreateArray(arraySize);
g_MapList = CreateArray(arraySize);
g_MapHistory = CreateArray(arraySize);
g_NextVoteMaps = CreateArray(arraySize);
g_SelectedMaps = CreateArray(arraySize);
g_NominatedMaps = CreateArray(arraySize);
g_TeamScores = CreateArray(2);
// Hook say
RegConsoleCmd("say", Command_Say);
RegConsoleCmd("say_team", Command_Say);
// Register all commands.
RegAdminCmd("sm_map", Command_Map, ADMFLAG_CHANGEMAP, "sm_map <map> [r/e]");
RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>");
RegAdminCmd("sm_votemap", Command_Votemap, ADMFLAG_VOTE|ADMFLAG_CHANGEMAP, "sm_votemap <mapname> [mapname2] ... [mapname5] ");
RegAdminCmd("sm_maplist", Command_List, ADMFLAG_GENERIC, "sm_maplist");
RegAdminCmd("sm_nominate", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate <mapname> - Nominates a map for RockTheVote and MapChooser. Overrides existing nominations.");
RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces the MapChooser vote to occur.");
if (GetCommandFlags("nextmap") == INVALID_FCVAR_FLAGS)
{
RegServerCmd("nextmap", Command_Nextmap);
}
// Register all convars
g_Cvar_Nextmap = CreateConVar("sm_nextmap", "", "Sets the Next Map", FCVAR_NOTIFY);
g_Cvar_MapCount = CreateConVar("sm_mm_maps", "4", "Number of maps to be voted on at end of map or RTV. 2 to 6. (Def 4)", 0, true, 2.0, true, 6.0);
g_Cvar_Excludes = CreateConVar("sm_mm_exclude", "5", "Specifies how many past maps to exclude from end of map vote and RTV.", _, true, 0.0);
g_Cvar_MapChooser = CreateConVar("sm_mm_mapchooser", "0", "Enables MapChooser (End of Map voting)", 0, true, 0.0, true, 1.0);
g_Cvar_RockTheVote = CreateConVar("sm_mm_rockthevote", "0", "Enables RockTheVote (Player initiated map votes)", 0, true, 0.0, true, 1.0);
g_Cvar_Randomize = CreateConVar("sm_mm_randomize", "0", "Enabled Randomizer (Randomly picks the next map)", 0, true, 0.0, true, 1.0);
g_Cvar_Nominate = CreateConVar("sm_mm_nominate", "1", "Enables nomination system.", 0, true, 0.0, true, 1.0);
g_Cvar_VoteMap = CreateConVar("sm_mm_votemap", "0.60", "Percentage required for successful sm_votemap.", 0, true, 0.05, true, 1.0);
g_Cvar_RTVLimit = CreateConVar("sm_mm_rtvlimit", "0.60", "Required percentage of players needed to rockthevote", 0, true, 0.05, true, 1.0);
g_Cvar_MinPlayers = CreateConVar("sm_mm_minplayers", "0", "Number of players required before RTV will be enabled.", 0, true, 0.0, true, float(MAXPLAYERS));
g_Cvar_StartTime = CreateConVar("sm_mapvote_start", "3.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0);
g_Cvar_StartRounds = CreateConVar("sm_mapvote_startround", "2.0", "Specifies when to start the vote based on rounds remaining.", _, true, 1.0);
g_Cvar_StartFrags = CreateConVar("sm_mapvote_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0);
g_Cvar_ExtendTimeMax = CreateConVar("sm_extendmap_maxtime", "90", "Specifies the maximum amount of time a map can be extended", _, true, 0.0);
g_Cvar_ExtendTimeStep = CreateConVar("sm_extendmap_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0);
g_Cvar_ExtendRoundMax = CreateConVar("sm_extendmap_maxrounds", "30", "Specfies the maximum amount of rounds a map can be extended", _, true, 0.0);
g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 5.0);
g_Cvar_ExtendFragMax = CreateConVar("sm_extendmap_maxfrags", "150", "Specfies the maximum frags allowed that a map can be extended.", _, true, 0.0);
g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0);
g_Cvar_Mapfile = CreateConVar("sm_mapvote_file", "configs/maps.ini", "Map file to use. (Def sourcemod/configs/maps.ini)");
g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0);
g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0);
g_Cvar_NoVoteMode = CreateConVar("sm_mapvote_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0);
g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "1", "Specifies whether or not MapChooser will allow the map to be extended.", _, true, 0.0, true, 1.0);
// Find game convars
g_Cvar_Chattime = FindConVar("mp_chattime");
g_Cvar_Winlimit = FindConVar("mp_winlimit");
g_Cvar_Maxrounds = FindConVar("mp_maxrounds");
g_Cvar_Fraglimit = FindConVar("mp_fraglimit");
if (GetCommandFlags("nextmap") == INVALID_FCVAR_FLAGS)
{
RegServerCmd("nextmap", Command_Nextmap);
}
// Hook events
HookEvent("round_end", Event_RoundEnd); // We always require round_end
if (g_Cvar_Fraglimit != INVALID_HANDLE)
{
HookEvent("player_death", Event_PlayerDeath);
}
// Set to the current map so OnMapStart() will know what to do
decl String:currentMap[64];
GetCurrentMap(currentMap, 64);
SetNextmap(currentMap);
// Create necessary menus for TopMenu
g_Menu_Map = CreateMenu(MenuHandler_Map);
SetMenuTitle(g_Menu_Map, "Please select a map");
SetMenuExitBackButton(g_Menu_Map, true);
g_Menu_Votemap = CreateMenu(MenuHandler_VoteMap, MenuAction_DrawItem);
SetMenuTitle(g_Menu_Votemap, "Please select a map");
SetMenuExitBackButton(g_Menu_Votemap, true);
// Bind TopMenu commands to adminmenu_maplist.ini, in cases it doesn't exist in maplists.cfg
decl String:mapListPath[PLATFORM_MAX_PATH];
BuildPath(Path_SM, mapListPath, sizeof(mapListPath), "configs/adminmenu_maplist.ini");
SetMapListCompatBind("sm_map menu", mapListPath);
SetMapListCompatBind("sm_votemap menu", mapListPath);
// Account for late loading
new Handle:topmenu;
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
{
OnAdminMenuReady(topmenu);
}
AutoExecConfig(true, "mapmanager");
}
public OnAdminMenuReady(Handle:topmenu)
{
/* Block us from being called twice */
if (topmenu == hTopMenu)
{
return;
}
/* Save the Handle */
hTopMenu = topmenu;
new TopMenuObject:server_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_SERVERCOMMANDS);
if (server_commands != INVALID_TOPMENUOBJECT)
{
AddToTopMenu(hTopMenu,
"sm_map",
TopMenuObject_Item,
AdminMenu_Map,
server_commands,
"sm_map",
ADMFLAG_CHANGEMAP);
}
new TopMenuObject:voting_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_VOTINGCOMMANDS);
if (voting_commands != INVALID_TOPMENUOBJECT)
{
AddToTopMenu(hTopMenu,
"sm_votemap",
TopMenuObject_Item,
AdminMenu_VoteMap,
voting_commands,
"sm_votemap",
ADMFLAG_VOTE|ADMFLAG_CHANGEMAP);
}
}
public OnLibraryRemoved(const String:name[])
{
if (strcmp(name, "adminmenu") == 0)
{
hTopMenu = INVALID_HANDLE;
}
}
public OnConfigsExecuted()
{
// Add map logic here
// Get the current and last maps.
decl String:lastMap[64], String:currentMap[64];
GetConVarString(g_Cvar_Nextmap, lastMap, 64);
GetCurrentMap(currentMap, 64);
// 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
// some other plugin/command), we don't want to scramble the map cycle. Or for example, admin switches to a custom map
// not in mapcyclefile. So we keep it set to the last expected nextmap. - ferret
if (strcmp(lastMap, currentMap) == 0)
{
FindAndSetNextMap();
}
// Build map menus for sm_map, sm_votemap, and RTV.
BuildMapMenu(g_Menu_Map, list);
BuildMapMenu(g_Menu_VoteMap, list);
// If the Randomize option is on, randomize!
if (GetConVarBool(g_Cvar_Randomize))
{
CreateTimer(5.0, Timer_RandomizeNextmap);
}
// If MapChooser is active, start it up!
if (GetConVarBool(g_Cvar_MapChooser))
{
SetupTimeleftTimer();
SetConVarString(g_Cvar_Nextmap, "Pending Vote");
}
// If RockTheVote is active, start it up!
if (GetConVarBool(g_Cvar_RockTheVote))
{
BuildMapMenu(g_Menu_RTV, list);
CreateTimer(30.0, Timer_DelayRTV);
}
}
// Reinitialize all our various globals
public OnMapStart()
{
if (g_Nominate != INVALID_HANDLE)
{
ClearArray(g_Nominate);
}
if (g_TeamScores != INVALID_HANDLE)
{
ClearArray(g_TeamScores);
}
g_TotalRounds = 0;
g_RTV_Voters = 0;
g_RTV_Votes = 0;
g_RTV_VotesNeeded = 0;
g_RTV_Started = false;
g_RTV_Ended = false;
}
// Reset globals as necessary and kill timers
public OnMapEnd()
{
g_IntermissionCalled = false;
g_HasVoteStarted = false;
g_RTV_Allowed = false;
if (g_VoteTimer != INVALID_HANDLE)
{
KillTimer(g_VoteTimer);
g_VoteTimer = INVALID_HANDLE;
}
if (g_RetryTimer != INVALID_HANDLE)
{
KillTimer(g_RetryTimer);
g_RetryTimer = INVALID_HANDLE;
}
}
public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
{
if (IsFakeClient(client))
{
return true;
}
// If RTV is active, deal with vote counting.
if (GetConVarBool(g_Cvar_RockTheVote))
{
g_RTV_Voted[client] = false;
g_RTV_Voters++;
g_RTV_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed));
}
// If Nominate is active, let the new client nominate
if (GetConVarBool(g_Cvar_Nominate))
{
g_Nominated[client] = false;
}
return true;
}
public OnClientDisconnect(client)
{
if (IsFakeClient(client))
{
return;
}
// If RTV is active, deal with vote counting.
if (GetConVarBool(g_Cvar_RockTheVote))
{
if(g_RTV_Voted[client])
{
g_RTV_Votes--;
}
g_RTV_Voters--;
g_RTV_VotesNeeded = RoundToFloor(float(g_RTV_Voters) * GetConVarFloat(g_Cvar_RTVLimit));
// If this client caused us to fall below the RTV threshold and its allowed be started, start it.
if (g_RTV_Votes && g_RTV_Voters && g_RTV_Votes >= g_RTV_VotesNeeded && g_RTV_Allowed && !g_RTV_Started)
{
g_RTV_Started = true;
CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE);
}
}
}
public OnMapTimeLeftChanged()
{
if (GetConVarBool(g_Cvar_MapChooser))
{
SetupTimeleftTimer();
}
}
+398
View File
@@ -0,0 +1,398 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains callbacks for commands
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
public Action:Command_Say(client, args)
{
decl String:text[192];
if (GetCmdArgString(text, sizeof(text)) < 1)
{
return Plugin_Continue;
}
new startidx;
if (text[strlen(text)-1] == '"')
{
text[strlen(text)-1] = '\0';
startidx = 1;
}
decl String:message[8];
BreakString(text[startidx], message, sizeof(message));
if (strcmp(message, "nextmap", false) == 0)
{
decl String:map[32];
GetConVarString(g_Cvar_Nextmap, map, sizeof(map));
PrintToChat(client, "%t", "Next Map", map);
}
else
{
if (GetConVarBool(g_Cvar_RockTheVote) && (strcmp(text[startidx], "rtv", false) == 0 || strcmp(text[startidx], "rockthevote", false) == 0))
{
if (g_MapChanged)
{
ReplyToCommand(client, "[SM] %t", "Map change in progress");
return Plugin_Continue;
}
if (!g_RTV_Allowed)
{
PrintToChat(client, "[SM] %t", "RTV Not Allowed");
return Plugin_Continue;
}
if (g_RTV_Ended)
{
PrintToChat(client, "[SM] %t", "RTV Ended");
return Plugin_Continue;
}
if (g_RTV_Started)
{
PrintToChat(client, "[SM] %t", "RTV Started");
return Plugin_Continue;
}
if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers) && g_RTV_Votes == 0) // Should we keep checking g_Votes here?
{
PrintToChat(client, "[SM] %t", "Minimal Players Not Met");
return Plugin_Continue;
}
if (g_RTV_Voted[client])
{
PrintToChat(client, "[SM] %t", "Already Voted");
return Plugin_Continue;
}
new String:name[64];
GetClientName(client, name, sizeof(name));
g_RTV_Votes++;
g_RTV_Voted[client] = true;
PrintToChatAll("[SM] %t", "RTV Requested", name, g_RTV_Votes, g_RTV_VotesNeeded);
if (g_RTV_Votes >= g_RTV_VotesNeeded)
{
g_RTV_Started = true;
CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE);
}
}
else if (GetConVarBool(g_Cvar_Nominate) && strcmp(text[startidx], "nominate", false) == 0)
{
if (g_MapChanged)
{
ReplyToCommand(client, "[SM] %t", "Map change in progress");
return Plugin_Continue;
}
if (g_RTV_Started || g_HasVoteStarted)
{
ReplyToCommand(client, "[SM] %t", "Map vote in progress");
return Plugin_Continue;
}
if (g_Nominated[client])
{
PrintToChat(client, "[SM] %t", "Already Nominated");
return Plugin_Continue;
}
if (GetArraySize(g_Nominate) >= GetConVarInt(g_Cvar_Maps))
{
PrintToChat(client, "[SM] %t", "Max Nominations");
return Plugin_Continue;
}
DisplayMenu(g_Menu_Nominate, client, MENU_TIME_FOREVER);
}
}
return Plugin_Continue;
}
public Action:Command_Mapvote(client, args)
{
InitiateVote();
return Plugin_Handled;
}
public Action:Command_Nextmap(args)
{
decl String:map[64];
GetConVarString(g_Cvar_Nextmap, map, sizeof(map));
ReplyToCommand(0, "%t", "Next Map", map);
return Plugin_Handled;
}
public Action:Command_List(client, args)
{
PrintToConsole(client, "Map Cycle:");
decl String:currentMap[64];
GetCurrentMap(currentMap, 64);
decl String:mapName[64];
for (new i = 0; i < GetArraySize(g_MapCycle); i++)
{
GetArrayString(g_MapCycle, i, mapName, sizeof(mapName));
if (strcmp(mapName, currentMap) == 0)
{
PrintToConsole(client, "%s <========= Current map", mapName);
}
else if (strcmp(mapName, g_NextMap) == 0)
{
PrintToConsole(client, "%s <========= Next map", mapName);
}
else
{
PrintToConsole(client, "%s", mapName);
}
}
return Plugin_Handled;
}
public Action:Command_SetNextmap(client, args)
{
if (args < 1)
{
ReplyToCommand(client, "[SM] Usage: sm_setnextmap <map>");
return Plugin_Handled;
}
if (g_MapChanged)
{
ReplyToCommand(client, "[SM] %t", "Map change in progress");
return Plugin_Handled;
}
decl String:map[64];
GetCmdArg(1, map, sizeof(map));
if (!IsMapValid(map))
{
ReplyToCommand(client, "[SM] %t", "Map was not found", map);
return Plugin_Handled;
}
ShowActivity(client, "%t", "Cvar changed", "sm_nextmap", map);
LogMessage("\"%L\" changed sm_nextmap to \"%s\"", client, map);
SetNextMap(map);
return Plugin_Handled;
}
public Action:Command_Map(client, args)
{
if (args < 1)
{
ReplyToCommand(client, "[SM] Usage: sm_map <map> [r/e]");
return Plugin_Handled;
}
if (g_MapChanged)
{
ReplyToCommand(client, "[SM] %t", "Map change in progress");
return Plugin_Handled;
}
decl String:map[64];
GetCmdArg(1, map, sizeof(map));
if (!IsMapValid(map))
{
ReplyToCommand(client, "[SM] %t", "Map was not found", map);
return Plugin_Handled;
}
decl String:when[2];
if (args > 1)
{
GetCmdArg(2, when, sizeof(when));
when[0] = CharToLower(when[0]);
if (when[0] != 'r' && when[0] != 'e')
{
when[0] = 'i';
}
}
SetMapChange(client, map, when);
return Plugin_Handled;
}
public Action:Command_Votemap(client, args)
{
if (args < 1)
{
ReplyToCommand(client, "[SM] Usage: sm_votemap [r/e] <mapname> [mapname2] ... [mapname5]");
return Plugin_Handled;
}
if (g_MapChanged)
{
ReplyToCommand(client, "[SM] %t", "Map change in progress");
return Plugin_Handled;
}
if (IsVoteInProgress())
{
ReplyToCommand(client, "[SM] %t", "Vote in Progress");
return Plugin_Handled;
}
if (!TestVoteDelay(client))
{
return Plugin_Handled;
}
decl String:text[256];
GetCmdArgString(text, sizeof(text));
decl String:maps[5][64];
new mapCount;
new len, pos;
// Find out if the user specified "when"
decl String:when[64];
pos = BreakString(text[len], when, sizeof(when));
if (!IsMapValid(when))
{
when[0] = CharToLower(when[0]);
if (when[0] != 'r' && when[0] != 'e')
{
ReplyToCommand(client, "[SM] %t", "Map was not found", maps[mapCount]);
return Plugin_Handled;
}
}
else
{
strcpy(maps[mapCount], sizeof(maps[]), when);
mapCount++;
when[0] = 'i';
}
len += pos;
while (pos != -1 && mapCount < 5)
{
pos = BreakString(text[len], maps[mapCount], sizeof(maps[]));
if (!IsMapValid(maps[mapCount]))
{
ReplyToCommand(client, "[SM] %t", "Map was not found", maps[mapCount]);
return Plugin_Handled;
}
mapCount++;
len += pos;
}
g_VoteMapInUse = client;
g_Client_Data[client][0] = when[0];
DisplayVoteMapMenu(client, mapCount, maps);
return Plugin_Handled;
}
public Action:Command_Nominate(client, args)
{
if (args < 1)
{
ReplyToCommand(client, "[SM] Usage: sm_nominate <mapname>");
return Plugin_Handled;
}
if (!GetConVarBool(g_Cvar_Nominate))
{
ReplyToCommand(client, "[SM] Nominations are currently disabled.");
return Plugin_Handled;
}
decl String:mapname[64];
GetCmdArg(1, mapname, sizeof(mapname));
if (FindStringInArray(g_MapList, mapname) == -1)
{
ReplyToCommand(client, "%t", "Map was not found", mapname);
return Plugin_Handled;
}
if (GetArraySize(g_Nominated) > 0)
{
if (FindStringInArray(g_Nominated, mapname) != -1)
{
ReplyToCommand(client, "%t", "Map Already In Vote", mapname);
return Plugin_Handled;
}
ShiftArrayUp(g_Nominated, 0);
SetArrayString(g_Nominated, 0, mapname);
while (GetArraySize(g_Nominated) > GetConVarInt(g_Cvar_Maps))
{
RemoveFromArray(g_Nominated, GetConVarInt(g_Cvar_Maps));
}
}
else
{
PushArrayString(g_Nominated, mapname);
}
decl String:item[64];
for (new i = 0; i < GetMenuItemCount(g_Menu_Nominate); i++)
{
GetMenuItem(g_Menu_Nominate, i, item, sizeof(item));
if (strcmp(item, mapname) == 0)
{
RemoveMenuItem(g_Menu_Nominate, i);
break;
}
}
ReplyToCommand(client, "%t", "Map Inserted", mapname);
LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname);
return Plugin_Handled;
}
+166
View File
@@ -0,0 +1,166 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains event callbacks
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
public Action:UserMsg_VGUIMenu(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init)
{
if (g_IntermissionCalled)
{
return Plugin_Handled;
}
decl String:type[15];
/* If we don't get a valid string, bail out. */
if (BfReadString(bf, type, sizeof(type)) < 0)
{
return Plugin_Handled;
}
if (BfReadByte(bf) == 1 && BfReadByte(bf) == 0 && (strcmp(type, "scores", false) == 0))
{
g_IntermissionCalled = true;
decl String:map[32];
new Float:fChatTime = GetConVarFloat(g_Cvar_Chattime);
if (fChatTime < 2.0)
{
SetConVarFloat(g_Cvar_Chattime, 2.0);
}
LogMessage("[MapManager] Changing map to '%s' due to map ending.", g_NextMap);
g_MapChanged = true;
CreateTimer(fChatTime - 1.0, Timer_ChangeMap);
}
return Plugin_Handled;
}
public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
if (g_MapChanged)
{
return;
}
if (g_MapChangeSet && g_MapChangeWhen == 'r')
{
LogMessage("[MapManager] Changing map to '%s' due to round ending.", g_NextMap);
g_MapChanged = true;
CreateTimer(1.0, Timer_ChangeMap);
return;
}
if (g_HasVoteStarted)
{
return;
}
new winner = GetEventInt(event, "winner");
if (winner == 0 || winner == 1)
{
return;
}
g_TotalRounds++;
new team[2], teamPos = -1;
for (new i; i < GetArraySize(g_TeamScores); i++)
{
GetArrayArray(g_TeamScores, i, team);
if (team[0] == winner)
{
teamPos = i;
break;
}
}
if (teamPos == -1)
{
team[0] = winner;
team[1] = 1;
PushArrayArray(g_TeamScores, team);
}
else
{
team[1]++;
SetArrayArray(g_TeamScores, teamPos, team);
}
if (g_Cvar_Winlimit != INVALID_HANDLE)
{
new winlimit = GetConVarInt(g_Cvar_Winlimit);
if (winlimit)
{
if (team[1] >= (winlimit - GetConVarInt(g_Cvar_StartRounds)))
{
InitiateVote();
}
}
}
if (g_Cvar_Maxrounds != INVALID_HANDLE)
{
new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
if (maxrounds)
{
if (g_TotalRounds >= (maxrounds - GetConVarInt(g_Cvar_StartRounds)))
{
InitiateVote();
}
}
}
}
public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
if (g_MapChanged || g_HasVoteStarted || g_Cvar_Fraglimit == INVALID_HANDLE)
{
return;
}
if (!GetConVarInt(g_Cvar_Fraglimit))
{
return;
}
new fragger = GetClientOfUserId(GetEventInt(event, "attacker"));
if (fragger && GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags)))
{
InitiateVote();
}
}
+335
View File
@@ -0,0 +1,335 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Management Plugin
* Contains misc functions.
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
SetNextMap(String:map[])
{
strcopy(g_NextMap, sizeof(g_NextMap), map);
SetConVarString(g_Cvar_Nextmap, map);
}
SetMapChange(client, map, when, Float:time = 3.0)
{
g_MapChangeSet = true;
g_MapChangeWhen = when[0];
SetNextMap(map);
if (when[0] == 'r')
{
ShowActivity2(client, "[SM] ", "%t", "Changing map end of round", map);
LogAction(client, -1, "\"%L\" set end of round map change to \"%s\"", client, map);
}
else if (when[0] == 'e')
{
ShowActivity2(client, "[SM] ", "%t", "Set nextmap", map);
LogAction(client, -1, "\"%L\" set the next map to \"%s\"", client, map);
}
else
{
ShowActivity2(client, "[SM] ", "%t", "Change map", map);
LogAction(client, -1, "\"%L\" changed map to \"%s\"", client, map);
g_MapChanged = true;
CreateTimer(3.0, Timer_ChangeMap);
}
}
FindAndSetNextMap()
{
if (ReadMapList(g_MapList,
g_MapListSerial,
"mapcyclefile",
MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT)
== INVALID_HANDLE)
{
if (g_MapListSerial == -1)
{
LogError("FATAL: Cannot load map cycle. Nextmap not loaded.");
SetFailState("Mapcycle Not Found");
}
}
new mapCount = GetArraySize(g_MapList);
decl String:mapName[32];
if (g_MapPos == -1)
{
decl String:current[64];
GetCurrentMap(current, 64);
for (new i = 0; i < mapCount; i++)
{
GetArrayString(g_MapList, i, mapName, sizeof(mapName));
if (strcmp(current, mapName, false) == 0)
{
g_MapPos = i;
break;
}
}
if (g_MapPos == -1)
g_MapPos = 0;
}
g_MapPos++;
if (g_MapPos >= mapCount)
g_MapPos = 0;
GetArrayString(g_MapList, g_MapPos, mapName, sizeof(mapName));
SetConVarString(g_Cvar_Nextmap, mapName);
}
Float:GetVotePercent(votes, totalVotes)
{
return FloatDiv(float(votes),float(totalVotes));
}
bool:TestVoteDelay(client)
{
new delay = CheckVoteDelay();
if (delay > 0)
{
if (delay > 60)
{
ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
}
else
{
ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);
}
return false;
}
return true;
}
BuildMapMenu()
{
if (g_MapMenu != INVALID_HANDLE)
{
CloseHandle(g_MapMenu);
g_MapMenu = INVALID_HANDLE;
}
g_MapMenu = CreateMenu(Handler_MapSelectMenu);
SetMenuTitle(g_MapMenu, "%t", "Nominate Title");
decl String:map[64];
for (new i = 0; i < GetArraySize(g_MapList); i++)
{
GetArrayString(g_MapList, i, map, sizeof(map));
AddMenuItem(g_MapMenu, map, map);
}
SetMenuExitButton(g_MapMenu, false);
}
SetupTimeleftTimer()
{
new time;
if (GetMapTimeLeft(time) && time > 0)
{
new startTime = GetConVarInt(g_Cvar_StartTime) * 60;
if (time - startTime < 0)
{
InitiateVote();
}
else
{
if (g_VoteTimer != INVALID_HANDLE)
{
KillTimer(g_VoteTimer);
g_VoteTimer = INVALID_HANDLE;
}
g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVote);
}
}
}
InitiateVote()
{
if (g_HasVoteStarted || g_RetryTimer != INVALID_HANDLE)
{
return;
}
if (IsVoteInProgress())
{
// Can't start a vote, try again in 5 seconds.
g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote);
return;
}
g_HasVoteStarted = true;
g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
SetMenuTitle(g_VoteMenu, "Vote Nextmap");
decl String:map[32];
for (new i = 0; i < GetArraySize(g_NextMapList); i++)
{
GetArrayString(g_NextMapList, i, map, sizeof(map));
AddMenuItem(g_VoteMenu, map, map);
}
if (GetConVarBool(g_Cvar_Extend))
{
new bool:allowExtend, time;
if (GetMapTimeLimit(time) && time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax))
{
allowExtend = true;
}
if (g_Cvar_Winlimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Winlimit) < GetConVarInt(g_Cvar_ExtendRoundMax))
{
allowExtend = true;
}
if (g_Cvar_Maxrounds != INVALID_HANDLE && GetConVarInt(g_Cvar_Maxrounds) < GetConVarInt(g_Cvar_ExtendRoundMax))
{
allowExtend = true;
}
if (g_Cvar_Fraglimit != INVALID_HANDLE && GetConVarInt(g_Cvar_Fraglimit) < GetConVarInt(g_Cvar_ExtendFragMax))
{
allowExtend = true;
}
if (allowExtend)
{
AddMenuItem(g_VoteMenu, VOTE_EXTEND, "Extend Map");
}
}
SetMenuExitButton(g_VoteMenu, false);
VoteMenuToAll(g_VoteMenu, 20);
LogMessage("Voting for next map has started.");
PrintToChatAll("[SM] %t", "Nextmap Voting Started");
}
SetNextMap(const String:map[])
{
SetConVarString(g_Cvar_Nextmap, map);
PushArrayString(g_OldMapList, map);
if (GetArraySize(g_OldMapList) > GetConVarInt(g_Cvar_ExcludeMaps))
{
RemoveFromArray(g_OldMapList, 0);
}
PrintToChatAll("[SM] %t", "Nextmap Voting Finished", map);
LogMessage("Voting for next map has finished. Nextmap: %s.", map);
}
CreateNextVote()
{
if(g_NextMapList != INVALID_HANDLE)
{
ClearArray(g_NextMapList);
}
decl String:map[32];
new index, Handle:tempMaps = CloneArray(g_MapList);
GetCurrentMap(map, sizeof(map));
index = FindStringInArray(tempMaps, map);
if (index != -1)
{
RemoveFromArray(tempMaps, index);
}
if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps))
{
for (new i = 0; i < GetArraySize(g_OldMapList); i++)
{
GetArrayString(g_OldMapList, i, map, sizeof(map));
index = FindStringInArray(tempMaps, map);
if (index != -1)
{
RemoveFromArray(tempMaps, index);
}
}
}
new limit = (GetConVarInt(g_Cvar_IncludeMaps) < GetArraySize(tempMaps) ? GetConVarInt(g_Cvar_IncludeMaps) : GetArraySize(tempMaps));
for (new i = 0; i < limit; i++)
{
new b = GetRandomInt(0, GetArraySize(tempMaps) - 1);
GetArrayString(tempMaps, b, map, sizeof(map));
PushArrayString(g_NextMapList, map);
RemoveFromArray(tempMaps, b);
}
CloseHandle(tempMaps);
}
/*
new Handle:g_map_array = INVALID_HANDLE;
new g_map_serial = -1;
LoadMapList(Handle:menu)
{
new Handle:map_array;
if ((map_array = ReadMapList(g_map_array,
g_map_serial,
"sm_map menu",
MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT|MAPLIST_FLAG_MAPSFOLDER))
!= INVALID_HANDLE)
{
g_map_array = map_array;
}
if (g_map_array == INVALID_HANDLE)
{
return 0;
}
RemoveAllMenuItems(menu);
decl String:map_name[64];
new map_count = GetArraySize(g_map_array);
for (new i = 0; i < map_count; i++)
{
GetArrayString(g_map_array, i, map_name, sizeof(map_name));
AddMenuItem(menu, map_name, map_name);
}
return map_count;
}
*/
+115
View File
@@ -0,0 +1,115 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Management Plugin
* Contains misc functions.
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
DisplayWhenMenu(client, bool:vote = false)
{
new Handle:
if (!vote)
{
menu = CreateMenu(MenuHandler_ChangeMap);
}
else
{
menu = CreateMenu(MenuHandler_VoteWhen);
}
decl String:title[100];
Format(title, sizeof(title), "%T:", "Map Change When", client);
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddMenuItem(menu, "i", "Immediately");
AddMenuItem(menu, "r", "Round End");
AddMenuItem(menu, "e", "Map End");
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
DisplayConfirmVoteMenu(client)
{
new Handle:menu = CreateMenu(MenuHandler_Confirm);
decl String:title[100];
Format(title, sizeof(title), "%T:", "Confirm Vote", client);
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddMenuItem(menu, "Confirm", "Start the Vote");
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
DisplayAcceptVoteMenu(String:map[])
{
new Handle:menu = CreateMenu(MenuHandler_Accept);
decl String:title[100];
Format(title, sizeof(title), "%T:", "Accept Vote", client);
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddMenuItem(menu, map, "Accept Vote");
DisplayMenu(menu, g_VoteMapInUse, MENU_TIME_FOREVER);
}
DisplayVoteMapMenu(client, mapCount, String:maps[5][])
{
LogAction(client, -1, "\"%L\" initiated a map vote.", client);
ShowActivity2(client, "[SM] ", "%t", "Initiated Vote Map");
new Handle:menu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
if (mapCount == 1)
{
//strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), maps[0]);
SetMenuTitle(menu, "Change Map To");
AddMenuItem(menu, maps[0], "Yes");
AddMenuItem(menu, VOTE_NO, "No");
}
else
{
//g_voteInfo[VOTE_NAME][0] = '\0';
SetMenuTitle(menu, "Map Vote");
for (new i = 0; i < mapCount; i++)
{
AddMenuItem(menu, maps[i], maps[i]);
}
}
SetMenuExitButton(menu, false);
VoteMenuToAll(menu, 20);
}
+104
View File
@@ -0,0 +1,104 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains globals and defines
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#define VOTE_EXTEND "##extend##"
#define VOTE_YES "###yes###"
#define VOTE_NO "###no###"
new Handle:hTopMenu = INVALID_HANDLE; // TopMenu
new Handle:g_MapCycle = INVALID_HANDLE; // mapcyclefile maps
new Handle:g_MapList = INVALID_HANDLE; // maplist.txt maps
new Handle:g_MapHistory = INVALID_HANDLE; // History of maps played
new Handle:g_NextVoteMaps = INVALID_HANDLE; // Array of maps for next RTV or MC vote
new Handle:g_NominatedMaps = INVALID_HANDLE; // Array of maps that have been nominated
new Handle:g_Menu_Map = INVALID_HANDLE; // Menu of maps used by sm_map in admin menu
new Handle:g_Menu_Votemap = INVALID_HANDLE; // Menu of maps used by sm_votemap in admin menu
new Handle:g_Menu_Nominate = INVALID_HANDLE; // Menu of maps used by Nomination system
new Handle:g_SelectedMaps; // List of maps chosen so far by a user in sm_votemap admin menu
new g_VoteMapInUse; // Client index of admin using sm_votemap
new String:g_Client_Data[MAXCLIENTS+1][64]; // Used to hold bits of client data during sm_votemap
new bool:g_MapChangeSet; // True if a command or vote has set the map
new bool:g_MapChanged; // True if a map change has been issued
new g_MapChangeWhen; // Either 'i' for immediate, 'r' for round end, or 'e' for end of map.
new UserMsg:g_VGUIMenu; // VGUI usermsg id for nextmap
new bool:g_NextMapEnabled = true // If set to false, all features requiring nextmap are disabled.
new bool:g_IntermissionCalled; // Has the end of map intermission begun?
new String:g_NextMap[64]; // All important! This is the next map!
new g_MapPos = -1; // Position in mapcycle
new bool:g_RTV_Voted[MAXPLAYERS+1] = {false, ...}; // Whether or not a player has voted for RTV
new bool:g_RTV_Allowed = false; // True if RTV is available to players. Used to delay rtv votes.
new bool:g_RTV_Started = false; // Indicates that the actual map vote has started
new bool:g_RTV_Ended = false; // Indicates that the actual map vote has concluded
new g_RTV_Voters = 0; // Total voters connected. Doesn't include fake clients.
new g_RTV_Votes = 0; // Total number of "say rtv" votes
new g_RTV_VotesNeeded = 0; // Necessary votes before map vote begins. (voters * percent_needed)
new bool:g_Nominated[MAXPLAYERS+1] = {false, ...}; // Whether or not a player has nominated a map
new Handle:g_TeamScores = INVALID_HANDLE; // Array of team scores
new g_TotalRounds; // Total rounds played this map
new bool:g_HasVoteStarted; // Whether or not MapChooser has begun
// ConVar handles
new Handle:g_Cvar_NextMap = INVALID_HANDLE;
new Handle:g_Cvar_VoteMap = INVALID_HANDLE;
new Handle:g_Cvar_Excludes = INVALID_HANDLE;
new Handle:g_Cvar_StartTime = INVALID_HANDLE;
new Handle:g_Cvar_StartRounds = INVALID_HANDLE;
new Handle:g_Cvar_StartFrags = INVALID_HANDLE;
new Handle:g_Cvar_ExtendTimeMax = INVALID_HANDLE;
new Handle:g_Cvar_ExtendTimeStep = INVALID_HANDLE;
new Handle:g_Cvar_ExtendRoundMax = INVALID_HANDLE;
new Handle:g_Cvar_ExtendRoundStep = INVALID_HANDLE;
new Handle:g_Cvar_ExtendFragMax = INVALID_HANDLE;
new Handle:g_Cvar_ExtendFragStep = INVALID_HANDLE;
new Handle:g_Cvar_Mapfile = INVALID_HANDLE;
new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE;
new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE;
new Handle:g_Cvar_NoVoteMode = INVALID_HANDLE;
new Handle:g_Cvar_Extend = INVALID_HANDLE;
new Handle:g_VoteTimer = INVALID_HANDLE;
new Handle:g_RetryTimer = INVALID_HANDLE;
// VALVe ConVars
new Handle:g_Cvar_Chattime = INVALID_HANDLE;
new Handle:g_Cvar_Winlimit = INVALID_HANDLE;
new Handle:g_Cvar_Maxrounds = INVALID_HANDLE;
new Handle:g_Cvar_Fraglimit = INVALID_HANDLE;
+263
View File
@@ -0,0 +1,263 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains menu callbacks
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
// Following callbacks are for sm_map
public AdminMenu_Map(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength)
{
if (action == TopMenuAction_DisplayOption)
{
Format(buffer, maxlength, "%T", "Choose Map", param);
}
else if (action == TopMenuAction_SelectOption)
{
DisplayMenu(g_Menu_Map, param, MENU_TIME_FOREVER);
}
}
public MenuHandler_Map(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_Cancel)
{
if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
{
DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory);
}
}
else if (action == MenuAction_Select)
{
GetMenuItem(menu, param2, g_Client_Data[param1], sizeof(g_Client_Data[]));
DisplayWhenMenu(param1);
}
}
public MenuHandler_ChangeMap(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_Cancel)
{
if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
{
DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory);
}
}
else if (action == MenuAction_Select)
{
decl String:when[2];
GetMenuItem(menu, param2, when, sizeof(when));
SetMapChange(client, g_Client_Data[param1], when[0])
}
}
// Following callbacks are for sm_votemap
public AdminMenu_VoteMap(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength)
{
if (action == TopMenuAction_DisplayOption)
{
Format(buffer, maxlength, "%T", "Map vote", param);
}
else if (action == TopMenuAction_SelectOption)
{
g_VoteMapInUse = param;
ClearArray(g_SelectedMaps);
DisplayMenu(g_Menu_Votemap, param, MENU_TIME_FOREVER);
}
else if (action == TopMenuAction_DrawOption)
{
/* disable this option if a vote is already running, theres no maps listed or someone else has already accessed this menu */
buffer[0] = (!IsNewVoteAllowed() || g_VoteMapInUse) ? ITEMDRAW_IGNORE : ITEMDRAW_DEFAULT;
}
}
public MenuHandler_VoteMap(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_Cancel)
{
if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
{
DisplayWhenMenu(param1, true);
}
else // no action was selected.
{
/* Re-enable the menu option */
g_VoteMapInUse = 0;
}
}
else if (action == MenuAction_DrawItem)
{
decl String:info[32];
GetMenuItem(menu, param2, info, sizeof(info));
if (FindStringInArray(g_SelectedMaps, info) != -1)
{
return ITEMDRAW_IGNORE;
}
else
{
return ITEMDRAW_DEFAULT;
}
}
else if (action == MenuAction_Select)
{
decl String:info[32];
GetMenuItem(menu, param2, info, sizeof(info));
PushArrayString(g_SelectedMaps, info);
/* Redisplay the list */
if (GetArraySize(g_SelectedMaps) < 5)
{
DisplayMenu(g_MapList, param1, MENU_TIME_FOREVER);
}
else
{
DisplayWhenMenu(param1, true);
}
}
return 0;
}
public MenuHandler_VoteWhen(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
else if (action == MenuAction_Cancel)
{
if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
{
g_Menu_Info[param1][0] = 'i';
DisplayConfirmVoteMenu(param1);
}
else
{
g_VoteMapInUse = 0;
}
}
else if (action == MenuAction_Select)
{
GetMenuItem(menu, param2, g_Menu_Info[param1], sizeof(g_Menu_Info[]));
DisplayConfirmVoteMenu(param1);
}
}
public MenuHandler_Confirm(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
else if (action == MenuAction_Cancel)
{
g_VoteMapInUse = 0;
if (param2 == MenuCancel_ExitBack && hTopMenu != INVALID_HANDLE)
{
DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory);
}
}
else if (action == MenuAction_Select)
{
decl String:maps[5][64];
new selectedmaps = GetArraySize(g_SelectedMaps);
for (new i = 0; i < selectedmaps; i++)
{
GetArrayString(g_SelectedMaps, i, maps[i], sizeof(maps[]));
}
DisplayVoteMapMenu(param1, selectedmaps, maps);
}
}
public MenuHandler_Accept(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
g_VoteMapInUse = 0;
}
else if (action == MenuAction_Select)
{
decl String:map[64]
GetMenuItem(menu, 1, map, sizeof(map));
SetMapChange(param1, map, g_Client_Data[param1][0])
}
}
public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2)
{
switch (action)
{
case MenuAction_Select:
{
if (GetArraySize(g_RTVMapList) >= GetConVarInt(g_Cvar_Maps))
{
PrintToChat(param1, "[SM] %t", "Max Nominations");
return;
}
decl String:map[64], String:name[64];
GetMenuItem(menu, param2, map, sizeof(map));
if (FindStringInArray(g_RTVMapList, map) != -1)
{
PrintToChat(param1, "[SM] %t", "Map Already Nominated");
return;
}
GetClientName(param1, name, 64);
PushArrayString(g_RTVMapList, map);
RemoveMenuItem(menu, param2);
g_Nominated[param1] = true;
PrintToChatAll("[SM] %t", "Map Nominated", name, map);
}
}
}
+166
View File
@@ -0,0 +1,166 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains timer callbacks
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
public Action:Timer_ChangeMap(Handle:timer)
{
ServerCommand("changelevel \"%s\"", g_NextMap);
PushArrayString(g_MapHistory, g_NextMap);
return Plugin_Stop;
}
public Action:Timer_RandomizeNextmap(Handle:timer)
{
decl String:map[64];
new exclusion = GetConVarInt(g_Cvar_ExcludeMaps);
if (exclusion > GetArraySize(g_MapCycle))
{
exclusion = GetArraySize(g_MapCycle) - 1;
}
new b = GetRandomInt(0, GetArraySize(g_MapCycle) - 1);
GetArrayString(g_MapCycle, b, map, sizeof(map));
while (FindStringInArray(g_MapHistory, map) != -1)
{
b = GetRandomInt(0, GetArraySize(g_MapCycle) - 1);
GetArrayString(g_MapCycle, b, map, sizeof(map));
}
SetNextmap(map);
LogMessage("[MapManager] Randomizer has chosen '%s' as the next map.", map);
return Plugin_Stop;
}
public Action:Timer_DelayRTV(Handle:timer)
{
g_RTVAllowed = true;
g_RTVStarted = false;
g_RTVEnded = false;
}
public Action:Timer_StartRTV(Handle:timer)
{
if (timer == g_RetryTimer)
{
g_RetryTimer = INVALID_HANDLE;
}
if (g_RetryTimer != INVALID_HANDLE)
{
return;
}
if (IsVoteInProgress())
{
// Can't start a vote, try again in 5 seconds.
g_RetryTimer = CreateTimer(5.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE);
return;
}
PrintToChatAll("[SM] %t", "RTV Vote Ready");
new Handle:MapVoteMenu = CreateMenu(Handler_MapMapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
SetMenuTitle(MapVoteMenu, "Rock The Vote");
new Handle:tempMaps = CloneArray(g_MapList);
decl String:map[32];
GetCurrentMap(map, sizeof(map));
new index = FindStringInArray(tempMaps, map);
if (index != -1)
{
RemoveFromArray(tempMaps, index);
}
// We assume that g_RTVMapList is within the correct limits, based on the logic for nominations
for (new i = 0; i < GetArraySize(g_RTVMapList); i++)
{
GetArrayString(g_RTVMapList, i, map, sizeof(map));
AddMenuItem(MapVoteMenu, map, map);
index = FindStringInArray(tempMaps, map);
if (index != -1)
{
RemoveFromArray(tempMaps, index);
}
}
new limit = GetConVarInt(g_Cvar_Maps) - GetArraySize(g_RTVMapList);
if (limit > GetArraySize(tempMaps))
{
limit = GetArraySize(tempMaps);
}
for (new i = 0; i < limit; i++)
{
new b = GetRandomInt(0, GetArraySize(tempMaps) - 1);
GetArrayString(tempMaps, b, map, sizeof(map));
PushArrayString(g_RTVMapList, map);
AddMenuItem(MapVoteMenu, map, map);
RemoveFromArray(tempMaps, b);
}
CloseHandle(tempMaps);
AddMenuItem(MapVoteMenu, "Don't Change", "Don't Change");
SetMenuExitButton(MapVoteMenu, false);
VoteMenuToAll(MapVoteMenu, 20);
LogMessage("[SM] Rockthevote was successfully started.");
}
public Action:Timer_StartMapVote(Handle:timer)
{
if (!GetArraySize(g_MapList))
{
return Plugin_Stop;
}
if (timer == g_RetryTimer)
{
g_RetryTimer = INVALID_HANDLE;
}
else
{
g_VoteTimer = INVALID_HANDLE;
}
InitiateVote();
return Plugin_Stop;
}
+318
View File
@@ -0,0 +1,318 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Manager Plugin
* Contains vote callbacks
*
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
// sm_votemap
public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
else if (action == MenuAction_Display)
{
decl String:title[64];
GetMenuTitle(menu, title, sizeof(title));
decl String:map[64];
GetMenuItem(menu, 1, map, sizeof(map));
decl String:buffer[255];
Format(buffer, sizeof(buffer), "%T", title, param1, map);
new Handle:panel = Handle:param2;
SetPanelTitle(panel, buffer);
}
else if (action == MenuAction_DisplayItem)
{
decl String:display[64];
GetMenuItem(menu, param2, "", 0, _, display, sizeof(display));
if (strcmp(display, "No") == 0 || strcmp(display, "Yes") == 0)
{
decl String:buffer[255];
Format(buffer, sizeof(buffer), "%T", display, param1);
return RedrawMenuItem(buffer);
}
}
else if (action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes)
{
PrintToChatAll("[SM] %t", "No Votes Cast");
}
else if (action == MenuAction_VoteEnd)
{
decl String:item[64], String:display[64];
new Float:percent, Float:limit, votes, totalVotes;
GetMenuVoteInfo(param2, votes, totalVotes);
GetMenuItem(menu, param1, item, sizeof(item), _, display, sizeof(display));
if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
{
votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
}
percent = GetVotePercent(votes, totalVotes);
limit = GetConVarFloat(g_Cvar_VoteMap);
// A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
{
LogAction(-1, -1, "Vote failed.");
PrintToChatAll("[SM] %t", "Votemap Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
}
else
{
PrintToChatAll("[SM] %t", "Votemap Successful", RoundToNearest(100.0*percent), totalVotes);
if (g_VoteMapInUse && IsClientInGame(g_VoteMapInUse))
{
DisplayAcceptVoteMenu(item);
}
else
{
LogAction(-1, -1, "Changing map to %s due to vote.", item);
PrintToChatAll("[SM] %t", "Changing map", item);
SetMapChange(0, item, g_Client_Data[g_VoteMapInUse][0])
}
}
}
return 0;
}
public Handler_MapMapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
{
switch (action)
{
case MenuAction_End:
{
CloseHandle(menu);
}
case MenuAction_Display:
{
decl String:oldTitle[255], String:buffer[255];
GetMenuTitle(menu, oldTitle, sizeof(oldTitle));
Format(buffer, sizeof(buffer), "%T", oldTitle, param1);
new Handle:panel = Handle:param2;
SetPanelTitle(panel, buffer);
}
case MenuAction_DisplayItem:
{
if (GetMenuItemCount(menu) - 1 == param2)
{
decl String:buffer[255];
Format(buffer, sizeof(buffer), "%T", "Don't Change", param1);
return RedrawMenuItem(buffer);
}
}
// Why am I commented out? Because BAIL hasn't decided yet if
// vote notification will be built into the Vote API.
/*case MenuAction_Select:
{
decl String:Name[32], String:Map[32];
GetClientName(param1, Name, sizeof(Name));
GetMenuItem(menu, param2, Map, sizeof(Map));
PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map);
}*/
case MenuAction_VoteCancel:
{
if (param1 == VoteCancel_NoVotes)
{
PrintToChatAll("[SM] %t", "No Votes");
g_RTVEnded = true;
}
}
case MenuAction_VoteEnd:
{
new String:map[64];
GetMenuItem(menu, param1, map, sizeof(map));
if (GetMenuItemCount(menu) - 1 == param1) // This should always match the "Keep Current" option
{
PrintToChatAll("[SM] %t", "Current Map Stays");
LogMessage("[SM] Rockthevote has ended, current map kept.");
}
else
{
PrintToChatAll("[SM] %t", "Changing Maps", map);
LogMessage("[SM] Rockthevote has ended, changing to map %s.", map);
new Handle:dp;
CreateDataTimer(5.0, Timer_ChangeMap, dp);
WritePackString(dp, map);
}
g_RTVEnded = true;
}
}
return 0;
}
public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
{
switch (action)
{
case MenuAction_End:
{
g_VoteMenu = INVALID_HANDLE;
CloseHandle(menu);
}
case MenuAction_Display:
{
decl String:buffer[255];
Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1);
new Handle:panel = Handle:param2;
SetPanelTitle(panel, buffer);
}
case MenuAction_DisplayItem:
{
if (GetMenuItemCount(menu) - 1 == param2)
{
decl String:map[64], String:buffer[255];
GetMenuItem(menu, param2, map, sizeof(map));
if (strcmp(map, VOTE_EXTEND, false) == 0)
{
Format(buffer, sizeof(buffer), "%T", "Extend Map", param1);
return RedrawMenuItem(buffer);
}
}
}
// Why am I commented out? Because BAIL hasn't decided yet if
// vote notification will be built into the Vote API.
/*case MenuAction_Select:
{
decl String:Name[32], String:Map[32];
GetClientName(param1, Name, sizeof(Name));
GetMenuItem(menu, param2, Map, sizeof(Map));
PrintToChatAll("[SM] %s has voted for map '%s'", Name, Map);
}*/
case MenuAction_VoteCancel:
{
// If we receive 0 votes, pick at random.
if (param1 == VoteCancel_NoVotes && GetConVarBool(g_Cvar_NoVoteMode))
{
new count = GetMenuItemCount(menu);
new item = GetRandomInt(0, count - 1);
decl String:map[32];
GetMenuItem(menu, item, map, sizeof(map));
while (strcmp(map, VOTE_EXTEND, false) == 0)
{
item = GetRandomInt(0, count - 1);
GetMenuItem(menu, item, map, sizeof(map));
}
SetNextMap(map);
}
else
{
// We were actually cancelled. What should we do?
}
}
case MenuAction_VoteEnd:
{
decl String:map[32];
GetMenuItem(menu, param1, map, sizeof(map));
if (strcmp(map, VOTE_EXTEND, false) == 0)
{
new time;
if (GetMapTimeLimit(time))
{
if (time > 0 && time < GetConVarInt(g_Cvar_ExtendTimeMax))
{
ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60);
}
}
if (g_Cvar_Winlimit != INVALID_HANDLE)
{
new winlimit = GetConVarInt(g_Cvar_Winlimit);
if (winlimit && winlimit < GetConVarInt(g_Cvar_ExtendRoundMax))
{
SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep));
}
}
if (g_Cvar_Maxrounds != INVALID_HANDLE)
{
new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
if (maxrounds && maxrounds < GetConVarInt(g_Cvar_ExtendRoundMax))
{
SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep));
}
}
if (g_Cvar_Fraglimit != INVALID_HANDLE)
{
new fraglimit = GetConVarInt(g_Cvar_Fraglimit);
if (fraglimit && fraglimit < GetConVarInt(g_Cvar_ExtendFragMax))
{
SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep));
}
}
PrintToChatAll("[SM] %t", "Current Map Extended");
LogMessage("Voting for next map has finished. The current map has been extended.");
// We extended, so we'll have to vote again.
g_HasVoteStarted = false;
CreateNextVote();
SetupTimeleftTimer();
}
else
{
SetNextMap(map);
}
}
}
return 0;
}
+28
View File
@@ -0,0 +1,28 @@
#include <sourcemod>
public OnPluginStart()
{
RegServerCmd("test_goto", Test_Goto);
}
public Action:Test_Goto(args)
{
new bool:hello = false;
new String:crab[] = "space crab";
sample_label:
new String:yam[] = "yams";
PrintToServer("%s %s", crab, yam);
if (!hello)
{
new bool:what = true;
hello = what
goto sample_label;
}
return Plugin_Handled;
}