merged trunk back into 1.1.0 branch for "safety"

--HG--
branch : sourcemod-1.1.0
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.1.0%401721
This commit is contained in:
David Anderson
2007-11-23 05:10:33 +00:00
parent 0601988e80
commit 3f49d29274
75 changed files with 3382 additions and 2175 deletions
+5 -17
View File
@@ -50,7 +50,6 @@ new String:g_ColorNames[13][10] = {"White", "Red", "Green", "Blue", "Yellow", "P
new g_Colors[13][3] = {{255,255,255},{255,0,0},{0,255,0},{0,0,255},{255,255,0},{255,0,255},{0,255,255},{255,128,0},{255,0,128},{128,255,0},{0,255,128},{128,0,255},{0,128,255}};
new Handle:g_Cvar_Chatmode = INVALID_HANDLE;
new Handle:g_Cvar_Psaymode = INVALID_HANDLE;
new bool:g_DoColor = true;
@@ -59,7 +58,6 @@ public OnPluginStart()
LoadTranslations("common.phrases");
g_Cvar_Chatmode = CreateConVar("sm_chat_mode", "1", "Allows player's to send messages to admin chat.", 0, true, 0.0, true, 1.0);
g_Cvar_Psaymode = CreateConVar("sm_psay_mode", "0", "Allows player's to use psay 'say @@' alias.", 0, true, 0.0, true, 1.0);
RegConsoleCmd("say", Command_SayChat);
RegConsoleCmd("say_team", Command_SayAdmin);
@@ -114,17 +112,17 @@ public Action:Command_SayChat(client, args)
decl String:name[64];
GetClientName(client, name, sizeof(name));
if (msgStart == 1 && CheckAdminForChat(client)) // sm_say alias
if (msgStart == 1 && CheckCommandAccess(client, "sm_say", ADMFLAG_CHAT)) // sm_say alias
{
SendChatToAll(name, message);
LogAction(client, -1, "%L triggered sm_say (text %s)", client, message);
}
else if (msgStart == 3 && CheckAdminForChat(client)) // sm_csay alias
else if (msgStart == 3 && CheckCommandAccess(client, "sm_csay", ADMFLAG_CHAT)) // sm_csay alias
{
PrintCenterTextAll("%s: %s", name, message);
LogAction(client, -1, "%L triggered sm_csay (text %s)", client, text);
}
else if (msgStart == 2 && (CheckAdminForChat(client) || GetConVarBool(g_Cvar_Psaymode))) // sm_psay alias
else if (msgStart == 2 && CheckCommandAccess(client, "sm_psay", ADMFLAG_CHAT)) // sm_psay alias
{
decl String:arg[64];
@@ -158,7 +156,7 @@ public Action:Command_SayChat(client, args)
public Action:Command_SayAdmin(client, args)
{
if (!CheckAdminForChat(client) && !GetConVarBool(g_Cvar_Chatmode))
if (!CheckCommandAccess(client, "sm_chat", ADMFLAG_CHAT) && !GetConVarBool(g_Cvar_Chatmode))
{
return Plugin_Continue;
}
@@ -359,16 +357,6 @@ public Action:Command_SmMsay(client, args)
return Plugin_Handled;
}
bool:CheckAdminForChat(client)
{
if (client == 0)
{
return true;
}
return CheckCommandAccess(client, "sm_chat", ADMFLAG_CHAT);
}
FindColor(String:color[])
{
for (new i = 0; i < 13; i++)
@@ -400,7 +388,7 @@ SendChatToAdmins(String:name[], String:message[])
{
if (IsClientInGame(i))
{
if (CheckAdminForChat(i))
if (CheckCommandAccess(i, "sm_chat", ADMFLAG_CHAT))
{
if (g_DoColor)
{
+1 -1
View File
@@ -58,7 +58,7 @@ DisplayGagPlayerMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, false);
AddTargetsToMenu(menu, client, true, false);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+1 -1
View File
@@ -13,7 +13,7 @@ DisplayBurnMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, true);
AddTargetsToMenu(menu, client, true, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+1 -1
View File
@@ -33,7 +33,7 @@ DisplaySlapTargetMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, true);
AddTargetsToMenu(menu, client, true, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+1 -1
View File
@@ -14,7 +14,7 @@ DisplaySlayMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, true);
AddTargetsToMenu(menu, client, true, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+1 -1
View File
@@ -31,7 +31,7 @@ DisplayBurnTargetMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, true);
AddTargetsToMenu(menu, client, true, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+1 -1
View File
@@ -32,7 +32,7 @@ DisplaySlayTargetMenu(client)
SetMenuTitle(menu, title);
SetMenuExitBackButton(menu, true);
AddTargetsToMenu(menu, client, false, true);
AddTargetsToMenu(menu, client, true, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
+7 -15
View File
@@ -51,8 +51,6 @@ public Plugin:myinfo =
new Handle:g_hVoteMenu = INVALID_HANDLE;
new Handle:g_hBanForward = INVALID_HANDLE;
new Handle:g_Cvar_Limits[3] = {INVALID_HANDLE, ...};
//new Handle:g_Cvar_VoteSay = INVALID_HANDLE;
@@ -111,8 +109,6 @@ public OnPluginStart()
g_Cvar_Limits[1] = CreateConVar("sm_vote_kick", "0.60", "percent required for successful kick vote.", 0, true, 0.05, true, 1.0);
g_Cvar_Limits[2] = CreateConVar("sm_vote_ban", "0.60", "percent required for successful ban vote.", 0, true, 0.05, true, 1.0);
g_hBanForward = CreateGlobalForward("OnClientBanned", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_String);
/* Account for late loading */
new Handle:topmenu;
if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
@@ -350,14 +346,6 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
case (voteType:ban):
{
/* Fire the ban forward */
Call_StartForward(g_hBanForward);
Call_PushCell(0);
Call_PushCell(g_voteClient[VOTE_USERID]);
Call_PushCell(30);
Call_PushString(g_voteArg);
Call_Finish();
if (g_voteArg[0] == '\0')
{
strcopy(g_voteArg, sizeof(g_voteArg), "Votebanned");
@@ -365,9 +353,13 @@ public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
PrintToChatAll("[SM] %t", "Banned player", g_voteInfo[VOTE_NAME], 30);
LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote ban successful, banned \"%L\" (minutes \"30\") (reason \"%s\")", g_voteClient[VOTE_CLIENTID], g_voteArg);
ServerCommand("banid %d %s", 30, g_voteClient[VOTE_AUTHID]);
ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg);
BanClient(g_voteClient[VOTE_CLIENTID],
30,
BANFLAG_AUTO,
g_voteArg,
"Banned by vote",
"sm_voteban");
}
}
}
+1 -1
View File
@@ -111,7 +111,7 @@ public MenuHandler_Map(Handle:menu, MenuAction:action, param1, param2)
GetMenuItem(menu, param2, info, sizeof(info), _, name, sizeof(name));
if (IsStringInArray(g_SelectedMaps, info))
if (FindStringInArray(g_SelectedMaps, info) != -1)
{
return ITEMDRAW_IGNORE;
}
+5 -5
View File
@@ -266,8 +266,8 @@ native SwapArrayItems(Handle:array, index1, index2);
*
* @param array Array Handle.
* @param item String to search for
* @return Array index, or -1 on failure
* @error Invalid Handle
* @return Array index, or -1 on failure
* @error Invalid Handle
*/
native FindStringInArray(Handle:array, const String:item[]);
@@ -277,8 +277,8 @@ native FindStringInArray(Handle:array, const String:item[]);
*
* @param array Array Handle.
* @param item Value to search for
* @return Array index, or -1 on failure
* @error Invalid Handle
* @return Array index, or -1 on failure
* @error Invalid Handle
*/
native FindValueInArray(Handle:array, item);
@@ -290,4 +290,4 @@ native FindValueInArray(Handle:array, item);
stock bool:IsStringInArray(Handle:array, const String:item[])
{
return (FindStringInArray(array, item) != -1);
}
}
+19
View File
@@ -191,6 +191,15 @@ native KvGetUInt64(Handle:kv, const String:key[], value[2], defvalue[2]={0,0});
*/
native bool:KvJumpToKey(Handle:kv, const String:key[], bool:create=false);
/**
* Sets the current position in the KeyValues tree to the given key.
*
* @param kv KeyValues Handle.
* @param id KeyValues id.
* @return True if the key exists, false if it does not.
*/
native bool:KvJumpToKeySymbol(Handle:kv, id);
/**
* Sets the current position in the KeyValues tree to the first sub key.
* This native adds to the internal traversal stack.
@@ -385,3 +394,13 @@ native bool:KvFindKeyById(Handle:kv, id, String:name[], maxlength);
* @error Invalid Handle.
*/
native bool:KvGetNameSymbol(Handle:kv, const String:key[], &id);
/**
* Retrieves the current section id.
*
* @param kv KeyValues Handle.
* @param id Id of the current section.
* @return True on success, false on failure.
* @error Invalid Handle.
*/
native bool:KvGetSectionSymbol(Handle:kv, &id);
+20
View File
@@ -732,6 +732,26 @@ native bool:SetPanelCurrentKey(Handle:panel, key);
*/
native RedrawMenuItem(const String:text[]);
/**
* This function is provided for legacy code only. Some older plugins may use
* network messages instead of the panel API. This function wraps the panel
* API for eased portability into the SourceMod menu system.
*
* This function is only usable with the Radio Menu style. You do not need to
* split up your menu into multiple packets; SourceMod will break the string
* up internally.
*
* @param client Client index.
* @param str Full menu string as would be passed over the network.
* @param time Time to hold the menu for.
* @param keys Selectable key bitstring.
* @param handler Optional handler function, with the same rules as
* SendPanelToClient().
* @return True on success, false on failure.
* @error Invalid client index, or radio menus not supported.
*/
native bool:InternalShowMenu(client, const String:str[], time, keys=-1, MenuHandler:handler=MenuHandler:-1);
/**
* Retrieves voting information from MenuAction_VoteEnd.
*
+45
View File
@@ -45,6 +45,16 @@ enum SortOrder
Sort_Descending = 1, /**< Descending order */
};
/**
* Data types for ADT Array Sorts
*/
enum SortType
{
Sort_Integer = 0,
Sort_Float,
Sort_String,
};
/**
* Sorts an array of integers.
*
@@ -128,3 +138,38 @@ funcenum SortFunc2D
* @noreturn
*/
native SortCustom2D(array[][], array_size, SortFunc2D:sortfunc, Handle:hndl=INVALID_HANDLE);
/**
* Sort an ADT Array. Specify the type as Integer, Float, or String.
*
* @param array Array Handle to sort
* @param order Sort order to use, same as other sorts.
* @param type Data type stored in the ADT Array
* @noreturn
*/
native SortADTArray(Handle:array, SortOrder:order = Sort_Ascending, SortType:type = Sort_Integer);
/**
* Sort comparison function for ADT Array elements. Function provides you with
* indexes currently being sorted, use ADT Array functions to retrieve the
* index values and compare.
*
* @param index1 First index to compare.
* @param index2 Second index to compare.
* @param array Array that is being sorted (order is undefined).
* @param hndl Handle optionally passed in while sorting.
* @return -1 if first should go before second
* 0 if first is equal to second
* 1 if first should go after second
*/
functag SortFuncADTArray public(index1, index2, Handle:array, Handle:hndl);
/**
* Custom sorts an ADT Array. You must pass in a comparison function.
*
* @param array Array Handle to sort
* @param sortfunc Sort comparision function to use
* @param hndl Optional Handle to pass through the comparison calls.
* @noreturn
*/
native SortADTArrayCustom(Handle:array, SortFuncADTArray:sortfunc, Handle:hndl=INVALID_HANDLE);
+290 -277
View File
@@ -1,277 +1,290 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This file is part of the SourceMod/SourcePawn SDK.
*
* 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$
*/
#if defined _topmenus_included
#endinput
#endif
#define _topmenus_included
#include <menus>
/**
* Actions a top menu will take on an object.
*/
enum TopMenuAction
{
/**
* An option is being drawn for a menu (or for sorting purposes).
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
TopMenuAction_DisplayOption = 0,
/**
* The title of a menu is being drawn for a given object.
*
* Note: The Object ID will be INVALID_TOPMENUOBJECT if drawing the
* root title. Otherwise, the Object ID is a category.
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
TopMenuAction_DisplayTitle = 1,
/**
* A menu option has been selected.
*
* The Object ID will always be an item (not a category).
*
* INPUT : TopMenu Handle, object ID, client index.
*/
TopMenuAction_SelectOption = 2,
/**
* A menu option is being drawn and its flags can be overridden.
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: The first byte of the 'buffer' string should be set
* to the desired flags. By default, it will contain
* ITEMDRAW_DEFAULT.
*/
TopMenuAction_DrawOption = 3,
/**
* Called when an object is being removed from the menu.
* This can be used to clean up data stored in the info string.
*
* INPUT : TopMenu Handle, object ID.
*/
TopMenuAction_RemoveObject = 4,
};
/**
* Top menu object types.
*/
enum TopMenuObjectType
{
TopMenuObject_Category = 0, /**< Category (sub-menu branching from root) */
TopMenuObject_Item = 1 /**< Item on a sub-menu */
};
/**
* Top menu starting positions for display.
*/
enum TopMenuPosition
{
TopMenuPosition_Start = 0, /**< Start/root of the menu */
TopMenuPosition_LastRoot = 1, /**< Last position in the root menu */
TopMenuPosition_LastCategory = 3, /**< Last position in their last category */
};
/**
* Top menu object tag for type checking.
*/
enum TopMenuObject
{
INVALID_TOPMENUOBJECT = 0,
}
/**
* TopMenu callback prototype.
*
* @param topmenu Handle to the TopMenu.
* @param action TopMenuAction being performed.
* @param object_id The object ID (if used).
* @param param Extra parameter (if used).
* @param buffer Output buffer (if used).
* @param maxlength Output buffer (if used).
* @noreturn
*/
functag TopMenuHandler public(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength);
/**
* Creates a TopMenu.
*
* @param handler Handler to use for drawing the root title.
* @return A new TopMenu Handle, or INVALID_HANDLE on failure.
*/
native Handle:CreateTopMenu(TopMenuHandler:handler);
/**
* Re-sorts the items in a TopMenu via a configuration file.
*
* The format of the configuration file should be a Valve Key-Values
* formatted file that SourceMod can parse. There should be one root
* section, and one sub-section for each category. Each sub-section's
* name should match the category name.
*
* Each sub-section may only contain key/value pairs in the form of:
* key: "item"
* value: Name of the item as passed to AddToTopMenu().
*
* The TopMenu will draw items in the order declared in the configuration
* file. If items do not appear in the configuration file, they are sorted
* per-player based on how the handler function renders for that player.
* These items appear after the configuration sorted items.
*
* @param topmenu TopMenu Handle.
* @param file File path.
* @param error Error buffer.
* @param maxlength Maximum size of the error buffer.
* Error buffer will be filled with a
* zero-terminated string if false is
* returned.
* @return True on success, false on failure.
* @error Invalid TopMenu Handle.
*/
native bool:LoadTopMenuConfig(Handle:topmenu, const String:file[], String:error[], maxlength);
/**
* Adds an object to a TopMenu.
*
* @param topmenu TopMenu Handle.
* @param name Object name (MUST be unique).
* @param type Object type.
* @param handler Handler for object.
* @param cmdname Command name (for access overrides).
* @param flags Default access flags.
* @param parent Parent object ID, or INVALID_TOPMENUOBJECT for none.
* Items must have a category parent.
* Categories must not have a parent.
* @param info_string Arbitrary storage (max 255 bytes).
* @return A new TopMenuObject ID, or INVALID_TOPMENUOBJECT on
* failure.
* @error Invalid TopMenu Handle.
*/
native TopMenuObject:AddToTopMenu(Handle:topmenu,
const String:name[],
TopMenuObjectType:type,
TopMenuHandler:handler,
TopMenuObject:parent,
const String:cmdname[]="",
flags=0,
const String:info_string[]="");
/**
* Retrieves the info string of a top menu item.
*
* @param topmenu TopMenu Handle.
* @param object TopMenuObject ID.
* @param buffer Buffer to store info string.
* @param maxlength Maximum size of info string.
* @return Number of bytes written, not including the
* null terminator.
* @error Invalid TopMenu Handle or TopMenuObject ID.
*/
native GetTopMenuInfoString(Handle:topmenu, TopMenuObject:parent, String:buffer[], maxlength);
/**
* Removes an object from a TopMenu.
*
* Plugins' objects are automatically removed all TopMenus when the given
* plugin unloads or pauses. In the case of unpausing, all items are restored.
*
* @param topmenu TopMenu Handle.
* @param object TopMenuObject ID.
* @noreturn
* @error Invalid TopMenu Handle.
*/
native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object);
/**
* Displays a TopMenu to a client.
*
* @param topmenu TopMenu Handle.
* @param client Client index.
* @param position Position to display from.
* @return True on success, false on failure.
* @error Invalid TopMenu Handle or client not in game.
*/
native bool:DisplayTopMenu(Handle:topmenu, client, TopMenuPosition:position);
/**
* Finds a category's object ID in a TopMenu.
*
* @param topmenu TopMenu Handle.
* @param name Object's unique name.
* @return TopMenuObject ID on success, or
* INVALID_TOPMENUOBJECT on failure.
* @error Invalid TopMenu Handle.
*/
native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]);
/**
* Do not edit below this line!
*/
public Extension:__ext_topmenus =
{
name = "TopMenus",
file = "topmenus.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_EXTENSIONS
public __ext_topmenus_SetNTVOptional()
{
MarkNativeAsOptional("CreateTopMenu");
MarkNativeAsOptional("LoadTopMenuConfig");
MarkNativeAsOptional("AddToTopMenu");
MarkNativeAsOptional("RemoveFromTopMenu");
MarkNativeAsOptional("DisplayTopMenu");
MarkNativeAsOptional("FindTopMenuCategory");
}
#endif
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This file is part of the SourceMod/SourcePawn SDK.
*
* 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$
*/
#if defined _topmenus_included
#endinput
#endif
#define _topmenus_included
#include <menus>
/**
* Actions a top menu will take on an object.
*/
enum TopMenuAction
{
/**
* An option is being drawn for a menu (or for sorting purposes).
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
TopMenuAction_DisplayOption = 0,
/**
* The title of a menu is being drawn for a given object.
*
* Note: The Object ID will be INVALID_TOPMENUOBJECT if drawing the
* root title. Otherwise, the Object ID is a category.
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
TopMenuAction_DisplayTitle = 1,
/**
* A menu option has been selected.
*
* The Object ID will always be an item (not a category).
*
* INPUT : TopMenu Handle, object ID, client index.
*/
TopMenuAction_SelectOption = 2,
/**
* A menu option is being drawn and its flags can be overridden.
*
* INPUT : TopMenu Handle, object ID, client index.
* OUTPUT: The first byte of the 'buffer' string should be set
* to the desired flags. By default, it will contain
* ITEMDRAW_DEFAULT.
*/
TopMenuAction_DrawOption = 3,
/**
* Called when an object is being removed from the menu.
* This can be used to clean up data stored in the info string.
*
* INPUT : TopMenu Handle, object ID.
*/
TopMenuAction_RemoveObject = 4,
};
/**
* Top menu object types.
*/
enum TopMenuObjectType
{
TopMenuObject_Category = 0, /**< Category (sub-menu branching from root) */
TopMenuObject_Item = 1 /**< Item on a sub-menu */
};
/**
* Top menu starting positions for display.
*/
enum TopMenuPosition
{
TopMenuPosition_Start = 0, /**< Start/root of the menu */
TopMenuPosition_LastRoot = 1, /**< Last position in the root menu */
TopMenuPosition_LastCategory = 3, /**< Last position in their last category */
};
/**
* Top menu object tag for type checking.
*/
enum TopMenuObject
{
INVALID_TOPMENUOBJECT = 0,
}
/**
* TopMenu callback prototype.
*
* @param topmenu Handle to the TopMenu.
* @param action TopMenuAction being performed.
* @param object_id The object ID (if used).
* @param param Extra parameter (if used).
* @param buffer Output buffer (if used).
* @param maxlength Output buffer (if used).
* @noreturn
*/
functag TopMenuHandler public(Handle:topmenu,
TopMenuAction:action,
TopMenuObject:object_id,
param,
String:buffer[],
maxlength);
/**
* Creates a TopMenu.
*
* @param handler Handler to use for drawing the root title.
* @return A new TopMenu Handle, or INVALID_HANDLE on failure.
*/
native Handle:CreateTopMenu(TopMenuHandler:handler);
/**
* Re-sorts the items in a TopMenu via a configuration file.
*
* The format of the configuration file should be a Valve Key-Values
* formatted file that SourceMod can parse. There should be one root
* section, and one sub-section for each category. Each sub-section's
* name should match the category name.
*
* Each sub-section may only contain key/value pairs in the form of:
* key: "item"
* value: Name of the item as passed to AddToTopMenu().
*
* The TopMenu will draw items in the order declared in the configuration
* file. If items do not appear in the configuration file, they are sorted
* per-player based on how the handler function renders for that player.
* These items appear after the configuration sorted items.
*
* @param topmenu TopMenu Handle.
* @param file File path.
* @param error Error buffer.
* @param maxlength Maximum size of the error buffer.
* Error buffer will be filled with a
* zero-terminated string if false is
* returned.
* @return True on success, false on failure.
* @error Invalid TopMenu Handle.
*/
native bool:LoadTopMenuConfig(Handle:topmenu, const String:file[], String:error[], maxlength);
/**
* Adds an object to a TopMenu.
*
* @param topmenu TopMenu Handle.
* @param name Object name (MUST be unique).
* @param type Object type.
* @param handler Handler for object.
* @param cmdname Command name (for access overrides).
* @param flags Default access flags.
* @param parent Parent object ID, or INVALID_TOPMENUOBJECT for none.
* Items must have a category parent.
* Categories must not have a parent.
* @param info_string Arbitrary storage (max 255 bytes).
* @return A new TopMenuObject ID, or INVALID_TOPMENUOBJECT on
* failure.
* @error Invalid TopMenu Handle.
*/
native TopMenuObject:AddToTopMenu(Handle:topmenu,
const String:name[],
TopMenuObjectType:type,
TopMenuHandler:handler,
TopMenuObject:parent,
const String:cmdname[]="",
flags=0,
const String:info_string[]="");
/**
* Retrieves the info string of a top menu item.
*
* @param topmenu TopMenu Handle.
* @param object TopMenuObject ID.
* @param buffer Buffer to store info string.
* @param maxlength Maximum size of info string.
* @return Number of bytes written, not including the
* null terminator.
* @error Invalid TopMenu Handle or TopMenuObject ID.
*/
native GetTopMenuInfoString(Handle:topmenu, TopMenuObject:parent, String:buffer[], maxlength);
/**
* Retrieves the name string of a top menu item.
*
* @param topmenu TopMenu Handle.
* @param object TopMenuObject ID.
* @param buffer Buffer to store info string.
* @param maxlength Maximum size of info string.
* @return Number of bytes written, not including the
* null terminator.
* @error Invalid TopMenu Handle or TopMenuObject ID.
*/
native GetTopMenuObjName(Handle:topmenu, TopMenuObject:object, String:buffer[], maxlength);
/**
* Removes an object from a TopMenu.
*
* Plugins' objects are automatically removed all TopMenus when the given
* plugin unloads or pauses. In the case of unpausing, all items are restored.
*
* @param topmenu TopMenu Handle.
* @param object TopMenuObject ID.
* @noreturn
* @error Invalid TopMenu Handle.
*/
native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object);
/**
* Displays a TopMenu to a client.
*
* @param topmenu TopMenu Handle.
* @param client Client index.
* @param position Position to display from.
* @return True on success, false on failure.
* @error Invalid TopMenu Handle or client not in game.
*/
native bool:DisplayTopMenu(Handle:topmenu, client, TopMenuPosition:position);
/**
* Finds a category's object ID in a TopMenu.
*
* @param topmenu TopMenu Handle.
* @param name Object's unique name.
* @return TopMenuObject ID on success, or
* INVALID_TOPMENUOBJECT on failure.
* @error Invalid TopMenu Handle.
*/
native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]);
/**
* Do not edit below this line!
*/
public Extension:__ext_topmenus =
{
name = "TopMenus",
file = "topmenus.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_EXTENSIONS
public __ext_topmenus_SetNTVOptional()
{
MarkNativeAsOptional("CreateTopMenu");
MarkNativeAsOptional("LoadTopMenuConfig");
MarkNativeAsOptional("AddToTopMenu");
MarkNativeAsOptional("RemoveFromTopMenu");
MarkNativeAsOptional("DisplayTopMenu");
MarkNativeAsOptional("FindTopMenuCategory");
}
#endif
+11 -4
View File
@@ -74,6 +74,7 @@ new Handle:g_NextMapList = INVALID_HANDLE;
new Handle:g_TeamScores = INVALID_HANDLE;
new Handle:g_VoteMenu = INVALID_HANDLE;
new g_TotalRounds;
new bool:g_HasVoteStarted;
new g_mapFileTime;
@@ -87,7 +88,6 @@ public OnPluginStart()
g_MapList = CreateArray(arraySize);
g_OldMapList = CreateArray(arraySize);
g_NextMapList = CreateArray(arraySize);
g_TeamScores = CreateArray(2);
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);
@@ -139,6 +139,14 @@ public OnConfigsExecuted()
SetupTimeleftTimer();
SetConVarString(g_Cvar_Nextmap, "Pending Vote");
}
if (g_TeamScores != INVALID_HANDLE)
{
CloseHandle(g_TeamScores);
}
g_TeamScores = CreateArray(2);
g_TotalRounds = 0;
}
public OnMapEnd()
@@ -225,8 +233,7 @@ public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
return;
}
static total;
total++;
g_TotalRounds++;
new team[2], teamPos = -1;
for (new i; i < GetArraySize(g_TeamScores); i++)
@@ -268,7 +275,7 @@ public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
new maxrounds = GetConVarInt(g_Cvar_Maxrounds);
if (maxrounds)
{
if (total >= (maxrounds - GetConVarInt(g_Cvar_StartRounds)))
if (g_TotalRounds >= (maxrounds - GetConVarInt(g_Cvar_StartRounds)))
{
InitiateVote();
}
+48 -32
View File
@@ -90,10 +90,8 @@ public OnConfigsExecuted()
}
}
public Action:OnTimedKick(Handle:timer, any:value)
{
new client = GetClientOfUserId(value);
public Action:OnTimedKick(Handle:timer, any:client)
{
if (!client || !IsClientInGame(client))
{
return Plugin_Handled;
@@ -101,6 +99,11 @@ public Action:OnTimedKick(Handle:timer, any:value)
KickClient(client, "%T", "Slot reserved", client);
if (GetConVarBool(sm_hide_slots))
{
SetVisibleMaxSlots(GetClientCount(false), g_MaxClients - GetConVarInt(sm_reserved_slots));
}
return Plugin_Handled;
}
@@ -113,32 +116,45 @@ public OnClientPostAdminCheck(client)
new clients = GetClientCount(false);
new limit = g_MaxClients - reserved;
new flags = GetUserFlagBits(client);
if (clients <= limit || IsFakeClient(client) || flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION)
new type = GetConVarInt(sm_reserve_type);
if (type == 0)
{
if (GetConVarBool(sm_hide_slots))
if (clients <= limit || IsFakeClient(client) || flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION)
{
SetVisibleMaxSlots(clients, limit);
if (GetConVarBool(sm_hide_slots))
{
SetVisibleMaxSlots(clients, limit);
}
return;
}
new type = GetConVarInt(sm_reserve_type);
if (type == 1)
{
new target = SelectKickClient();
if (target)
/* Kick player because there are no public slots left */
CreateTimer(0.1, OnTimedKick, client);
}
else
{
if (clients > limit)
{
if (flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION)
{
/* Kick public player to free the reserved slot again */
CreateTimer(0.1, OnTimedKick, GetClientUserId(target));
new target = SelectKickClient();
if (target)
{
/* Kick public player to free the reserved slot again */
CreateTimer(0.1, OnTimedKick, target);
}
}
else
{
/* Kick player because there are no public slots left */
CreateTimer(0.1, OnTimedKick, client);
}
}
return;
}
/* Kick player because there are no public slots left */
CreateTimer(0.1, OnTimedKick, GetClientUserId(client));
}
}
@@ -161,7 +177,7 @@ public SlotsChanged(Handle:convar, const String:oldValue[], const String:newValu
SetVisibleMaxSlots(clients, limit)
{
new num = clients + 1;
new num = clients;
if (clients == g_MaxClients)
{
@@ -186,7 +202,7 @@ SelectKickClient()
new Float:latency;
for (new i=1; i<=g_MaxClients; i++)
{
{
if (!IsClientConnected(i))
{
continue;
@@ -198,13 +214,17 @@ SelectKickClient()
{
continue;
}
latency = 0.0;
if (IsClientInGame(i))
{
latency = GetClientAvgLatency(i, NetFlow_Both);
{
latency = GetClientAvgLatency(i, NetFlow_Outgoing);
LogMessage("Latency : %f",latency);
if (IsClientObserver(i))
{
{
specFound = true;
if (latency > highestSpecLatency)
@@ -214,12 +234,8 @@ SelectKickClient()
}
}
}
else
{
latency = 0.0;
}
if (latency > highestLatency)
if (latency >= highestLatency)
{
highestLatency = latency;
highestLatencyId = i;
+42 -31
View File
@@ -88,27 +88,15 @@ public OnPluginStart()
AutoExecConfig(true, "rtv");
}
public OnConfigsExecuted()
{
if (g_RTVMapList != INVALID_HANDLE)
{
ClearArray(g_RTVMapList);
}
g_Voters = 0;
g_Votes = 0;
g_VotesNeeded = 0;
g_RTVStarted = false;
g_RTVEnded = false;
if (LoadMaps(g_MapList, g_mapFileTime, g_Cvar_File))
{
BuildMapMenu();
g_CanRTV = true;
CreateTimer(30.0, Timer_DelayRTV);
}
}
public OnMapStart()
{
g_Voters = 0;
g_Votes = 0;
g_VotesNeeded = 0;
g_RTVStarted = false;
g_RTVEnded = false;
}
public OnMapEnd()
{
@@ -116,10 +104,24 @@ public OnMapEnd()
g_RTVAllowed = false;
}
public OnConfigsExecuted()
{
if (g_RTVMapList != INVALID_HANDLE)
{
ClearArray(g_RTVMapList);
}
if (LoadMaps(g_MapList, g_mapFileTime, g_Cvar_File))
{
BuildMapMenu();
g_CanRTV = true;
CreateTimer(30.0, Timer_DelayRTV);
}
}
public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
{
if(IsFakeClient(client))
if(!g_CanRTV || IsFakeClient(client))
return true;
g_Voted[client] = false;
@@ -133,7 +135,7 @@ public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
public OnClientDisconnect(client)
{
if(IsFakeClient(client))
if(!g_CanRTV || IsFakeClient(client))
return;
if(g_Voted[client])
@@ -145,8 +147,9 @@ public OnClientDisconnect(client)
g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed));
if (g_Votes && g_Voters && g_Votes >= g_VotesNeeded && g_RTVAllowed)
{
if (g_Votes && g_Voters && g_Votes >= g_VotesNeeded && g_RTVAllowed && !g_RTVStarted)
{
g_RTVStarted = true;
CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE);
}
}
@@ -157,6 +160,12 @@ public Action:Command_Addmap(client, args)
{
ReplyToCommand(client, "[SM] Usage: sm_rtv_addmap <mapname>");
return Plugin_Handled;
}
if (!g_CanRTV)
{
ReplyToCommand(client, "[SM] RockTheVote is not available.");
return Plugin_Handled;
}
decl String:mapname[64];
@@ -208,8 +217,10 @@ public Action:Command_Addmap(client, args)
public Action:Command_Say(client, args)
{
if (!g_CanRTV || !client)
return Plugin_Continue;
if (!g_CanRTV || !client)
{
return Plugin_Continue;
}
decl String:text[192];
if (!GetCmdArgString(text, sizeof(text)))
@@ -265,7 +276,8 @@ public Action:Command_Say(client, args)
PrintToChatAll("[SM] %t", "RTV Requested", name, g_Votes, g_VotesNeeded);
if (g_Votes >= g_VotesNeeded)
{
{
g_RTVStarted = true;
CreateTimer(2.0, Timer_StartRTV, TIMER_FLAG_NO_MAPCHANGE);
}
}
@@ -318,8 +330,6 @@ public Action:Timer_StartRTV(Handle:timer)
return;
}
g_RTVStarted = true;
if (IsVoteInProgress())
{
// Can't start a vote, try again in 5 seconds.
@@ -429,7 +439,8 @@ public Handler_MapMapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
{
if (param1 == VoteCancel_NoVotes)
{
PrintToChatAll("[SM] %t", "No Votes");
PrintToChatAll("[SM] %t", "No Votes");
g_RTVEnded = true;
}
}
+145 -2
View File
@@ -9,13 +9,17 @@ public Plugin:myinfo =
url = "http://www.sourcemod.net/"
};
public OnPluginStart(Handle:myself)
public OnPluginStart()
{
RegServerCmd("test_sort_ints", Command_TestSortInts)
RegServerCmd("test_sort_floats", Command_TestSortFloats)
RegServerCmd("test_sort_strings", Command_TestSortStrings)
RegServerCmd("test_sort_1d", Command_TestSort1D)
RegServerCmd("test_sort_2d", Command_TestSort2D)
RegServerCmd("test_adtsort_ints", Command_TestSortADTInts)
RegServerCmd("test_adtsort_floats", Command_TestSortADTFloats)
RegServerCmd("test_adtsort_strings", Command_TestSortADTStrings)
RegServerCmd("test_adtsort_custom", Command_TestSortADTCustom)
}
/*****************
@@ -138,7 +142,7 @@ public Action:Command_TestSortStrings(args)
public Custom2DSort(String:elem1[], String:elem2[], String:array[][], Handle:hndl)
{
return StrCompare(elem1, elem2)
return strcmp(elem1, elem2)
}
public Action:Command_TestSort2D(args)
@@ -162,3 +166,142 @@ public Action:Command_TestSort2D(args)
return Plugin_Handled
}
/*******************
* ADT ARRAY TESTS *
*******************/
// Int and floats work the same as normal comparisions. Strings are direct
// comparisions with no hacky memory stuff like Pawn arrays.
PrintADTArrayIntegers(Handle:array)
{
new size = GetArraySize(array);
for (new i=0; i<size;i++)
{
PrintToServer("array[%d] = %d", i, GetArrayCell(array, i));
}
}
public Action:Command_TestSortADTInts(args)
{
new Handle:array = CreateArray();
PushArrayCell(array, 6);
PushArrayCell(array, 7);
PushArrayCell(array, 3);
PushArrayCell(array, 2);
PushArrayCell(array, 8);
PushArrayCell(array, 5);
PushArrayCell(array, 0);
PushArrayCell(array, 1);
PushArrayCell(array, 4);
PushArrayCell(array, 9);
PrintToServer("Testing ascending sort:")
SortADTArray(array, Sort_Ascending, Sort_Integer)
PrintADTArrayIntegers(array)
PrintToServer("Testing descending sort:")
SortADTArray(array, Sort_Descending, Sort_Integer)
PrintADTArrayIntegers(array)
return Plugin_Handled
}
PrintADTArrayFloats(Handle:array)
{
new size = GetArraySize(array);
for (new i=0; i<size;i++)
{
PrintToServer("array[%d] = %f", i, float:GetArrayCell(array, i));
}
}
public Action:Command_TestSortADTFloats(args)
{
new Handle:array = CreateArray();
PushArrayCell(array, 6.0);
PushArrayCell(array, 7.0);
PushArrayCell(array, 3.0);
PushArrayCell(array, 2.0);
PushArrayCell(array, 8.0);
PushArrayCell(array, 5.0);
PushArrayCell(array, 0.0);
PushArrayCell(array, 1.0);
PushArrayCell(array, 4.0);
PushArrayCell(array, 9.0);
PrintToServer("Testing ascending sort:")
SortADTArray(array, Sort_Ascending, Sort_Float)
PrintADTArrayFloats(array)
PrintToServer("Testing descending sort:")
SortADTArray(array, Sort_Descending, Sort_Float)
PrintADTArrayFloats(array)
return Plugin_Handled
}
PrintADTArrayStrings(Handle:array)
{
new size = GetArraySize(array);
decl String:buffer[64];
for (new i=0; i<size;i++)
{
GetArrayString(array, i, buffer, sizeof(buffer));
PrintToServer("array[%d] = %s", i, buffer);
}
}
public Action:Command_TestSortADTStrings(args)
{
new Handle:array = CreateArray(ByteCountToCells(64));
PushArrayString(array, "faluco");
PushArrayString(array, "bailopan");
PushArrayString(array, "pm onoto");
PushArrayString(array, "damaged soul");
PushArrayString(array, "sniperbeamer");
PushArrayString(array, "sidluke");
PushArrayString(array, "johnny got his gun");
PushArrayString(array, "gabe newell");
PushArrayString(array, "hello");
PushArrayString(array, "WHAT?!");
PrintToServer("Testing ascending sort:")
SortADTArray(array, Sort_Ascending, Sort_String)
PrintADTArrayStrings(array)
PrintToServer("Testing descending sort:")
SortADTArray(array, Sort_Descending, Sort_String)
PrintADTArrayStrings(array)
return Plugin_Handled
}
public ArrayADTCustomCallback(index1, index2, Handle:array, Handle:hndl)
{
decl String:buffer1[64], String:buffer2[64];
GetArrayString(array, index1, buffer1, sizeof(buffer1));
GetArrayString(array, index2, buffer2, sizeof(buffer2));
return strcmp(buffer1, buffer2);
}
public Action:Command_TestSortADTCustom(args)
{
new Handle:array = CreateArray(ByteCountToCells(64));
PushArrayString(array, "faluco");
PushArrayString(array, "bailopan");
PushArrayString(array, "pm onoto");
PushArrayString(array, "damaged soul");
PushArrayString(array, "sniperbeamer");
PushArrayString(array, "sidluke");
PushArrayString(array, "johnny got his gun");
PushArrayString(array, "gabe newell");
PushArrayString(array, "hello");
PushArrayString(array, "WHAT?!");
PrintToServer("Testing custom sort:")
SortADTArrayCustom(array, ArrayADTCustomCallback)
PrintADTArrayStrings(array);
}