commit 5066190db27ffa300480a2ff8b1c5847ede94333 Author: zaCade Date: Sat Mar 16 21:16:04 2019 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/compile.bat b/compile.bat new file mode 100644 index 0000000..5e48a8a --- /dev/null +++ b/compile.bat @@ -0,0 +1,20 @@ +@echo off + +set SOURCEDIR=src +set SMINCLUDES=env\include +set BUILDDIR=build +set SPCOMP=env\win32\bin\spcomp.exe + +:: Make build directory. +if not exist "%BUILDDIR%" ( + mkdir %BUILDDIR% +) + +:: Compile. +echo Starting compiler: +%SPCOMP% -i%SOURCEDIR% -i%SOURCEDIR%/include -i%SMINCLUDES% -o%BUILDDIR%/zombieriot.smx %SOURCEDIR%\zombieriot.sp + +echo Compiling done. This script is looped, close if you're done. +pause + +compile.bat \ No newline at end of file diff --git a/env/include/admin.inc b/env/include/admin.inc new file mode 100644 index 0000000..b367eb5 --- /dev/null +++ b/env/include/admin.inc @@ -0,0 +1,622 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _admin_included + #endinput +#endif +#define _admin_included + +/** + * Access levels (flags) for admins. + */ +enum AdminFlag +{ + Admin_Reservation = 0, /**< Reserved slot */ + Admin_Generic, /**< Generic admin abilities */ + Admin_Kick, /**< Kick another user */ + Admin_Ban, /**< Ban another user */ + Admin_Unban, /**< Unban another user */ + Admin_Slay, /**< Slay/kill/damage another user */ + Admin_Changemap, /**< Change the map */ + Admin_Convars, /**< Change basic convars */ + Admin_Config, /**< Change configuration */ + Admin_Chat, /**< Special chat privileges */ + Admin_Vote, /**< Special vote privileges */ + Admin_Password, /**< Set a server password */ + Admin_RCON, /**< Use RCON */ + Admin_Cheats, /**< Change sv_cheats and use its commands */ + Admin_Root, /**< All access by default */ + Admin_Custom1, /**< First custom flag type */ + Admin_Custom2, /**< Second custom flag type */ + Admin_Custom3, /**< Third custom flag type */ + Admin_Custom4, /**< Fourth custom flag type */ + Admin_Custom5, /**< Fifth custom flag type */ + Admin_Custom6, /**< Sixth custom flag type */ + /* --- */ +}; + +#define AdminFlags_TOTAL 21 /**< Total number of admin flags */ + +/** + * @section Bitwise values definitions for admin flags. + */ +#define ADMFLAG_RESERVATION (1<<0) /**< Convenience macro for Admin_Reservation as a FlagBit */ +#define ADMFLAG_GENERIC (1<<1) /**< Convenience macro for Admin_Generic as a FlagBit */ +#define ADMFLAG_KICK (1<<2) /**< Convenience macro for Admin_Kick as a FlagBit */ +#define ADMFLAG_BAN (1<<3) /**< Convenience macro for Admin_Ban as a FlagBit */ +#define ADMFLAG_UNBAN (1<<4) /**< Convenience macro for Admin_Unban as a FlagBit */ +#define ADMFLAG_SLAY (1<<5) /**< Convenience macro for Admin_Slay as a FlagBit */ +#define ADMFLAG_CHANGEMAP (1<<6) /**< Convenience macro for Admin_Changemap as a FlagBit */ +#define ADMFLAG_CONVARS (1<<7) /**< Convenience macro for Admin_Convars as a FlagBit */ +#define ADMFLAG_CONFIG (1<<8) /**< Convenience macro for Admin_Config as a FlagBit */ +#define ADMFLAG_CHAT (1<<9) /**< Convenience macro for Admin_Chat as a FlagBit */ +#define ADMFLAG_VOTE (1<<10) /**< Convenience macro for Admin_Vote as a FlagBit */ +#define ADMFLAG_PASSWORD (1<<11) /**< Convenience macro for Admin_Password as a FlagBit */ +#define ADMFLAG_RCON (1<<12) /**< Convenience macro for Admin_RCON as a FlagBit */ +#define ADMFLAG_CHEATS (1<<13) /**< Convenience macro for Admin_Cheats as a FlagBit */ +#define ADMFLAG_ROOT (1<<14) /**< Convenience macro for Admin_Root as a FlagBit */ +#define ADMFLAG_CUSTOM1 (1<<15) /**< Convenience macro for Admin_Custom1 as a FlagBit */ +#define ADMFLAG_CUSTOM2 (1<<16) /**< Convenience macro for Admin_Custom2 as a FlagBit */ +#define ADMFLAG_CUSTOM3 (1<<17) /**< Convenience macro for Admin_Custom3 as a FlagBit */ +#define ADMFLAG_CUSTOM4 (1<<18) /**< Convenience macro for Admin_Custom4 as a FlagBit */ +#define ADMFLAG_CUSTOM5 (1<<19) /**< Convenience macro for Admin_Custom5 as a FlagBit */ +#define ADMFLAG_CUSTOM6 (1<<20) /**< Convenience macro for Admin_Custom6 as a FlagBit */ + +/** + * @endsection + */ + +/** + * @section Hardcoded authentication methods + */ +#define AUTHMETHOD_STEAM "steam" /**< SteamID based authentication */ +#define AUTHMETHOD_IP "ip" /**< IP based authentication */ +#define AUTHMETHOD_NAME "name" /**< Name based authentication */ + +/** + * @endsection + */ + +/** + * Access override types. + */ +enum OverrideType +{ + Override_Command = 1, /**< Command */ + Override_CommandGroup, /**< Command group */ +}; + +/** + * Access override rules. + */ +enum OverrideRule +{ + Command_Deny = 0, + Command_Allow = 1, +}; + +/** + * DEPRECATED, do not use. + */ +enum ImmunityType +{ + Immunity_Default = 1, /**< Deprecated. */ + Immunity_Global, /**< Deprecated. */ +}; + +/** + * Identifies a unique entry in the group permissions cache. These are not Handles. + */ +enum GroupId +{ + INVALID_GROUP_ID = -1, /**< An invalid/nonexistant group */ +}; + +/** + * Identifies a unique entry in the admin permissions cache. These are not Handles. + */ +enum AdminId +{ + INVALID_ADMIN_ID = -1, /**< An invalid/nonexistant admin */ +}; + +/** + * Methods of computing access permissions. + */ +enum AdmAccessMode +{ + Access_Real, /**< Access the user has inherently */ + Access_Effective, /**< Access the user has from their groups */ +}; + +/** + * Represents the various cache regions. + */ +enum AdminCachePart +{ + AdminCache_Overrides = 0, /**< Global overrides */ + AdminCache_Groups = 1, /**< All groups (automatically invalidates admins too) */ + AdminCache_Admins = 2, /**< All admins */ +}; + +/** + * Called when part of the cache which needs to be rebuilt. + * + * @param part Part of the admin cache to rebuild. + */ +forward OnRebuildAdminCache(AdminCachePart:part); + +/** + * Tells the admin system to dump a portion of the cache. + * + * @param part Part of the cache to dump. Specifying groups also dumps admins. + * @param rebuild If true, the rebuild forwards will fire. + * @noreturn + */ +native DumpAdminCache(AdminCachePart:part, bool:rebuild); + +/** + * Adds a global command flag override. Any command registered with this name + * will assume the new flag. This is applied retroactively as well. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param flags New admin flag. + * @noreturn + */ +native AddCommandOverride(const String:cmd[], OverrideType:type, flags); + +/** + * Returns a command override. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param flags By-reference cell to store the flag (undefined if not found). + * @return True if there is an override, false otherwise. + */ +native bool:GetCommandOverride(const String:cmd[], OverrideType:type, &flags); + +/** + * Unsets a command override. + * + * @param cmd String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @noreturn + */ +native UnsetCommandOverride(const String:cmd[], OverrideType:type); + +/** + * Adds a new group. Name must be unique. + * + * @param group_name String containing the group name. + * @return A new group id, INVALID_GROUP_ID if it already exists. + */ +native GroupId:CreateAdmGroup(const String:group_name[]); + +/** + * Finds a group by name. + * + * @param group_name String containing the group name. + * @return A group id, or INVALID_GROUP_ID if not found. + */ +native GroupId:FindAdmGroup(const String:group_name[]); + +/** + * Adds or removes a flag from a group's flag set. + * @note These are called "add flags" because they add to a user's flags. + * + * @param id Group id. + * @param flag Admin flag to toggle. + * @param enabled True to set the flag, false to unset/disable. + * @noreturn + */ +native SetAdmGroupAddFlag(GroupId:id, AdminFlag:flag, bool:enabled); + +/** + * Gets the set value of an add flag on a group's flag set. + * @note These are called "add flags" because they add to a user's flags. + * + * @param id Group id. + * @param flag Admin flag to retrieve. + * @return True if enabled, false otherwise, + */ +native bool:GetAdmGroupAddFlag(GroupId:id, AdminFlag:flag); + +/** + * Returns the flag set that is added to a user from their group. + * @note These are called "add flags" because they add to a user's flags. + * + * @param id GroupId of the group. + * @return Bitstring containing the flags enabled. + */ +native GetAdmGroupAddFlags(GroupId:id); + +/** + * @deprecated Functionality removed. + */ +#pragma deprecated Use SetAdmGroupImmunityLevel() instead. +native SetAdmGroupImmunity(GroupId:id, ImmunityType:type, bool:enabled); + +/** + * @deprecated Functionality removed. + */ +#pragma deprecated Use GetAdmGroupImmunityLevel() instead. +native bool:GetAdmGroupImmunity(GroupId:id, ImmunityType:type); + +/** + * Adds immunity to a specific group. + * + * @param id Group id. + * @param other_id Group id to receive immunity to. + * @noreturn + */ +native SetAdmGroupImmuneFrom(GroupId:id, GroupId:other_id); + +/** + * Returns the number of specific group immunities. + * + * @param id Group id. + * @return Number of group immunities. + */ +native GetAdmGroupImmuneCount(GroupId:id); + +/** + * Returns a group that this group is immune to given an index. + * + * @param id Group id. + * @param number Index from 0 to N-1, from GetAdmGroupImmuneCount(). + * @return GroupId that this group is immune to, or INVALID_GROUP_ID on failure. + */ +native GroupId:GetAdmGroupImmuneFrom(GroupId:id, number); + +/** + * Adds a group-specific override type. + * + * @param id Group id. + * @param name String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param rule Override allow/deny setting. + * @noreturn + */ +native AddAdmGroupCmdOverride(GroupId:id, const String:name[], OverrideType:type, OverrideRule:rule); + +/** + * Retrieves a group-specific command override. + * + * @param id Group id. + * @param name String containing command name (case sensitive). + * @param type Override type (specific command or group). + * @param rule Optional pointer to store allow/deny setting. + * @return True if an override exists, false otherwise. + */ +native bool:GetAdmGroupCmdOverride(GroupId:id, const String:name[], OverrideType:type, &OverrideRule:rule); + +/** + * Registers an authentication identity type. You normally never need to call this except for + * very specific systems. + * + * @param codename Codename to use for your authentication type. + * @noreturn + */ +native RegisterAuthIdentType(const String:name[]); + +/** + * Creates a new admin entry in the permissions cache. + * + * @param name Name for this entry (does not have to be unique). + * Specify an empty string for an anonymous admin. + */ +native AdminId:CreateAdmin(const String:name[]=""); + +/** + * Retrieves an admin's user name as made with CreateAdmin(). + * + * @note This function can return UTF-8 strings, and will safely chop UTF-8 strings. + * + * @param id AdminId of the admin. + * @param name String buffer to store name. + * @param maxlength Maximum size of string buffer. + * @return Number of bytes written. + */ +native GetAdminUsername(AdminId:id, const String:name[], maxlength); + +/** + * Binds an admin to an identity for fast lookup later on. The bind must be unique. + * + * @param id AdminId of the admin. + * @param auth Auth method to use, predefined or from RegisterAuthIdentType(). + * @param ident String containing the arbitrary, unique identity. + * @return True on success, false if the auth method was not found, + * or ident was already taken. + */ +native bool:BindAdminIdentity(AdminId:id, const String:auth[], const String:ident[]); + +/** + * Sets whether or not a flag is enabled on an admin. + * + * @param id AdminId index of the admin. + * @param flag Admin flag to use. + * @param enabled True to enable, false to disable. + * @noreturn + */ +native SetAdminFlag(AdminId:id, AdminFlag:flag, bool:enabled); + +/** + * Returns whether or not a flag is enabled on an admin. + * + * @param id AdminId index of the admin. + * @param flag Admin flag to use. + * @param mode Access mode to check. + * @return True if enabled, false otherwise. + */ +native bool:GetAdminFlag(AdminId:id, AdminFlag:flag, AdmAccessMode:mode=Access_Effective); + +/** + * Returns the bitstring of access flags on an admin. + * + * @param id AdminId index of the admin. + * @param mode Access mode to use. + * @return A bitstring containing which flags are enabled. + */ +native GetAdminFlags(AdminId:id, AdmAccessMode:mode); + +/** + * Adds a group to an admin's inherited group list. Any flags the group has + * will be added to the admin's effective flags. + * + * @param id AdminId index of the admin. + * @param gid GroupId index of the group. + * @return True on success, false on invalid input or duplicate membership. + */ +native bool:AdminInheritGroup(AdminId:id, GroupId:gid); + +/** + * Returns the number of groups this admin is a member of. + * + * @param id AdminId index of the admin. + * @return Number of groups this admin is a member of. + */ +native GetAdminGroupCount(AdminId:id); + +/** + * Returns group information from an admin. + * + * @param id AdminId index of the admin. + * @param index Group number to retrieve, from 0 to N-1, where N + * is the value of GetAdminGroupCount(id). + * @param name Buffer to store the group's name. + * Note: This will safely chop UTF-8 strings. + * @param maxlength Maximum size of the output name buffer. + * @return A GroupId index and a name pointer, or + * INVALID_GROUP_ID and NULL if an error occurred. +*/ +native GroupId:GetAdminGroup(AdminId:id, index, const String:name[], maxlength); + +/** + * Sets a password on an admin. + * + * @param id AdminId index of the admin. + * @param passwd String containing the password. + * @noreturn + */ +native SetAdminPassword(AdminId:id, const String:password[]); + +/** + * Gets an admin's password. + * + * @param id AdminId index of the admin. + * @param name Optional buffer to store the admin's password. + * @param maxlength Maximum size of the output name buffer. + * Note: This will safely chop UTF-8 strings. + * @return True if there was a password set, false otherwise. + */ +native bool:GetAdminPassword(AdminId:id, const String:buffer[]="", maxlength=0); + +/** + * Attempts to find an admin by an auth method and an identity. + * + * @param auth Auth method to try. + * @param identity Identity string to look up. + * @return An AdminId index if found, INVALID_ADMIN_ID otherwise. + */ +native AdminId:FindAdminByIdentity(const String:auth[], const String:identity[]); + +/** + * Removes an admin entry from the cache. + * + * @note This will remove any bindings to a specific user. + * + * @param id AdminId index to remove/invalidate. + * @return True on success, false otherwise. + */ +native bool:RemoveAdmin(AdminId:id); + +/** + * Converts a flag bit string to a bit array. + * + * @param bits Bit string containing the flags. + * @param array Array to write the flags to. Enabled flags will be 'true'. + * @param maxSize Maximum number of flags the array can store. + * @return Number of flags written. + */ +native FlagBitsToBitArray(bits, bool:array[], maxSize); + +/** + * Converts a flag array to a bit string. + * + * @param array Array containing true or false for each AdminFlag. + * @param maxSize Maximum size of the flag array. + * @return A bit string composed of the array bits. + */ +native FlagBitArrayToBits(const bool:array[], maxSize); + +/** + * Converts an array of flags to bits. + * + * @param array Array containing flags that are enabled. + * @param numFlags Number of flags in the array. + * @return A bit string composed of the array flags. + */ +native FlagArrayToBits(const AdminFlag:array[], numFlags); + +/** + * Converts a bit string to an array of flags. + * + * @param bits Bit string containing the flags. + * @param array Output array to write flags. + * @param maxSize Maximum size of the flag array. + * @return Number of flags written. + */ +native FlagBitsToArray(bits, AdminFlag:array[], maxSize); + +/** + * Finds a flag by its string name. + * + * @param name Flag name (like "kick"), case sensitive. + * @param flag Variable to store flag in. + * @return True on success, false if not found. + */ +native bool:FindFlagByName(const String:name[], &AdminFlag:flag); + +/** + * Finds a flag by a given character. + * + * @param c Flag ASCII character/token. + * @param flag Variable to store flag in. + * @return True on success, false if not found. + */ +native bool:FindFlagByChar(c, &AdminFlag:flag); + +/** + * Converts a string of flag characters to a bit string. + * + * @param flags Flag ASCII string. + * @param numchars Optional variable to store the number of bytes read. + * @return Bit string of ADMFLAG values. + */ +native ReadFlagString(const String:flags[], &numchars=0); + +/** + * Tests whether one admin can target another. + * + * The hueristics for this check are as follows: + * 0. If the targeting AdminId is INVALID_ADMIN_ID, targeting fails. + * 1. If the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds. + * 2. If the targeted AdminId is the same as the targeting AdminId, + * (self) targeting succeeds. + * 3. If the targeting admin is root, targeting succeeds. + * 4. If the targeted admin has access higher (as interpreted by + * (sm_immunity_mode) than the targeting admin, then targeting fails. + * 5. If the targeted admin has specific immunity from the + * targeting admin via group immunities, targeting fails. + * 6. Targeting succeeds. + * + * @param admin Admin doing the targetting (may be INVALID_ADMIN_ID). + * @param target Target admin (may be INVALID_ADMIN_ID). + * @return True if targetable, false if immune. + */ +native CanAdminTarget(AdminId:admin, AdminId:target); + +/** + * Creates an admin auth method. This does not need to be called more than once + * per method, ever. + * + * @param method Name of the authentication method. + * @return True on success, false on failure. + */ +native bool:CreateAuthMethod(const String:method[]); + +/** + * Sets a group's immunity level. + * + * @param gid Group Id. + * @param level Immunity level value. + * @return Old immunity level value. + */ +native SetAdmGroupImmunityLevel(GroupId:gid, level); + +/** + * Gets a group's immunity level (defaults to 0). + * + * @param gid Group Id. + * @return Immunity level value. + */ +native GetAdmGroupImmunityLevel(GroupId:gid); + +/** + * Sets an admin's immunity level. + * + * @param id Admin Id. + * @param level Immunity level value. + * @return Old immunity level value. + */ +native SetAdminImmunityLevel(AdminId:id, level); + +/** + * Gets an admin's immunity level. + * + * @param id Admin Id. + * @return Immunity level value. + */ +native GetAdminImmunityLevel(AdminId:id); + +/** + * Converts a flag to its single bit. + * + * @param flag Flag to convert. + * @return Bit representation of the flag. + */ +stock FlagToBit(AdminFlag:flag) +{ + return (1<<_:flag); +} + +/** + * Converts a bit to an AdminFlag. + * + * @param bit Bit to convert. + * @param flag Stores the converted flag by reference. + * @return True on success, false otherwise. + */ +stock bool:BitToFlag(bit, &AdminFlag:flag) +{ + new AdminFlag:array[1]; + + if (FlagBitsToArray(bit, array, 1)) + { + flag = array[0]; + return true; + } + + return false; +} + diff --git a/env/include/adminmenu.inc b/env/include/adminmenu.inc new file mode 100644 index 0000000..f96eb2a --- /dev/null +++ b/env/include/adminmenu.inc @@ -0,0 +1,154 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _adminmenu_included + #endinput +#endif +#define _adminmenu_included + +/* Decide whether topmenus should be required */ +#if !defined REQUIRE_PLUGIN + #if defined REQUIRE_EXTENSIONS + #define TEMP_REQUIRE_EXTENSIONS + #undef REQUIRE_EXTENSIONS + #endif +#endif + +#include + +/* Restore old REQUIRE_EXTENSIONS value if necessary */ +#if defined TEMP_REQUIRE_EXTENSIONS + #define REQUIRE_EXTENSIONS + #undef TEMP_REQUIRE_EXTENSIONS +#endif + +/** Category for player commands. */ +#define ADMINMENU_PLAYERCOMMANDS "PlayerCommands" +/** Category for server commands. */ +#define ADMINMENU_SERVERCOMMANDS "ServerCommands" +/** Category for voting commands. */ +#define ADMINMENU_VOTINGCOMMANDS "VotingCommands" + +/** + * Called when the admin menu is created and 3rd party plugins can grab + * the Handle or add categories. + * + * @param topmenu Handle to the admin menu's TopMenu. + * @noreturn + */ +forward OnAdminMenuCreated(Handle:topmenu); + +/** + * Called when the admin menu is ready to have items added. + * + * @param topmenu Handle to the admin menu's TopMenu. + * @noreturn + */ +forward OnAdminMenuReady(Handle:topmenu); + +/** + * Retrieves the Handle to the admin top menu. + * + * @return Handle to the admin menu's TopMenu, + * or INVALID_HANDLE if not created yet. + */ +native Handle:GetAdminTopMenu(); + +/** + * Adds targets to an admin menu. + * + * Each client is displayed as: name (userid) + * Each item contains the userid as a string for its info. + * + * @param menu Menu Handle. + * @param source_client Source client, or 0 to ignore immunity. + * @param in_game_only True to only select in-game players. + * @param alive_only True to only select alive players. + * @return Number of clients added. + */ +native AddTargetsToMenu(Handle:menu, + source_client, + bool:in_game_only=true, + bool:alive_only=false); + +/** + * Adds targets to an admin menu. + * + * Each client is displayed as: name (userid) + * Each item contains the userid as a string for its info. + * + * @param menu Menu Handle. + * @param source_client Source client, or 0 to ignore immunity. + * @param flags COMMAND_FILTER flags from commandfilters.inc. + * @return Number of clients added. + */ +native AddTargetsToMenu2(Handle:menu, source_client, flags); + +/** + * Re-displays the admin menu to a client after selecting an item. + * Auto-aborts if the Handle is invalid. + * + * @param topmenu TopMenu Handle. + * @param client Client index. + * @return True on success, false on failure. + */ +stock bool:RedisplayAdminMenu(Handle:topmenu, client) +{ + if (topmenu == INVALID_HANDLE) + { + return false; + } + + return DisplayTopMenu(topmenu, client, TopMenuPosition_LastCategory); +} + +/* DO NOT EDIT BELOW THIS LINE */ + +public SharedPlugin:__pl_adminmenu = +{ + name = "adminmenu", + file = "adminmenu.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public __pl_adminmenu_SetNTVOptional() +{ + MarkNativeAsOptional("GetAdminTopMenu"); + MarkNativeAsOptional("AddTargetsToMenu"); + MarkNativeAsOptional("AddTargetsToMenu2"); +} +#endif diff --git a/env/include/adt.inc b/env/include/adt.inc new file mode 100644 index 0000000..75051bf --- /dev/null +++ b/env/include/adt.inc @@ -0,0 +1,40 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _adt_included + #endinput +#endif +#define _adt_included + +#include +#include +#include diff --git a/env/include/adt_array.inc b/env/include/adt_array.inc new file mode 100644 index 0000000..b76991c --- /dev/null +++ b/env/include/adt_array.inc @@ -0,0 +1,283 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _adt_array_included + #endinput +#endif +#define _adt_array_included + +/** + * Given a maximum string size (including the null terminator), + * returns the number of cells required to fit that string. + * + * @param size Number of bytes. + * @return Minimum number of cells required to fit the byte count. + */ +stock ByteCountToCells(size) +{ + if (!size) + { + return 1; + } + + return (size + 3) / 4; +} + +/** + * Creates a dynamic global cell array. While slower than a normal array, + * it can be used globally AND dynamically, which is otherwise impossible. + * + * The contents of the array are uniform; i.e. storing a string at index X + * and then retrieving it as an integer is NOT the same as StringToInt()! + * The "blocksize" determines how many cells each array slot has; it cannot + * be changed after creation. + * + * @param blocksize The number of cells each member of the array can + * hold. For example, 32 cells is equivalent to: + * new Array[X][32] + * @param startsize Initial size of the array. Note that data will + * NOT be auto-intialized. + * @return New Handle to the array object. + */ +native Handle:CreateArray(blocksize=1, startsize=0); + +/** + * Clears an array of all entries. This is the same as ResizeArray(0). + * + * @param array Array Handle. + * @noreturn + * @error Invalid Handle. + */ +native ClearArray(Handle:array); + +/** + * Clones an array, returning a new handle with the same size and data. This should NOT + * be confused with CloneHandle. This is a completely new handle with the same data but + * no relation to the original. You MUST close it. + * + * @param array Array handle to be cloned + * @return New handle to the cloned array object + * @error Invalid Handle + */ + native Handle:CloneArray(Handle:array); + +/** + * Resizes an array. If the size is smaller than the current size, + * the array is truncated. + * + * @param array Array Handle. + * @param newsize New size. + * @noreturn + * @error Invalid Handle or out of memory. + */ +native bool:ResizeArray(Handle:array, newsize); + +/** + * Returns the array size. + * + * @param array Array Handle. + * @return Number of elements in the array. + * @error Invalid Handle. + */ +native GetArraySize(Handle:array); + +/** + * Pushes a value onto the end of an array, adding a new index. + * + * This may safely be used even if the array has a blocksize + * greater than 1. + * + * @param array Array Handle. + * @param value Value to push. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayCell(Handle:array, any:value); + +/** + * Pushes a string onto the end of an array, truncating it + * if it is too big. + * + * @param array Array Handle. + * @param value String to push. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayString(Handle:array, const String:value[]); + +/** + * Pushes an array of cells onto the end of an array. The cells + * are pushed as a block (i.e. the entire array sits at the index), + * rather than pushing each cell individually. + * + * @param array Array Handle. + * @param values Block of values to copy. + * @param size If not set, the number of elements copied from the array + * will be equal to the blocksize. If set higher than the + * blocksize, the operation will be truncated. + * @return Index of the new entry. + * @error Invalid Handle or out of memory. + */ +native PushArrayArray(Handle:array, const any:values[], size=-1); + +/** + * Retrieves a cell value from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param block Optionally specify which block to read from + * (useful if the blocksize > 0). + * @param asChar Optionally read as a byte instead of a cell. + * @return Value read. + * @error Invalid Handle, invalid index, or invalid block. + */ +native any:GetArrayCell(Handle:array, index, block=0, bool:asChar=false); + +/** + * Retrieves a string value from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Buffer to copy to. + * @param maxlength Maximum size of the buffer. + * @return Number of characters copied. + * @error Invalid Handle or invalid index. + */ +native GetArrayString(Handle:array, index, String:buffer[], maxlength); + +/** + * Retrieves an array of cells from an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Buffer to store the array in. + * @param size If not set, assumes the buffer size is equal to the + * blocksize. Otherwise, the size passed is used. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +native GetArrayArray(Handle:array, index, any:buffer[], size=-1); + +/** + * Sets a cell value in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param value Cell value to set. + * @param block Optionally specify which block to write to + * (useful if the blocksize > 0). + * @param asChar Optionally set as a byte instead of a cell. + * @noreturn + * @error Invalid Handle, invalid index, or invalid block. + */ +native any:SetArrayCell(Handle:array, index, any:value, block=0, bool:asChar=false); + +/** + * Sets a string value in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param value String value to set. + * @return Number of characters copied. + * @error Invalid Handle or invalid index. + */ +native SetArrayString(Handle:array, index, const String:buffer[]); + +/** + * Sets an array of cells in an array. + * + * @param array Array Handle. + * @param index Index in the array. + * @param buffer Array to copy. + * @param size If not set, assumes the buffer size is equal to the + * blocksize. Otherwise, the size passed is used. + * @return Number of cells copied. + * @error Invalid Handle or invalid index. + */ +native SetArrayArray(Handle:array, index, const any:values[], size=-1); + +/** + * Shifts an array up. All array contents after and including the given + * index are shifted up by one, and the given index is then "free." + * After shifting, the contents of the given index is undefined. + * + * @param array Array Handle. + * @param index Index in the array to shift up from. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native ShiftArrayUp(Handle:array, index); + +/** + * Removes an array index, shifting the entire array down from that position + * on. For example, if item 8 of 10 is removed, the last 3 items will then be + * (6,7,8) instead of (7,8,9), and all indexes before 8 will remain unchanged. + * + * @param array Array Handle. + * @param index Index in the array to remove at. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native RemoveFromArray(Handle:array, index); + +/** + * Swaps two items in the array. + * + * @param array Array Handle. + * @param index1 First index. + * @param index2 Second index. + * @noreturn + * @error Invalid Handle or invalid index. + */ +native SwapArrayItems(Handle:array, index1, index2); + +/** + * Returns the index for the first occurance of the provided string. If the string + * cannot be located, -1 will be returned. + * + * @param array Array Handle. + * @param item String to search for + * @return Array index, or -1 on failure + * @error Invalid Handle + */ +native FindStringInArray(Handle:array, const String:item[]); + +/** + * Returns the index for the first occurance of the provided value. If the value + * cannot be located, -1 will be returned. + * + * @param array Array Handle. + * @param item Value to search for + * @return Array index, or -1 on failure + * @error Invalid Handle + */ +native FindValueInArray(Handle:array, any:item); diff --git a/env/include/adt_stack.inc b/env/include/adt_stack.inc new file mode 100644 index 0000000..54029c3 --- /dev/null +++ b/env/include/adt_stack.inc @@ -0,0 +1,154 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _adt_stack_included + #endinput +#endif +#define _adt_stack_included + +/** + * Creates a stack structure. A stack is a LIFO (last in, first out) + * vector (array) of items. It has O(1) insertion and O(1) removal. + * + * Stacks have two operations: Push (adding an item) and Pop (removes + * items in reverse-push order). + * + * The contents of the stack are uniform; i.e. storing a string and then + * retrieving it as an integer is NOT the same as StringToInt()! + * + * The "blocksize" determines how many cells each slot has; it cannot + * be changed after creation. + * + * @param blocksize The number of cells each entry in the stack can + * hold. For example, 32 cells is equivalent to: + * new Array[X][32] + * @return New stack Handle. + */ +native Handle:CreateStack(blocksize=1); + +/** + * Pushes a value onto the end of the stack, adding a new index. + * + * This may safely be used even if the stack has a blocksize + * greater than 1. + * + * @param stack Stack Handle. + * @param value Value to push. + * @noreturn + * @error Invalid Handle or out of memory. + */ +native PushStackCell(Handle:stack, any:value); + +/** + * Pushes a string onto the end of a stack, truncating it if it is + * too big. + * + * @param stack Stack Handle. + * @param value String to push. + * @noreturn + * @error Invalid Handle or out of memory. + */ +native PushStackString(Handle:stack, const String:value[]); + +/** + * Pushes an array of cells onto the end of a stack. The cells + * are pushed as a block (i.e. the entire array takes up one stack slot), + * rather than pushing each cell individually. + * + * @param stack Stack Handle. + * @param values Block of values to copy. + * @param size If not set, the number of elements copied from the array + * will be equal to the blocksize. If set higher than the + * blocksize, the operation will be truncated. + * @noreturn + * @error Invalid Handle or out of memory. + */ +native PushStackArray(Handle:stack, const any:values[], size=-1); + +/** + * Pops a cell value from a stack. + * + * @param stack Stack Handle. + * @param value Variable to store the value. + * @param block Optionally specify which block to read from + * (useful if the blocksize > 0). + * @param asChar Optionally read as a byte instead of a cell. + * @return True on success, false if the stack is empty. + * @error Invalid Handle. + */ +native bool:PopStackCell(Handle:stack, &any:value, block=0, bool:asChar=false); + +/** + * Pops a string value from a stack. + * + * @param stack Stack Handle. + * @param buffer Buffer to store string. + * @param maxlength Maximum size of the buffer. + * @return True on success, false if the stack is empty. + * @error Invalid Handle. + */ +native bool:PopStackString(Handle:stack, String:buffer[], maxlength, &written=0); + +/** + * Pops an array of cells from a stack. + * + * @param stack Stack Handle. + * @param buffer Buffer to store the array in. + * @param size If not set, assumes the buffer size is equal to the + * blocksize. Otherwise, the size passed is used. + * @return True on success, false if the stack is empty. + * @error Invalid Handle. + */ +native bool:PopStackArray(Handle:stack, any:buffer[], size=-1); + +/** + * Checks if a stack is empty. + * + * @param stack Stack Handle. + * @return True if empty, false if not empty. + * @error Invalid Handle. + */ +native bool:IsStackEmpty(Handle:stack); + +/** + * Pops a value off a stack, ignoring it completely. + * + * @param stack Stack Handle. + * @return True if something was popped, false otherwise. + * @error Invalid Handle. + */ +stock PopStack(Handle:stack) +{ + new value; + + return PopStackCell(stack, value); +} diff --git a/env/include/adt_trie.inc b/env/include/adt_trie.inc new file mode 100644 index 0000000..516c794 --- /dev/null +++ b/env/include/adt_trie.inc @@ -0,0 +1,158 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _adt_trie_included + #endinput +#endif +#define _adt_trie_included + +/** + * Creates a Trie structure. A trie is a data storage object that maps any value to a + * string of text. It features very fast lookup and deletion, but grows very slow for + * insertion once tens of thousands of items are added. + * + * Keys in Tries are unique. That is, each key may only have one value. Unlike arrays, + * Tries cannot be iterated right now. Since the contents are known to be unique, to + * work around this, you can use ADT Arrays to store a list of keys known to be in a + * Trie. + * + * @return New Trie Handle, which must be freed via CloseHandle(). + */ +native Handle:CreateTrie(); + +/** + * Sets a value in a Trie, either inserting a new entry or replacing an old one. + * + * @param trie Trie Handle. + * @param key Key string. + * @param value Value to store at this key. + * @param replace If false, operation will fail if the key is already set. + * @return True on success, false on failure. + * @error Invalid Handle. + */ +native bool:SetTrieValue(Handle:trie, const String:key[], any:value, bool:replace=true); + +/** + * Sets an array value in a Trie, either inserting a new entry or replacing an old one. + * + * @param trie Trie Handle. + * @param key Key string. + * @param array Array to store. + * @param num_items Number of items in the array. + * @param replace If false, operation will fail if the key is already set. + * @return True on success, false on failure. + * @error Invalid Handle. + */ +native bool:SetTrieArray(Handle:trie, const String:key[], const any:array[], num_items, bool:replace=true); + +/** + * Sets a string value in a Trie, either inserting a new entry or replacing an old one. + * + * @param trie Trie Handle. + * @param key Key string. + * @param array Array to store. + * @param num_items Number of items in the array. + * @param replace If false, operation will fail if the key is already set. + * @return True on success, false on failure. + * @error Invalid Handle. + */ +native bool:SetTrieString(Handle:trie, const String:key[], const String:value[], bool:replace=true); + +/** + * Retrieves a value in a Trie. + * + * @param trie Trie Handle. + * @param key Key string. + * @param val Variable to store value. + * @return True on success. False if the key is not set, or the key is set + * as an array or string (not a value). + * @error Invalid Handle. + */ +native bool:GetTrieValue(Handle:trie, const String:key[], &any:value); + +/** + * Retrieves an array in a Trie. + * + * @param trie Trie Handle. + * @param key Key string. + * @param array Buffer to store array. + * @param max_size Maximum size of array buffer. + * @param size Optional parameter to store the number of elements written to the buffer. + * @return True on success. False if the key is not set, or the key is set + * as a value or string (not an array). + * @error Invalid Handle. + */ +native bool:GetTrieArray(Handle:trie, const String:key[], any:array[], max_size, &size=0); + +/** + * Retrieves a string in a Trie. + * + * @param trie Trie Handle. + * @param key Key string. + * @param value Buffer to store value. + * @param max_size Maximum size of string buffer. + * @param size Optional parameter to store the number of bytes written to the buffer. + * @return True on success. False if the key is not set, or the key is set + * as a value or array (not a string). + * @error Invalid Handle. + */ +native bool:GetTrieString(Handle:trie, const String:key[], String:value[], max_size, &size=0); + +/** + * Removes a key entry from a Trie. + * + * @param trie Trie Handle. + * @param key Key string. + * @return True on success, false if the value was never set. + * @error Invalid Handle. + */ +native RemoveFromTrie(Handle:trie, const String:key[]); + +/** + * Clears all entries from a Trie. + * + * @param trie Trie Handle. + * @error Invalid Handle. + */ +native ClearTrie(Handle:trie); + +/** + * Retrieves the number of elements in a trie. + * + * Note that trie items are not enumerable/iteratable. If you need to + * retrieve the elements in a trie, store its keys in an ADT Array. + * + * @param trie Trie Handle. + * @return Number of elements in the trie. + * @error Invalid Handle. + */ +native GetTrieSize(Handle:trie); diff --git a/env/include/banning.inc b/env/include/banning.inc new file mode 100644 index 0000000..038b113 --- /dev/null +++ b/env/include/banning.inc @@ -0,0 +1,157 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _banning_included + #endinput +#endif +#define _banning_included + +#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */ +#define BANFLAG_IP (1<<1) /**< Always ban by IP address */ +#define BANFLAG_AUTHID (1<<2) /**< Always ban by authstring (for BanIdentity) if possible */ +#define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */ + +/** + * Called for calls to BanClient() with a non-empty command. + * + * @param client Client being banned. + * @param time Time the client is being banned for (0 = permanent). + * @param flags One if AUTHID or IP will be enabled. If AUTO is also + * enabled, it means Core autodetected which to use. + * @param reason Reason passed via BanClient(). + * @param kick_message Kick message passed via BanClient(). + * @param command Command string to identify the ban source. + * @param source Source value passed via BanClient(). + * @return Plugin_Handled to block the actual server banning. + * Kicking will still occur. + */ +forward Action:OnBanClient(client, + time, + flags, + const String:reason[], + const String:kick_message[], + const String:command[], + any:source); + +/** + * Called for calls to BanIdentity() with a non-empty command. + * + * @param identity Identity string being banned (authstring or ip). + * @param time Time the client is being banned for (0 = permanent). + * @param flags Ban flags (only IP or AUTHID are valid here). + * @param reason Reason passed via BanIdentity(). + * @param command Command string to identify the ban source. + * @param source Source value passed via BanIdentity(). + * @return Plugin_Handled to block the actual server banning. + */ +forward Action:OnBanIdentity(const String:identity[], + time, + flags, + const String:reason[], + const String:command[], + any:source); + +/** + * Called for calls to RemoveBan() with a non-empty command. + * + * @param identity Identity string being banned (authstring or ip). + * @param flags Ban flags (only IP or AUTHID are valid here). + * @param command Command string to identify the ban source. + * @param source Source value passed via BanIdentity(). + * @return Plugin_Handled to block the actual server banning. + */ +forward Action:OnRemoveBan(const String:identity[], + flags, + const String:command[], + any:source); + +/** + * Bans a client. + * + * @param client Client being banned. + * @param time Time (in minutes) to ban (0 = permanent). + * @param flags Flags for controlling the ban mechanism. If AUTHID + * is set and no AUTHID is available, the ban will fail + * unless AUTO is also flagged. + * @param reason Reason to ban the client for. + * @param kick_message Message to display to the user when kicking. + * @param command Command string to identify the source. If this is left + * empty, then the OnBanClient forward will not be called. + * @param source A source value that could be interpreted as a player + * index of any sort (not actually checked by Core). + * @return True on success, false on failure. + * @error Invalid client index or client not in game. + */ +native bool:BanClient(client, + time, + flags, + const String:reason[], + const String:kick_message[]="", + const String:command[]="", + any:source=0); + +/** + * Bans an identity (either an IP address or auth string). + * + * @param identity String to ban (ip or authstring). + * @param time Time to ban for (0 = permanent). + * @param flags Flags (only IP and AUTHID are valid flags here). + * @param reason Ban reason string. + * @param command Command string to identify the source. If this is left + * empty, then the OnBanIdentity forward will not be called. + * @param source A source value that could be interpreted as a player + * index of any sort (not actually checked by Core). + * @return True on success, false on failure. + */ +native bool:BanIdentity(const String:identity[], + time, + flags, + const String:reason[], + const String:command[]="", + any:source=0); + +/** + * Removes a ban that was written to the server (either in memory or on disk). + * + * @param identity String to unban (ip or authstring). + * @param flags Flags (only IP and AUTHID are valid flags here). + * @param command Command string to identify the source. If this is left + * empty, then OnRemoveBan will not be called. + * @param source A source value that could be interpreted as a player + * index of any sort (not actually checked by Core). + * @return True on success, false on failure. + */ +native bool:RemoveBan(const String:identity[], + flags, + const String:command[]="", + any:source=0); + diff --git a/env/include/bitbuffer.inc b/env/include/bitbuffer.inc new file mode 100644 index 0000000..fd1c18e --- /dev/null +++ b/env/include/bitbuffer.inc @@ -0,0 +1,325 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _bitbuffer_included + #endinput +#endif +#define _bitbuffer_included + +/** + * Writes a single bit to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param bit Bit to write (true for 1, false for 0). + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteBool(Handle:bf, bool:bit); + +/** + * Writes a byte to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param byte Byte to write (value will be written as 8bit). + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteByte(Handle:bf, byte); + +/** + * Writes a byte to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param chr Character to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteChar(Handle:bf, chr); + +/** + * Writes a 16bit integer to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param num Integer to write (value will be written as 16bit). + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteShort(Handle:bf, num); + +/** + * Writes a 16bit unsigned integer to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param num Integer to write (value will be written as 16bit). + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteWord(Handle:bf, num); + +/** + * Writes a normal integer to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param num Integer to write (value will be written as 32bit). + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteNum(Handle:bf, num); + +/** + * Writes a floating point number to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param num Number to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteFloat(Handle:bf, Float:num); + +/** + * Writes a string to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param string Text string to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteString(Handle:bf, const String:string[]); + +/** + * Writes an entity to a writable bitbuffer (bf_write). + * @note This is a wrapper around BfWriteShort(). + * + * @param bf bf_write handle to write to. + * @param ent Entity index to write. + * @noreturn + * @error Invalid or incorrect Handle, or invalid entity. + */ +native BfWriteEntity(Handle:bf, ent); + +/** + * Writes a bit angle to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param angle Angle to write. + * @param numBits Optional number of bits to use. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteAngle(Handle:bf, Float:angle, numBits=8); + +/** + * Writes a coordinate to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param coord Coordinate to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteCoord(Handle:bf, Float:coord); + +/** + * Writes a 3D vector of coordinates to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param coord Coordinate array to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteVecCoord(Handle:bf, Float:coord[3]); + +/** + * Writes a 3D normal vector to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param vec Vector to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteVecNormal(Handle:bf, Float:vec[3]); + +/** + * Writes a 3D angle vector to a writable bitbuffer (bf_write). + * + * @param bf bf_write handle to write to. + * @param angles Angle vector to write. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfWriteAngles(Handle:bf, Float:angles[3]); + +/** + * Reads a single bit from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Bit value read. + * @error Invalid or incorrect Handle. + */ +native bool:BfReadBool(Handle:bf); + +/** + * Reads a byte from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Byte value read (read as 8bit). + * @error Invalid or incorrect Handle. + */ +native BfReadByte(Handle:bf); + +/** + * Reads a character from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Character value read. + * @error Invalid or incorrect Handle. + */ +native BfReadChar(Handle:bf); + +/** + * Reads a 16bit integer from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Integer value read (read as 16bit). + * @error Invalid or incorrect Handle. + */ +native BfReadShort(Handle:bf); + +/** + * Reads a 16bit unsigned integer from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Integer value read (read as 16bit). + * @error Invalid or incorrect Handle. + */ +native BfReadWord(Handle:bf); + +/** + * Reads a normal integer to a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Integer value read (read as 32bit). + * @error Invalid or incorrect Handle. + */ +native BfReadNum(Handle:bf); + +/** + * Reads a floating point number from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Floating point value read. + * @error Invalid or incorrect Handle. + */ +native Float:BfReadFloat(Handle:bf); + +/** + * Reads a string from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param line If true the buffer will be copied until it reaches a '\n' or a null terminator. + * @return Number of bytes written to the buffer. If the bitbuffer stream overflowed, + * that is, had no terminator before the end of the stream, then a negative + * number will be returned equal to the number of characters written to the + * buffer minus 1. The buffer will be null terminated regardless of the + * return value. + * @error Invalid or incorrect Handle. + */ +native BfReadString(Handle:bf, String:buffer[], maxlength, bool:line=false); + +/** + * Reads an entity from a readable bitbuffer (bf_read). + * @note This is a wrapper around BfReadShort(). + * + * @param bf bf_read handle to read from. + * @return Entity index read. + * @error Invalid or incorrect Handle. + */ +native BfReadEntity(Handle:bf); + +/** + * Reads a bit angle from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @param numBits Optional number of bits to use. + * @return Angle read. + * @error Invalid or incorrect Handle. + */ +native Float:BfReadAngle(Handle:bf, numBits=8); + +/** + * Reads a coordinate from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Coordinate read. + * @error Invalid or incorrect Handle. + */ +native Float:BfReadCoord(Handle:bf); + +/** + * Reads a 3D vector of coordinates from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @param coord Destination coordinate array. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfReadVecCoord(Handle:bf, Float:coord[3]); + +/** + * Reads a 3D normal vector from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @param vec Destination vector array. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfReadVecNormal(Handle:bf, Float:vec[3]); + +/** + * Reads a 3D angle vector from a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @param angles Destination angle vector. + * @noreturn + * @error Invalid or incorrect Handle. + */ +native BfReadAngles(Handle:bf, Float:angles[3]); + +/** + * Returns the number of bytes left in a readable bitbuffer (bf_read). + * + * @param bf bf_read handle to read from. + * @return Number of bytes left unread. + * @error Invalid or incorrect Handle. + */ +native BfGetNumBytesLeft(Handle:bf); diff --git a/env/include/clientprefs.inc b/env/include/clientprefs.inc new file mode 100644 index 0000000..5466399 --- /dev/null +++ b/env/include/clientprefs.inc @@ -0,0 +1,254 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _clientprefs_included + #endinput +#endif +#define _clientprefs_included + +/** + * Cookie access types for client viewing + */ +enum CookieAccess +{ + CookieAccess_Public, /**< Visible and Changeable by users */ + CookieAccess_Protected, /**< Read only to users */ + CookieAccess_Private, /**< Completely hidden cookie */ +}; + +/** + * Cookie Prefab menu types + */ +enum CookieMenu +{ + CookieMenu_YesNo, /**< Yes/No menu with "yes"/"no" results saved into the cookie */ + CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */ + CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */ + CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */ +}; + +enum CookieMenuAction +{ + /** + * An option is being drawn for a menu. + * + * INPUT : Client index and data if available. + * OUTPUT: Buffer for rendering, maxlength of buffer. + */ + CookieMenuAction_DisplayOption = 0, + + /** + * A menu option has been selected. + * + * INPUT : Client index and any data if available. + */ + CookieMenuAction_SelectOption = 1, +}; + +/** + * Note: + * + * A successful return value/result on any client prefs native only guarantees that the local cache has been updated. + * Database connection problems can still prevent the data from being permanently saved. Connection problems will be logged as + * errors by the clientprefs extension. + */ + +/** + * Creates a new Client preference cookie. + * + * Handles returned by RegClientCookie can be closed via CloseHandle() when + * no longer needed. + * + * @param name Name of the new preference cookie. + * @param description Optional description of the preference cookie. + * @param access What CookieAccess level to assign to this cookie. + * @return A handle to the newly created cookie. If the cookie already + * exists, a handle to it will still be returned. + * @error Cookie name is blank. + */ +native Handle:RegClientCookie(const String:name[], const String:description[], CookieAccess:access); + +/** + * Searches for a Client preference cookie. + * + * Handles returned by FindClientCookie can be closed via CloseHandle() when + * no longer needed. + * + * @param name Name of cookie to find. + * @return A handle to the cookie if it is found. INVALID_HANDLE otherwise. + */ +native Handle:FindClientCookie(const String:name[]); + +/** + * Set the value of a Client preference cookie. + * + * @param client Client index. + * @param cookie Client preference cookie handle. + * @param value String value to set. + * @noreturn + * @error Invalid cookie handle or invalid client index. + */ +native SetClientCookie(client, Handle:cookie, const String:value[]); + +/** + * Retrieve the value of a Client preference cookie. + * + * @param client Client index. + * @param cookie Client preference cookie handle. + * @param buffer Copyback buffer for value. + * @param maxlen Maximum length of the buffer. + * @noreturn + * @error Invalid cookie handle or invalid client index. + */ +native GetClientCookie(client, Handle:cookie, String:buffer[], maxlen); + +/** + * Checks if a clients cookies have been loaded from the database. + * + * @param client Client index. + * @return True if loaded, false otherwise. + * @error Invalid client index. + */ +native bool:AreClientCookiesCached(client); + +/** + * Called once a client's saved cookies have been loaded from the database. + * + * @param client Client index. + */ +forward OnClientCookiesCached(client); + +/** + * Cookie Menu Callback prototype + * + * @param client Client index. + * @param action CookeMenuAction being performed. + * @param data Info data passed. + * @param buffer Outbut buffer. + * @param maxlen Max length of the output buffer. + */ +functag public CookieMenuHandler(client, CookieMenuAction:action, any:info, String:buffer[], maxlen); + +/** + * Add a new prefab item to the client cookie settings menu. + * + * Note: This handles everything automatically and does not require a callback + * + * @param cookie Client preference cookie handle. + * @param type A CookieMenu prefab menu type. + * @param display Text to show on the menu. + * @param handler Optional handler callback for translations and output on selection + * @param info Info data to pass to the callback. + * @noreturn + * @error Invalid cookie handle. + */ +native SetCookiePrefabMenu(Handle:cookie, CookieMenu:type, const String:display[], CookieMenuHandler:handler=CookieMenuHandler:-1, info=0); + +/** + * Adds a new item to the client cookie settings menu. + * + * Note: This only adds the top level menu item. You need to handle any submenus from the callback. + * + * @param handler A MenuHandler callback function. + * @param info Data to pass to the callback. + * @param display Text to show on the menu. + * @noreturn + * @error Invalid cookie handle. + */ +native SetCookieMenuItem(CookieMenuHandler:handler, any:info, const String:display[]); + +/** + * Displays the settings menu to a client. + * + * @param client Client index. + * @noreturn + */ +native ShowCookieMenu(client); + +/** + * Gets a cookie iterator. Must be freed with CloseHandle(). + * + * @return A new cookie iterator. + */ +native Handle:GetCookieIterator(); + +/** + * Reads a cookie iterator, then advances to the next cookie if any. + * + * @param iter Cookie iterator Handle. + * @param name Name buffer. + * @param nameLen Name buffer size. + * @param access Access level of the cookie. + * @param desc Cookie description buffer. + * @param descLen Cookie description buffer size. + * @param + * @return True on success, false if there are no more commands. + */ +native bool:ReadCookieIterator(Handle:iter, + String:name[], + nameLen, + &CookieAccess:access, + String:desc[]="", + descLen=0); + +/** + * Returns the access level of a cookie + * + * @param cookie Client preference cookie handle. + * @return CookieAccess access level. + * @error Invalid cookie handle. + */ +native CookieAccess:GetCookieAccess(Handle:cookie); + +/** + * Returns the last updated timestamp for a client cookie + * + * @param client Client index. + * @param cookie Cookie handle. + * @return Last updated timestamp. + */ +native GetClientCookieTime(client, Handle:cookie); + +/** + * Do not edit below this line! + */ +public Extension:__ext_clientprefs = +{ + name = "Client Preferences", + file = "clientprefs.ext", + autoload = 1, +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/env/include/clients.inc b/env/include/clients.inc new file mode 100644 index 0000000..3b70a8d --- /dev/null +++ b/env/include/clients.inc @@ -0,0 +1,730 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _clients_included + #endinput +#endif +#define _clients_included + +/** + * Network flow directions. + */ +enum NetFlow +{ + NetFlow_Outgoing = 0, /**< Outgoing traffic */ + NetFlow_Incoming, /**< Incoming traffic */ + NetFlow_Both, /**< Both values added together */ +}; + +/** + * MAXPLAYERS is not the same as MaxClients. + * MAXPLAYERS is a hardcoded value as an upper limit. MaxClients changes based on the server. + * + * Both GetMaxClients() and MaxClients are only available once the map is loaded, and should + * not be used in OnPluginStart(). + */ + +#define MAXPLAYERS 64 /**< Maximum number of players SourceMod supports */ +#define MAX_NAME_LENGTH 32 /**< Maximum buffer required to store a client name */ + +public const MaxClients; /**< Maximum number of players the server supports (dynamic) */ + +/** + * Called on client connection. If you return true, the client will be allowed in the server. + * If you return false (or return nothing), the client will be rejected. If the client is + * rejected by this forward or any other, OnClientDisconnect will not be called. + * + * Note: Do not write to rejectmsg if you plan on returning true. If multiple plugins write + * to the string buffer, it is not defined which plugin's string will be shown to the client, + * but it is guaranteed one of them will. + * + * @param client Client index. + * @param rejectmsg Buffer to store the rejection message when the connection is refused. + * @param maxlen Maximum number of characters for rejection buffer. + * @return True to validate client's connection, false to refuse it. + */ +forward bool:OnClientConnect(client, String:rejectmsg[], maxlen); + +/** + * Called once a client successfully connects. This callback is paired with OnClientDisconnect. + * + * @param client Client index. + * @noreturn + */ +forward OnClientConnected(client); + +/** + * Called when a client is entering the game. + * + * Whether a client has a steamid is undefined until OnClientAuthorized + * is called, which may occur either before or after OnClientPutInServer. + * Similarly, use OnClientPostAdminCheck() if you need to verify whether + * connecting players are admins. + * + * GetClientCount() will include clients as they are passed through this + * function, as clients are already in game at this point. + * + * @param client Client index. + * @noreturn + */ +forward OnClientPutInServer(client); + +/** + * Called when a client is disconnecting from the server. + * + * @param client Client index. + * @noreturn + */ +forward OnClientDisconnect(client); + +/** + * Called when a client is disconnected from the server. + * + * @param client Client index. + * @noreturn + */ +forward OnClientDisconnect_Post(client); + +/** + * Called when a client is sending a command. + * + * As of SourceMod 1.3, the client is guaranteed to be in-game. + * Use command listeners (console.inc) for more advanced hooks. + * + * @param client Client index. + * @param args Number of arguments. + * @noreturn + */ +forward Action:OnClientCommand(client, args); + +/** + * Called whenever the client's settings are changed. + * + * @param client Client index. + * @noreturn + */ +forward OnClientSettingsChanged(client); + +/** + * Called when a client receives a Steam ID. The state of a client's + * authorization as an admin is not guaranteed here. Use + * OnClientPostAdminCheck() if you need a client's admin status. + * + * This is called by bots, but the ID will be "BOT". + * + * @param client Client index. + * @param auth Client auth string. + * @noreturn + */ +forward OnClientAuthorized(client, const String:auth[]); + +/** + * Called once a client is authorized and fully in-game, but + * before admin checks are done. This can be used to override + * the default admin checks for a client. You should only use + * this for overriding; use OnClientPostAdminCheck() instead + * if you want notification. + * + * Note: If handled/blocked, PostAdminCheck must be signalled + * manually via NotifyPostAdminCheck(). + * + * This callback is gauranteed to occur on all clients, and always + * after each OnClientPutInServer() call. + * + * @param client Client index. + * @return Plugin_Handled to block admin checks. + */ +forward Action:OnClientPreAdminCheck(client); + +/** + * Called directly before OnClientPostAdminCheck() as a method to + * alter administrative permissions before plugins perform final + * post-connect operations. + * + * In general, do not use this function unless you are specifically + * attempting to change access permissions. Use OnClientPostAdminCheck() + * instead if you simply want to perform post-connect authorization + * routines. + * + * See OnClientPostAdminCheck() for more information. + * + * @param client Client index. + * @noreturn + */ +forward OnClientPostAdminFilter(client); + +/** + * Called once a client is authorized and fully in-game, and + * after all post-connection authorizations have been performed. + * + * This callback is gauranteed to occur on all clients, and always + * after each OnClientPutInServer() call. + * + * @param client Client index. + * @noreturn + */ +forward OnClientPostAdminCheck(client); + +/** + * This function will be deprecated in a future release. Use the MaxClients variable instead. + * + * Returns the maximum number of clients allowed on the server. This may + * return 0 if called before OnMapStart(), and thus should not be called + * in OnPluginStart(). + * + * You should not globally cache the value to GetMaxClients() because it can change from + * SourceTV or TF2's arena mode. Use the "MaxClients" dynamic variable documented at the + * top of this file. + * + * @return Maximum number of clients allowed. + */ +native GetMaxClients(); + +/** + * Returns the client count put in the server. + * + * @param inGameOnly If false connecting players are also counted. + * @return Client count in the server. + */ +native GetClientCount(bool:inGameOnly=true); + +/** + * Returns the client's name. + * + * @param client Player index. + * @param name Buffer to store the client's name. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @return True on success, false otherwise. + * @error If the client is not connected an error will be thrown. + */ +native bool:GetClientName(client, String:name[], maxlen); + +/** + * Retrieves a client's IP address. + * + * @param client Player index. + * @param name Buffer to store the client's ip address. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @param remport Remove client's port from the ip string (true by default). + * @return True on success, false otherwise. + * @error If the client is not connected or the index is invalid. + */ +native bool:GetClientIP(client, String:ip[], maxlen, bool:remport=true); + +/** + * Retrieves a client's authentication string (SteamID). + * + * @param client Player index. + * @param auth Buffer to store the client's auth string. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @return True on success, false otherwise. + * @error If the client is not connected or the index is invalid. + */ +native bool:GetClientAuthString(client, String:auth[], maxlen); + +/** + * Retrieves a client's user id, which is an index incremented for every client + * that joins the server. + * + * @param client Player index. + * @return User id of the client. + * @error If the client is not connected or the index is invalid. + */ +native GetClientUserId(client); + +/** + * Returns if a certain player is connected. + * + * @param client Player index. + * @return True if player is connected to the server, false otherwise. + */ +native bool:IsClientConnected(client); + +/** + * Returns if a certain player has entered the game. + * + * @param client Player index (index does not have to be connected). + * @return True if player has entered the game, false otherwise. + * @error Invalid client index. + */ +native bool:IsClientInGame(client); + +/** + * Returns if a client is in the "kick queue" (i.e. the client will be kicked + * shortly and thus they should not appear as valid). + * + * @param client Player index (must be connected). + * @return True if in the kick queue, false otherwise. + * @error Invalid client index. + */ +native bool:IsClientInKickQueue(client); + +/** + * Backwards compatibility stock - use IsClientInGame + * @deprecated Renamed to IsClientInGame + */ +#pragma deprecated Use IsClientInGame() instead +stock bool:IsPlayerInGame(client) +{ + return IsClientInGame(client); +} + +/** + * Returns if a certain player has been authenticated. + * + * @param client Player index. + * @return True if player has been authenticated, false otherwise. + */ +native bool:IsClientAuthorized(client); + +/** + * Returns if a certain player is a fake client. + * + * @param client Player index. + * @return True if player is a fake client, false otherwise. + */ +native bool:IsFakeClient(client); + +/** + * Returns if a certain player is an observer/spectator. + * + * @param client Player index. + * @return True if player is an obverser, false otherwise. + */ +native bool:IsClientObserver(client); + +/** + * Returns if the client is alive or dead. + * + * Note: This function was originally in SDKTools and was moved to core. + * + * @param client Player's index. + * @return True if the client is alive, false otherwise. + * @error Invalid client index, client not in game, or no mod support. + */ +native bool:IsPlayerAlive(client); + +/** + * Retrieves values from client replicated keys. + * + * @param client Player's index. + * @param key Key string. + * @param value Buffer to store value. + * @param maxlen Maximum length of valve (UTF-8 safe). + * @return True on success, false otherwise. + * @error Invalid client index, or client not connected. + */ +native bool:GetClientInfo(client, const String:key[], String:value[], maxlen); + +/** + * Retrieves a client's team index. + * + * @param client Player's index. + * @return Team index the client is on (mod specific). + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientTeam(client); + +/** + * Sets a client's AdminId. + * + * @param client Player's index. + * @param id AdminId to set. INVALID_ADMIN_ID removes admin permissions. + * @param temp True if the id should be freed on disconnect. + * @noreturn + * @error Invalid client index, client not connected, or bogus AdminId. + */ +native SetUserAdmin(client, AdminId:id, bool:temp=false); + +/** + * Retrieves a client's AdminId. + * + * @param client Player's index. + * @return AdminId of the client, or INVALID_ADMIN_ID if none. + * @error Invalid client index, or client not connected. + */ +native AdminId:GetUserAdmin(client); + +/** + * Sets access flags on a client. If the client is not an admin, + * a temporary, anonymous AdminId is given. + * + * @param client Player's index. + * @param ... Flags to set on the client. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native AddUserFlags(client, AdminFlag:...); + +/** + * Removes flags from a client. If the client is not an admin, + * this has no effect. + * + * @param client Player's index. + * @param ... Flags to remove from the client. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native RemoveUserFlags(client, AdminFlag:...); + +/** + * Sets access flags on a client using bits instead of flags. If the + * client is not an admin, and flags not 0, a temporary, anonymous AdminId is given. + * + * @param client Player's index. + * @param flags Bitstring of flags to set on client. + * @noreturn + */ +native SetUserFlagBits(client, flags); + +/** + * Returns client access flags. If the client is not an admin, + * the result is always 0. + * + * @param client Player's index. + * @return Flags + * @error Invalid client index, or client not connected. + */ +native GetUserFlagBits(client); + +/** + * Returns whether a user can target another user. + * This is a helper function for CanAdminTarget. + * + * @param client Player's index. + * @param target Target player's index. + * @return True if target is targettable by the player, false otherwise. + * @error Invalid or unconnected player indexers. + */ +native bool:CanUserTarget(client, target); + +/** + * Runs through the Core-defined admin authorization checks on a player. + * Has no effect if the player is already an admin. + * + * Note: This function is based on the internal cache only. + * + * @param client Client index. + * @return True if access was changed, false if it did not. + * @error Invalid client index or client not in-game AND authorized. + */ +native bool:RunAdminCacheChecks(client); + +/** + * Signals that a player has completed post-connection admin checks. + * Has no effect if the player has already had this event signalled. + * + * Note: This must be sent even if no admin id was assigned. + * + * @param client Client index. + * @noreturn + * @error Invalid client index or client not in-game AND authorized. + */ +native NotifyPostAdminCheck(client); + +/** + * Creates a fake client. + * + * @param name Name to use. + * @return Client index on success, 0 otherwise. + */ +native CreateFakeClient(const String:name[]); + +/** + * Sets a convar value on a fake client. + * + * @param client Client index. + * @param cvar ConVar name. + * @param value ConVar value. + * @noreturn + * @error Invalid client index, client not connected, + * or client not a fake client. + */ +native SetFakeClientConVar(client, const String:cvar[], const String:value[]); + +/** + * Returns the client's health. + * + * @param client Player's index. + * @return Health value. + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientHealth(client); + +/** + * Returns the client's model name. + * + * @param client Player's index. + * @param model Buffer to store the client's model name. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientModel(client, String:model[], maxlen); + +/** + * Returns the client's weapon name. + * + * @param client Player's index. + * @param weapon Buffer to store the client's weapon name. + * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientWeapon(client, String:weapon[], maxlen); + +/** + * Returns the client's max size vector. + * + * @param client Player's index. + * @param vec Destination vector to store the client's max size. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientMaxs(client, Float:vec[3]); + +/** + * Returns the client's min size vector. + * + * @param client Player's index. + * @param vec Destination vector to store the client's min size. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientMins(client, Float:vec[3]); + +/** + * Returns the client's position angle. + * + * @param client Player's index. + * @param ang Destination vector to store the client's position angle. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientAbsAngles(client, Float:ang[3]); + +/** + * Returns the client's origin vector. + * + * @param client Player's index. + * @param vec Destination vector to store the client's origin vector. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientAbsOrigin(client, Float:vec[3]); + +/** + * Returns the client's armor. + * + * @param client Player's index. + * @return Armor value. + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientArmor(client); + +/** + * Returns the client's death count. + * + * @param client Player's index. + * @return Death count. + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientDeaths(client); + +/** + * Returns the client's frag count. + * + * @param client Player's index. + * @return Frag count. + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientFrags(client); + +/** + * Returns the client's send data rate in bytes/sec. + * + * @param client Player's index. + * @return Data rate. + * @error Invalid client index, client not in game, or fake client. + */ +native GetClientDataRate(client); + +/** + * Returns if a client is timing out + * + * @param client Player's index. + * @return True if client is timing out, false otherwise. + * @error Invalid client index, client not in game, or fake client. + */ +native bool:IsClientTimingOut(client); + +/** + * Returns the client's connection time in seconds. + * + * @param client Player's index. + * @return Connection time. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientTime(client); + +/** + * Returns the client's current latency (RTT), more accurate than GetAvgLatency but jittering. + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Latency. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientLatency(client, NetFlow:flow); + +/** + * Returns the client's average packet latency in seconds. + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Average latency. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientAvgLatency(client, NetFlow:flow); + +/** + * Returns the client's average packet loss, values go from 0 to 1 (for percentages). + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Average packet loss. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientAvgLoss(client, NetFlow:flow); + +/** + * Returns the client's average packet choke, values go from 0 to 1 (for percentages). + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Average packet choke. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientAvgChoke(client, NetFlow:flow); + +/** + * Returns the client's data flow in bytes/sec. + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Data flow. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientAvgData(client, NetFlow:flow); + +/** + * Returns the client's average packet frequency in packets/sec. + * + * @param client Player's index. + * @param flow Traffic flowing direction. + * @return Packet frequency. + * @error Invalid client index, client not in game, or fake client. + */ +native Float:GetClientAvgPackets(client, NetFlow:flow); + +/** + * Translates an userid index to the real player index. + * + * @param userid Userid value. + * @return Client value. + * @error Returns 0 if invalid userid. + */ +native GetClientOfUserId(userid); + +/** + * Disconnects a client from the server as soon as the next frame starts. + * + * Note: Originally, KickClient() was immediate. The delay was introduced + * because despite warnings, plugins were using it in ways that would crash. + * The new safe version can break cases that rely on immediate disconnects, + * but ensures that plugins do not accidentally cause crashes. + * + * If you need immediate disconnects, use KickClientEx(). + * + * Note: IsClientInKickQueue() will return true before the kick occurs. + * + * @param client Client index. + * @param format Optional formatting rules for disconnect reason. + * Note that a period is automatically appended to the string by the engine. + * @param ... Variable number of format parameters. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native KickClient(client, const String:format[]="", any:...); + +/** + * Immediately disconnects a client from the server. + * + * Kicking clients from certain events or callbacks may cause crashes. If in + * doubt, create a short (0.1 second) timer to kick the client in the next + * available frame. + * + * @param client Client index. + * @param format Optional formatting rules for disconnect reason. + * Note that a period is automatically appended to the string by the engine. + * @param ... Variable number of format parameters. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native KickClientEx(client, const String:format[]="", any:...); + +/** + * Changes a client's team through the mod's generic team changing function. + * On CS:S, this will kill the player. + * + * @param client Client index. + * @param team Mod-specific team index. + * @noreturn + * @error Invalid client index, client not connected, or lack of + * mod support. + */ +native ChangeClientTeam(client, team); + +/** + * Returns the clients unique serial identifier. + * + * @return Serial number. + */ +native GetClientSerial(client); + +/** + * Returns the client index by its serial number. + * + * @return Client index, or 0 for invalid serial. + */ +native GetClientFromSerial(serial); + diff --git a/env/include/commandfilters.inc b/env/include/commandfilters.inc new file mode 100644 index 0000000..1143627 --- /dev/null +++ b/env/include/commandfilters.inc @@ -0,0 +1,134 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _commandfilters_included + #endinput +#endif +#define _commandfilters_included + +#define MAX_TARGET_LENGTH 64 + +#define COMMAND_FILTER_ALIVE (1<<0) /**< Only allow alive players */ +#define COMMAND_FILTER_DEAD (1<<1) /**< Only filter dead players */ +#define COMMAND_FILTER_CONNECTED (1<<2) /**< Allow players not fully in-game */ +#define COMMAND_FILTER_NO_IMMUNITY (1<<3) /**< Ignore immunity rules */ +#define COMMAND_FILTER_NO_MULTI (1<<4) /**< Do not allow multiple target patterns */ +#define COMMAND_FILTER_NO_BOTS (1<<5) /**< Do not allow bots to be targetted */ + +#define COMMAND_TARGET_NONE 0 /**< No target was found */ +#define COMMAND_TARGET_NOT_ALIVE -1 /**< Single client is not alive */ +#define COMMAND_TARGET_NOT_DEAD -2 /**< Single client is not dead */ +#define COMMAND_TARGET_NOT_IN_GAME -3 /**< Single client is not in game */ +#define COMMAND_TARGET_IMMUNE -4 /**< Single client is immune */ +#define COMMAND_TARGET_EMPTY_FILTER -5 /**< A multi-filter (such as @all) had no targets */ +#define COMMAND_TARGET_NOT_HUMAN -6 /**< Target was not human */ +#define COMMAND_TARGET_AMBIGUOUS -7 /**< Partial name had too many targets */ + +/** + * Processes a generic command target string, and resolves it to a list + * of clients or one client, based on filtering rules and a pattern. + * + * Note that you should use LoadTranslations("common.phrases") in OnPluginStart(), + * as that file is guaranteed to contain all of the translatable phrases that + * ProcessTargetString() will return. + * + * @param pattern Pattern to find clients against. + * @param admin Admin performing the action, or 0 if the server. + * @param targets Array to hold targets. + * @param max_targets Maximum size of the targets array. + * @param filter_flags Filter flags. + * @param target_name Buffer to store the target name. + * @param tn_maxlength Maximum length of the target name buffer. + * @param tn_is_ml OUTPUT: Will be true if the target name buffer is an ML phrase, + * false if it is a normal string. + * @return If a multi-target pattern was used, the number of clients found + * is returned. If a single-target pattern was used, 1 is returned + * if one valid client is found. Otherwise, a COMMAND_TARGET reason + * for failure is returned. + */ +native ProcessTargetString(const String:pattern[], + admin, + targets[], + max_targets, + filter_flags, + String:target_name[], + tn_maxlength, + &bool:tn_is_ml); + +/** + * Replies to a client with a given message describing a targetting + * failure reason. + * + * Note: The translation phrases are found in common.phrases.txt. + * + * @param client Client index, or 0 for server. + * @param reason COMMAND_TARGET reason. + * @noreturn + */ +stock ReplyToTargetError(client, reason) +{ + switch (reason) + { + case COMMAND_TARGET_NONE: + { + ReplyToCommand(client, "[SM] %t", "No matching client"); + } + case COMMAND_TARGET_NOT_ALIVE: + { + ReplyToCommand(client, "[SM] %t", "Target must be alive"); + } + case COMMAND_TARGET_NOT_DEAD: + { + ReplyToCommand(client, "[SM] %t", "Target must be dead"); + } + case COMMAND_TARGET_NOT_IN_GAME: + { + ReplyToCommand(client, "[SM] %t", "Target is not in game"); + } + case COMMAND_TARGET_IMMUNE: + { + ReplyToCommand(client, "[SM] %t", "Unable to target"); + } + case COMMAND_TARGET_EMPTY_FILTER: + { + ReplyToCommand(client, "[SM] %t", "No matching clients"); + } + case COMMAND_TARGET_NOT_HUMAN: + { + ReplyToCommand(client, "[SM] %t", "Cannot target bot"); + } + case COMMAND_TARGET_AMBIGUOUS: + { + ReplyToCommand(client, "[SM] %t", "More than one client matched"); + } + } +} diff --git a/env/include/console.inc b/env/include/console.inc new file mode 100644 index 0000000..b6d3489 --- /dev/null +++ b/env/include/console.inc @@ -0,0 +1,891 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _console_included + #endinput +#endif +#define _console_included + +#define INVALID_FCVAR_FLAGS (-1) + +/** + * Console variable bound values used with Get/SetConVarBounds() + */ +enum ConVarBounds +{ + ConVarBound_Upper = 0, + ConVarBound_Lower +}; + +/** + * Console variable query helper values. + */ +enum QueryCookie +{ + QUERYCOOKIE_FAILED = 0, +}; + +/** + * Reply sources for commands. + */ +enum ReplySource +{ + SM_REPLY_TO_CONSOLE = 0, + SM_REPLY_TO_CHAT = 1, +}; + +/** + * Console variable query result values. + */ +enum ConVarQueryResult +{ + ConVarQuery_Okay = 0, /**< Retrieval of client convar value was successful. */ + ConVarQuery_NotFound, /**< Client convar was not found. */ + ConVarQuery_NotValid, /**< A console command with the same name was found, but there is no convar. */ + ConVarQuery_Protected /**< Client convar was found, but it is protected. The server cannot retrieve its value. */ +}; + +/** + * @section Flags for console commands and console variables. The descriptions + * for each constant come directly from the Source SDK. + */ +#define FCVAR_NONE 0 /**< The default, no flags at all */ +#define FCVAR_UNREGISTERED (1<<0) /**< If this is set, don't add to linked list, etc. */ +#define FCVAR_LAUNCHER (1<<1) /**< Defined by launcher. */ +#define FCVAR_GAMEDLL (1<<2) /**< Defined by the game DLL. */ +#define FCVAR_CLIENTDLL (1<<3) /**< Defined by the client DLL. */ +#define FCVAR_MATERIAL_SYSTEM (1<<4) /**< Defined by the material system. */ +#define FCVAR_PROTECTED (1<<5) /**< It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value. */ +#define FCVAR_SPONLY (1<<6) /**< This cvar cannot be changed by clients connected to a multiplayer server. */ +#define FCVAR_ARCHIVE (1<<7) /**< Set to cause it to be saved to vars.rc */ +#define FCVAR_NOTIFY (1<<8) /**< Notifies players when changed. */ +#define FCVAR_USERINFO (1<<9) /**< Changes the client's info string. */ +#define FCVAR_PRINTABLEONLY (1<<10) /**< This cvar's string cannot contain unprintable characters (e.g., used for player name, etc.) */ +#define FCVAR_UNLOGGED (1<<11) /**< If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log */ +#define FCVAR_NEVER_AS_STRING (1<<12) /**< Never try to print that cvar. */ +#define FCVAR_REPLICATED (1<<13) /**< Server setting enforced on clients. */ +#define FCVAR_CHEAT (1<<14) /**< Only useable in singleplayer / debug / multiplayer & sv_cheats */ +#define FCVAR_STUDIORENDER (1<<15) /**< Defined by the studiorender system. */ +#define FCVAR_DEMO (1<<16) /**< Record this cvar when starting a demo file. */ +#define FCVAR_DONTRECORD (1<<17) /**< Don't record these command in demo files. */ +#define FCVAR_PLUGIN (1<<18) /**< Defined by a 3rd party plugin. */ +#define FCVAR_DATACACHE (1<<19) /**< Defined by the datacache system. */ +#define FCVAR_TOOLSYSTEM (1<<20) /**< Defined by an IToolSystem library */ +#define FCVAR_FILESYSTEM (1<<21) /**< Defined by the file system. */ +#define FCVAR_NOT_CONNECTED (1<<22) /**< Cvar cannot be changed by a client that is connected to a server. */ +#define FCVAR_SOUNDSYSTEM (1<<23) /**< Defined by the soundsystem library. */ +#define FCVAR_ARCHIVE_XBOX (1<<24) /**< Cvar written to config.cfg on the Xbox. */ +#define FCVAR_INPUTSYSTEM (1<<25) /**< Defined by the inputsystem DLL. */ +#define FCVAR_NETWORKSYSTEM (1<<26) /**< Defined by the network system. */ +#define FCVAR_VPHYSICS (1<<27) /**< Defined by vphysics. */ + +/** + * @endsection + */ + +/** + * Executes a server command as if it were on the server console (or RCON) + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +native ServerCommand(const String:format[], any:...); + +/** + * Inserts a server command at the beginning of the server command buffer. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +native InsertServerCommand(const String:format[], any:...); + +/** + * Executes every command in the server's command buffer, rather than once per frame. + * + * @noreturn + */ +native ServerExecute(); + +/** + * Executes a client command. Note that this will not work on clients unless + * they have cl_restrict_server_commands set to 0. + * + * @param client Index of the client. + * @param fmt Format of the client command. + * @param ... Format parameters/ + * @noreturn + * @error Invalid client index, or client not connected. + */ +native ClientCommand(client, const String:fmt[], any:...); + +/** + * Executes a client command on the server without being networked. + * + * FakeClientCommand() overwrites the command tokenization buffer. This can + * cause undesired effects because future calls to GetCmdArg* will return + * data from the FakeClientCommand(), not the parent command. If you are in + * a hook where this matters (for example, a "say" hook), you should use + * FakeClientCommandEx() instead. + * + * @param client Index of the client. + * @param fmt Format of the client command. + * @param ... Format parameters + * @noreturn + * @error Invalid client index, or client not connected. + */ +native FakeClientCommand(client, const String:fmt[], any:...); + +/** + * Executes a client command on the server without being networked. The + * execution of the client command is delayed by one frame to prevent any + * re-entrancy issues that might surface with FakeClientCommand(). + * + * @param client Index of the client. + * @param fmt Format of the client command. + * @param ... Format parameters + * @noreturn + * @error Invalid client index, or client not connected. + */ +native FakeClientCommandEx(client, const String:fmt[], any:...); + +/** + * Sends a message to the server console. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +native PrintToServer(const String:format[], any:...); + +/** + * Sends a message to a client's console. + * + * @param client Client index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +native PrintToConsole(client, const String:format[], any:...); + +/** + * Reples to a message in a command. + * + * A client index of 0 will use PrintToServer(). + * If the command was from the console, PrintToConsole() is used. + * If the command was from chat, PrintToChat() is used. + * + * @param client Client index, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error If the client is not connected or invalid. + */ +native ReplyToCommand(client, const String:format[], any:...); + +/** + * Returns the current reply source of a command. + * + * @return ReplySource value. + */ +native ReplySource:GetCmdReplySource(); + +/** + * Sets the current reply source of a command. + * + * Only use this if you know what you are doing. You should save the old value + * and restore it once you are done. + * + * @param source New ReplySource value. + * @return Old ReplySource value. + */ +native ReplySource:SetCmdReplySource(ReplySource:source); + +/** + * Returns whether the current say hook is a chat trigger. + * + * This function is only meaningful inside say or say_team hooks. + * + * @return True if a chat trigger, false otherwise. + */ +native bool:IsChatTrigger(); + +/** + * Displays usage of an admin command to users depending on the + * setting of the sm_show_activity cvar. All users receive a message + * in their chat text, except for the originating client, who receives + * the message based on the current ReplySource. + * + * @param client Client index doing the action, or 0 for server. + * @param tag Tag to prepend to the message. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +native ShowActivity2(client, const String:tag[], const String:format[], any:...); + +/** + * Displays usage of an admin command to users depending on the + * setting of the sm_show_activity cvar. + * + * This version does not display a message to the originating client + * if used from chat triggers or menus. If manual replies are used + * for these cases, then this function will suffice. Otherwise, + * ShowActivity2() is slightly more useful. + * + * @param client Client index doing the action, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +native ShowActivity(client, const String:format[], any:...); + +/** + * Same as ShowActivity(), except the tag parameter is used instead of + * "[SM] " (note that you must supply any spacing). + * + * @param client Client index doing the action, or 0 for server. + * @param tag Tag to display with. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +native ShowActivityEx(client, const String:tag[], const String:format[], any:...); + +/** + * Given an originating client and a target client, returns the string + * that describes the originating client according to the sm_show_activity cvar. + * + * For example, "ADMIN", "PLAYER", or a player's name could be placed in this buffer. + * + * @param client Originating client; may be 0 for server console. + * @param target Targeted client. + * @param namebuf Name buffer. + * @param maxlength Maximum size of the name buffer. + * @return True if activity should be shown. False otherwise. In either + * case, the name buffer is filled. The return value can be used + * to broadcast a "safe" name to all players regardless of the + * sm_show_activity filters. + * @error Invalid client index or client not connected. + */ +native FormatActivitySource(client, target, const String:namebuf[], maxlength); + +/** + * Called when a server-only command is invoked. + * + * @params args Number of arguments that were in the argument string. + * @return An Action value. Not handling the command + * means that Source will report it as "not found." + */ +functag public Action:SrvCmd(args); + +/** + * Creates a server-only console command, or hooks an already existing one. + * + * Server commands are case sensitive. + * + * @param cmd Name of the command to hook or create. + * @param callback A function to use as a callback for when the command is invoked. + * @param description Optional description to use for command creation. + * @param flags Optional flags to use for command creation. + * @noreturn + * @error Command name is the same as an existing convar. + */ +native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0); + +/** + * Called when a generic console command is invoked. + * + * @param client Index of the client, or 0 from the server. + * @param args Number of arguments that were in the argument string. + * @return An Action value. Not handling the command + * means that Source will report it as "not found." + */ +functag public Action:ConCmd(client, args); + +/** + * Creates a console command, or hooks an already existing one. + * + * Console commands are case sensitive. However, if the command already exists in the game, + * the a client may enter the command in any case. SourceMod corrects for this automatically, + * and you should only hook the "real" version of the command. + * + * @param cmd Name of the command to hook or create. + * @param callback A function to use as a callback for when the command is invoked. + * @param description Optional description to use for command creation. + * @param flags Optional flags to use for command creation. + * @noreturn + * @error Command name is the same as an existing convar. + */ +native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0); + +/** + * Creates a console command as an administrative command. If the command does not exist, + * it is created. When this command is invoked, the access rights of the player are + * automatically checked before allowing it to continue. + * + * Admin commands are case sensitive from both the client and server. + * + * @param cmd String containing command to register. + * @param callback A function to use as a callback for when the command is invoked. + * @param adminflags Administrative flags (bitstring) to use for permissions. + * @param description Optional description to use for help. + * @param group String containing the command group to use. If empty, + * the plugin's filename will be used instead. + * @param flags Optional console flags. + * @noreturn + * @error Command name is the same as an existing convar. + */ +native RegAdminCmd(const String:cmd[], + ConCmd:callback, + adminflags, + const String:description[]="", + const String:group[]="", + flags=0); + +/** + * Returns the number of arguments from the current console or server command. + * @note Unlike the HL2 engine call, this does not include the command itself. + * + * @return Number of arguments to the current command. + */ +native GetCmdArgs(); + +/** + * Retrieves a command argument given its index, from the current console or + * server command. + * @note Argument indexes start at 1; 0 retrieves the command name. + * + * @param argnum Argument number to retrieve. + * @param buffer Buffer to use for storing the string. + * @param maxlength Maximum length of the buffer. + * @return Length of string written to buffer. + */ +native GetCmdArg(argnum, String:buffer[], maxlength); + +/** + * Retrieves the entire command argument string in one lump from the current + * console or server command. + * + * @param buffer Buffer to use for storing the string. + * @param maxlength Maximum length of the buffer. + * @return Length of string written to buffer. + */ +native GetCmdArgString(String:buffer[], maxlength); + +/** + * Creates a new console variable. + * + * @param name Name of new convar. + * @param defaultValue String containing the default value of new convar. + * @param description Optional description of the convar. + * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. + * @param hasMin Optional boolean that determines if the convar has a minimum value. + * @param min Minimum floating point value that the convar can have if hasMin is true. + * @param hasMax Optional boolean that determines if the convar has a maximum value. + * @param max Maximum floating point value that the convar can have if hasMax is true. + * @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned. + * @error Convar name is blank or is the same as an existing console command. + */ +native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0); + +/** + * Searches for a console variable. + * + * @param name Name of convar to find. + * @return A handle to the convar if it is found. INVALID_HANDLE otherwise. + */ +native Handle:FindConVar(const String:name[]); + +/** + * Called when a console variable's value is changed. + * + * @param convar Handle to the convar that was changed. + * @param oldValue String containing the value of the convar before it was changed. + * @param newValue String containing the new value of the convar. + * @noreturn + */ +functag public ConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]); + +/** + * Creates a hook for when a console variable's value is changed. + * + * @param convar Handle to the convar. + * @param callback An OnConVarChanged function pointer. + * @noreturn + * @error Invalid or corrupt Handle or invalid callback function. + */ +native HookConVarChange(Handle:convar, ConVarChanged:callback); + +/** + * Removes a hook for when a console variable's value is changed. + * + * @param convar Handle to the convar. + * @param callback An OnConVarChanged function pointer. + * @noreturn + * @error Invalid or corrupt Handle, invalid callback function, or no active hook on convar. + */ +native UnhookConVarChange(Handle:convar, ConVarChanged:callback); + +/** + * Returns the boolean value of a console variable. + * + * @param convar Handle to the convar. + * @return The boolean value of the convar. + * @error Invalid or corrupt Handle. + */ +native bool:GetConVarBool(Handle:convar); + +/** + * Sets the boolean value of a console variable. + * + * Note: The replicate and notify params are ignored on the engines for Episode 2/Orange Box + * and Left 4 Dead. These engines automatically replicates and notifies as soon as the convar + * is changed. + * + * @param convar Handle to the convar. + * @param value New boolean value. + * @param replicate If set to true, the new convar value will be set on all clients. + * This will only work if the convar has the FCVAR_REPLICATED flag + * and actually exists on clients. + * @param notify If set to true, clients will be notified that the convar has changed. + * This will only work if the convar has the FCVAR_NOTIFY flag. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarBool(Handle:convar, bool:value, bool:replicate=false, bool:notify=false); + +/** + * Returns the integer value of a console variable. + * + * @param convar Handle to the convar. + * @return The integer value of the convar. + * @error Invalid or corrupt Handle. + */ +native GetConVarInt(Handle:convar); + +/** + * Sets the integer value of a console variable. + * + * Note: The replicate and notify params are ignored on the engines for Episode 2/Orange Box + * and Left 4 Dead. These engines automatically replicates and notifies as soon as the convar + * is changed. + * + * @param convar Handle to the convar. + * @param value New integer value. + * @param replicate If set to true, the new convar value will be set on all clients. + * This will only work if the convar has the FCVAR_REPLICATED flag + * and actually exists on clients. + * @param notify If set to true, clients will be notified that the convar has changed. + * This will only work if the convar has the FCVAR_NOTIFY flag. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarInt(Handle:convar, value, bool:replicate=false, bool:notify=false); + +/** + * Returns the floating point value of a console variable. + * + * @param convar Handle to the convar. + * @return The floating point value of the convar. + * @error Invalid or corrupt Handle. + */ +native Float:GetConVarFloat(Handle:convar); + +/** + * Sets the floating point value of a console variable. + * + * Note: The replicate and notify params are ignored on the engines for Episode 2/Orange Box + * and Left 4 Dead. These engines automatically replicates and notifies as soon as the convar + * is changed. + * + * @param convar Handle to the convar. + * @param value New floating point value. + * @param replicate If set to true, the new convar value will be set on all clients. + * This will only work if the convar has the FCVAR_REPLICATED flag + * and actually exists on clients. + * @param notify If set to true, clients will be notified that the convar has changed. + * This will only work if the convar has the FCVAR_NOTIFY flag. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarFloat(Handle:convar, Float:value, bool:replicate=false, bool:notify=false); + +/** + * Retrieves the string value of a console variable. + * + * @param convar Handle to the convar. + * @param value Buffer to store the value of the convar. + * @param maxlength Maximum length of string buffer. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native GetConVarString(Handle:convar, String:value[], maxlength); + +/** + * Sets the string value of a console variable. + * + * Note: The replicate and notify params are ignored on the engines for Episode 2/Orange Box + * and Left 4 Dead. These engines automatically replicates and notifies as soon as the convar + * is changed. + * + * @param convar Handle to the convar. + * @param value New string value. + * @param replicate If set to true, the new convar value will be set on all clients. + * This will only work if the convar has the FCVAR_REPLICATED flag + * and actually exists on clients. + * @param notify If set to true, clients will be notified that the convar has changed. + * This will only work if the convar has the FCVAR_NOTIFY flag. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarString(Handle:convar, const String:value[], bool:replicate=false, bool:notify=false); + +/** + * Resets the console variable to its default value. + * + * Note: The replicate and notify params are ignored on the engines for Episode 2/Orange Box + * and Left 4 Dead. These engines automatically replicates and notifies as soon as the convar + * is changed. + * + * @param convar Handle to the convar. + * @param replicate If set to true, the new convar value will be set on all clients. + * This will only work if the convar has the FCVAR_REPLICATED flag + * and actually exists on clients. + * @param notify If set to true, clients will be notified that the convar has changed. + * This will only work if the convar has the FCVAR_NOTIFY flag. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native ResetConVar(Handle:convar, bool:replicate=false, bool:notify=false); + +/** + * Returns the bitstring of flags on a console variable. + * + * @param convar Handle to the convar. + * @return A bitstring containing the FCVAR_* flags that are enabled. + * @error Invalid or corrupt Handle. + */ +native GetConVarFlags(Handle:convar); + +/** + * Sets the bitstring of flags on a console variable. + * + * @param convar Handle to the convar. + * @param flags A bitstring containing the FCVAR_* flags to enable. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarFlags(Handle:convar, flags); + +/** + * Retrieves the specified bound of a console variable. + * + * @param convar Handle to the convar. + * @param type Type of bound to retrieve, ConVarBound_Lower or ConVarBound_Upper. + * @param value By-reference cell to store the specified floating point bound value. + * @return True if the convar has the specified bound set, false otherwise. + * @error Invalid or corrupt Handle. + */ +native bool:GetConVarBounds(Handle:convar, ConVarBounds:type, &Float:value); + +/** + * Sets the specified bound of a console variable. + * + * @param convar Handle to the convar. + * @param type Type of bound to set, ConVarBound_Lower or ConVarBound_Upper + * @param set If set to true, convar will use specified bound. If false, bound will be removed. + * @param value Floating point value to use as the specified bound. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetConVarBounds(Handle:convar, ConVarBounds:type, bool:set, Float:value=0.0); + +/** + * Retrieves the name of a console variable. + * + * @param convar Handle to the convar. + * @param value Buffer to store the name of the convar. + * @param maxlength Maximum length of string buffer. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native GetConVarName(Handle:convar, const String:name[], maxlength); + +funcenum ConVarQueryFinished +{ + /** + * Called when a query to retrieve a client's console variable has finished. + * + * @param cookie Unique identifier of query. + * @param client Player index. + * @param result Result of query that tells one whether or not query was successful. + * See ConVarQueryResult enum for more details. + * @param convarName Name of client convar that was queried. + * @param convarValue Value of client convar that was queried if successful. This will be "" if it was not. + * @param value Value that was passed when query was started. + * @noreturn + */ + public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[], any:value), + + /** + * Called when a query to retrieve a client's console variable has finished. + * + * @param cookie Unique identifier of query. + * @param client Player index. + * @param result Result of query that tells one whether or not query was successful. + * See ConVarQueryResult enum for more details. + * @param convarName Name of client convar that was queried. + * @param convarValue Value of client convar that was queried if successful. This will be "" if it was not. + * @noreturn + */ + public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) +}; + +/** + * Starts a query to retrieve the value of a client's console variable. + * + * @param client Player index. + * @param name Name of client convar to query. + * @param callback A function to use as a callback when the query has finished. + * @param value Optional value to pass to the callback function. + * @return A cookie that uniquely identifies the query. + * Returns QUERYCOOKIE_FAILED on failure, such as when used on a bot. + */ +native QueryCookie:QueryClientConVar(client, const String:cvarName[], ConVarQueryFinished:callback, any:value=0); + +/** + * Gets a command iterator. Must be freed with CloseHandle(). + * + * @return A new command iterator. + */ +native Handle:GetCommandIterator(); + +/** + * Reads a command iterator, then advances to the next command if any. + * Only SourceMod specific commands are returned. + * + * @param iter Command iterator Handle. + * @param name Name buffer. + * @param nameLen Name buffer size. + * @param eflags Effective default flags of a command. + * @param desc Command description buffer. + * @param descLen Command description buffer size. + * @return True on success, false if there are no more commands. + */ +native bool:ReadCommandIterator(Handle:iter, + String:name[], + nameLen, + &eflags=0, + String:desc[]="", + descLen=0); + +/** + * Returns whether a client has access to a given command string. The string + * can also be any override string, as overrides can be independent of + * commands. This important feature essentially allows you to create custom + * flags using the override system. + * + * @param client Client index. + * @param command Command name. If the command is not found, the default + * flags are used. + * @param flags Flag string to use as a default, if the command or override + * is not found. + * @param override_only If true, SourceMod will not attempt to find a matching + * command, and it will only use the default flags specified. + * Otherwise, SourceMod will ignore the default flags if + * there is a matching admin command. + * @return True if the client has access, false otherwise. + */ +native bool:CheckCommandAccess(client, + const String:command[], + flags, + bool:override_only=false); + +/** + * Returns true if the supplied character is valid in a ConVar name. + * + * @param c Character to validate. + * @return True is valid for ConVars, false otherwise + */ +stock bool:IsValidConVarChar(c) +{ + return (c == '_' || IsCharAlpha(c) || IsCharNumeric(c)); +} + +/** + * Returns the bitstring of flags of a command. + * + * @param name Name of the command. + * @return A bitstring containing the FCVAR_* flags that are enabled + * or INVALID_FCVAR_FLAGS if command not found. + */ +native GetCommandFlags(const String:name[]); + +/** + * Sets the bitstring of flags of a command. + * + * @param name Name of the command. + * @param flags A bitstring containing the FCVAR_* flags to enable. + * @return True on success, otherwise false. + */ +native bool:SetCommandFlags(const String:name[], flags); + +/** + * Starts a ConCommandBase search, traversing the list of ConVars and + * ConCommands. If a Handle is returned, the next entry must be read + * via FindNextConCommand(). The order of the list is undefined. + * + * @param buffer Buffer to store entry name. + * @param max_size Maximum size of the buffer. + * @param isCommand Variable to store whether the entry is a command. + * If it is not a command, it is a ConVar. + * @param flags Variable to store entry flags. + * @param description Buffer to store the description, empty if no description present. + * @param descrmax_size Maximum size of the description buffer. + * @return On success, a ConCmdIter Handle is returned, which + * can be read via FindNextConCommand(), and must be + * closed via CloseHandle(). Additionally, the output + * parameters will be filled with information of the + * first ConCommandBase entry. + * On failure, INVALID_HANDLE is returned, and the + * contents of outputs is undefined. + */ +native Handle:FindFirstConCommand(String:buffer[], max_size, &bool:isCommand, &flags=0, String:description[]="", descrmax_size=0); + +/** + * Reads the next entry in a ConCommandBase iterator. + * + * @param search ConCmdIter Handle to search. + * @param buffer Buffer to store entry name. + * @param max_size Maximum size of the buffer. + * @param isCommand Variable to store whether the entry is a command. + * If it is not a command, it is a ConVar. + * @param flags Variable to store entry flags. + * @param description Buffer to store the description, empty if no description present. + * @param descrmax_size Maximum size of the description buffer. + * @return On success, the outputs are filled, the iterator is + * advanced to the next entry, and true is returned. + * If no more entries exist, false is returned, and the + * contents of outputs is undefined. + */ +native bool:FindNextConCommand(Handle:search, String:buffer[], max_size, &bool:isCommand, &flags=0, String:description[]="", descrmax_size=0); + +/** + * Replicates a convar value to a specific client. This does not change the actual convar value. + * + * @param client Client index + * @param convar ConVar handle + * @param value String value to send + * @return True on success, false on failure + * @error Invalid client index, client not in game, or client is fake + */ +native bool:SendConVarValue(client, Handle:convar, const String:value[]); + +/** + * Adds an informational string to the server's public "tags". + * This string should be a short, unique identifier. + * + * Note: Tags are automatically removed when a plugin unloads. + * Note: Currently, this function does nothing because of bugs in the Valve master. + * + * @param tag Tag string to append. + * @noreturn + */ +native AddServerTag(const String:tag[]); + +/** + * Removes a tag previously added by the calling plugin. + * + * @param tag Tag string to remove. + * @noreturn + */ +native RemoveServerTag(const String:tag[]); + +/** + * Callback for command listeners. This is invoked whenever any command + * reaches the server, from the server console itself or a player. + + * Returning Plugin_Handled or Plugin_Stop will prevent the original, + * baseline code from running. + * + * -- TEXT BELOW IS IMPLEMENTATION, AND NOT GUARANTEED -- + * Even if returning Plugin_Handled or Plugin_Stop, some callbacks will still + * trigger. These are: + * * C++ command dispatch hooks from Metamod:Source plugins + * * Reg*Cmd() hooks that did not create new commands. + * + * @param client Client, or 0 for server. Client will be connected but + * not necessarily in game. + * @param command Command name, lower case. To get name as typed, use + * GetCmdArg() and specify argument 0. + * @param argc Argument count. + * @return Action to take (see extended notes above). + */ +functag public Action:CommandListener(client, const String:command[], argc); + +#define FEATURECAP_COMMANDLISTENER "command listener" + +/** + * Adds a callback that will fire when a command is sent to the server. + * + * Registering commands is designed to create a new command as part of the UI, + * whereas this is a lightweight hook on a command string, existing or not. + * Using Reg*Cmd to intercept is in poor practice, as it physically creates a + * new command and can slow down dispatch in general. + * + * To see if this feature is available, use FeatureType_Capability and + * FEATURECAP_COMMANDLISTENER. + * + * @param callback Callback. + * @param command Command, or if not specified, a global listener. + * The command is case insensitive. + * @return True if this feature is available on the current game, + * false otherwise. + */ +native bool:AddCommandListener(CommandListener:callback, const String:command[]=""); + +/** + * Removes a previously added command listener, in reverse order of being added. + * + * @param callback Callback. + * @param command Command, or if not specified, a global listener. + * The command is case insensitive. + * @error Callback has no active listeners. + */ +native RemoveCommandListener(CommandListener:callback, const String:command[]=""); + diff --git a/env/include/core.inc b/env/include/core.inc new file mode 100644 index 0000000..13ae42a --- /dev/null +++ b/env/include/core.inc @@ -0,0 +1,176 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _core_included + #endinput +#endif +#define _core_included + +#include + +/** If this gets changed, you need to update Core's check. */ +#define SOURCEMOD_PLUGINAPI_VERSION 5 + +struct PlVers +{ + version, + String:filevers[], + String:date[], + String:time[] +}; + +/** + * Function helper values. + */ +enum Function +{ + INVALID_FUNCTION = -1, +}; + +/** + * Specifies what to do after a hook completes. + */ +enum Action +{ + Plugin_Continue = 0, /**< Continue with the original action */ + Plugin_Changed = 1, /**< Inputs or outputs have been overridden with new values */ + Plugin_Handled = 3, /**< Handle the action at the end (don't call it) */ + Plugin_Stop = 4, /**< Immediately stop the hook chain and handle the original */ +}; + +/** + * Specifies identity types. + */ +enum Identity +{ + Identity_Core = 0, + Identity_Extension = 1, + Identity_Plugin = 2 +}; + +public PlVers:__version = +{ + version = SOURCEMOD_PLUGINAPI_VERSION, + filevers = SOURCEMOD_VERSION, + date = __DATE__, + time = __TIME__ +}; + +/** + * Plugin status values. + */ +enum PluginStatus +{ + Plugin_Running=0, /**< Plugin is running */ + /* All states below are "temporarily" unexecutable */ + Plugin_Paused, /**< Plugin is loaded but paused */ + Plugin_Error, /**< Plugin is loaded but errored/locked */ + /* All states below do not have all natives */ + Plugin_Loaded, /**< Plugin has passed loading and can be finalized */ + Plugin_Failed, /**< Plugin has a fatal failure */ + Plugin_Created, /**< Plugin is created but not initialized */ + Plugin_Uncompiled, /**< Plugin is not yet compiled by the JIT */ + Plugin_BadLoad, /**< Plugin failed to load */ +}; + +/** + * Plugin information properties. + */ +enum PluginInfo +{ + PlInfo_Name, /**< Plugin name */ + PlInfo_Author, /**< Plugin author */ + PlInfo_Description, /**< Plugin description */ + PlInfo_Version, /**< Plugin verison */ + PlInfo_URL, /**< Plugin URL */ +}; + +/** + * Defines how an extension must expose itself for autoloading. + */ +struct Extension +{ + const String:name[], /**< Short name */ + const String:file[], /**< Default file name */ + bool:autoload, /**< Whether or not to auto-load */ + bool:required, /**< Whether or not to require */ +}; + +/** + * Defines how a plugin must expose itself for native requiring. + */ +struct SharedPlugin +{ + const String:name[], /**< Short name */ + const String:file[], /**< File name */ + bool:required, /**< Whether or not to require */ +}; + +public Float:NULL_VECTOR[3]; /**< Pass this into certain functions to act as a C++ NULL */ +public const String:NULL_STRING[1]; /**< pass this into certain functions to act as a C++ NULL */ + +/** + * Horrible compatibility shim. + */ +public Extension:__ext_core = +{ + name = "Core", + file = "core", + autoload = 0, + required = 0, +}; + +native VerifyCoreVersion(); + +/** + * Sets a native as optional, such that if it is unloaded, removed, + * or otherwise non-existent, the plugin will still work. Calling + * removed natives results in a run-time error. + * + * @param name Native name. + * @noreturn + */ +native MarkNativeAsOptional(const String:name[]); + +public __ext_core_SetNTVOptional() +{ + MarkNativeAsOptional("GetFeatureStatus"); + MarkNativeAsOptional("RequireFeature"); + MarkNativeAsOptional("AddCommandListener"); + MarkNativeAsOptional("RemoveCommandListener"); + VerifyCoreVersion(); +} + + +#define AUTOLOAD_EXTENSIONS +#define REQUIRE_EXTENSIONS +#define REQUIRE_PLUGIN diff --git a/env/include/cstrike.inc b/env/include/cstrike.inc new file mode 100644 index 0000000..954dc2f --- /dev/null +++ b/env/include/cstrike.inc @@ -0,0 +1,88 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _cstrike_included + #endinput +#endif +#define _cstrike_included + +#define CS_TEAM_NONE 0 /**< No team yet. */ +#define CS_TEAM_SPECTATOR 1 /**< Spectators. */ +#define CS_TEAM_T 2 /**< Terrorists. */ +#define CS_TEAM_CT 3 /**< Counter-Terrorists. */ + +#define CS_SLOT_PRIMARY 0 /**< Primary weapon slot. */ +#define CS_SLOT_SECONDARY 1 /**< Secondary weapon slot. */ +#define CS_SLOT_GRENADE 3 /**< Grenade slot (will only return one grenade). */ +#define CS_SLOT_C4 4 /**< C4 slot. */ + +/** + * Respawns a player. + * + * @param client Player's index. + * @noreturn + * @error Invalid client index, client not in game. + */ +native CS_RespawnPlayer(client); + +/** + * Switches the player's team. + * + * @param client Player's index. + * @param team Team index. + * @noreturn + * @error Invalid client index, client not in game. + */ +native CS_SwitchTeam(client, team); + +/** + * Do not edit below this line! + */ +public Extension:__ext_cstrike = +{ + name = "cstrike", + file = "games/game.cstrike.ext", + autoload = 0, +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_EXTENSIONS +public __ext_cstrike_SetNTVOptional() +{ + MarkNativeAsOptional("CS_RespawnPlayer"); + MarkNativeAsOptional("CS_SwitchTeam"); +} +#endif diff --git a/env/include/datapack.inc b/env/include/datapack.inc new file mode 100644 index 0000000..4ad8eb4 --- /dev/null +++ b/env/include/datapack.inc @@ -0,0 +1,142 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _datapack_included + #endinput +#endif +#define _datapack_included + +/** + * Creates a new data pack. + * + * @return A Handle to the data pack. Must be closed with CloseHandle(). + */ +native Handle:CreateDataPack(); + +/** + * Packs a normal cell into a data pack. + * + * @param pack Handle to the data pack. + * @param cell Cell to add. + * @noreturn + * @error Invalid handle. + */ +native WritePackCell(Handle:pack, cell); + +/** + * Packs a float into a data pack. + * + * @param pack Handle to the data pack. + * @param val Float to add. + * @noreturn + * @error Invalid handle. + */ +native WritePackFloat(Handle:pack, Float:val); + +/** + * Packs a string into a data pack. + * + * @param pack Handle to the data pack. + * @param str String to add. + * @noreturn + * @error Invalid handle. + */ +native WritePackString(Handle:pack, const String:str[]); + +/** + * Reads a cell from a data pack. + * + * @param pack Handle to the data pack. + * @return Cell value. + * @error Invalid handle, or bounds error. + */ +native ReadPackCell(Handle:pack); + +/** + * Reads a float from a data pack. + * + * @param pack Handle to the data pack. + * @return Float value. + * @error Invalid handle, or bounds error. + */ +native Float:ReadPackFloat(Handle:pack); + +/** + * Reads a string from a data pack. + * + * @param pack Handle to the data pack. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @noreturn + * @error Invalid handle, or bounds error. + */ +native ReadPackString(Handle:pack, String:buffer[], maxlen); + +/** + * Resets the position in a data pack. + * + * @param pack Handle to the data pack. + * @param clear If true, clears the contained data. + * @noreturn + * @error Invalid handle. + */ +native ResetPack(Handle:pack, bool:clear=false); + +/** + * Returns the read or write position in a data pack. + * + * @param pack Handle to the data pack. + * @return Numerical position in the data pack. + * @error Invalid handle. + */ +native GetPackPosition(Handle:pack); + +/** + * Sets the read/write position in a data pack. + * + * @param pack Handle to the data pack. + * @param position New position to set. + * @noreturn + * @error Invalid handle, or position is beyond the pack bounds. + */ +native SetPackPosition(Handle:pack, position); + +/** + * Returns whether or not a specified number of bytes from the data pack + * position to the end can be read. + * + * @param pack Handle to the data pack. + * @param bytes Number of bytes to simulate reading. + * @return True if can be read, false otherwise. + * @error Invalid handle. + */ +native bool:IsPackReadable(Handle:pack, bytes); diff --git a/env/include/dbi.inc b/env/include/dbi.inc new file mode 100644 index 0000000..5fb9ba8 --- /dev/null +++ b/env/include/dbi.inc @@ -0,0 +1,681 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _dbi_included + #endinput +#endif +#define _dbi_included + +/** + * @handle Driver + * + * Contains information about an SQL driver. + */ + +/** + * @handle Database + * + * Contains information about a database connection. + */ + +/** + * @handle Query + * + * Contains information about an active query and its + * result sets. + */ + +/** + * @handle Statement : Query + * + * Extends a Query Handle and can be used as a Query Handle. + * Statement Handles are for prepared queries and contain + * their own function for binding parameters. Statement + * Handles can be used instead of database Handles in a few + * select functions. + */ + +/** + * Describes a database field fetch status. + */ +enum DBResult +{ + DBVal_Error = 0, /**< Column number/field is invalid. */ + DBVal_TypeMismatch = 1, /**< You cannot retrieve this data with this type. */ + DBVal_Null = 2, /**< Field has no data (NULL) */ + DBVal_Data = 3, /**< Field has data */ +}; + +/** + * Describes binding types. + */ +enum DBBindType +{ + DBBind_Int = 0, /**< Bind an integer. */ + DBBind_Float = 1, /**< Bind a float. */ + DBBind_String = 2, /**< Bind a string. */ +}; + +/** + * Threading priority level. + */ +enum DBPriority +{ + DBPrio_High = 0, /**< High priority. */ + DBPrio_Normal = 1, /**< Normal priority. */ + DBPrio_Low = 2, /**< Low priority. */ +}; + +/** + * Creates an SQL connection from a named configuration. + * + * @param confname Named configuration. + * @param persistent True to re-use a previous persistent connection if + * possible, false otherwise. + * @param error Error buffer. + * @param maxlength Maximum length of the error buffer. + * @return A database connection Handle, or INVALID_HANDLE on failure. + */ +native Handle:SQL_Connect(const String:confname[], bool:persistent, String:error[], maxlength); + +/** + * Creates a default SQL connection. + * + * @param error Error buffer. + * @param maxlength Maximum length of the error buffer. + * @param persistent True to re-use a previous persistent connection + * if possible, false otherwise. + * @return A database connection Handle, or INVALID_HANDLE on failure. + * On failure the error buffer will be filled with a message. + */ +stock Handle:SQL_DefConnect(String:error[], maxlength, bool:persistent=true) +{ + return SQL_Connect("default", persistent, error, maxlength); +} + +/** + * Connects to a database using key value pairs containing the database info. + * The key/value pairs should match what would be in databases.cfg. + * + * I.e. "driver" should be "default" or a driver name (or ommitted for + * the default). For SQLite, only the "database" parameter is needed in addition. + * For drivers which require external connections, more of the parameters may be + * needed. + * + * In general it is discouraged to use this function. Connections should go through + * databases.cfg for greatest flexibility on behalf of users. + * + * @param keyvalues Key/value pairs from a KeyValues handle, describing the connection. + * @param error Error buffer. + * @param maxlength Maximum length of the error buffer. + * @return A database connection Handle, or INVALID_HANDLE on failure. + * On failure the error buffer will be filled with a message. + * @error Invalid KeyValues handle. + */ +native Handle:SQL_ConnectCustom(Handle:keyvalues, + String:error[], + maxlength, + bool:persistent); + +/** + * Grabs a handle to an SQLite database, creating one if it does not exist. + * + * Unless there are extenuating circumstances, you should consider using "sourcemod-local" as the + * database name. This provides some unification between plugins on behalf of users. + * + * As a precaution, you should always create some sort of unique prefix to your table names so + * there are no conflicts, and you should never drop or modify tables that you do not own. + * + * @param database Database name. + * @param error Error buffer. + * @param maxlength Maximum length of the error buffer. + * @return A database connection Handle, or INVALID_HANDLE on failure. + * On failure the error buffer will be filled with a message. + */ +stock Handle:SQLite_UseDatabase(const String:database[], + String:error[], + maxlength) +{ + new Handle:kv, Handle:db; + + kv = CreateKeyValues(""); + KvSetString(kv, "driver", "sqlite"); + KvSetString(kv, "database", database); + + db = SQL_ConnectCustom(kv, error, maxlength, false); + + CloseHandle(kv); + + return db; +} + +/** + * This function is deprecated. Use SQL_ConnectCustom or SQLite_UseDatabase instead. + */ +#pragma deprecated Use SQL_ConnectCustom instead. +native Handle:SQL_ConnectEx(Handle:driver, + const String:host[], + const String:user[], + const String:pass[], + const String:database[], + String:error[], + maxlength, + bool:persistent=true, + port=0, + maxTimeout=0); + +/** + * Returns if a named configuration is present in databases.cfg. + * + * @param name Configuration name. + * @return True if it exists, false otherwise. + */ +native bool:SQL_CheckConfig(const String:name[]); + +/** + * Returns a driver Handle from a name string. + * + * If the driver is not found, SourceMod will attempt + * to load an extension named dbi..ext.[dll|so]. + * + * @param name Driver identification string, or an empty + * string to return the default driver. + * @return Driver Handle, or INVALID_HANDLE on failure. + */ +native Handle:SQL_GetDriver(const String:name[]=""); + +/** + * Reads the driver of an opened database. + * + * @param database Database Handle. + * @param ident Option buffer to store the identification string. + * @param ident_length Maximum length of the buffer. + * @return Driver Handle. + */ +native Handle:SQL_ReadDriver(Handle:database, String:ident[]="", ident_length=0); + +/** + * Retrieves a driver's identification string. + * + * Example: "mysql", "sqlite" + * + * @param driver Driver Handle, or INVALID_HANDLE for the default driver. + * @param ident Identification string buffer. + * @param maxlength Maximum length of the buffer. + * @noreturn + * @error Invalid Handle other than INVALID_HANDLE. + */ +native SQL_GetDriverIdent(Handle:driver, String:ident[], maxlength); + +/** + * Retrieves a driver's product string. + * + * Example: "MySQL", "SQLite" + * + * @param driver Driver Handle, or INVALID_HANDLE for the default driver. + * @param product Product string buffer. + * @param maxlength Maximum length of the buffer. + * @noreturn + * @error Invalid Handle other than INVALID_HANDLE. + */ +native SQL_GetDriverProduct(Handle:driver, String:product[], maxlength); + +/** + * Returns the number of affected rows from the last query. + * + * @param hndl A database OR statement Handle. + * @return Number of rows affected by the last query. + * @error Invalid database or statement Handle. + */ +native SQL_GetAffectedRows(Handle:hndl); + +/** + * Returns the last query's insertion id. + * + * @param hndl A database OR statement Handle. + * @return Last query's insertion id. + * @error Invalid database or statement Handle. + */ +native SQL_GetInsertId(Handle:hndl); + +/** + * Returns the error reported by the last query. + * + * @param hndl A database OR statement Handle. + * @param error Error buffer. + * @param maxlength Maximum length of the buffer. + * @return True if there was an error, false otherwise. + * @error Invalid database or statement Handle. + */ +native bool:SQL_GetError(Handle:hndl, String:error[], maxlength); + +/** + * Escapes a database string for literal insertion. This is not needed + * for binding strings in prepared statements. + * + * Generally, database strings are inserted into queries enclosed in + * single quotes ('). If user input has a single quote in it, the + * quote needs to be escaped. This function ensures that any unsafe + * characters are safely escaped according to the database engine and + * the database's character set. + * + * NOTE: SourceMod only guarantees properly escaped strings when the query + * encloses the string in ''. While drivers tend to allow " instead, the string + * may be not be escaped (for example, on SQLite)! + * + * @param hndl A database Handle. + * @param string String to quote. + * @param buffer Buffer to store quoted string in. + * @param maxlength Maximum length of the buffer. + * @param written Optionally returns the number of bytes written. + * @return True on success, false if buffer is not big enough. + * The buffer must be at least 2*strlen(string)+1. + * @error Invalid database or statement Handle. + */ +native bool:SQL_EscapeString(Handle:database, + const String:string[], + String:buffer[], + maxlength, + &written=0); + +/** + * This is a backwards compatibility stock. You should use SQL_EscapeString() + * instead, as this function will probably be deprecated in SourceMod 1.1. + */ +stock bool:SQL_QuoteString(Handle:database, + const String:string[], + String:buffer[], + maxlength, + &written=0) +{ + return SQL_EscapeString(database, string, buffer, maxlength, written); +} + +/** + * Executes a query and ignores the result set. + * + * @param database A database Handle. + * @param query Query string. + * @param len Optional parameter to specify the query length, in + * bytes. This can be used to send binary queries that + * have a premature terminator. + * @return True if query succeeded, false otherwise. Use + * SQL_GetError to find the last error. + * @error Invalid database Handle. + */ +native bool:SQL_FastQuery(Handle:database, const String:query[], len=-1); + +/** + * Executes a simple query and returns a new query Handle for + * receiving the results. + * + * @param database A database Handle. + * @param query Query string. + * @param len Optional parameter to specify the query length, in + * bytes. This can be used to send binary queries that + * have a premature terminator. + * @return A new Query Handle on success, INVALID_HANDLE + * otherwise. The Handle must be freed with CloseHandle(). + * @error Invalid database Handle. + */ +native Handle:SQL_Query(Handle:database, const String:query[], len=-1); + +/** + * Creates a new prepared statement query. Prepared statements can + * be executed any number of times. They can also have placeholder + * parameters, similar to variables, which can be bound safely and + * securely (for example, you do not need to quote bound strings). + * + * Statement handles will work in any function that accepts a Query handle. + * + * @param database A database Handle. + * @param query Query string. + * @param error Error buffer. + * @param maxlength Maximum size of the error buffer. + * @return A new statement Handle on success, INVALID_HANDLE + * otherwise. The Handle must be freed with CloseHandle(). + * @error Invalid database Handle. + */ +native Handle:SQL_PrepareQuery(Handle:database, const String:query[], String:error[], maxlength); + +/** + * Advances to the next set of results. + * + * In some SQL implementations, multiple result sets can exist on one query. + * This is possible in MySQL with simple queries when executing a CALL + * query. If this is the case, all result sets must be processed before + * another query is made. + * + * @param query A query Handle. + * @return True if there was another result set, false otherwise. + * @error Invalid query Handle. + */ +native bool:SQL_FetchMoreResults(Handle:query); + +/** + * Returns whether or not a result set exists. This will + * return true even if 0 results were returned, but false + * on queries like UPDATE, INSERT, or DELETE. + * + * @param query A query (or statement) Handle. + * @return True if there is a result set, false otherwise. + * @error Invalid query Handle. + */ +native bool:SQL_HasResultSet(Handle:query); + +/** + * Retrieves the number of rows in the last result set. + * + * @param query A query (or statement) Handle. + * @return Number of rows in the current result set. + * @error Invalid query Handle. + */ +native SQL_GetRowCount(Handle:query); + +/** + * Retrieves the number of fields in the last result set. + * + * @param query A query (or statement) Handle. + * @return Number of fields in the current result set. + * @error Invalid query Handle. + */ +native SQL_GetFieldCount(Handle:query); + +/** + * Retrieves the name of a field by index. + * + * @param query A query (or statement) Handle. + * @param field Field number (starting from 0). + * @param name Name buffer. + * @param maxlength Maximum length of the name buffer. + * @noreturn + * @error Invalid query Handle, invalid field index, or + * no current result set. + */ +native SQL_FieldNumToName(Handle:query, field, String:name[], maxlength); + +/** + * Retrieves a field index by name. + * + * @param query A query (or statement) Handle. + * @param name Name of the field (case sensitive). + * @param field Variable to store field index in. + * @return True if found, false if not found. + * @error Invalid query Handle or no current result set. + */ +native bool:SQL_FieldNameToNum(Handle:query, const String:name[], &field); + +/** + * Fetches a row from the current result set. This must be + * successfully called before any results are fetched. + * + * If this function fails, SQL_MoreResults() can be used to + * tell if there was an error or the result set is finished. + * + * @param query A query (or statement) Handle. + * @return True if a row was fetched, false otherwise. + * @error Invalid query Handle. + */ +native bool:SQL_FetchRow(Handle:query); + +/** + * Returns if there are more rows. + * + * @param query A query (or statement) Handle. + * @return True if there are more rows, false otherwise. + * @error Invalid query Handle. + */ +native bool:SQL_MoreRows(Handle:query); + +/** + * Rewinds a result set back to the first result. + * + * @param query A query (or statement) Handle. + * @return True on success, false otherwise. + * @error Invalid query Handle or no current result set. + */ +native bool:SQL_Rewind(Handle:query); + +/** + * Fetches a string from a field in the current row of a result set. + * If the result is NULL, an empty string will be returned. A NULL + * check can be done with the result parameter, or SQL_IsFieldNull(). + * + * @param query A query (or statement) Handle. + * @param field The field index (starting from 0). + * @param buffer String buffer. + * @param maxlength Maximum size of the string buffer. + * @param result Optional variable to store the status of the return value. + * @return Number of bytes written. + * @error Invalid query Handle or field index, invalid + * type conversion requested from the database, + * or no current result set. + */ +native SQL_FetchString(Handle:query, field, String:buffer[], maxlength, &DBResult:result=DBVal_Error); + +/** + * Fetches a float from a field in the current row of a result set. + * If the result is NULL, a value of 0.0 will be returned. A NULL + * check can be done with the result parameter, or SQL_IsFieldNull(). + * + * @param query A query (or statement) Handle. + * @param field The field index (starting from 0). + * @param result Optional variable to store the status of the return value. + * @return A float value. + * @error Invalid query Handle or field index, invalid + * type conversion requested from the database, + * or no current result set. + */ +native Float:SQL_FetchFloat(Handle:query, field, &DBResult:result=DBVal_Error); + +/** + * Fetches an integer from a field in the current row of a result set. + * If the result is NULL, a value of 0 will be returned. A NULL + * check can be done with the result parameter, or SQL_IsFieldNull(). + * + * @param query A query (or statement) Handle. + * @param field The field index (starting from 0). + * @param result Optional variable to store the status of the return value. + * @return An integer value. + * @error Invalid query Handle or field index, invalid + * type conversion requested from the database, + * or no current result set. + */ +native SQL_FetchInt(Handle:query, field, &DBResult:result=DBVal_Error); + +/** + * Returns whether a field's data in the current row of a result set is + * NULL or not. NULL is an SQL type which means "no data." + * + * @param query A query (or statement) Handle. + * @param field The field index (starting from 0). + * @return True if data is NULL, false otherwise. + * @error Invalid query Handle or field index, or no + * current result set. + */ +native bool:SQL_IsFieldNull(Handle:query, field); + +/** + * Returns the length of a field's data in the current row of a result + * set. This only needs to be called for strings to determine how many + * bytes to use. Note that the return value does not include the null + * terminator. + * + * @param query A query (or statement) Handle. + * @param field The field index (starting from 0). + * @return Number of bytes for the field's data size. + * @error Invalid query Handle or field index or no + * current result set. + */ +native SQL_FetchSize(Handle:query, field); + +/** + * Binds a parameter in a prepared statement to a given integer value. + * + * @param statement A statement (prepared query) Handle. + * @param param The parameter index (starting from 0). + * @param number The number to bind. + * @param signed True to bind the number as signed, false to + * bind it as unsigned. + * @noreturn + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native SQL_BindParamInt(Handle:statement, param, number, bool:signed=true); + +/** + * Binds a parameter in a prepared statement to a given float value. + * + * @param statement A statement (prepared query) Handle. + * @param param The parameter index (starting from 0). + * @param float The float number to bind. + * @noreturn + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native SQL_BindParamFloat(Handle:statement, param, Float:value); + +/** + * Binds a parameter in a prepared statement to a given string value. + * + * @param statement A statement (prepared query) Handle. + * @param param The parameter index (starting from 0). + * @param value The string to bind. + * @param copy Whether or not SourceMod should copy the value + * locally if necessary. If the string contents + * won't change before calling SQL_Execute(), this + * can be set to false for optimization. + * @noreturn + * @error Invalid statement Handle or parameter index, or + * SQL error. + */ +native SQL_BindParamString(Handle:statement, param, const String:value[], bool:copy); + +/** + * Executes a prepared statement. All parameters must be bound beforehand. + * + * @param statement A statement (prepared query) Handle. + * @return True on success, false on failure. + * @error Invalid statement Handle. + */ +native bool:SQL_Execute(Handle:statement); + +/** + * Locks a database so threading operations will not interrupt. + * + * If you are using a database Handle for both threading and non-threading, + * this MUST be called before doing any set of non-threading DB operations. + * Otherwise you risk corrupting the database driver's memory or network + * connection. + * + * Leaving a lock on a database and then executing a threaded query results + * in a dead lock! Make sure to call SQL_UnlockDatabase()! + * + * If the lock cannot be acquired, the main thread will pause until the + * threaded operation has concluded. + * + * @param database A database Handle. + * @noreturn + * @error Invalid database Handle. + */ +native SQL_LockDatabase(Handle:database); + +/** + * Unlocks a database so threading operations may continue. + * + * @param database A database Handle. + * @noreturn + * @error Invalid database Handle. + */ +native SQL_UnlockDatabase(Handle:database); + +/** + * General callback for threaded SQL stuff. + * + * @param db Parent object of the Handle (or INVALID_HANDLE if none). + * @param hndl Handle to the child object (or INVALID_HANDLE if none). + * @param error Error string if there was an error. The error could be + * empty even if an error condition exists, so it is important + * to check the actual Handle value instead. + * @param data Data passed in via the original threaded invocation. + * @param + */ +functag public SQLTCallback(Handle:owner, Handle:hndl, const String:error[], any:data); + +/** + * Tells whether two database handles both point to the same database + * connection. + * + * @param hndl1 First database Handle. + * @param hndl2 Second database Handle. + * @return True if the Handles point to the same + * connection, false otherwise. + * @error Invalid Handle. + */ +native bool:SQL_IsSameConnection(Handle:hndl1, Handle:hndl2); + +/** + * Connects to a database via a thread. This can be used instead of + * SQL_Connect() if you wish for non-blocking functionality. + * + * It is not necessary to use this to use threaded queries. However, if you + * don't (or you mix threaded/non-threaded queries), you should see + * SQL_LockDatabase(). + * + * @param callback Callback; new Handle will be in hndl, owner is the driver. + * If no driver was found, the owner is INVALID_HANDLE. + * @param name Database name. + * @noreturn + */ +native SQL_TConnect(SQLTCallback:callback, const String:name[]="default", any:data=0); + +/** + * Executes a simple query via a thread. The query Handle is passed through + * the callback. + * + * The database Handle returned through the callback is always a new Handle, + * and if necessary, SQL_IsSameConnection() should be used to test against + * other conenctions. + * + * The query Handle returned through the callback is temporary and destroyed + * at the end of the callback. If you need to hold onto it, use CloneHandle(). + * + * @param database A database Handle. + * @param callback Callback; database is in "owner" and the query Handle + * is passed in "hndl". + * @param query Query string. + * @param data Extra data value to pass to the callback. + * @param prio Priority queue to use. + * @noreturn + * @error Invalid database Handle. + */ +native SQL_TQuery(Handle:database, SQLTCallback:callback, const String:query[], any:data=0, DBPriority:prio=DBPrio_Normal); diff --git a/env/include/entity.inc b/env/include/entity.inc new file mode 100644 index 0000000..8a7335c --- /dev/null +++ b/env/include/entity.inc @@ -0,0 +1,671 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _entity_included + #endinput +#endif +#define _entity_included + +/** + * Property types for entities. + */ +enum PropType +{ + Prop_Send = 0, /**< This property is networked. */ + Prop_Data = 1, /**< This property is for save game data fields. */ +}; + +/** + * @section For more information on these, see the HL2SDK (public/edict.h) + */ +#define FL_EDICT_CHANGED (1<<0) /**< Game DLL sets this when the entity state changes + Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. */ +#define FL_EDICT_FREE (1<<1) /**< this edict if free for reuse */ +#define FL_EDICT_FULL (1<<2) /**< this is a full server entity */ +#define FL_EDICT_FULLCHECK (0<<0) /**< call ShouldTransmit() each time, this is a fake flag */ +#define FL_EDICT_ALWAYS (1<<3) /**< always transmit this entity */ +#define FL_EDICT_DONTSEND (1<<4) /**< don't transmit this entity */ +#define FL_EDICT_PVSCHECK (1<<5) /**< always transmit entity, but cull against PVS */ +#define FL_EDICT_PENDING_DORMANT_CHECK (1<<6) +#define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7) +#define FL_FULL_EDICT_CHANGED (1<<8) + +enum PropFieldType +{ + PropField_Unsupported, /**< The type is unsupported. */ + PropField_Integer, /**< Valid for SendProp and Data fields */ + PropField_Float, /**< Valid for SendProp and Data fields */ + PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */ + PropField_Vector, /**< Valid for SendProp and Data fields */ + PropField_String, /**< Valid for SendProp and Data fields */ + PropField_String_T, /**< Valid for Data fields. Read only. + Note that the size of a string_t is dynamic, and + thus FindDataMapOffs() will return the constant size + of the string_t container (which is 32 bits right now). + */ +}; + +/** + * @endsection + */ + +/** + * Returns the maximum number of entities. + * + * @return Maximum number of entities. + */ +native GetMaxEntities(); + +/** + * Returns the number of entities in the server. + * + * @return Number of entities in the server. + */ +native GetEntityCount(); + +/** + * Returns whether or not an entity is valid. Returns false + * if there is no matching CBaseEntity for this edict index. + * + * @param edict Index of the entity/edict. + * @return True if valid, false otherwise. + */ +native bool:IsValidEntity(edict); + +/** + * Returns whether or not an edict index is valid. + * + * @param edict Index of the edict. + * @return True if valid, false otherwise. + */ +native bool:IsValidEdict(edict); + +/** + * Returns whether or not an entity is a valid networkable edict. + * + * @param edict Index of the edict. + * @return True if networkable, false if invalid or not networkable. + */ +native bool:IsEntNetworkable(edict); + +/** + * Creates a new edict (the basis of a networkable entity) + * + * @return Index of the edict, 0 on failure. + */ +native CreateEdict(); + +/** + * Removes an edict from the world. + * + * @param edict Index of the edict. + * @noreturn + * @error Invalid edict index. + */ +native RemoveEdict(edict); + +/** + * Returns the flags on an edict. These are not the same as entity flags. + * + * @param edict Index of the entity. + * @return Edict flags. + * @error Invalid edict index. + */ +native GetEdictFlags(edict); + +/** + * Sets the flags on an edict. These are not the same as entity flags. + * + * @param edict Index of the entity. + * @param flags Flags to set. + * @noreturn + * @error Invalid edict index. + */ +native SetEdictFlags(edict, flags); + +/** + * Retrieves an edict classname. + * + * @param edict Index of the entity. + * @param clsname Buffer to store the classname. + * @param maxlength Maximum length of the buffer. + * @return True on success, false if there is no classname set. + */ +native bool:GetEdictClassname(edict, String:clsname[], maxlength); + +/** + * Retrieves an entity's networkable serverclass name. + * This is not the same as the classname and is used for networkable state changes. + * + * @param edict Index of the entity. + * @param clsname Buffer to store the serverclass name. + * @param maxlength Maximum lnegth of the buffer. + * @return True on success, false if the edict is not networkable. + * @error Invalid edict index. + */ +native bool:GetEntityNetClass(edict, String:clsname[], maxlength); + +/** + * @section Entity offset functions + * + * Offsets should be specified in byte distance from the CBaseEntity + * structure, not short (double byte) or integer (four byte) multiples. + * It is somewhat common practice to use offsets aligned to their final + * type, and thus make sure you are not falling to this error in SourceMod. + * For example, if your "integer-aligned" offset was 119, your byte-aligned + * offset is 119*4, or 476. + + * Specifying incorrect offsets or the incorrect data type for an offset + * can have fatal consequences. If you are hardcoding offsets, and the + * layout of CBaseEntity does not match, you can easily crash the server. + * + * The reasonable bounds for offsets is greater than or equal to 0 and + * below 32768. Offsets out of these bounds will throw an error. However, + * this does not represent any real range, it is simply a sanity check for + * illegal values. Any range outside of the CBaseEntity structure's private + * size will cause undefined behaviour or even crash. + */ + +/** + * Marks an entity as state changed. This can be useful if you set an offset + * and wish for it to be immediately changed over the network. By default this + * is not done for offset setting functions. + * + * @param edict Index to the edict. + * @param offset Offset to mark as changed. If 0, + * the entire edict is marked as changed. + * @noreturn + * @error Invalid entity or offset out of bounds. + */ +native ChangeEdictState(edict, offset = 0); + +/** + * Peeks into an entity's object data and retrieves the integer value at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param size Number of bytes to read (valid values are 1, 2, or 4). + * @return Value at the given memory location. + * @error Invalid entity or offset out of reasonable bounds. + */ +native GetEntData(entity, offset, size=4); + +/** + * Peeks into an entity's object data and sets the integer value at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param size Number of bytes to write (valid values are 1, 2, or 4). + * @param changeState If true, change will be sent over the network. + * @return Value at the given memory location. + * @error Invalid entity or offset out of reasonable bounds. + * @noreturn + */ +native SetEntData(entity, offset, any:value, size=4, bool:changeState=false); + +/** + * Peeks into an entity's object data and retrieves the float value at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @return Value at the given memory location. + * @error Invalid entity or offset out of reasonable bounds. + */ +native Float:GetEntDataFloat(entity, offset); + +/** + * Peeks into an entity's object data and sets the integer value at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param changeState If true, change will be sent over the network. + * @return Value at the given memory location. + * @error Invalid entity or offset out of reasonable bounds. + * @noreturn + */ +native SetEntDataFloat(entity, offset, Float:value, bool:changeState=false); + +/** + * This function is deprecated. Use GetEntDataEnt2 instead, for + * reasons explained in the notes. + * + * Note: This function returns 0 on failure, which may be misleading, + * as the number 0 is also used for the world entity index. + * + * Note: This function makes no attempt to validate the returned + * entity, and in fact, it could be garbage or completely unexpected. + * + * @param entity Edict index. + * @param offset Offset to use. + * @return Entity index at the given location, or 0 if none. + * @error Invalid entity or offset out of reasonable bounds. + */ +#pragma deprecated Use GetEntDataEnt2() instead. +native GetEntDataEnt(entity, offset); + +/** + * This function is deprecated. Use SetEntDataEnt2 instead, for + * reasons explained in the notes. + * + * Note: This function uses 0 as an indicator to unset data, but + * 0 is also the world entity index. Thus, the a property cannot + * be set to the world entity using this native. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param other Entity index to set, or 0 to clear. + * @param changeState If true, change will be sent over the network. + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +#pragma deprecated Use SetEntDataEnt2() instead. +native SetEntDataEnt(entity, offset, other, bool:changeState=false); + +/** + * Peeks into an entity's object data and retrieves the entity index + * at the given offset. + * + * Note: This will only work on offsets that are stored as "entity + * handles" (which usually looks like m_h* in properties). These + * are not SourceMod Handles, but internal Source structures. + * + * @param entity Edict index. + * @param offset Offset to use. + * @return Entity index at the given location. If there is no entity, + * or the stored entity is invalid, then -1 is returned. + * @error Invalid input entity, or offset out of reasonable bounds. + */ +native GetEntDataEnt2(entity, offset); + +/** + * Peeks into an entity's object data and sets the entity index at the + * given offset. + * + * Note: This will only work on offsets that are stored as "entity + * handles" (which usually looks like m_h* in properties). These + * are not SourceMod Handles, but internal Source structures. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param other Entity index to set, or -1 to clear. + * @param changeState If true, change will be sent over the network. + * @noreturn + * @error Invalid input entity, or offset out of reasonable bounds. + */ +native SetEntDataEnt2(entity, offset, other, bool:changeState=false); + +/** + * Peeks into an entity's object data and retrieves the vector at the + * given offset. + * @note Both a Vector and a QAngle are three floats. This is a + * convenience function and will work with both types. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param vec Vector buffer to store data in. + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +native GetEntDataVector(entity, offset, Float:vec[3]); + +/** + * Peeks into an entity's object data and sets the vector at the given + * offset. + * @note Both a Vector and a QAngle are three floats. This is a + * convenience function and will work with both types. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param vec Vector to set. + * @param changeState If true, change will be sent over the network. + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +native SetEntDataVector(entity, offset, const Float:vec[3], bool:changeState=false); + +/** + * Peeks into an entity's object data and retrieves the string at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @return Number of non-null bytes written. + * @error Invalid entity or offset out of reasonable bounds. + */ +native GetEntDataString(entity, offset, String:buffer[], maxlen); + +/** + * Peeks into an entity's object data and sets the string at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param buffer String to set. + * @param maxlen Maximum length of bytes to write. + * @param changeState If true, change will be sent over the network. + * @return Number of non-null bytes written. + * @error Invalid entity or offset out of reasonable bounds. + */ +native SetEntDataString(entity, offset, const String:buffer[], maxlen, bool:changeState=false); + +/** + * @endsection + */ + +/** + * Given a ServerClass name, finds a networkable send property offset. + * This information is cached for future calls. + * + * Note, this function may return offsets that do not work! + * If a property is nested beneath a parent object, the resulting offset + * will be invalid for direct use with data functions. Therefore, you + * should use FindSendPropInfo() instead. An example of such a property is + * CTFPlayer::DT_LocalPlayer.m_nDisguiseClass on Team Fortress. + * + * @param cls Classname. + * @param prop Property name. + * @return An offset, or -1 on failure. + */ +native FindSendPropOffs(const String:cls[], const String:prop[]); + +/** + * Given a ServerClass name, finds a networkable send property offset. + * This information is cached for future calls. + * + * Note: This function will correctly compute nested offsets, unlike + * FindSendPropOffs(). YOU SHOULD NOT use this function to self-compute + * nested offsets. For example, it is okay to add indexes for arrays, + * but not to add DT_LocalPlayer to m_nDisguiseClass. + * + * @param cls Classname. + * @param prop Property name. + * @param type Optional parameter to store the type. + * @param num_bits Optional parameter to store the number of bits the field + * uses, if applicable (otherwise 0 is stored). The number + * of bits varies for integers and floats, and is always 0 + * for strings. + * @param local_offset Optional parameter to store the local offset, as + * FindSendPropOffs() would return. + * @return On success, returns an absolutely computed offset. + * If no offset is available, 0 is returned. + * If the property is not found, -1 is returned. + */ +native FindSendPropInfo(const String:cls[], + const String:prop[], + &PropFieldType:type=PropFieldType:0, + &num_bits=0, + &local_offset=0); + +/** + * Given an entity, finds a datamap property offset. + * This information is cached for future calls. + * + * @param entity Entity index. + * @param prop Property name. + * @param type Optional parameter to store the type. + * @param num_bits Optional parameter to store the number of bits the field + * uses. The bit count will either be 1 (for boolean) or + * divisible by 8 (including 0 if unknown). + * @return An offset, or -1 on failure. + */ +native FindDataMapOffs(entity, + const String:prop[], + &PropFieldType:type=PropFieldType:0, + &num_bits=0); + +/** + * Wrapper function for finding a send property for a particular entity. + * + * @param ent Entity index. + * @param prop Property name. + * @param actual Defaults to false for backwards compatibility. + * If true, the newer FindSendPropInfo() function + * is used instead. + * @return An offset, or -1 on failure. + */ +stock GetEntSendPropOffs(ent, const String:prop[], bool:actual=false) +{ + decl String:cls[64]; + + if (!GetEntityNetClass(ent, cls, sizeof(cls))) + { + return -1; + } + + if (actual) + { + return FindSendPropInfo(cls, prop); + } + else + { + return FindSendPropOffs(cls, prop); + } +} + +/** + * Retrieves an integer value from an entity's property. + * + * This function is considered safer and more robust over GetEntData, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param size Number of bytes to write (valid values are 1, 2, or 4). + * This value is auto-detected, and the size parameter is + * only used as a fallback in case detection fails. + * @return Value at the given property offset. + * @error Invalid entity or property not found. + */ +native GetEntProp(entity, PropType:type, const String:prop[], size=4); + +/** + * Sets an integer value in an entity's property. + * + * This function is considered safer and more robust over SetEntData, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param size Number of bytes to write (valid values are 1, 2, or 4). + * This value is auto-detected, and the size parameter is + * only used as a fallback in case detection fails. + * @error Invalid entity or offset out of reasonable bounds. + * @noreturn + */ +native SetEntProp(entity, PropType:type, const String:prop[], any:value, size=4); + +/** + * Retrieves a float value from an entity's property. + * + * This function is considered safer and more robust over GetEntDataFloat, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @return Value at the given property offset. + * @error Invalid entity or offset out of reasonable bounds. + */ +native Float:GetEntPropFloat(entity, PropType:type, const String:prop[]); + +/** + * Sets a float value in an entity's property. + * + * This function is considered safer and more robust over SetEntDataFloat, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param value Value to set. + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +native SetEntPropFloat(entity, PropType:type, const String:prop[], Float:value); + +/** + * Retrieves an entity index from an entity's property. + * + * This function is considered safer and more robust over GetEntDataEnt*, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @return Entity index at the given property. + * If there is no entity, or the entity is not valid, + * then -1 is returned. + * @error Invalid entity or offset out of reasonable bounds. + */ +native GetEntPropEnt(entity, PropType:type, const String:prop[]); + +/** + * Sets an entity index in an entity's property. + * + * This function is considered safer and more robust over SetEntDataEnt*, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param other Entity index to set, or -1 to unset. + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +native SetEntPropEnt(entity, PropType:type, const String:prop[], other); + +/** + * Retrieves a vector of floats from an entity, given a named network property. + * + * This function is considered safer and more robust over GetEntDataVector, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param vec Vector buffer to store data in. + * @noreturn + * @error Invalid entity, property not found, or property not + * actually a vector data type. + */ +native GetEntPropVector(entity, PropType:type, const String:prop[], Float:vec[3]); + +/** + * Sets a vector of floats in an entity, given a named network property. + * + * This function is considered safer and more robust over SetEntDataVector, + * because it performs strict offset checking and typing rules. + * + * @param entity Entity/edict index. + * @param type Property type. + * @param prop Property name. + * @param vec Vector to set. + * @noreturn + * @error Invalid entity, property not found, or property not + * actually a vector data type. + */ +native SetEntPropVector(entity, PropType:type, const String:prop[], const Float:vec[3]); + +/** + * Gets a network property as a string. + * + * @param entity Edict index. + * @param type Property type. + * @param prop Property to use. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native GetEntPropString(entity, PropType:type, const String:prop[], String:buffer[], maxlen); + +/** + * Sets a network property as a string. + * + * This cannot set property fields of type PropField_String_T (such as "m_target"). + * To set such fields, you should use DispatchKeyValue() from SDKTools. + * + * @param entity Edict index. + * @param type Property type. + * @param prop Property to use. + * @param buffer String to set. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native SetEntPropString(entity, PropType:type, const String:prop[], const String:buffer[]); + +/** + * Copies an array of cells from an entity at a given offset. + * + * @param entity Entity index. + * @param offset Offset to use. + * @param array Array to read into. + * @param arraySize Number of values to read. + * @param dataSize Size of each value in bytes (1, 2, or 4). + * @noreturn + * @error Invalid entity or offset out of reasonable bounds. + */ +stock GetEntDataArray(entity, offset, array[], arraySize, dataSize=4) +{ + for (new i=0; i. + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _entity_prop_stocks_included + #endinput +#endif +#define _entity_prop_stocks_included + +enum MoveType +{ + MOVETYPE_NONE = 0, /**< never moves */ + MOVETYPE_ISOMETRIC, /**< For players */ + MOVETYPE_WALK, /**< Player only - moving on the ground */ + MOVETYPE_STEP, /**< gravity, special edge handling -- monsters use this */ + MOVETYPE_FLY, /**< No gravity, but still collides with stuff */ + MOVETYPE_FLYGRAVITY, /**< flies through the air + is affected by gravity */ + MOVETYPE_VPHYSICS, /**< uses VPHYSICS for simulation */ + MOVETYPE_PUSH, /**< no clip to world, push and crush */ + MOVETYPE_NOCLIP, /**< No gravity, no collisions, still do velocity/avelocity */ + MOVETYPE_LADDER, /**< Used by players only when going onto a ladder */ + MOVETYPE_OBSERVER, /**< Observer movement, depends on player's observer mode */ + MOVETYPE_CUSTOM, /**< Allows the entity to describe its own physics */ +}; + +enum RenderMode +{ + RENDER_NORMAL, /**< src */ + RENDER_TRANSCOLOR, /**< c*a+dest*(1-a) */ + RENDER_TRANSTEXTURE, /**< src*a+dest*(1-a) */ + RENDER_GLOW, /**< src*a+dest -- No Z buffer checks -- Fixed size in screen space */ + RENDER_TRANSALPHA, /**< src*srca+dest*(1-srca) */ + RENDER_TRANSADD, /**< src*a+dest */ + RENDER_ENVIRONMENTAL, /**< not drawn, used for environmental effects */ + RENDER_TRANSADDFRAMEBLEND, /**< use a fractional frame value to blend between animation frames */ + RENDER_TRANSALPHAADD, /**< src + dest*(1-a) */ + RENDER_WORLDGLOW, /**< Same as kRenderGlow but not fixed size in screen space */ + RENDER_NONE, /**< Don't render. */ +}; + +enum RenderFx +{ + RENDERFX_NONE = 0, + RENDERFX_PULSE_SLOW, + RENDERFX_PULSE_FAST, + RENDERFX_PULSE_SLOW_WIDE, + RENDERFX_PULSE_FAST_WIDE, + RENDERFX_FADE_SLOW, + RENDERFX_FADE_FAST, + RENDERFX_SOLID_SLOW, + RENDERFX_SOLID_FAST, + RENDERFX_STROBE_SLOW, + RENDERFX_STROBE_FAST, + RENDERFX_STROBE_FASTER, + RENDERFX_FLICKER_SLOW, + RENDERFX_FLICKER_FAST, + RENDERFX_NO_DISSIPATION, + RENDERFX_DISTORT, /**< Distort/scale/translate flicker */ + RENDERFX_HOLOGRAM, /**< kRenderFxDistort + distance fade */ + RENDERFX_EXPLODE, /**< Scale up really big! */ + RENDERFX_GLOWSHELL, /**< Glowing Shell */ + RENDERFX_CLAMP_MIN_SCALE, /**< Keep this sprite from getting very small (SPRITES only!) */ + RENDERFX_ENV_RAIN, /**< for environmental rendermode, make rain */ + RENDERFX_ENV_SNOW, /**< " " " , make snow */ + RENDERFX_SPOTLIGHT, /**< TEST CODE for experimental spotlight */ + RENDERFX_RAGDOLL, /**< HACKHACK: TEST CODE for signalling death of a ragdoll character */ + RENDERFX_PULSE_FAST_WIDER, + RENDERFX_MAX +}; + +// These defines are for client button presses. +#define IN_ATTACK (1 << 0) +#define IN_JUMP (1 << 1) +#define IN_DUCK (1 << 2) +#define IN_FORWARD (1 << 3) +#define IN_BACK (1 << 4) +#define IN_USE (1 << 5) +#define IN_CANCEL (1 << 6) +#define IN_LEFT (1 << 7) +#define IN_RIGHT (1 << 8) +#define IN_MOVELEFT (1 << 9) +#define IN_MOVERIGHT (1 << 10) +#define IN_ATTACK2 (1 << 11) +#define IN_RUN (1 << 12) +#define IN_RELOAD (1 << 13) +#define IN_ALT1 (1 << 14) +#define IN_ALT2 (1 << 15) +#define IN_SCORE (1 << 16) // Used by client.dll for when scoreboard is held down +#define IN_SPEED (1 << 17) // Player is holding the speed key +#define IN_WALK (1 << 18) // Player holding walk key +#define IN_ZOOM (1 << 19) // Zoom key for HUD zoom +#define IN_WEAPON1 (1 << 20) // weapon defines these bits +#define IN_WEAPON2 (1 << 21) // weapon defines these bits +#define IN_BULLRUSH (1 << 22) +#define IN_GRENADE1 (1 << 23) // grenade 1 +#define IN_GRENADE2 (1 << 24) // grenade 2 + +// CBaseEntity::m_fFlags +// PLAYER SPECIFIC FLAGS FIRST BECAUSE WE USE ONLY A FEW BITS OF NETWORK PRECISION +#define FL_ONGROUND (1 << 0) // At rest / on the ground +#define FL_DUCKING (1 << 1) // Player flag -- Player is fully crouched +#define FL_WATERJUMP (1 << 2) // player jumping out of water +#define FL_ONTRAIN (1 << 3) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction. +#define FL_INRAIN (1 << 4) // Indicates the entity is standing in rain +#define FL_FROZEN (1 << 5) // Player is frozen for 3rd person camera +#define FL_ATCONTROLS (1 << 6) // Player can't move, but keeps key inputs for controlling another entity +#define FL_CLIENT (1 << 7) // Is a player +#define FL_FAKECLIENT (1 << 8) // Fake client, simulated server side; don't send network messages to them +// NOTE if you move things up, make sure to change this value +#define PLAYER_FLAG_BITS 9 +// NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though +#define FL_INWATER (1 << 9) // In water +#define FL_FLY (1 << 10) // Changes the SV_Movestep() behavior to not need to be on ground +#define FL_SWIM (1 << 11) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water) +#define FL_CONVEYOR (1 << 12) +#define FL_NPC (1 << 13) +#define FL_GODMODE (1 << 14) +#define FL_NOTARGET (1 << 15) +#define FL_AIMTARGET (1 << 16) // set if the crosshair needs to aim onto the entity +#define FL_PARTIALGROUND (1 << 17) // not all corners are valid +#define FL_STATICPROP (1 << 18) // Eetsa static prop! +#define FL_GRAPHED (1 << 19) // worldgraph has this ent listed as something that blocks a connection +#define FL_GRENADE (1 << 20) +#define FL_STEPMOVEMENT (1 << 21) // Changes the SV_Movestep() behavior to not do any processing +#define FL_DONTTOUCH (1 << 22) // Doesn't generate touch functions, generates Untouch() for anything it was touching when this flag was set +#define FL_BASEVELOCITY (1 << 23) // Base velocity has been applied this frame (used to convert base velocity into momentum) +#define FL_WORLDBRUSH (1 << 24) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something) +#define FL_OBJECT (1 << 25) // Terrible name. This is an object that NPCs should see. Missiles, for example. +#define FL_KILLME (1 << 26) // This entity is marked for death -- will be freed by game DLL +#define FL_ONFIRE (1 << 27) // You know... +#define FL_DISSOLVING (1 << 28) // We're dissolving! +#define FL_TRANSRAGDOLL (1 << 29) // In the process of turning into a client side ragdoll. +#define FL_UNBLOCKABLE_BY_PLAYER (1 << 30) // pusher that can't be blocked by the player +// END m_fFlags #defines + +/** + * Get an entity's flags. + * + * @param entity Entity index. + * @return Entity's flags, see m_fFlag defines above + * @error Invalid entity index, or lack of mod compliance. + */ +stock GetEntityFlags(entity) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_fFlags", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_fFlags"); + } + + gotconfig = true; + } + + return GetEntProp(entity, Prop_Data, datamap); +} + + +/** + * Gets an entity's movetype. + * + * @param entity Entity index. + * @return Movetype, see enum above. + * @error Invalid entity index, or lack of mod compliance. + */ +stock MoveType:GetEntityMoveType(entity) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_MoveType"); + } + + gotconfig = true; + } + + return MoveType:GetEntProp(entity, Prop_Data, datamap); +} + +/** + * Sets an entity's movetype. + * + * @param entity Entity index. + * @param mt Movetype, see enum above. + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityMoveType(entity, MoveType:mt) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_MoveType"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Data, datamap, mt); +} + +/** + * Gets an entity's render mode. + * + * @param entity Entity index. + * @return RenderMode value. + * @error Invalid entity index, or lack of mod compliance. + */ +stock RenderMode:GetEntityRenderMode(entity) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderMode"); + } + + gotconfig = true; + } + + return RenderMode:GetEntProp(entity, Prop_Send, prop, 1); +} + +/** + * Sets an entity's render mode. + * + * @param entity Entity index. + * @param mode RenderMode value. + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityRenderMode(entity, RenderMode:mode) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderMode"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Send, prop, mode, 1); +} + +/** + * Gets an entity's render Fx. + * + * @param entity Entity index. + * @return RenderFx value. + * @error Invalid entity index, or lack of mod compliance. + */ +stock RenderFx:GetEntityRenderFx(entity) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + return RenderFx:GetEntProp(entity, Prop_Send, prop, 1); +} + +/** + * Sets an entity's render Fx. + * + * @param entity Entity index. + * @param fx RenderFx value. + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityRenderFx(entity, RenderFx:fx) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_nRenderFX"); + } + + gotconfig = true; + } + + SetEntProp(entity, Prop_Send, prop, fx, 1); +} + +/** + * Sets an entity's color. + * + * @param entity Entity index + * @param r Amount of red (0-255) + * @param g Amount of green (0-255) + * @param b Amount of blue (0-255) + * @param a Amount of alpha (0-255) + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityRenderColor(entity, r=255, g=255, b=255, a=255) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + new offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) + { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + + SetEntData(entity, offset, r, 1, true); + SetEntData(entity, offset + 1, g, 1, true); + SetEntData(entity, offset + 2, b, 1, true); + SetEntData(entity, offset + 3, a, 1, true); +} + +/** + * Gets an entity's gravity. + * + * @param entity Entity index. + * @return Entity's m_flGravity value. + * @error Invalid entity index, or lack of mod compliance. + */ +stock Float:GetEntityGravity(entity) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_flGravity"); + } + + gotconfig = true; + } + + return GetEntPropFloat(entity, Prop_Data, datamap); +} + +/** + * Sets an entity's gravity. + * + * @param entity Entity index. + * @param amount Gravity to set (default = 1.0, half = 0.5, double = 2.0). + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityGravity(entity, Float:amount) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_flGravity"); + } + + gotconfig = true; + } + + SetEntPropFloat(entity, Prop_Data, datamap, amount); +} + +/** + * Sets an entity's health + * + * @param entity Entity index. + * @param amount Health amount. + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock SetEntityHealth(entity, amount) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_iHealth", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) + { + strcopy(prop, sizeof(prop), "m_iHealth"); + } + + gotconfig = true; + } + + decl String:cls[64]; + new PropFieldType:type; + new offset; + + if (!GetEntityNetClass(entity, cls, sizeof(cls))) + { + ThrowError("SetEntityHealth not supported by this mod: Could not get serverclass name"); + return; + } + + offset = FindSendPropInfo(cls, prop, type); + + if (offset <= 0) + { + ThrowError("SetEntityHealth not supported by this mod"); + return; + } + + /* Dark Messiah uses a float for the health instead an integer */ + if (type == PropField_Float) + { + SetEntDataFloat(entity, offset, float(amount)); + } + else + { + SetEntProp(entity, Prop_Send, prop, amount); + } +} + +/** + * Get's a users current pressed buttons + * + * @param client Client index + * @return Bitsum of buttons + * @error Invalid client index, client not in game, + * or lack of mod compliance. + */ +stock GetClientButtons(client) +{ + static bool:gotconfig = false; + static String:datamap[32]; + + if (!gotconfig) + { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_nButtons", datamap, sizeof(datamap)); + CloseHandle(gc); + + if (!exists) + { + strcopy(datamap, sizeof(datamap), "m_nButtons"); + } + + gotconfig = true; + } + + return GetEntProp(client, Prop_Data, datamap); +} diff --git a/env/include/events.inc b/env/include/events.inc new file mode 100644 index 0000000..3308fe7 --- /dev/null +++ b/env/include/events.inc @@ -0,0 +1,257 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _events_included + #endinput +#endif +#define _events_included + +/** + * Event hook modes determining how hooking should be handled + */ +enum EventHookMode +{ + EventHookMode_Pre, /**< Hook callback fired before event is fired */ + EventHookMode_Post, /**< Hook callback fired after event is fired */ + EventHookMode_PostNoCopy /**< Hook callback fired after event is fired, but event data won't be copied */ +}; + +/** + * Hook function types for events. + */ +funcenum EventHook +{ + /** + * Called when a game event is fired. + * + * @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking + * this event has set the hook mode EventHookMode_PostNoCopy. + * @param name String containing the name of the event. + * @param dontBroadcast True if event was not broadcast to clients, false otherwise. + * @return Ignored for post hooks. Plugin_Handled will block event if hooked as pre. + */ + Action:public(Handle:event, const String:name[], bool:dontBroadcast), + /** + * Called when a game event is fired. + * + * @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking + * this event has set the hook mode EventHookMode_PostNoCopy. + * @param name String containing the name of the event. + * @param dontBroadcast True if event was not broadcast to clients, false otherwise. + * @noreturn + */ + public(Handle:event, const String:name[], bool:dontBroadcast), +}; + +/** + * Creates a hook for when a game event is fired. + * + * @param name Name of event. + * @param callback An EventHook function pointer. + * @param mode Optional EventHookMode determining the type of hook. + * @noreturn + * @error Invalid event name or invalid callback function. + */ +native HookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post); + +/** + * Creates a hook for when a game event is fired. + * + * @param name Name of event. + * @param callback An EventHook function pointer. + * @param mode Optional EventHookMode determining the type of hook. + * @return True if event exists and was hooked successfully, false otherwise. + * @error Invalid callback function. + */ +native bool:HookEventEx(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post); + +/** + * Removes a hook for when a game event is fired. + * + * @param name Name of event. + * @param callback An EventHook function pointer. + * @param mode Optional EventHookMode determining the type of hook. + * @noreturn + * @error Invalid callback function or no active hook for specified event. + */ +native UnhookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post); + +/** + * Creates a game event to be fired later. + * + * The Handle should not be closed via CloseHandle(). It must be closed via + * FireEvent() or CancelCreatedEvent(). + * + * @param name Name of event. + * @param force If set to true, this forces the event to be created even if it's not being hooked. + * Note that this will not force it if the event doesn't exist at all. + * @return Handle to event. INVALID_HANDLE is returned if the event doesn't exist or isn't + being hooked (unless force is true). + */ +native Handle:CreateEvent(const String:name[], bool:force=false); + +/** + * Fires a game event. + * + * This function closes the event Handle after completing. + * + * @param event Handle to the event. + * @param dontBroadcast Optional boolean that determines if event should be broadcast to clients. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native FireEvent(Handle:event, bool:dontBroadcast=false); + +/** + * Cancels a previously created game event that has not been fired. + * + * @param event Handled to the event. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native CancelCreatedEvent(Handle:event); + +/** + * Returns the boolean value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @return The boolean value of the specfied event key. + * @error Invalid or corrupt Handle. + */ +native bool:GetEventBool(Handle:event, const String:key[]); + +/** + * Sets the boolean value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @param value New boolean value. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetEventBool(Handle:event, const String:key[], bool:value); + +/** + * Returns the integer value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @return The integer value of the specfied event key. + * @error Invalid or corrupt Handle. + */ +native GetEventInt(Handle:event, const String:key[]); + +/** + * Sets the integer value of a game event's key. + * + * Integer value refers to anything that can be reduced to an integer. + * The various size specifiers, such as "byte" and "short" are still + * integers, and only refer to how much data will actually be sent + * over the network (if applicable). + * + * @param event Handle to the event. + * @param key Name of event key. + * @param value New integer value. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetEventInt(Handle:event, const String:key[], value); + +/** + * Returns the floating point value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @return The floating point value of the specfied event key. + * @error Invalid or corrupt Handle. + */ +native Float:GetEventFloat(Handle:event, const String:key[]); + +/** + * Sets the floating point value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @param value New floating point value. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetEventFloat(Handle:event, const String:key[], Float:value); + +/** + * Retrieves the string value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @param value Buffer to store the value of the specified event key. + * @param maxlength Maximum length of string buffer. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native GetEventString(Handle:event, const String:key[], String:value[], maxlength); + +/** + * Sets the string value of a game event's key. + * + * @param event Handle to the event. + * @param key Name of event key. + * @param value New string value. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SetEventString(Handle:event, const String:key[], const String:value[]); + +/** + * Retrieves the name of a game event. + * + * @param event Handle to the event. + * @param value Buffer to store the name of the event. + * @param maxlength Maximum length of string buffer. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native GetEventName(Handle:event, String:name[], maxlength); + +/** + * Sets whether an event's broadcasting will be disabled or not. + * + * This has no effect on events Handles that are not from HookEvent + * or HookEventEx callbacks. + * + * @param event Handle to an event from an event hook. + * @param dontBroadcast True to disable broadcasting, false otherwise. + * @noreturn + * @error Invalid Handle. + */ +native SetEventBroadcast(Handle:event, bool:dontBroadcast); + diff --git a/env/include/files.inc b/env/include/files.inc new file mode 100644 index 0000000..8a4d2d2 --- /dev/null +++ b/env/include/files.inc @@ -0,0 +1,407 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _files_included + #endinput +#endif +#define _files_included + +/** + * @global All paths in SourceMod natives are relative to the mod folder + * unless otherwise noted. + * + * Most functions in SourceMod (at least, ones that deal with direct + * file manipulation) will support an alternate path specification. + * + * If the path starts with the string "file://" and the PathType is + * not relative, then the "file://" portion is stripped off, and the + * rest of the path is used without any modification (except for + * correcting slashes). This can be used to override the path + * builder to supply alternate absolute paths. Examples: + * + * file://C:/Temp/file.txt + * file:///tmp/file.txt + */ + +/** + * File inode types. + */ +enum FileType +{ + FileType_Unknown = 0, /* Unknown file type (device/socket) */ + FileType_Directory = 1, /* File is a directory */ + FileType_File = 2, /* File is a file */ +}; + +/** + * File time modes. + */ +enum FileTimeMode +{ + FileTime_LastAccess = 0, /* Last access (does not work on FAT) */ + FileTime_Created = 1, /* Creation (does not work on FAT) */ + FileTime_LastChange = 2, /* Last modification */ +}; + +#define PLATFORM_MAX_PATH 256 /**< Maximum path length. */ + +#define SEEK_SET 0 /**< Seek from start. */ +#define SEEK_CUR 1 /**< Seek from current position. */ +#define SEEK_END 2 /**< Seek from end position. */ + +/** + * Path types. + */ +enum PathType +{ + Path_SM, /**< SourceMod root folder */ +}; + +/** + * Builds a path relative to the SourceMod folder. This should be used instead of + * directly referencing addons/sourcemod, in case users change the name of their + * folder layout. + * + * @param type Type of path to build as the base. + * @param buffer Buffer to store the path. + * @param maxlength Maximum length of buffer. + * @param fmt Format string. + * @param ... Format arguments. + * @return Number of bytes written to buffer (not including null terminator). + */ +native BuildPath(PathType:type, String:buffer[], maxlength, const String:fmt[], any:...); + +/** + * Opens a directory/folder for contents enumeration. + * + * @note Directories are closed with CloseHandle(). + * @note Directories Handles can be cloned. + * @note OpenDirectory() supports the "file://" notation. + * + * @param path Path to open. + * @return A Handle to the directory, INVALID_HANDLE on open error. + */ +native Handle:OpenDirectory(const String:path[]); + +/** + * Reads the current directory entry as a local filename, then moves to the next file. + * + * @note Contents of buffers are undefined when returning false. + * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux. + * + * @param dir Handle to a directory. + * @param buffer String buffer to hold directory name. + * @param maxlength Maximum size of string buffer. + * @param type Optional variable to store the file type. + * @return True on success, false if there are no more files to read. + * @error Invalid or corrupt Handle. + */ +native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type=FileType_Unknown); + +/** + * Opens a file. + * + * @note Files are closed with CloseHandle(). + * @note File Handles can be cloned. + * @note OpenFile() supports the "file://" notation. + * + * @param file File to open. + * @param mode Open mode. + * @return A Handle to the file, INVALID_HANDLE on open error. + */ +native Handle:OpenFile(const String:file[], const String:mode[]); + +/** + * Deletes a file. + * + * @param path Path of the file to delete. + * @return True on success, false otherwise. + */ +native bool:DeleteFile(const String:path[]); + +/** + * Reads a line from a text file. + * + * @param hndl Handle to the file. + * @param buffer String buffer to hold the line. + * @param maxlength Maximum size of string buffer. + * @return True on success, false otherwise. + */ +native bool:ReadFileLine(Handle:hndl, String:buffer[], maxlength); + +/** + * Reads binary data from a file. + * + * @param hndl Handle to the file. + * @param items Array to store each item read. + * @param num_items Number of items to read into the array. + * @param size Size of each element, in bytes, to be read. + * Valid sizes are 1, 2, or 4. + * @return Number of elements read, or -1 on error. + */ +native ReadFile(Handle:hndl, items[], num_items, size); + +/** + * Reads a UTF8 or ANSI string from a file. + * + * @param hndl Handle to the file. + * @param buffer Buffer to store the string. + * @param max_size Maximum size of the string buffer. + * @param read_count If -1, reads until a null terminator is encountered in + * the file. Otherwise, read_count bytes are read + * into the buffer provided. In this case the buffer + * is not explicitly null terminated, and the buffer + * will contain any null terminators read from the file. + * @return Number of characters written to the buffer, or -1 + * if an error was encountered. + * @error Invalid Handle, or read_count > max_size. + */ +native ReadFileString(Handle:hndl, String:buffer[], max_size, read_count=-1); + +/** + * Writes binary data to a file. + * + * @param hndl Handle to the file. + * @param items Array of items to write. The data is read directly. + * That is, in 1 or 2-byte mode, the lower byte(s) in + * each cell are used directly, rather than performing + * any casts from a 4-byte number to a smaller number. + * @param num_items Number of items in the array. + * @param size Size of each item in the array in bytes. + * Valid sizes are 1, 2, or 4. + * @return True on success, false on error. + * @error Invalid Handle. + */ +native bool:WriteFile(Handle:hndl, const items[], num_items, size); + +/** + * Writes a binary string to a file. + * + * @param hndl Handle to th efile. + * @param buffer String to write. + * @param term True to append NUL terminator, false otherwise. + * @return True on success, false on error. + * @error Invalid Handle. + */ +native bool:WriteFileString(Handle:hndl, const String:buffer[], bool:term); + +/** + * Writes a line of text to a text file. A newline is automatically appended. + * + * @param hndl Handle to the file. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool:WriteFileLine(Handle:hndl, const String:format[], any:...); + +/** + * Reads a single binary cell from a file. + * + * @param hndl Handle to the file. + * @param data Variable to store the data read. + * @param size Size of the data to read in bytes. Valid + * sizes are 1, 2, or 4 bytes. + * @return Number of elements read (max 1), or -1 on error. + * @error Invalid Handle. + */ +stock ReadFileCell(Handle:hndl, &data, size) +{ + new array[1], ret; + + if ((ret = ReadFile(hndl, array, 1, size)) == 1) + { + data = array[0]; + } + + return ret; +} + +/** + * Writes a single binary cell to a file. + * + * @param hndl Handle to the file. + * @param data Cell to write to the file. + * @param size Size of the data to read in bytes. Valid + * sizes are 1, 2, or 4 bytes. If the size + * is less than 4 bytes, the data is truncated + * rather than casted. That is, only the lower + * bits will be read. + * @return True on success, false on error. + * @error Invalid Handle. + */ +stock bool:WriteFileCell(Handle:hndl, data, size) +{ + new array[1]; + + array[0] = data; + + return WriteFile(hndl, array, 1, size); +} + +/** + * Tests if the end of file has been reached. + * + * @param file Handle to the file. + * @return True if end of file has been reached, false otherwise. + * @error Invalid Handle. + */ +native bool:IsEndOfFile(Handle:file); + +/** + * Sets the file position indicator. + * + * @param file Handle to the file. + * @param position Position relative to what is specified in whence. + * @param where SEEK_ constant value of where to see from. + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool:FileSeek(Handle:file, position, where); + +/** + * Get current position in the file. + * + * @param file Handle to the file. + * @return Value for the file position indicator. + * @error Invalid Handle. + */ +native FilePosition(Handle:file); + +/** + * Checks if a file exists. + * + * @param path Path to the file. + * @param use_valve_fs If true, the Valve file system will be used instead. + * This can be used to check for the existance of files + * inside GCFs or the game cache, rather than solely files + * that are on disk. + * @return True if the file exists, false otherwise. + */ +native bool:FileExists(const String:path[], bool:use_valve_fs=false); + +/** + * Renames a file. + * + * @param newpath New path to the file. + * @param oldpath Path to the existing file. + * @return True on success, false otherwise. + */ +native bool:RenameFile(const String:newpath[], const String:oldpath[]); + +/** + * Checks if a directory exists. + * + * @param path Path to the directory. + * @return True if the directory exists, false otherwise. + */ +native bool:DirExists(const String:path[]); + +/** + * Get the file size in bytes. + * + * @param path Path to the file. + * @return File size in bytes, -1 if file not found. + */ +native FileSize(const String:path[]); + +/** + * Flushes a file's buffered output; any buffered output + * is immediately written to the file. + * + * @param file Handle to the file. + * @return True on success, false on failure. + */ +native FlushFile(Handle:file); + +/** + * Removes a directory. + * @note On most Operating Systems you cannot remove a directory which has files inside it. + * + * @param path Path to the directory. + * @return True on success, false otherwise. + */ +native bool:RemoveDir(const String:path[]); + +#define FPERM_U_READ 0x0100 /* User can read. */ +#define FPERM_U_WRITE 0x0080 /* User can write. */ +#define FPERM_U_EXEC 0x0040 /* User can exec. */ +#define FPERM_G_READ 0x0020 /* Group can read. */ +#define FPERM_G_WRITE 0x0010 /* Group can write. */ +#define FPERM_G_EXEC 0x0008 /* Group can exec. */ +#define FPERM_O_READ 0x0004 /* Anyone can read. */ +#define FPERM_O_WRITE 0x0002 /* Anyone can write. */ +#define FPERM_O_EXEC 0x0001 /* Anyone can exec. */ + +/** + * Creates a directory. + * + * @param path Path to create. + * @param mode Permissions (default is o=rx,g=rx,u=rwx). Note that folders must have + * the execute bit set on Linux. On Windows, the mode is ignored. + */ +native bool:CreateDirectory(const String:path[], mode); + +/** + * Returns a file timestamp as a unix timestamp. + * + * @param file File name. + * @param tmode Time mode. + * @return Time value, or -1 on failure. + */ +native GetFileTime(const String:file[], FileTimeMode:tmode); + +/** + * Same as LogToFile(), except uses an open file Handle. The file must + * be opened in text appending mode. + * + * @param hndl Handle to the file. + * @param message Message format. + * @param ... Message format parameters. + * @noreturn + * @error Invalid Handle. + */ +native LogToOpenFile(Handle:hndl, const String:message[], any:...); + +/** + * Same as LogToFileEx(), except uses an open file Handle. The file must + * be opened in text appending mode. + * + * @param hndl Handle to the file. + * @param message Message format. + * @param ... Message format parameters. + * @noreturn + * @error Invalid Handle. + */ +native LogToOpenFileEx(Handle:hndl, const String:message[], any:...); + diff --git a/env/include/float.inc b/env/include/float.inc new file mode 100644 index 0000000..73a5c3e --- /dev/null +++ b/env/include/float.inc @@ -0,0 +1,458 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _float_included + #endinput +#endif +#define _float_included + +/** + * Converts an integer into a floating point value. + * + * @param value Integer to convert. + * @return Floating point value. + */ +native Float:float(value); + +/** + * Multiplies two floats together. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1*oper2. + */ +native Float:FloatMul(Float:oper1, Float:oper2); + +/** + * Divides the dividend by the divisor. + * + * @param dividend First value. + * @param divisor Second value. + * @return dividend/divisor. + */ +native Float:FloatDiv(Float:dividend, Float:divisor); + +/** + * Adds two floats together. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1+oper2. + */ +native Float:FloatAdd(Float:oper1, Float:oper2); + +/** + * Subtracts oper2 from oper1. + * + * @param oper1 First value. + * @param oper2 Second value. + * @return oper1-oper2. + */ +native Float:FloatSub(Float:oper1, Float:oper2); + +/** + * Returns the decimal part of a float. + * + * @param value Input value. + * @return Decimal part. + */ +native Float:FloatFraction(Float:value); + +/** + * Rounds a float to the closest integer to zero. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native RoundToZero(Float:value); + +/** + * Rounds a float to the next highest integer value. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native RoundToCeil(Float:value); + +/** + * Rounds a float to the next lowest integer value. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native RoundToFloor(Float:value); + +/** + * Standard IEEE rounding. + * + * @param value Input value to be rounded. + * @return Rounded value. + */ +native RoundToNearest(Float:value); + +/** + * Compares two floats. + * + * @param fOne First value. + * @param fTwo Second value. + * @return Returns 1 if the first argument is greater than the second argument. + * Returns -1 if the first argument is smaller than the second argument. + * Returns 0 if both arguments are equal. + */ +native FloatCompare(Float:fOne, Float:fTwo); + +/** + * Returns the square root of the input value, equivalent to floatpower(value, 0.5). + * + * @param value Input value. + * @return Square root of the value. + */ +native Float:SquareRoot(Float:value); + +/** + * Returns the value raised to the power of the exponent. + * + * @param value Value to be raised. + * @param exponent Value to raise the base. + * @return value^exponent. + */ +native Float:Pow(Float:value, Float:exponent); + +/** + * Returns the value of raising the input by e. + * + * @param value Input value. + * @return exp(value). + */ +native Float:Exponential(Float:value); + +/** + * Returns the logarithm of any base specified. + * + * @param value Input value. + * @param base Logarithm base to use, default is 10. + * @return log(value)/log(base). + */ +native Float:Logarithm(Float:value, Float:base=10.0); + +/** + * Returns the sine of the argument. + * + * @param value Input value in radians. + * @return sin(value). + */ +native Float:Sine(Float:value); + +/** + * Returns the cosine of the argument. + * + * @param value Input value in radians. + * @return cos(value). + */ +native Float:Cosine(Float:value); + +/** + * Returns the tangent of the argument. + * + * @param value Input value in radians. + * @return tan(value). + */ +native Float:Tangent(Float:value); + +/** + * Returns an absolute value. + * + * @param value Input value. + * @return Absolute value of the input. + */ +native Float:FloatAbs(Float:value); + +/** + * Returns the arctangent of the input value. + * + * @param angle Input value. + * @return atan(value) in radians. + */ +native Float:ArcTangent(Float:angle); + +/** + * Returns the arccosine of the input value. + * + * @param angle Input value. + * @return acos(value) in radians. + */ +native Float:ArcCosine(Float:angle); + +/** + * Returns the arcsine of the input value. + * + * @param angle Input value. + * @return asin(value) in radians. + */ +native Float:ArcSine(Float:angle); + +/** + * Returns the arctangent2 of the input values. + * + * @param x Horizontal value. + * @param y Vertical value. + * @return atan2(value) in radians. + */ +native Float:ArcTangent2(Float:x, Float:y); + +/** + * Rounds a floating point number using the "round to nearest" algorithm. + * + * @param value Floating point value to round. + * @return The value rounded to the nearest integer. + */ +stock RoundFloat(Float:value) +{ + return RoundToNearest(value); +} + +/** + * User defined operators. + * + */ +#pragma rational Float + +native Float:operator*(Float:oper1, Float:oper2) = FloatMul; +native Float:operator/(Float:oper1, Float:oper2) = FloatDiv; +native Float:operator+(Float:oper1, Float:oper2) = FloatAdd; +native Float:operator-(Float:oper1, Float:oper2) = FloatSub; + +stock Float:operator++(Float:oper) +{ + return oper+1.0; +} + +stock Float:operator--(Float:oper) +{ + return oper-1.0; +} + +stock Float:operator-(Float:oper) +{ + return oper^Float:((-1)^((-1)/2)); /* IEEE values are sign/magnitude */ +} + +stock Float:operator*(Float:oper1, oper2) +{ + return FloatMul(oper1, float(oper2)); /* "*" is commutative */ +} + +stock Float:operator/(Float:oper1, oper2) +{ + return FloatDiv(oper1, float(oper2)); +} + +stock Float:operator/(oper1, Float:oper2) +{ + return FloatDiv(float(oper1), oper2); +} + +stock Float:operator+(Float:oper1, oper2) +{ + return FloatAdd(oper1, float(oper2)); /* "+" is commutative */ +} + +stock Float:operator-(Float:oper1, oper2) +{ + return FloatSub(oper1, float(oper2)); +} + +stock Float:operator-(oper1, Float:oper2) +{ + return FloatSub(float(oper1), oper2); +} + +stock bool:operator==(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) == 0; +} + +stock bool:operator==(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) == 0; /* "==" is commutative */ +} + +stock bool:operator!=(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) != 0; +} + +stock bool:operator!=(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) != 0; /* "==" is commutative */ +} + +stock bool:operator>(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) > 0; +} + +stock bool:operator>(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) > 0; +} + +stock bool:operator>(oper1, Float:oper2) +{ + return FloatCompare(float(oper1), oper2) > 0; +} + +stock bool:operator>=(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) >= 0; +} + +stock bool:operator>=(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) >= 0; +} + +stock bool:operator>=(oper1, Float:oper2) +{ + return FloatCompare(float(oper1), oper2) >= 0; +} + +stock bool:operator<(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) < 0; +} + +stock bool:operator<(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) < 0; +} + +stock bool:operator<(oper1, Float:oper2) +{ + return FloatCompare(float(oper1), oper2) < 0; +} + +stock bool:operator<=(Float:oper1, Float:oper2) +{ + return FloatCompare(oper1, oper2) <= 0; +} + +stock bool:operator<=(Float:oper1, oper2) +{ + return FloatCompare(oper1, float(oper2)) <= 0; +} + +stock bool:operator<=(oper1, Float:oper2) +{ + return FloatCompare(float(oper1), oper2) <= 0; +} + +stock bool:operator!(Float:oper) +{ + return (_:oper & ((-1)/2)) == 0; /* -1 = all bits to 1; /2 = remove most significant bit (sign) + works on both 32bit and 64bit systems; no constant required */ +} + +/** + * Forbidden operators. + * + */ +forward operator%(Float:oper1, Float:oper2); +forward operator%(Float:oper1, oper2); +forward operator%(oper1, Float:oper2); + +#define FLOAT_PI 3.1415926535897932384626433832795 + +/** + * Converts degrees to radians. + * + * @param angle Degrees. + * @return Radians. + */ +stock Float:DegToRad(Float:angle) +{ + return (angle*FLOAT_PI)/180; +} + +/** + * Converts degrees to radians. + * + * @param angle Radians. + * @return Degrees. + */ +stock Float:RadToDeg(Float:angle) +{ + return (angle*180)/FLOAT_PI; +} + +/** + * Returns a random integer in the range [0, 2^31-1]. + * + * Note: Uniform random number streams are seeded automatically per-plugin. + * + * @return Random integer. + */ +native GetURandomInt(); + +/** + * Returns a uniform random float in the range [0, 1). + * + * Note: Uniform random number streams are seeded automatically per-plugin. + * + * @return Uniform random floating-point number. + */ +native Float:GetURandomFloat(); + +/** + * Seeds a plugin's uniform random number stream. This is done automatically, + * so normally it is totally unnecessary to call this. + * + * @param seeds Array of numbers to use as seeding data. + * @param numSeeds Number of seeds in the seeds array. + * @noreturn + */ +native SetURandomSeed(const seeds[], numSeeds); + +/** + * Seeds a plugin's uniform random number stream. This is done automatically, + * so normally it is totally unnecessary to call this. + * + * @param seed Single seed value. + * @noreturn + */ +stock SetURandomSeedSimple(seed) +{ + new seeds[1]; + seeds[0] = seed; + SetURandomSeed(seeds, 1); +} + diff --git a/env/include/functions.inc b/env/include/functions.inc new file mode 100644 index 0000000..1ad804f --- /dev/null +++ b/env/include/functions.inc @@ -0,0 +1,489 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#define SP_PARAMFLAG_BYREF (1<<0) /**< Internal use only. */ + +/** + * Describes the various ways to pass parameters to functions or forwards. + */ +enum ParamType +{ + Param_Any = 0, /**< Any data type can be pushed */ + Param_Cell = (1<<1), /**< Only basic cells can be pushed */ + Param_Float = (2<<1), /**< Only floats can be pushed */ + Param_String = (3<<1)|SP_PARAMFLAG_BYREF, /**< Only strings can be pushed */ + Param_Array = (4<<1)|SP_PARAMFLAG_BYREF, /**< Only arrays can be pushed */ + Param_VarArgs = (5<<1), /**< Same as "..." in plugins, anything can be pushed, but it will always be byref */ + Param_CellByRef = (1<<1)|SP_PARAMFLAG_BYREF, /**< Only a cell by reference can be pushed */ + Param_FloatByRef = (2<<1)|SP_PARAMFLAG_BYREF /**< Only a float by reference can be pushed */ +}; + +/** + * Defines how a forward iterates through plugin functions. + */ +enum ExecType +{ + ET_Ignore = 0, /**< Ignore all return values, return 0 */ + ET_Single = 1, /**< Only return the last exec, ignore all others */ + ET_Event = 2, /**< Acts as an event with the Actions defined in core.inc, no mid-Stops allowed, returns highest */ + ET_Hook = 3 /**< Acts as a hook with the Actions defined in core.inc, mid-Stops allowed, returns highest */ +}; + +/** + * @section Flags that are used with Call_PushArrayEx() and Call_PushStringEx() + */ + +#define SM_PARAM_COPYBACK (1<<0) /**< Copy an array/reference back after call */ + +#define SM_PARAM_STRING_UTF8 (1<<0) /**< String should be UTF-8 handled */ +#define SM_PARAM_STRING_COPY (1<<1) /**< String should be copied into the plugin */ +#define SM_PARAM_STRING_BINARY (1<<2) /**< Treat the string as a binary string */ + +/** + * @endsection + */ + +/** + * @section Error codes + */ +#define SP_ERROR_NONE 0 /**< No error occurred */ +#define SP_ERROR_FILE_FORMAT 1 /**< File format unrecognized */ +#define SP_ERROR_DECOMPRESSOR 2 /**< A decompressor was not found */ +#define SP_ERROR_HEAPLOW 3 /**< Not enough space left on the heap */ +#define SP_ERROR_PARAM 4 /**< Invalid parameter or parameter type */ +#define SP_ERROR_INVALID_ADDRESS 5 /**< A memory address was not valid */ +#define SP_ERROR_NOT_FOUND 6 /**< The object in question was not found */ +#define SP_ERROR_INDEX 7 /**< Invalid index parameter */ +#define SP_ERROR_STACKLOW 8 /**< Nnot enough space left on the stack */ +#define SP_ERROR_NOTDEBUGGING 9 /**< Debug mode was not on or debug section not found */ +#define SP_ERROR_INVALID_INSTRUCTION 10 /**< Invalid instruction was encountered */ +#define SP_ERROR_MEMACCESS 11 /**< Invalid memory access */ +#define SP_ERROR_STACKMIN 12 /**< Stack went beyond its minimum value */ +#define SP_ERROR_HEAPMIN 13 /**< Heap went beyond its minimum value */ +#define SP_ERROR_DIVIDE_BY_ZERO 14 /**< Division by zero */ +#define SP_ERROR_ARRAY_BOUNDS 15 /**< Array index is out of bounds */ +#define SP_ERROR_INSTRUCTION_PARAM 16 /**< Instruction had an invalid parameter */ +#define SP_ERROR_STACKLEAK 17 /**< A native leaked an item on the stack */ +#define SP_ERROR_HEAPLEAK 18 /**< A native leaked an item on the heap */ +#define SP_ERROR_ARRAY_TOO_BIG 19 /**< A dynamic array is too big */ +#define SP_ERROR_TRACKER_BOUNDS 20 /**< Tracker stack is out of bounds */ +#define SP_ERROR_INVALID_NATIVE 21 /**< Native was pending or invalid */ +#define SP_ERROR_PARAMS_MAX 22 /**< Maximum number of parameters reached */ +#define SP_ERROR_NATIVE 23 /**< Error originates from a native */ +#define SP_ERROR_NOT_RUNNABLE 24 /**< Function or plugin is not runnable */ +#define SP_ERROR_ABORTED 25 /**< Function call was aborted */ + +/** + * @endsection + */ + +/** + * Gets a function id from a function name. + * + * @param plugin Handle of the plugin that contains the function. + Pass INVALID_HANDLE to search in the calling plugin. + * @param name Name of the function. + * @return Function id or INVALID_FUNCTION if not found. + * @error Invalid or corrupt plugin handle. + */ +native Function:GetFunctionByName(Handle:plugin, const String:name[]); + +/** + * Creates a global forward. + * + * @note The name used to create the forward is used as its public function in all target plugins. + * @note This is ideal for global, static forwards that are never changed. + * @note Global forwards cannot be cloned. + * @note Use CloseHandle() to destroy these. + * + * @param name Name of public function to use in forward. + * @param type Execution type to be used. + * @param ... Variable number of parameter types (up to 32). + * @return Handle to new global forward. + * @error More than 32 paramater types passed. + */ +native Handle:CreateGlobalForward(const String:name[], ExecType:type, ParamType:...); + +/** + * Creates a private forward. + * + * @note No functions are automatically added. Use AddToForward() to do this. + * @note Private forwards can be cloned. + * @note Use CloseHandle() to destroy these. + * + * @param type Execution type to be used. + * @param ... Variable number of parameter types (up to 32). + * @return Handle to new private forward. + * @error More than 32 paramater types passed. + */ +native Handle:CreateForward(ExecType:type, ParamType:...); + +/** + * Returns the number of functions in a global or private forward's call list. + * + * @param fwd Handle to global or private forward. + * @return Number of functions in forward. + * @error Invalid or corrupt forward handle. + */ +native GetForwardFunctionCount(Handle:fwd); + +/** + * Adds a function to a private forward's call list. + * + * @note Cannot be used during an incompleted call. + * + * @param fwd Handle to private forward. + * @param plugin Handle of the plugin that contains the function. + * Pass INVALID_HANDLE to specify the calling plugin. + * @param func Function to add to forward. + * @return True on success, false otherwise. + * @error Invalid or corrupt private forward handle, invalid or corrupt plugin handle, or invalid function. + */ +native bool:AddToForward(Handle:fwd, Handle:plugin, Function:func); + +/** + * Removes a function from a private forward's call list. + * + * @note Only removes one instance. + * @note Functions will be removed automatically if their parent plugin is unloaded. + * + * @param fwd Handle to private forward. + * @param plugin Handle of the plugin that contains the function. + * Pass INVALID_HANDLE to specify the calling plugin. + * @param func Function to remove from forward. + * @return True on success, false otherwise. + * @error Invalid or corrupt private forward handle, invalid or corrupt plugin handle, or invalid function. + */ +native bool:RemoveFromForward(Handle:fwd, Handle:plugin, Function:func); + +/** + * Removes all instances of a plugin from a private forward's call list. + * + * @note Functions will be removed automatically if their parent plugin is unloaded. + * + * @param fwd Handle to private forward. + * @param plugin Handle of the plugin to remove instances of. + * Pass INVALID_HANDLE to specify the calling plugin. + * @return Number of functions removed from forward. + * @error Invalid or corrupt private forward handle or invalid or corrupt plugin handle. + */ +native RemoveAllFromForward(Handle:fwd, Handle:plugin); + +/** + * Starts a call to functions in a forward's call list. + * + * @note Cannot be used during an incompleted call. + * + * @param fwd Handle to global or private forward. + * @noreturn + * @error Invalid or corrupt forward handle or called before another call has completed. + */ +native Call_StartForward(Handle:fwd); + +/** + * Starts a call to a function. + * + * @note Cannot be used during an incompleted call. + * + * @param plugin Handle of the plugin that contains the function. + * Pass INVALID_HANDLE to specify the calling plugin. + * @param func Function to call. + * @noreturn + * @error Invalid or corrupt plugin handle, invalid function, or called before another call has completed. + */ +native Call_StartFunction(Handle:plugin, Function:func); + +/** + * Pushes a cell onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value Cell value to push. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushCell(any:value); + +/** + * Pushes a cell by reference onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value Cell reference to push. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushCellRef(&any:value); + +/** + * Pushes a float onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value Floating point value to push. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushFloat(Float:value); + +/** + * Pushes a float by reference onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value Floating point reference to push. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushFloatRef(&Float:value); + +/** + * Pushes an array onto the current call. + * + * @note Changes to array are not copied back to caller. Use PushArrayEx() to do this. + * @note Cannot be used before a call has been started. + * + * @param value Array to push. + * @param size Size of array. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushArray(const any:value[], size); + +/** + * Pushes an array onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value Array to push. + * @param size Size of array. + * @param cpflags Whether or not changes should be copied back to the input array. + * See SP_PARAM_* constants for details. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushArrayEx(any:value[], size, cpflags); + +/** + * Pushes a string onto the current call. + * + * @note Changes to string are not copied back to caller. Use PushStringEx() to do this. + * @note Cannot be used before a call has been started. + * + * @param value String to push. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushString(const String:value[]); + +/** + * Pushes a string onto the current call. + * + * @note Cannot be used before a call has been started. + * + * @param value String to push. + * @param length Length of string buffer. + * @param szflags Flags determining how string should be handled. + * See SP_PARAM_STRING_* constants for details. + * The default (0) is to push ASCII. + * @param cpflags Whether or not changes should be copied back to the input array. + * See SP_PARAM_* constants for details. + * @noreturn + * @error Called before a call has been started. + */ +native Call_PushStringEx(String:value[], length, szflags, cpflags); + +/** + * Completes a call to a function or forward's call list. + * + * @note Cannot be used before a call has been started. + * + * @param result Return value of function or forward's call list. + * @return SP_ERROR_NONE on success, any other integer on failure. + * @error Called before a call has been started. + */ +native Call_Finish(&any:result=0); + +/** + * Cancels a call to a function or forward's call list. + * + * @note Cannot be used before a call has been started. + * + * @noreturn + * @error Called before a call has been started. + */ +native Call_Cancel(); + +/** + * Defines a native function. + * + * It is not necessary to validate the parameter count + * + * @param plugin Handle of the calling plugin. + * @param numParams Number of parameters passed to the native. + * @return Value for the native call to return. + */ +functag public NativeCall(Handle:plugin, numParams); + +/** + * Creates a dynamic native. This should only be called in AskPluginLoad(), or + * else you risk not having your native shared with other plugins. + * + * @param name Name of the dynamic native; must be unique amongst + * all other registered dynamic natives. + * @param func Function to use as the dynamic native. + * @noreturn + */ +native CreateNative(const String:name[], NativeCall:func); + +/** + * Throws an error in the calling plugin of a native, instead of your own plugin. + * + * @param error Error code to use. + * @param fmt Error message format. + * @param ... Format arguments. + */ +native ThrowNativeError(error, const String:fmt[], any:...); + +/** + * Retrieves the string length from a native parameter string. This is useful + * fetching the entire string using dynamic arrays. + * @note If this function succeeds, Get/SetNativeString will also succeed. + * + * @param param Parameter number, starting from 1. + * @param length Stores the length of the string. + * @return SP_ERROR_NONE on success, any other integer on failure. + * @error Invalid parameter number or calling from a non-native function. + */ +native GetNativeStringLength(param, &length); + +/** + * Retrieves a string from a native parameter. + * @note Output conditions are undefined on failure. + * + * @param param Parameter number, starting from 1. + * @param buffer Buffer to store the string in. + * @param maxlength Maximum length of the buffer. + * @param bytes Optionally store the number of bytes written. + * @return SP_ERROR_NONE on success, any other integer on failure. + * @error Invalid parameter number or calling from a non-native function. + */ +native GetNativeString(param, String:buffer[], maxlength, &bytes=0); + +/** + * Sets a string in a native parameter. + * @note Output conditions are undefined on failure. + * + * @param param Parameter number, starting from 1. + * @param source Source string to use. + * @param maxlength Maximum number of bytes to write. + * @param utf8 If false, string will not be written + * with UTF8 safety. + * @param bytes Optionally store the number of bytes written. + * @return SP_ERROR_NONE on success, any other integer on failure. + * @error Invalid parameter number or calling from a non-native function. + */ +native SetNativeString(param, const String:source[], maxlength, bool:utf8=true, &bytes=0); + +/** + * Gets a cell from a native parameter. + * + * @param param Parameter number, starting from 1. + * @return Cell value at the parameter number. + * @error Invalid parameter number or calling from a non-native function. + */ +native any:GetNativeCell(param); + +/** + * Gets a cell from a native parameter, by reference. + * + * @param param Parameter number, starting from 1. + * @return Cell value at the parameter number. + * @error Invalid parameter number or calling from a non-native function. + */ +native any:GetNativeCellRef(param); + +/** + * Sets a cell from a native parameter, by reference. + * + * @param param Parameter number, starting from 1. + * @param value Cell value at the parameter number to set by reference. + * @noreturn + * @error Invalid parameter number or calling from a non-native function. + */ +native SetNativeCellRef(param, any:value); + +/** + * Gets an array from a native parameter (always by reference). + * + * @param param Parameter number, starting from 1. + * @param local Local array to copy into. + * @param size Maximum size of local array. + * @return SP_ERROR_NONE on success, anything else on failure. + * @error Invalid parameter number or calling from a non-native function. + */ +native GetNativeArray(param, any:local[], size); + +/** + * Copies a local array into a native parameter array (always by reference). + * + * @param param Parameter number, starting from 1. + * @param local Local array to copy from. + * @param size Size of the local array to copy. + * @return SP_ERROR_NONE on success, anything else on failure. + * @error Invalid parameter number or calling from a non-native function. + */ +native SetNativeArray(param, const any:local[], size); + +/** + * Formats a string using parameters from a native. + * + * @note All parameter indexes start at 1. + * @note If the input and output buffers overlap, the contents + * of the output buffer at the end is undefined. + * + * @param out_param Output parameter number to write to. If 0, out_string is used. + * @param fmt_param Format parameter number. If 0, fmt_string is used. + * @param vararg_param First variable parameter number. + * @param out_len Output string buffer maximum length (always required). + * @param written Optionally stores the number of bytes written. + * @param out_string Output string buffer to use if out_param is not used. + * @param fmt_string Format string to use if fmt_param is not used. + * @return SP_ERROR_NONE on success, anything else on failure. + */ +native FormatNativeString(out_param, + fmt_param, + vararg_param, + out_len, + &written=0, + String:out_string[]="", + const String:fmt_string[]=""); diff --git a/env/include/geoip.inc b/env/include/geoip.inc new file mode 100644 index 0000000..725126e --- /dev/null +++ b/env/include/geoip.inc @@ -0,0 +1,102 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _geoip_included + #endinput +#endif +#define _geoip_included + +#include + +/** + * @section IP addresses can contain ports, the ports will be stripped out. + */ + +/** + * Gets the two character country code from an IP address. (US, CA, etc) + * + * @param ip Ip to determine the country code. + * @param ccode Destination string buffer to store the code. + * @return True on success, false if no country found. + */ +native bool:GeoipCode2(const String:ip[], String:ccode[3]); + +/** + * Gets the three character country code from an IP address. (USA, CAN, etc) + * + * @param ip Ip to determine the country code. + * @param ccode Destination string buffer to store the code. + * @return True on success, false if no country found. + */ +native bool:GeoipCode3(const String:ip[], String:ccode[4]); + +/** + * Gets the full country name. (max length of output string is 45) + * + * @param ip Ip to determine the country code. + * @param ccode Destination string buffer to store the country name. + * @param len Maximum length of output string buffer. + * @return True on success, false if no country found. + */ +native bool:GeoipCountry(const String:ip[], String:name[], maxlength); + +/** + * @endsection + */ + +/** + * Do not edit below this line! + */ +public Extension:__ext_geoip = +{ + name = "GeoIP", + file = "geoip.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_geoip_SetNTVOptional() +{ + MarkNativeAsOptional("GeoipCode2"); + MarkNativeAsOptional("GeoipCode3"); + MarkNativeAsOptional("GeoipCountry"); +} +#endif diff --git a/env/include/halflife.inc b/env/include/halflife.inc new file mode 100644 index 0000000..9e52361 --- /dev/null +++ b/env/include/halflife.inc @@ -0,0 +1,572 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _halflife_included + #endinput +#endif +#define _halflife_included + +#define SOURCE_SDK_UNKNOWN 0 /**< Could not determine the engine version */ +#define SOURCE_SDK_ORIGINAL 10 /**< Original Source engine (still used by "The Ship") */ +#define SOURCE_SDK_DARKMESSIAH 15 /**< Modified version of original engine used by Dark Messiah (no SDK) */ +#define SOURCE_SDK_EPISODE1 20 /**< SDK+Engine released after Episode 1 */ +#define SOURCE_SDK_EPISODE2 30 /**< SDK+Engine released after Episode 2/Orange Box */ +#define SOURCE_SDK_EPISODE2VALVE 35 /**< SDK+Engine released after Episode 2/Orange Box */ +#define SOURCE_SDK_LEFT4DEAD 40 /**< Engine released after Left 4 Dead (no SDK yet) */ +#define SOURCE_SDK_LEFT4DEAD2 50 /**< Engine released after Left 4 Dead 2 (no SDK yet) */ + +#define MOTDPANEL_TYPE_TEXT 0 /**< Treat msg as plain text */ +#define MOTDPANEL_TYPE_INDEX 1 /**< Msg is auto determined by the engine */ +#define MOTDPANEL_TYPE_URL 2 /**< Treat msg as an URL link */ +#define MOTDPANEL_TYPE_FILE 3 /**< Treat msg as a filename to be openned */ + +enum DialogType +{ + DialogType_Msg = 0, /**< just an on screen message */ + DialogType_Menu, /**< an options menu */ + DialogType_Text, /**< a richtext dialog */ + DialogType_Entry, /**< an entry box */ + DialogType_AskConnect /**< ask the client to connect to a specified IP */ +}; + +#define INVALID_ENT_REFERENCE 0xFFFFFFFF + +/** + * Logs a generic message to the HL2 logs. + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + */ +native LogToGame(const String:format[], any:...); + +/** + * Sets the seed value for the global Half-Life 2 Random Stream. + * + * @param seed Seed value. + * @noreturn + */ +native SetRandomSeed(seed); + +/** + * Returns a random floating point number from the Half-Life 2 Random Stream. + * + * @param fMin Minimum random bound. + * @param fMax Maximum random bound. + * @return A random number between (inclusive) fMin and fMax. + */ +native Float:GetRandomFloat(Float:fMin=0.0, Float:fMax=1.0); + +/** + * Returns a random number from the Half-Life 2 Random Stream. + * + * @param nmin Minimum random bound. + * @param nmax Maximum random bound. + * @return A random number between (inclusive) nmin and nmax. + */ +native GetRandomInt(nmin, nmax); + +/** + * Returns whether a map is valid or not. + * + * @param Map name, excluding .bsp extension. + * @return True if valid, false otherwise. + */ +native bool:IsMapValid(const String:map[]); + +/** + * Returns whether the server is dedicated. + * + * @return True if dedicated, false otherwise. + */ +native bool:IsDedicatedServer(); + +/** + * Returns a high-precision time value for profiling the engine. + * + * @return A floating point time value. + */ +native Float:GetEngineTime(); + +/** + * Returns the game time based on the game tick. + * + * @return Game tick time. + */ +native Float:GetGameTime(); + +/** + * Returns the game description from the mod. + * + * @param buffer Buffer to store the description. + * @param maxlength Maximum size of the buffer. + * @param original If true, retrieves the original game description, + * ignoring any potential hooks from plugins. + * @return Number of bytes written to the buffer (UTF-8 safe). + */ +native GetGameDescription(String:buffer[], maxlength, bool:original=false); + +/** + * Returns the name of the game's directory. + * + * @param buffer Buffer to store the directory name. + * @param maxlength Maximum size of the buffer. + * + * return Number of bytes written to the buffer (UTF-8 safe). + */ +native GetGameFolderName(String:buffer[], maxlength); + +/** + * Returns the current map name. + * + * @param buffer Buffer to store map name. + * @param maxlength Maximum length of buffer. + * @return Number of bytes written (UTF-8 safe). + */ +native GetCurrentMap(String:buffer[], maxlength); + +/** + * Precaches a given model. + * + * @param model Name of the model to precache. + * @param preload If preload is true the file will be precached before level startup. + * @return Returns the model index, 0 for error. + */ +native PrecacheModel(const String:model[], bool:preload=false); + +/** + * Precaches a given sentence file. + * + * @param file Name of the sentence file to precache. + * @param preload If preload is true the file will be precached before level startup. + * @return Returns a sentence file index. + */ +native PrecacheSentenceFile(const String:file[], bool:preload=false); + +/** + * Precaches a given decal. + * + * @param decal Name of the decal to precache. + * @param preload If preload is true the file will be precached before level startup. + * @return Returns a decal index. + */ +native PrecacheDecal(const String:decal[], bool:preload=false); + +/** + * Precaches a given generic file. + * + * @param generic Name of the generic file to precache. + * @param preload If preload is true the file will be precached before level startup. + * @return Returns a generic file index. + */ +native PrecacheGeneric(const String:generic[], bool:preload=false); + +/** + * Returns if a given model is precached. + * + * @param model Name of the model to check. + * @return True if precached, false otherwise. + */ +native bool:IsModelPrecached(const String:model[]); + +/** + * Returns if a given decal is precached. + * + * @param decal Name of the decal to check. + * @return True if precached, false otherwise. + */ +native bool:IsDecalPrecached(const String:decal[]); + +/** + * Returns if a given generic file is precached. + * + * @param decal Name of the generic file to check. + * @return True if precached, false otherwise. + */ +native bool:IsGenericPrecached(const String:generic[]); + +/** + * Precaches a given sound. + * + * @param sound Name of the sound to precache. + * @param preload If preload is true the file will be precached before level startup. + * @return True if successfully precached, false otherwise. + */ +native bool:PrecacheSound(const String:sound[], bool:preload=false); + +/** + * Returns if a given sound is precached. + * + * @param sound Name of the sound to check. + * @return True if precached, false otherwise. + */ +native bool:IsSoundPrecached(const String:sound[]); + +/** + * Creates different types of ingame messages. + * + * @param client Index of the client. + * @param kv KeyValues handle to set the menu keys and options. (Check iserverplugin.h for more information). + * @param type Message type to display ingame. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native CreateDialog(client, Handle:kv, DialogType:type); + +/** + * Guesses the SDK version a mod was compiled against. If nothing + * specific is known about the game, the engine version is used instead. + * + * The return values are guaranteed to increase chronologically (that is, + * a later release will have a higher value). + * + * @return SOURCE_SDK version code. + */ +native GuessSDKVersion(); + +/** + * Prints a message to a specific client in the chat area. + * + * @param client Client index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +native PrintToChat(client, const String:format[], any:...); + +/** + * Prints a message to all clients in the chat area. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock PrintToChatAll(const String:format[], any:...) +{ + decl String:buffer[192]; + + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i)) + { + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintToChat(i, "%s", buffer); + } + } +} + +/** + * Prints a message to a specific client in the center of the screen. + * + * @param client Client index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +native PrintCenterText(client, const String:format[], any:...); + +/** + * Prints a message to all clients in the center of the screen. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock PrintCenterTextAll(const String:format[], any:...) +{ + decl String:buffer[192]; + + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i)) + { + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintCenterText(i, "%s", buffer); + } + } +} + +/** + * Prints a message to a specific client with a hint box. + * + * @param client Client index. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +native PrintHintText(client, const String:format[], any:...); + +/** + * Prints a message to all clients with a hint box. + * + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock PrintHintTextToAll(const String:format[], any:...) +{ + decl String:buffer[192]; + + for (new i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i)) + { + SetGlobalTransTarget(i); + VFormat(buffer, sizeof(buffer), format, 2); + PrintHintText(i, "%s", buffer); + } + } +} + +/** + * Shows a VGUI panel to a specific client. + * + * @param client Client index. + * @param name Panel type name (Check viewport_panel_names.h to see a list of + * some panel names). + * @param Kv KeyValues handle with all the data for the panel setup (Depends + * on the panel type and may be unused). + * @param show True to show the panel, or false to remove it from the client screen. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +native ShowVGUIPanel(client, const String:name[], Handle:Kv=INVALID_HANDLE, bool:show=true); + +/** + * Creates a HUD synchronization object. This object is used to automatically assign and + * re-use channels for a set of messages. + * + * The HUD has a hardcoded number of channels (usually 6) for displaying + * text. You can use any channel for any area of the screen. Text on + * different channels can overlap, but text on the same channel will + * erase the old text first. This overlapping and overwriting gets problematic. + * + * A HUD synchronization object automatically selects channels for you based on + * the following heuristics: + * - If channel X was last used by the object, and hasn't been modified again, + * channel X gets re-used. + * - Otherwise, a new channel is chosen based on the least-recently-used channel. + * + * This ensures that if you display text on a sync object, that the previous text + * displayed on it will always be cleared first. This is because your new text + * will either overwrite the old text on the same channel, or because another + * channel has already erased your text. + * + * Note that messages can still overlap if they are on different synchronization + * objects, or they are displayed to manual channels. + * + * These are particularly useful for displaying repeating or refreshing HUD text, in + * addition to displaying multiple message sets in one area of the screen (for example, + * center-say messages that may pop up randomly that you don't want to overlap each + * other). + * + * @return New HUD synchronization object. + * The Handle can be closed with CloseHandle(). + * If HUD text is not supported on this mod, then + * INVALID_HANDLE is returned. + */ +native Handle:CreateHudSynchronizer(); + +/** + * Sets the HUD parameters for drawing text. These parameters are stored + * globally, although nothing other than this function and SetHudTextParamsEx + * modify them. + * + * You must call this function before drawing text. If you are drawing + * text to multiple clients, you can set the parameters once, since + * they won't be modified. However, as soon as you pass control back + * to other plugins, you must reset the parameters next time you draw. + * + * @param x x coordinate, from 0 to 1. -1.0 is the center. + * @param y y coordinate, from 0 to 1. -1.0 is the center. + * @param holdTime Number of seconds to hold the text. + * @param r Red color value. + * @param g Green color value. + * @param b Blue color value. + * @param a Alpha transparency value. + * @param effect 0/1 causes the text to fade in and fade out. + * 2 causes the text to flash[?]. + * @param fxTime Duration of chosen effect (may not apply to all effects). + * @param fadeIn Number of seconds to spend fading in. + * @param fadeOut Number of seconds to spend fading out. + * @noreturn + */ +native SetHudTextParams(Float:x, Float:y, Float:holdTime, r, g, b, a, effect = 0, + Float:fxTime=6.0, Float:fadeIn=0.1, Float:fadeOut=0.2); + +/** + * Sets the HUD parameters for drawing text. These parameters are stored + * globally, although nothing other than this function and SetHudTextParams + * modify them. + * + * This is the same as SetHudTextParams(), except it lets you set the alternate + * color for when effects require it. + * + * @param x x coordinate, from 0 to 1. -1.0 is the center. + * @param y y coordinate, from 0 to 1. -1.0 is the center. + * @param holdTime Number of seconds to hold the text. + * @param color1 First color set, array values being [red, green, blue, alpha] + * @param color2 Second color set, array values being [red, green, blue, alpha] + * @param effect 0/1 causes the text to fade in and fade out. + * 2 causes the text to flash[?]. + * @param fxTime Duration of chosen effect (may not apply to all effects). + * @param fadeIn Number of seconds to spend fading in. + * @param fadeOut Number of seconds to spend fading out. + * @noreturn + */ +native SetHudTextParamsEx(Float:x, Float:y, Float:holdTime, color1[4], + color2[4]={255,255,255,0}, effect = 0, Float:fxTime=6.0, + Float:fadeIn=0.1, Float:fadeOut=0.2); + +/** + * Shows a synchronized HUD message to a client. + * + * As of this writing, only TF, HL2MP, and SourceForts support HUD Text. + * + * @param client Client index to send the message to. + * @param sync Synchronization object. + * @param message Message text or formatting rules. + * @param ... Message formatting parameters. + * @return -1 on failure, anything else on success. + * This function fails if the mod does not support it. + * @error Client not in-game, or sync object not valid. + */ +native ShowSyncHudText(client, Handle:sync, const String:message[], any:...); + +/** + * Clears the text on a synchronized HUD channel. + * + * This is not the same as sending "" because it guarantees that it won't + * overwrite text on another channel. For example, consider the scenario: + * + * 1. Your synchronized message goes to channel 3. + * 2. Someone else's non-synchronized message goes to channel 3. + * + * If you were to simply send "" on your synchronized message, + * then someone else's text could be overwritten. + * + * @param client Client index to send the message to. + * @param sync Synchronization object. + * @noreturn + * @error Client not in-game, or sync object not valid. + */ +native ClearSyncHud(client, Handle:sync); + +/** + * Shows a HUD message to a client on the given channel. + * + * As of this writing, only TF, HL2MP, and SourceForts support HUD Text. + * + * @param client Client index to send the message to. + * @param channel A channel number. + * If -1, then a channel will automatically be selected + * based on the least-recently-used channel. If the + * channel is any other number, it will be modulo'd with + * the channel count to get a final channel number. + * @param message Message text or formatting rules. + * @param ... Message formatting parameters. + * @return -1 on failure (lack of mod support). + * Any other return value is the channel number that was + * used to render the text. + */ +native ShowHudText(client, channel, const String:message[], any:...); + +/** + * Shows a MOTD panel to a specific client. + * + * @param client Client index. + * @param title Title of the panel (printed on the top border of the window). + * @param msg Contents of the panel, it can be treated as an url, filename or plain text + * depending on the type parameter (WARNING: msg has to be 192 bytes maximum!) + * @param type Determines the way to treat the message body of the panel. + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +stock ShowMOTDPanel(client, const String:title[], const String:msg[], type=MOTDPANEL_TYPE_INDEX) +{ + decl String:num[3]; + new Handle:Kv = CreateKeyValues("data"); + IntToString(type, num, sizeof(num)); + + KvSetString(Kv, "title", title); + KvSetString(Kv, "type", num); + KvSetString(Kv, "msg", msg); + ShowVGUIPanel(client, "info", Kv); + CloseHandle(Kv); +} + +/** + * Displays a panel asking the client to connect to a specified IP. + * + * @param client Client index. + * @param time Duration to hold the panel on the client's screen. + * @param ip Destionation IP. + * @noreturn + */ +stock DisplayAskConnectBox(client, Float:time, const String:ip[]) +{ + new Handle:Kv = CreateKeyValues("data"); + KvSetFloat(Kv, "time", time); + KvSetString(Kv, "title", ip); + CreateDialog(client, Kv, DialogType_AskConnect); + CloseHandle(Kv); +} + +/** + * Converts an entity index into a serial encoded entity reference. + * + * @param entity Entity index. + * @return Entity reference. + */ +native EntIndexToEntRef(entity); + +/** + * Retrieves the entity index from a reference. + * + * @param ref Entity reference. + * @return Entity index. + */ +native EntRefToEntIndex(ref); + +/** + * Converts a reference into a backwards compatible version. + * + * @param ref Entity reference. + * @return Bcompat reference. + */ +native MakeCompatEntRef(ref); + diff --git a/env/include/handles.inc b/env/include/handles.inc new file mode 100644 index 0000000..053ad6f --- /dev/null +++ b/env/include/handles.inc @@ -0,0 +1,96 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _handles_included + #endinput +#endif +#define _handles_included + +/** + * Handle helper macros. + */ +enum Handle +{ + INVALID_HANDLE = 0, +}; + + +/** + * Closes a Handle. If the handle has multiple copies open, + * it is not destroyed unless all copies are closed. + * + * @note Closing a Handle has a different meaning for each Handle type. Make + * sure you read the documentation on whatever provided the Handle. + * + * @param hndl Handle to close. + * @return True if successful, false if not closeable. + * @error Invalid handles will cause a run time error. + */ +native bool:CloseHandle(Handle:hndl); + +/** + * Clones a Handle. When passing handles in between plugins, caching handles + * can result in accidental invalidation when one plugin releases the Handle, or is its owner + * is unloaded from memory. To prevent this, the Handle may be "cloned" with a new owner. + * + * @note Usually, you will be cloning Handles for other plugins. This means that if you clone + * the Handle without specifying the new owner, it will assume the identity of your original calling + * plugin, which is not very useful. You should either specify that the receiving plugin should + * clone the handle on its own, or you should explicitly clone the Handle using the receiving plugin's + * identity Handle. + * + * @param hndl Handle to clone/duplicate. + * @param plugin Optional Handle to another plugin to mark as the new owner. + * If no owner is passed, the owner becomes the calling plugin. + * @return Handle on success, INVALID_HANDLE if not cloneable. + * @error Invalid handles will cause a run time error. + */ +native Handle:CloneHandle(Handle:hndl, Handle:plugin=INVALID_HANDLE); + +/** + * Do not use this function. Returns if a Handle and its contents + * are readable, whereas INVALID_HANDLE only checks for the absence + * of a Handle. + * + * This function is intended only for tests where the validity of a + * Handle can absolutely not be known. + * + * Do not use this to check the return values of functions, or to + * check if timers should be closed (except in very rare cases). + * This function is for very specific usage and using it for general + * purpose routines can and will hide very subtle bugs. + * + * @param hndl Handle to test for validity. + * @return True if handle is valid, false otherwise. + */ +#pragma deprecated Do not use this function. +native bool:IsValidHandle(Handle:hndl); diff --git a/env/include/helpers.inc b/env/include/helpers.inc new file mode 100644 index 0000000..3b70165 --- /dev/null +++ b/env/include/helpers.inc @@ -0,0 +1,293 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _helpers_included + #endinput +#endif +#define _helpers_included + +/** + * Formats a user's info as log text. This is usually not needed because + * %L can be used to auto-format client information into a string. + * + * @param client Client index. + * @param buffer Buffer for text. + * @param maxlength Maximum length of text. + */ +stock FormatUserLogText(client, String:buffer[], maxlength) +{ + decl String:auth[32]; + decl String:name[40]; + + new userid = GetClientUserId(client); + if (!GetClientAuthString(client, auth, sizeof(auth))) + { + strcopy(auth, sizeof(auth), "UNKNOWN"); + } + if (!GetClientName(client, name, sizeof(name))) + { + strcopy(name, sizeof(name), "UNKNOWN"); + } + + /** Currently, no team stuff ... */ + + Format(buffer, maxlength, "\"%s<%d><%s><>\"", name, userid, auth); +} + +/** + * Returns plugin handle from plugin filename. + * + * @param filename Filename of the plugin to search for. + * @return Handle to plugin if found, INVALID_HANDLE otherwise. + */ +stock Handle:FindPluginByFile(const String:filename[]) +{ + decl String:buffer[256]; + + new Handle:iter = GetPluginIterator(); + new Handle:pl; + + while (MorePlugins(iter)) + { + pl = ReadPlugin(iter); + + GetPluginFilename(pl, buffer, sizeof(buffer)); + if (strcmp(buffer, filename, false) == 0) + { + CloseHandle(iter); + return pl; + } + } + + CloseHandle(iter); + + return INVALID_HANDLE; +} + +/** + * @deprecated Use FindTarget() or ProcessTargetString(). + */ +#pragma deprecated Use FindTarget() or ProcessTargetString() +stock SearchForClients(const String:pattern[], clients[], maxClients) +{ + new total = 0; + + if (maxClients == 0) + { + return 0; + } + + if (pattern[0] == '#') + { + new input = StringToInt(pattern[1]); + if (!input) + { + decl String:name[65] + for (new i=1; i<=MaxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + GetClientName(i, name, sizeof(name)); + if (strcmp(name, pattern, false) == 0) + { + clients[0] = i; + return 1; + } + } + } else { + new client = GetClientOfUserId(input); + if (client) + { + clients[0] = client; + return 1; + } + } + } + + decl String:name[65] + for (new i=1; i<=MaxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + GetClientName(i, name, sizeof(name)); + if (StrContains(name, pattern, false) != -1) + { + clients[total++] = i; + if (total >= maxClients) + { + break; + } + } + } + + return total; +} + +/** + * Wraps ProcessTargetString() and handles producing error messages for + * bad targets. + * + * @param client Client who issued command + * @param target Client's target argument + * @param nobots Optional. Set to true if bots should NOT be targetted + * @param immunity Optional. Set to false to ignore target immunity. + * @return Index of target client, or -1 on error. + */ +stock FindTarget(client, const String:target[], bool:nobots = false, bool:immunity = true) +{ + decl String:target_name[MAX_TARGET_LENGTH]; + decl target_list[1], target_count, bool:tn_is_ml; + + new flags = COMMAND_FILTER_NO_MULTI; + if (nobots) + { + flags |= COMMAND_FILTER_NO_BOTS; + } + if (!immunity) + { + flags |= COMMAND_FILTER_NO_IMMUNITY; + } + + if ((target_count = ProcessTargetString( + target, + client, + target_list, + 1, + flags, + target_name, + sizeof(target_name), + tn_is_ml)) > 0) + { + return target_list[0]; + } + else + { + ReplyToTargetError(client, target_count); + return -1; + } +} + +/** + * This function is no longer supported. It has been replaced with ReadMapList(), + * which uses a more unified caching and configuration mechanism. This function also + * has a bug where if the cvar contents changes, the fileTime change won't be recognized. + * + * Loads a specified array with maps. The maps will be either loaded from mapcyclefile, or if supplied + * a cvar containing a file name. If the file in the cvar is bad, it will use mapcyclefile. The fileTime + * parameter is used to store a timestamp of the file. If specified, the file will only be reloaded if it + * has changed. + * + * @param array Valid array handle, should be created with CreateArray(33) or larger. + * @param fileTime Variable containing the "last changed" time of the file. Used to avoid needless reloading. + * @param fileCvar CVAR set to the file to be loaded. Optional. + * @return Number of maps loaded or 0 if in error. + */ +#pragma deprecated Use ReadMapList() instead. + stock LoadMaps(Handle:array, &fileTime = 0, Handle:fileCvar = INVALID_HANDLE) + { + decl String:mapPath[256], String:mapFile[64]; + new bool:fileFound = false; + + if (fileCvar != INVALID_HANDLE) + { + GetConVarString(fileCvar, mapFile, 64); + BuildPath(Path_SM, mapPath, sizeof(mapPath), mapFile); + fileFound = FileExists(mapPath); + } + + if (!fileFound) + { + new Handle:mapCycleFile = FindConVar("mapcyclefile"); + GetConVarString(mapCycleFile, mapPath, sizeof(mapPath)); + fileFound = FileExists(mapPath); + } + + if (!fileFound) + { + LogError("Failed to find a file to load maps from. No maps loaded."); + ClearArray(array); + + return 0; + } + + // If the file hasn't changed, there's no reason to reload + // all of the maps. + new newTime = GetFileTime(mapPath, FileTime_LastChange); + if (fileTime == newTime) + { + return GetArraySize(array); + } + + fileTime = newTime; + + ClearArray(array); + + new Handle:file = OpenFile(mapPath, "rt"); + if (file == INVALID_HANDLE) + { + LogError("Could not open file: %s", mapPath); + + return 0; + } + + LogMessage("Loading maps from file: %s", mapPath); + + decl String:buffer[64], len; + while (!IsEndOfFile(file) && ReadFileLine(file, buffer, sizeof(buffer))) + { + TrimString(buffer); + + if ((len = StrContains(buffer, ".bsp", false)) != -1) + { + buffer[len] = '\0'; + } + + if (buffer[0] == '\0' || !IsValidConVarChar(buffer[0]) || !IsMapValid(buffer)) + { + continue; + } + + if (FindStringInArray(array, buffer) != -1) + { + continue; + } + + PushArrayString(array, buffer); + } + + CloseHandle(file); + return GetArraySize(array); +} diff --git a/env/include/keyvalues.inc b/env/include/keyvalues.inc new file mode 100644 index 0000000..97f4991 --- /dev/null +++ b/env/include/keyvalues.inc @@ -0,0 +1,429 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _keyvalues_included + #endinput +#endif +#define _keyvalues_included + +/** + * KeyValue data value types + */ +enum KvDataTypes +{ + KvData_None = 0, /**< Type could not be identified, or no type */ + KvData_String, /**< String value */ + KvData_Int, /**< Integer value */ + KvData_Float, /**< Floating point value */ + KvData_Ptr, /**< Pointer value (sometimes called "long") */ + KvData_WString, /**< Wide string value */ + KvData_Color, /**< Color value */ + KvData_UInt64, /**< Large integer value */ + /* --- */ + KvData_NUMTYPES, +}; + +/** + * Creates a new KeyValues structure. The Handle must always be closed. + * + * @param name Name of the root section. + * @param firstKey If non-empty, specifies the first key value. + * @param firstValue If firstKey is non-empty, specifies the first key's value. + * @return A Handle to a new KeyValues structure. + */ +native Handle:CreateKeyValues(const String:name[], const String:firstkey[]="", const String:firstValue[]=""); + +/** + * Sets a string value of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value String value. + * @noreturn + * @error Invalid Handle. + */ +native KvSetString(Handle:kv, const String:key[], const String:value[]); + +/** + * Sets an integer value of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value Value number. + * @noreturn + * @error Invalid Handle. + */ +native KvSetNum(Handle:kv, const String:key[], value); + +/** + * Sets a large integer value of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value Large integer value (0=High bits, 1=Low bits) + * @noreturn + * @error Invalid Handle. + */ +native KvSetUInt64(Handle:kv, const String:key[], const value[2]); + +/** + * Sets a floating point value of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value Floating point value. + * @noreturn + * @error Invalid Handle. + */ +native KvSetFloat(Handle:kv, const String:key[], Float:value); + +/** + * Sets a set of color values of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param r Red value. + * @param g Green value. + * @param b Blue value. + * @param a Alpha value. + * @noreturn + * @error Invalid Handle. + */ +native KvSetColor(Handle:kv, const String:key[], r, g, b, a=0); + +/** + * Sets a vector value of a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param vec Vector value. + * @noreturn + * @error Invalid Handle. + */ +native KvSetVector(Handle:kv, const String:key[], const Float:vec[3]); + +/** + * Retrieves a string value from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value Buffer to store key value in. + * @param maxlength Maximum length of the value buffer. + * @param defvalue Optional default value to use if the key is not found. + * @noreturn + * @error Invalid Handle. + */ +native KvGetString(Handle:kv, const String:key[], String:value[], maxlength, const String:defvalue[]=""); + +/** + * Retrieves an integer value from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param defvalue Optional default value to use if the key is not found. + * @return Integer value of the key. + * @error Invalid Handle. + */ +native KvGetNum(Handle:kv, const String:key[], defvalue=0); + +/** + * Retrieves a floating point value from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param defvalue Optional default value to use if the key is not found. + * @return Floating point value of the key. + * @error Invalid Handle. + */ +native Float:KvGetFloat(Handle:kv, const String:key[], Float:defvalue=0.0); + +/** + * Retrieves a set of color values from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param r Red value, set by reference. + * @param g Green value, set by reference. + * @param b Blue value, set by reference. + * @param a Alpha value, set by reference. + * @noreturn + * @error Invalid Handle. + */ +native KvGetColor(Handle:kv, const String:key[], &r, &g, &b, &a); + +/** + * Retrieves a large integer value from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param value Array to represent the large integer. + * @param defvalue Optional default value to use if the key is not found. + * @noreturn + * @error Invalid Handle. + */ +native KvGetUInt64(Handle:kv, const String:key[], value[2], defvalue[2]={0,0}); + +/** + * Retrieves a vector value from a KeyValues key. + * + * @param kv KeyValues Handle. + * @param key Name of the key, or NULL_STRING. + * @param vec Destination vector to store the value in. + * @param defvalue Optional default value to use if the key is not found. + * @noreturn + * @error Invalid Handle. + */ +native KvGetVector(Handle:kv, const String:key[], Float:vec[3], const Float:defvalue[3]={0.0, 0.0, 0.0}); + +/** + * Sets the current position in the KeyValues tree to the given key. + * + * @param kv KeyValues Handle. + * @param key Name of the key. + * @param create If true, and the key does not exist, it will be created. + * @return True if the key exists, false if it does not and was not created. + */ +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. + * + * @param kv KeyValues Handle. + * @param keyOnly If false, non-keys will be traversed (values). + * @return True on success, false if there was no first sub key. + * @error Invalid Handle. + */ +native bool:KvGotoFirstSubKey(Handle:kv, bool:keyOnly=true); + +/** + * Sets the current position in the KeyValues tree to the next sub key. + * This native does NOT add to the internal traversal stack, and thus + * KvGoBack() is not needed for each successive call to this function. + * + * @param kv KeyValues Handle. + * @param keyOnly If false, non-keys will be traversed (values). + * @return True on success, false if there was no next sub key. + * @error Invalid Handle. + */ +native bool:KvGotoNextKey(Handle:kv, bool:keyOnly=true); + +/** + * Saves the current position in the traversal stack onto the traversal + * stack. This can be useful if you wish to use KvGotoNextKey() and + * have the previous key saved for backwards traversal. + * + * @param kv KeyValues Handle. + * @noreturn + * @error Invalid Handle. + */ +native KvSavePosition(Handle:kv); + +/** + * Removes the given key from the current position. + * + * @param kv KeyValues Handle. + * @param key Name of the key. + * @return True on success, false if key did not exist. + * @error Invalid Handle. + */ +native bool:KvDeleteKey(Handle:kv, const String:key[]); + +/** + * Removes the current sub-key and attempts to set the position + * to the sub-key after the removed one. If no such sub-key exists, + * the position will be the parent key in the traversal stack. + * Given the sub-key having position "N" in the traversal stack, the + * removal will always take place from position "N-1." + * + * @param kv KeyValues Handle. + * @return 1 if removal succeeded and there was another key. + * 0 if the current node was not contained in the + * previous node, or no previous node exists. + * -1 if removal succeeded and there were no more keys, + * thus the state is as if KvGoBack() was called. + * @error Invalid Handle. + */ +native KvDeleteThis(Handle:kv); + +/** + * Jumps back to the previous position. Returns false if there are no + * previous positions (i.e., at the root node). This should be called + * once for each successful Jump call, in order to return to the top node. + * This function pops one node off the internal traversal stack. + * + * @param kv KeyValues Handle. + * @return True on success, false if there is no higher node. + * @error Invalid Handle. + */ +native bool:KvGoBack(Handle:kv); + +/** + * Sets the position back to the top node, emptying the entire node + * traversal history. This can be used instead of looping KvGoBack() + * if recursive iteration is not important. + * + * @param kv KeyValues Handle. + * @noreturn + * @error Invalid Handle. + */ +native KvRewind(Handle:kv); + +/** + * Retrieves the current section name. + * + * @param kv KeyValues Handle. + * @param section Buffer to store the section name. + * @param maxlength Maximum length of the name buffer. + * @return True on success, false on failure. + * @error Invalid Handle. + */ +native bool:KvGetSectionName(Handle:kv, String:section[], maxlength); + +/** + * Sets the current section name. + * + * @param kv KeyValues Handle. + * @param section Section name. + * @noreturn + * @error Invalid Handle. + */ +native KvSetSectionName(Handle:kv, const String:section[]); + +/** + * Returns the data type at a key. + * + * @param kv KeyValues Handle. + * @param key Key name. + * @return KvDataType value of the key. + * @error Invalid Handle. + */ +native KvDataTypes:KvGetDataType(Handle:kv, const String:key[]); + +/** + * Converts a KeyValues tree to a file. The tree is dumped + * from the current position. + * + * @param kv KeyValues Handle. + * @param file File to dump write to. + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool:KeyValuesToFile(Handle:kv, const String:file[]); + +/** + * Converts a file to a KeyValues tree. The file is read into + * the current position of the tree. + * + * @param kv KeyValues Handle. + * @param file File to read from. + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool:FileToKeyValues(Handle:kv, const String:file[]); + +/** + * Sets whether or not the KeyValues parser will read escape sequences. + * For example, \n would be read as a literal newline. This defaults + * to false for new KeyValues structures. + * + * @param kv KeyValues Handle. + * @param useEscapes Whether or not to read escape sequences. + * @noreturn + * @error Invalid Handle. + */ +native KvSetEscapeSequences(Handle:kv, bool:useEscapes); + +/** + * Returns the position in the jump stack; I.e. the number of calls + * required for KvGoBack to return to the root node. If at the root node, + * 0 is returned. + * + * @param kv KeyValues Handle. + * @return Number of non-root nodes in the jump stack. + * @error Invalid Handle. + */ +native KvNodesInStack(Handle:kv); + +/** + * Makes a new copy of all subkeys in the origin KeyValues to + * the destination KeyValues. + * NOTE: All KeyValues are processed from the current location not the root one. + * + * @param origin Origin KeyValues Handle. + * @param dest Destination KeyValues Handlee. + * @noreturn + * @error Invalid Handle. + */ +native KvCopySubkeys(Handle:origin, Handle:dest); + +/** + * Finds a KeyValues name by id. + * + * @param kv KeyValues Handle. + * @param id KeyValues id. + * @param name Buffer to store the name. + * @param maxlength Maximum length of the value buffer. + * @return True on success, false if id not found. + * @error Invalid Handle. + */ +native bool:KvFindKeyById(Handle:kv, id, String:name[], maxlength); + +/** + * Finds a KeyValues id inside a KeyValues tree. + * + * @param kv KeyValues Handle. + * @param key Key name. + * @param id Id of the found KeyValue. + * @return True on success, false if key not found. + * @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); diff --git a/env/include/lang.inc b/env/include/lang.inc new file mode 100644 index 0000000..4f570a6 --- /dev/null +++ b/env/include/lang.inc @@ -0,0 +1,96 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _lang_included + #endinput +#endif +#define _lang_included + +#define LANG_SERVER 0 /**< Translate using the server's language */ + +/** + * Loads a translation file for the plugin calling this native. + * If no extension is specified, .txt is assumed. + * + * @param path Translation file. + * @noreturn + */ +native LoadTranslations(const String:file[]); + +/** + * Sets the global language target. This is useful for creating functions + * that will be compatible with the %t format specifier. Note that invalid + * indexes can be specified but the error will occur during translation, + * not during this function call. + * + * @param client Client index or LANG_SERVER. + * @noreturn + */ +native SetGlobalTransTarget(client); + +/** + * Retrieves the language number of a client. + * Currently this simply returns the server language index. + * + * @param client Client index. + * @return Language number client is using. + * @error Invalid client index or client not in game. + */ +native GetClientLanguage(client); + +/** + * Retrieves the server's language. + * + * @return Language number server is using. + */ +native GetServerLanguage(); + +/** + * Returns the number of languages known in languages.cfg. + * + * @return Language count. + */ +native GetLanguageCount(); + +/** + * Retrieves info about a given language number. + * + * @param language Language number. + * @param code Language code buffer (2-3 characters usually). + * @param codeLen Maximum length of the language code buffer. + * @param name Language name buffer. + * @param nameLen Maximum length of the language name buffer. + * @noreturn + * @error Invalid language number. + */ +native GetLanguageInfo(language, String:code[]="", codeLen=0, String:name[]="", nameLen=0); + diff --git a/env/include/logging.inc b/env/include/logging.inc new file mode 100644 index 0000000..39028c6 --- /dev/null +++ b/env/include/logging.inc @@ -0,0 +1,153 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sm_logging_included + #endinput +#endif +#define _sm_logging_included + +/** + * Logs a plugin message to the SourceMod logs. The log message will be + * prefixed by the plugin's logtag (filename). + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + */ +native LogMessage(const String:format[], any:...); + +/** + * Logs a message to the SourceMod logs without any plugin logtag. This is + * useful for re-routing messages from other plugins, for example, messages + * from LogAction(). + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + */ +native LogMessageEx(const String:format[], any:...); + +/** + * Logs a message to any file. The log message will be in the normal + * SourceMod format, with the plugin logtag prepended. + * + * @param file File to write the log message in. + * @param format String format. + * @param ... Format arguments. + * @noreturn + * @error File could not be opened/written. + */ +native LogToFile(const String:file[], const String:format[], any:...); + +/** + * Same as LogToFile(), except no plugin logtag is prepended. + * + * @param file File to write the log message in. + * @param format String format. + * @param ... Format arguments. + * @noreturn + * @error File could not be opened/written. + */ +native LogToFileEx(const String:file[], const String:format[], any:...); + +/** + * Logs an action from a command or event whereby interception and routing may + * be important. This is intended to be a logging version of ShowActivity(). + * + * @param client Client performing the action, 0 for server, or -1 if not + * applicable. + * @param target Client being targetted, or -1 if not applicable. + * @param message Message format. + * @param ... Message formatting parameters. + * @noreturn + */ +native LogAction(client, target, const String:message[], any:...); + +/** + * Logs a plugin error message to the SourceMod logs. + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + */ +native LogError(const String:format[], any:...); + +/** + * Called when an action is going to be logged. + * + * @param source Handle to the object logging the action, or INVALID_HANDLE + * if Core is logging the action. + * @param ident Type of object logging the action (plugin, ext, or core). + * @param client Client the action is from; 0 for server, -1 if not applicable. + * @param target Client the action is targetting, or -1 if not applicable. + * @param message Message that is being logged. + * @return Plugin_Continue will cause Core to defaulty log the message. + * Plugin_Handled will stop Core from logging the message. + * Plugin_Stop is the same as Handled, but prevents any other + * plugins from handling the message. + */ +forward Action:OnLogAction(Handle:source, + Identity:ident, + client, + target, + const String:message[]); + +/** + * Called when a game log message is received. + * + * Any Log*() functions called within this callback will not recursively + * pass through. That is, they will log directly, bypassing this callback. + * + * Note that this does not capture log messages from the engine. It only + * captures log messages being sent from the game/mod itself. + * + * @param message Message contents. + * @return Plugin_Handled or Plugin_Stop will prevent the message + * from being written to the log file. + */ +functag public Action:GameLogHook(const String:message[]); + +/** + * Adds a game log hook. + * + * @param hook Hook function. + * @noreturn + */ +native AddGameLogHook(GameLogHook:hook); + +/** + * Removes a game log hook. + * + * @param hook Hook function. + * @noreturn + */ +native RemoveGameLogHook(GameLogHook:hook); diff --git a/env/include/mapchooser.inc b/env/include/mapchooser.inc new file mode 100644 index 0000000..7da8a29 --- /dev/null +++ b/env/include/mapchooser.inc @@ -0,0 +1,99 @@ +#if defined _mapchooser_included_ + #endinput +#endif +#define _mapchooser_included_ + +enum NominateResult +{ + Nominate_Added, /** The map was added to the nominate list */ + Nominate_Replaced, /** A clients existing nomination was replaced */ + Nominate_AlreadyInVote, /** Specified map was already in the vote */ + Nominate_InvalidMap, /** Mapname specifed wasn't a valid map */ + Nominate_VoteFull, /** This will only occur if force was set to false */ +}; + +enum MapChange +{ + MapChange_Instant, /** Change map as soon as the voting results have come in */ + MapChange_RoundEnd, /** Change map at the end of the round */ + MapChange_MapEnd, /** Change the sm_nextmap cvar */ +}; + +/** + * Attempt to add a map to the mapchooser map list. + * + * @param map Map to add. + * @param force Should we force the map in even if it requires overwriting an existing nomination? + * @param owner Client index of the nominater. If the client disconnects the nomination will be removed. Use 0 for constant nominations + * @return Nominate Result of the outcome + */ +native NominateResult:NominateMap(const String:map[], bool:force, owner); + +/** + * Gets the current list of excluded maps. + * + * @param array An ADT array handle to add the map strings to. Needs to be + * @noreturn + */ +native GetExcludeMapList(Handle:array); + +/** + * Checks if MapChooser will allow a vote + * + * @return True if a vote can be held, or false if mapchooser is already holding a vote. + */ +native bool:CanMapChooserStartVote(); + +/** + * Initiates a MapChooser map vote + * + * Note: If no input array is specified mapchooser will use its internal list. This includes + * any nominations and excluded maps (as per mapchoosers convars). + * + * @param when MapChange consant of when the resulting mapchange should occur. + * @param inputarray ADT array list of maps to add to the vote. + */ +native InitiateMapChooserVote(MapChange:when, Handle:inputarray=INVALID_HANDLE); + +/** + * Checks if MapChooser's end of map vote has completed. + * + * @return True if complete, false otherwise. + */ +native bool:HasEndOfMapVoteFinished(); + +/** + * Checks if MapChooser is set to run an end of map vote. + * + * @return True if enabled, false otherwise. + */ +native bool:EndOfMapVoteEnabled(); + +/** + * Called when mapchooser removes a nomination from its list. + * Nominations cleared on map start will not trigger this forward + */ +forward OnNominationRemoved(const String:map[], owner); + + +public SharedPlugin:__pl_mapchooser = +{ + name = "mapchooser", + file = "mapchooser.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +public __pl_mapchooser_SetNTVOptional() +{ + MarkNativeAsOptional("NominateMap"); + MarkNativeAsOptional("GetExcludeMapList"); + MarkNativeAsOptional("CanMapChooserStartVote"); + MarkNativeAsOptional("InitiateMapChooserVote"); + MarkNativeAsOptional("HasEndOfMapVoteFinished"); + MarkNativeAsOptional("EndOfMapVoteEnabled"); +} + diff --git a/env/include/market.inc b/env/include/market.inc new file mode 100644 index 0000000..64eeff0 --- /dev/null +++ b/env/include/market.inc @@ -0,0 +1,62 @@ +/** + * ==================== + * Market + * File: market.inc + * Version: 1.2 + * Author: Greyscale + * ==================== + */ + +/** + * Used to send the market to a client + * @param client Client index + * @param title Title of the market menu + * @param rebuy Text to display for the "Rebuy" option + * @noreturn + */ +native Market_Send(client, const String:title[], const String:rebuy[]); + +/** + * Used to send the market to a client + * @param weapondid ID of the weapon whose info will be returned + * @param display The display name of the weapon + * @param weapon The entity name of the weapon + * @param price The price of the weapon + * @return True if weaponid exists, false if not + */ +native bool:Market_GetWeaponIDInfo(const String:weaponid[], String:display[], String:weapon[], &price); + +/** + * Called when a player makes a selection from the menu + * @param client Client index + * @param weaponid Returns the ID of the weapon selected ("rebuy" is returned when player selected rebuy) + * @return True to allow purchase, false to block + */ +forward bool:Market_OnWeaponSelected(client, String:weaponid[]); + +/** + * Called after a player makes a selection from the menu + * @param client Client index + * @param allowed True if selection was allowed and false if it was blocked + * noreturn + */ +forward Market_PostOnWeaponSelected(client, &bool:allowed); + + + +public SharedPlugin:__pl_market = +{ + name = "market", + file = "market.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +public __pl_market_SetNTVOptional() +{ + MarkNativeAsOptional("Market_Send"); + MarkNativeAsOptional("Market_GetWeaponIDInfo"); +} \ No newline at end of file diff --git a/env/include/menus.inc b/env/include/menus.inc new file mode 100644 index 0000000..8ff1d69 --- /dev/null +++ b/env/include/menus.inc @@ -0,0 +1,814 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _menus_included + #endinput +#endif +#define _menus_included + +/** + * Low-level drawing style of the menu. + */ +enum MenuStyle +{ + MenuStyle_Default = 0, /**< The "default" menu style for the mod */ + MenuStyle_Valve = 1, /**< The Valve provided menu style (Used on HL2DM) */ + MenuStyle_Radio = 2, /**< The simpler menu style commonly used on CS:S */ +}; + +/** + * Different actions for the menu "pump" callback + */ +enum MenuAction +{ + MenuAction_Start = (1<<0), /**< A menu has been started (nothing passed) */ + MenuAction_Display = (1<<1), /**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */ + MenuAction_Select = (1<<2), /**< An item was selected (param1=client, param2=item) */ + MenuAction_Cancel = (1<<3), /**< The menu was cancelled (param1=client, param2=reason) */ + MenuAction_End = (1<<4), /**< A menu display has fully ended. + param1 is the MenuEnd reason, and if it's MenuEnd_Cancelled, then + param2 is the MenuCancel reason from MenuAction_Cancel. + */ + MenuAction_VoteEnd = (1<<5), /**< (VOTE ONLY): A vote sequence has succeeded (param1=chosen item) + This is not called if SetVoteResultCallback has been used on the menu. */ + MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started (nothing passed) */ + MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (param1=reason) */ + MenuAction_DrawItem = (1<<8), /**< An item is being drawn; return the new style (param1=client, param2=item) */ + MenuAction_DisplayItem = (1<<9),/**< Item text is being drawn to the display (param1=client, param2=item) + To change the text, use RedrawMenuItem(). + If you do so, return its return value. Otherwise, return 0. + */ +}; + +/** Default menu actions */ +#define MENU_ACTIONS_DEFAULT MenuAction_Select|MenuAction_Cancel|MenuAction_End +/** All menu actions */ +#define MENU_ACTIONS_ALL MenuAction:0xFFFFFFFF + +#define MENU_NO_PAGINATION 0 /**< Menu should not be paginated (10 items max) */ +#define MENU_TIME_FOREVER 0 /**< Menu should be displayed as long as possible */ + +#define ITEMDRAW_DEFAULT (0) /**< Item should be drawn normally */ +#define ITEMDRAW_DISABLED (1<<0) /**< Item is drawn but not selectable */ +#define ITEMDRAW_RAWLINE (1<<1) /**< Item should be a raw line, without a slot */ +#define ITEMDRAW_NOTEXT (1<<2) /**< No text should be drawn */ +#define ITEMDRAW_SPACER (1<<3) /**< Item should be drawn as a spacer, if possible */ +#define ITEMDRAW_IGNORE ((1<<1)|(1<<2)) /**< Item should be completely ignored (rawline + notext) */ +#define ITEMDRAW_CONTROL (1<<4) /**< Item is control text (back/next/exit) */ + +#define MENUFLAG_BUTTON_EXIT (1<<0) /**< Menu has an "exit" button (default if paginated) */ +#define MENUFLAG_BUTTON_EXITBACK (1<<1) /**< Menu has an "exit back" button */ +#define MENUFLAG_NO_SOUND (1<<2) /**< Menu will not have any select sounds */ + +#define VOTEINFO_CLIENT_INDEX 0 /**< Client index */ +#define VOTEINFO_CLIENT_ITEM 1 /**< Item the client selected, or -1 for none */ +#define VOTEINFO_ITEM_INDEX 0 /**< Item index */ +#define VOTEINFO_ITEM_VOTES 1 /**< Number of votes for the item */ + +#define VOTEFLAG_NO_REVOTES (1<<0) /**< Players cannot change their votes */ + +/** + * Reasons a menu can be cancelled (MenuAction_Cancel). + */ +enum +{ + MenuCancel_Disconnected = -1, /**< Client dropped from the server */ + MenuCancel_Interrupted = -2, /**< Client was interrupted with another menu */ + MenuCancel_Exit = -3, /**< Client exited via "exit" */ + MenuCancel_NoDisplay = -4, /**< Menu could not be displayed to the client */ + MenuCancel_Timeout = -5, /**< Menu timed out */ + MenuCancel_ExitBack = -6, /**< Client selected "exit back" on a paginated menu */ +}; + +/** + * Reasons a vote can be cancelled (MenuAction_VoteCancel). + */ +enum +{ + VoteCancel_Generic = -1, /**< Vote was generically cancelled. */ + VoteCancel_NoVotes = -2, /**< Vote did not receive any votes. */ +}; + +/** + * Reasons a menu ended (MenuAction_End). + */ +enum +{ + MenuEnd_Selected = 0, /**< Menu item was selected */ + MenuEnd_VotingDone = -1, /**< Voting finished */ + MenuEnd_VotingCancelled = -2, /**< Voting was cancelled */ + MenuEnd_Cancelled = -3, /**< Menu was cancelled (reason in param2) */ + MenuEnd_Exit = -4, /**< Menu was cleanly exited via "exit" */ + MenuEnd_ExitBack = -5, /**< Menu was cleanly exited via "back" */ +}; + +/** + * Describes a menu's source + */ +enum MenuSource +{ + MenuSource_None = 0, /**< No menu is being displayed */ + MenuSource_External = 1, /**< External menu */ + MenuSource_Normal = 2, /**< A basic menu is being displayed */ + MenuSource_RawPanel = 3, /**< A display is active, but it is not tied to a menu */ +}; + +/** + * Called when a menu action is completed. + * + * @param menu The menu being acted upon. + * @param action The action of the menu. + * @param param1 First action parameter (usually the client). + * @param param2 Second action parameter (usually the item). + * @noreturn + */ +functag public MenuHandler(Handle:menu, MenuAction:action, param1, param2); + +/** + * Creates a new, empty menu using the default style. + * + * @param handler Function which will receive menu actions. + * @param actions Optionally set which actions to receive. Select, + * Cancel, and End will always be received regardless + * of whether they are set or not. They are also + * the only default actions. + * @return A new menu Handle. + */ +native Handle:CreateMenu(MenuHandler:handler, MenuAction:actions=MENU_ACTIONS_DEFAULT); + +/** + * Displays a menu to a client. + * + * @param menu Menu Handle. + * @param client Client index. + * @param time Maximum time to leave menu on the screen. + * @return True on success, false on failure. + * @error Invalid Handle or client not in game. + */ +native bool:DisplayMenu(Handle:menu, client, time); + +/** + * Displays a menu to a client, starting from the given item. + * + * @param menu Menu Handle. + * @param client Client index. + * @param first_item First item to begin drawing from. + * @param time Maximum time to leave menu on the screen. + * @return True on success, false on failure. + * @error Invalid Handle or client not in game. + */ +native bool:DisplayMenuAtItem(Handle:menu, client, first_item, time); + +/** + * Appends a new item to the end of a menu. + * + * @param menu Menu Handle. + * @param info Item information string. + * @param display Default item display string. + * @param style Drawing style flags. Anything other than DEFAULT or + * DISABLED will be completely ignored when paginating. + * @return True on success, false on failure. + * @error Invalid Handle or item limit reached. + */ +native AddMenuItem(Handle:menu, + const String:info[], + const String:display[], + style=ITEMDRAW_DEFAULT); + +/** + * Inserts an item into the menu before a certain position; the new item will + * be at the given position and all next items pushed forward. + * + * @param menu Menu Handle. + * @param position Position, starting from 0. + * @param info Item information string. + * @param display Default item display string. + * @param style Drawing style flags. Anything other than DEFAULT or + * DISABLED will be completely ignored when paginating. + * @return True on success, false on failure. + * @error Invalid Handle or menu position. + */ +native bool:InsertMenuItem(Handle:menu, + position, + const String:info[], + const String:display[], + style=ITEMDRAW_DEFAULT); + +/** + * Removes an item from the menu. + * + * @param menu Menu Handle. + * @param position Position, starting from 0. + * @return True on success, false on failure. + * @error Invalid Handle or menu position. + */ +native bool:RemoveMenuItem(Handle:menu, position); + +/** + * Removes all items from a menu. + * + * @param menu Menu Handle. + * @noreturn + * @error Invalid Handle or menu position. + */ +native RemoveAllMenuItems(Handle:menu); + +/** + * Retrieves information about a menu item. + * + * @param menu Menu Handle. + * @param position Position, starting from 0. + * @param infoBuf Info buffer. + * @param infoBufLen Maximum length of the info buffer. + * @param style By-reference variable to store drawing flags. + * @param dispBuf Display buffer. + * @param dispBufLen Maximum length of the display buffer. + * @return True on success, false if position is invalid. + * @error Invalid Handle. + */ +native bool:GetMenuItem(Handle:menu, + position, + String:infoBuf[], + infoBufLen, + &style=0, + String:dispBuf[]="", + dispBufLen=0); + +/** + * Returns the first item on the page of a currently selected menu. + * + * This is only valid inside a MenuAction_Select callback. + * + * @return First item number on the page the client was viewing + * before selecting the item in the callback. This can + * be used to re-display the menu from the original + * position. + * @error Not called from inside a MenuAction_Select callback. + */ +native GetMenuSelectionPosition(); + +/** + * Returns the number of items in a menu. + * + * @param menu Menu Handle. + * @return Number of items in the menu. + * @error Invalid Handle. + */ +native GetMenuItemCount(Handle:menu); + +/** + * Sets whether the menu should be paginated or not. + * + * If itemsPerPage is MENU_NO_PAGINATION, and the exit button flag is set, + * then the exit button flag is removed. It can be re-applied if desired. + * + * @param menu Handle to the menu. + * @param itemsPerPage Number of items per page, or MENU_NO_PAGINATION. + * @return True on success, false if pagination is too high or + * low. + * @error Invalid Handle. + */ +native bool:SetMenuPagination(Handle:menu, itemsPerPage); + +/** + * Returns a menu's pagination setting. + * + * @param menu Handle to the menu. + * @return Pagination setting. + * @error Invalid Handle. + */ +native GetMenuPagination(Handle:menu); + +/** + * Returns a menu's MenuStyle Handle. The Handle + * is global and cannot be freed. + * + * @param menu Handle to the menu. + * @return Handle to the menu's draw style. + * @error Invalid Handle. + */ +native Handle:GetMenuStyle(Handle:menu); + +/** + * Sets the menu's default title/instruction message. + * + * @param menu Menu Handle. + * @param fmt Message string format + * @param ... Message string arguments. + * @noreturn + * @error Invalid Handle. + */ +native SetMenuTitle(Handle:menu, const String:fmt[], any:...); + +/** + * Returns the text of a menu's title. + * + * @param menu Menu Handle. + * @param buffer Buffer to store title. + * @param maxlength Maximum length of the buffer. + * @return Number of bytes written. + * @error Invalid Handle/ + */ +native GetMenuTitle(Handle:menu, String:buffer[], maxlength); + +/** + * Creates a raw MenuPanel based off the menu's style. + * The Handle must be freed with CloseHandle(). + * + * @return A new MenuPanel Handle. + * @error Invalid Handle. + */ +native Handle:CreatePanelFromMenu(Handle:menu); + +/** + * Returns whether or not the menu has an exit button. + * By default, menus have an exit button. + * + * @param menu Menu Handle. + * @return True if the menu has an exit button; false otherwise. + * @error Invalid Handle. + */ +native bool:GetMenuExitButton(Handle:menu); + +/** + * Sets whether or not the menu has an exit button. By default, paginated menus + * have an exit button. + * + * If a menu's pagination is changed to MENU_NO_PAGINATION, and the pagination + * was previously a different value, then the Exit button status is changed to + * false. It must be explicitly re-enabled afterwards. + * + * If a non-paginated menu has an exit button, then at most 9 items will be + * displayed. + * + * @param menu Menu Handle. + * @param button True to enable the button, false to remove it. + * @return True if allowed; false on failure. + * @error Invalid Handle. + */ +native bool:SetMenuExitButton(Handle:menu, bool:button); + +/** + * Returns whether or not the menu has an "exit back" button. By default, + * menus do not have an exit back button. + * + * Exit Back buttons appear as "Back" on page 1 of paginated menus and have + * functionality defined by the user in MenuEnd_ExitBack. + * + * @param menu Menu Handle. + * @return True if the menu has an exit back button; false otherwise. + * @error Invalid Handle. + */ +native bool:GetMenuExitBackButton(Handle:menu); + +/** + * Sets whether or not the menu has an "exit back" button. By default, menus + * do not have an exit back button. + * + * Exit Back buttons appear as "Back" on page 1 of paginated menus and have + * functionality defined by the user in MenuEnd_ExitBack. + * + * @param menu Menu Handle. + * @param button True to enable the button, false to remove it. + * @error Invalid Handle. + */ +native SetMenuExitBackButton(Handle:menu, bool:button); + + +/** + * Cancels a menu from displaying on all clients. While the + * cancellation is in progress, this menu cannot be re-displayed + * to any clients. + * + * The menu may still exist on the client's screen after this command. + * This simply verifies that the menu is not being used anywhere. + * + * If any vote is in progress on a menu, it will be cancelled. + * + * @param menu Menu Handle. + * @noreturn + * @error Invalid Handle. + */ +native CancelMenu(Handle:menu); + +/** + * Retrieves a menu's option flags. + * + * @param menu Menu Handle. + * @return A bitstring of MENUFLAG bits. + * @error Invalid Handle. + */ +native GetMenuOptionFlags(Handle:menu); + +/** + * Sets a menu's option flags. + * + * If a certain bit is not supported, it will be stripped before being set. + * See SetMenuExitButton() for information on Exit buttons. + * See SetMenuExitBackButton() for information on Exit Back buttons. + * + * @param menu Menu Handle. + * @param flags A new bitstring of MENUFLAG bits. + * @noreturn + * @error Invalid Handle. + */ +native SetMenuOptionFlags(Handle:menu, flags); + +/** + * Returns whether a vote is in progress. + * + * @param menu Deprecated; no longer used. + * @return True if a vote is in progress, false otherwise. + */ +native bool:IsVoteInProgress(Handle:menu=INVALID_HANDLE); + +/** + * Cancels the vote in progress. + * + * @noreturn + * @error If no vote is in progress. + */ +native CancelVote(); + +/** + * Broadcasts a menu to a list of clients. The most selected item will be + * returned through MenuAction_End. On a tie, a random item will be returned + * from a list of the tied items. + * + * Note that MenuAction_VoteEnd and MenuAction_VoteStart are both + * default callbacks and do not need to be enabled. + * + * @param menu Menu Handle. + * @param clients Array of clients to broadcast to. + * @param numClients Number of clients in the array. + * @param time Maximum time to leave menu on the screen. + * @param flags Optional voting flags. + * @return True on success, false if this menu already has a vote session + * in progress. + * @error Invalid Handle, or a vote is already in progress. + */ +native bool:VoteMenu(Handle:menu, clients[], numClients, time, flags=0); + +/** + * Sends a vote menu to all clients. See VoteMenu() for more information. + * + * @param menu Menu Handle. + * @param time Maximum time to leave menu on the screen. + * @param flags Optional voting flags. + * @return True on success, false if this menu already has a vote session + * in progress. + * @error Invalid Handle. + */ +stock VoteMenuToAll(Handle:menu, time, flags=0) +{ + new total; + decl players[MaxClients]; + + for (new i=1; i<=MaxClients; i++) + { + if (!IsClientInGame(i)) + { + continue; + } + players[total++] = i; + } + + return VoteMenu(menu, players, total, time, flags); +} +/** + * Callback for when a vote has ended and results are available. + * + * @param menu The menu being voted on. + * @param num_votes Number of votes tallied in total. + * @param num_clients Number of clients who could vote. + * @param client_info Array of clients. Use VOTEINFO_CLIENT_ defines. + * @param num_items Number of unique items that were selected. + * @param item_info Array of items, sorted by count. Use VOTEINFO_ITEM + * defines. + * @noreturn + */ +functag public VoteHandler(Handle:menu, + num_votes, + num_clients, + const client_info[][2], + num_items, + const item_info[][2]); + +/** + * Sets an advanced vote handling callback. If this callback is set, + * MenuAction_VoteEnd will not be called. + * + * @param menu Menu Handle. + * @param callback Callback function. + * @noreturn + * @error Invalid Handle or callback. + */ +native SetVoteResultCallback(Handle:menu, VoteHandler:callback); + +/** + * Returns the number of seconds you should "wait" before displaying + * a publicly invocable menu. This number is the time remaining until + * (last_vote + sm_vote_delay). + * + * @return Number of seconds to wait, or 0 for none. + */ +native CheckVoteDelay(); + +/** + * Returns whether a client is in the pool of clients allowed + * to participate in the current vote. This is determined by + * the client list passed to VoteMenu(). + * + * @param client Client index. + * @return True if client is allowed to vote, false otherwise. + * @error If no vote is in progress or client index is invalid. + */ +native bool:IsClientInVotePool(client); + +/** + * Redraws the current vote menu to a client in the voting pool. + * + * @param client Client index. + * @param revotes True to allow revotes, false otherwise. + * @return True on success, false if the client is in the vote pool + * but cannot vote again. + * @error No vote in progress, client is not in the voting pool, + * or client index is invalid. + */ +native bool:RedrawClientVoteMenu(client, bool:revotes=true); + +/** + * Returns a style's global Handle. + * + * @param style Menu Style. + * @return A Handle, or INVALID_HANDLE if not found or unusable. + */ +native Handle:GetMenuStyleHandle(MenuStyle:style); + +/** + * Creates a MenuPanel from a MenuStyle. Panels are used for drawing raw + * menus without any extra helper functions. The Handle must be closed + * with CloseHandle(). + * + * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @return A new MenuPanel Handle. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native Handle:CreatePanel(Handle:hStyle=INVALID_HANDLE); + +/** + * Creates a Menu from a MenuStyle. The Handle must be closed with + * CloseHandle(). + * + * @parma hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @param handler Function which will receive menu actions. + * @param actions Optionally set which actions to receive. Select, + * Cancel, and End will always be received regardless + * of whether they are set or not. They are also + * the only default actions. + * @return A new menu Handle. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native Handle:CreateMenuEx(Handle:hStyle=INVALID_HANDLE, MenuHandler:handler, MenuAction:actions=MENU_ACTIONS_DEFAULT); + +/** + * Returns whether a client is viewing a menu. + * + * @param client Client index. + * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @return A MenuSource value. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native MenuSource:GetClientMenu(client, Handle:hStyle=INVALID_HANDLE); + +/** + * Cancels a menu on a client. This will only affect non-external menus. + * + * @param hstyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @param client Client index. + * @param autoIgnore If true, no menus can be re-drawn on the client during + * the cancellation process. + * @return True if a menu was cancelled, false otherwise. + */ +native bool:CancelClientMenu(client, bool:autoIgnore=false, Handle:hStyle=INVALID_HANDLE); + +/** + * Returns a style's maximum items per page. + * + * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style. + * @return Maximum items per page. + * @error Invalid Handle other than INVALID_HANDLE. + */ +native GetMaxPageItems(Handle:hStyle=INVALID_HANDLE); + +/** + * Returns a MenuPanel's parent style. + * + * @param panel A MenuPanel Handle. + * @return The MenuStyle Handle that created the panel. + * @error Invalid Handle. + */ +native Handle:GetPanelStyle(Handle:panel); + +/** + * Sets the panel's title. + * + * @param panel A MenuPanel Handle. + * @param title Text to set as the title. + * @param onlyIfEmpty If true, the title will only be set if no title is set. + * @noreturn + * @error Invalid Handle. + */ +native Handle:SetPanelTitle(Handle:panel, const String:text[], bool:onlyIfEmpty=false); + +/** + * Draws an item on a panel. If the item takes up a slot, the position + * is returned. + * + * @param panel A MenuPanel Handle. + * @param text Display text to use. If not a raw line, + * the style may automatically add color markup. + * No numbering or newlines are needed. + * @param style ITEMDRAW style flags. + * @return A slot position, or 0 if item was a rawline or could not be drawn. + * @error Invalid Handle. + */ +native DrawPanelItem(Handle:panel, const String:text[], style=ITEMDRAW_DEFAULT); + +/** + * Draws a raw line of text on a panel, without any markup other than a newline. + * + * @param panel A MenuPanel Handle, or INVALID_HANDLE if inside a + * MenuAction_DisplayItem callback. + * @param text Display text to use. + * @return True on success, false if raw lines are not supported. + * @error Invalid Handle. + */ +native DrawPanelText(Handle:panel, const String:text[]); + +/** + * Returns whether or not the given drawing flags are supported by + * the menu style. + * + * @param panel A MenuPanel Handle. + * @param style ITEMDRAW style flags. + * @return True if item is drawable, false otherwise. + * @error Invalid Handle. + */ +native CanPanelDrawFlags(Handle:panel, style); + +/** + * Sets the selectable key map of a panel. This is not supported by + * all styles (only by Radio, as of this writing). + * + * @param keys An integer where each bit N allows key + * N+1 to be selected. If no keys are selectable, + * then key 0 (bit 9) is automatically set. + * @return True if supported, false otherwise. + */ +native bool:SetPanelKeys(Handle:panel, keys); + +/** + * Sends a panel to a client. Unlike full menus, the handler + * function will only receive the following actions, both of + * which will have INVALID_HANDLE for a menu, and the client + * as param1. + * + * MenuAction_Select (param2 will be the key pressed) + * MenuAction_Cancel (param2 will be the reason) + * + * Also, if the menu fails to display, no callbacks will be called. + * + * @param panel A MenuPanel Handle. + * @param client A client to draw to. + * @param handler The MenuHandler function to catch actions with. + * @param time Time to hold the menu for. + * @return True on success, false on failure. + * @error Invalid Handle. + */ +native bool:SendPanelToClient(Handle:panel, client, MenuHandler:handler, time); + +/** + * @brief Returns the amount of text the menu can still hold. If this is + * limit is reached or overflowed, the text is silently truncated. + * + * Radio menus: Currently 511 characters (512 bytes). + * Valve menus: Currently -1 (no meaning). + * + * @param panel A MenuPanel Handle. + * @return Number of characters that the menu can still hold, + * or -1 if there is no known limit. + * @error Invalid Handle. + */ +native GetPanelTextRemaining(Handle:panel); + +/** + * @brief Returns the current key position. + * + * @param panel A MenuPanel Handle. + * @return Current key position starting at 1. + * @error Invalid Handle. + */ +native GetPanelCurrentKey(Handle:panel); + +/** + * @brief Sets the next key position. This cannot be used + * to traverse backwards. + * + * @param panel A MenuPanel Handle. + * @param key Key that is greater or equal to + * GetPanelCurrentKey(). + * @return True on success, false otherwise. + * @error Invalid Handle. + */ +native bool:SetPanelCurrentKey(Handle:panel, key); + +/** + * @brief Redraws menu text from inside a MenuAction_DisplayItem callback. + * + * @param text Menu text to draw. + * @return Item position; must be returned via the callback. + */ +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. + * + * @param param2 Second parameter of MenuAction_VoteEnd. + * @param winningVotes Number of votes received by the winning option. + * @param totalVotes Number of total votes received. + * @noreturn + */ +stock GetMenuVoteInfo(param2, &winningVotes, &totalVotes) +{ + winningVotes = param2 & 0xFFFF; + totalVotes = param2 >> 16; +} + +/** + * Quick stock to determine whether voting is allowed. This doesn't let you + * fine-tune a reason for not voting, so it's not recommended for lazily + * telling clients that voting isn't allowed. + * + * @return True if voting is allowed, false if voting is in progress + * or the cooldown is active. + */ +stock bool:IsNewVoteAllowed() +{ + if (IsVoteInProgress() || CheckVoteDelay() != 0) + { + return false; + } + + return true; +} + diff --git a/env/include/nextmap.inc b/env/include/nextmap.inc new file mode 100644 index 0000000..af539f7 --- /dev/null +++ b/env/include/nextmap.inc @@ -0,0 +1,84 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _nextmap_included_ + #endinput +#endif +#define _nextmap_included_ + +/** + * Sets SourceMod's internal nextmap. + * Equivalent to changing sm_nextmap but with an added validity check. + * + * @param map Next map to set. + * @return True if the nextmap was set, false if map was invalid. + */ +native bool:SetNextMap(const String:map[]); + +/** + * Returns SourceMod's internal nextmap. + * + * @param map Buffer to store the nextmap name. + * @param maxlen Maximum length of the map buffer. + * @return True if a Map was found and copied, false if no nextmap is set (map will be unchanged). + */ +native bool:GetNextMap(String:map[], maxlen); + +/** + * Changes the current map and records the reason for the change with maphistory + * + * @param map Map to change to. + * @param reason Reason for change. + * @noreturn + */ +native ForceChangeLevel(const String:map[], const String:reason[]); + +/** + * Gets the current number of maps in the map history + * + * @return Number of maps. + */ +native GetMapHistorySize(); + +/** + * Retrieves a map from the map history list. + * + * @param item Item number. Must be 0 or greater and less than GetMapHistorySize(). + * @param map Buffer to store the map name. + * @param mapLen Length of map buffer. + * @param reason Buffer to store the change reason. + * @param reasonLen Length of the reason buffer. + * @param startTime Time the map started. + * @noreturn + * @error Invalid item number. + */ +native GetMapHistory(item, String:map[], mapLen, String:reason[], reasonLen, &startTime); \ No newline at end of file diff --git a/env/include/profiler.inc b/env/include/profiler.inc new file mode 100644 index 0000000..68f1ca7 --- /dev/null +++ b/env/include/profiler.inc @@ -0,0 +1,77 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _profiler_included + #endinput +#endif +#define _profiler_included + +/** + * ONLY AVAILABLE ON WINDOWS RIGHT NOW K. + */ + +/** + * Creates a new profile object. The Handle must be freed + * using CloseHandle(). + * + * @return Handle to the profiler object. + */ +native Handle:CreateProfiler(); + +/** + * Starts profiling. + * + * @param prof Profiling object. + * @noreturn + * @error Invalid Handle. + */ +native StartProfiling(Handle:prof); + +/** + * Stops profiling. + * + * @param prof Profiling object. + * @noreturn + * @error Invalid Handle or profiling was never started. + */ +native StopProfiling(Handle:prof); + +/** + * Returns the amount of high-precision time in seconds + * that passed during the profiler's last start/stop + * cycle. + * + * @param prof Profiling object. + * @return Time elapsed in seconds. + * @error Invalid Handle. + */ +native Float:GetProfilerTime(Handle:prof); diff --git a/env/include/regex.inc b/env/include/regex.inc new file mode 100644 index 0000000..bfdd22c --- /dev/null +++ b/env/include/regex.inc @@ -0,0 +1,173 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#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 +}; diff --git a/env/include/sdkhooks.inc b/env/include/sdkhooks.inc new file mode 100644 index 0000000..bba7237 --- /dev/null +++ b/env/include/sdkhooks.inc @@ -0,0 +1,210 @@ +#if defined _sdkhooks_included + #endinput +#endif +#define _sdkhooks_included + +#define DMG_GENERIC 0 // generic damage was done +#define DMG_CRUSH (1 << 0) // crushed by falling or moving object. + // NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage. + // DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. +#define DMG_BULLET (1 << 1) // shot +#define DMG_SLASH (1 << 2) // cut, clawed, stabbed +#define DMG_BURN (1 << 3) // heat burned +#define DMG_VEHICLE (1 << 4) // hit by a vehicle +#define DMG_FALL (1 << 5) // fell too far +#define DMG_BLAST (1 << 6) // explosive blast damage +#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt +#define DMG_SHOCK (1 << 8) // electric shock +#define DMG_SONIC (1 << 9) // sound pulse shockwave +#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam +#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force +#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death +#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death. +#define DMG_DROWN (1 << 14) // Drowning +#define DMG_PARALYZE (1 << 15) // slows affected creature down +#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad +#define DMG_POISON (1 << 17) // blood poisoning - heals over time like drowning damage +#define DMG_RADIATION (1 << 18) // radiation exposure +#define DMG_DROWNRECOVER (1 << 19) // drowning recovery +#define DMG_ACID (1 << 20) // toxic chemicals or acid burns +#define DMG_SLOWBURN (1 << 21) // in an oven +#define DMG_REMOVENORAGDOLL (1 << 22) // with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed. + // use this to kill an entity that you've already got a server-side ragdoll for +#define DMG_PHYSGUN (1 << 23) // Hit by manipulator. Usually doesn't do any damage. +#define DMG_PLASMA (1 << 24) // Shot by Cremator +#define DMG_AIRBOAT (1 << 25) // Hit by the airboat's gun +#define DMG_DISSOLVE (1 << 26) // Dissolving! +#define DMG_BLAST_SURFACE (1 << 27) // A blast on the surface of water that cannot harm things underwater +#define DMG_DIRECT (1 << 28) +#define DMG_BUCKSHOT (1 << 29) // not quite a bullet. Little, rounder, different. + + +enum SDKHookType +{ + SDKHook_EndTouch, + SDKHook_FireBulletsPost, + SDKHook_OnTakeDamage, + SDKHook_OnTakeDamagePost, + SDKHook_PreThink, + SDKHook_PostThink, + SDKHook_SetTransmit, + SDKHook_Spawn, + SDKHook_StartTouch, + SDKHook_Think, + SDKHook_Touch, + SDKHook_TraceAttack, + SDKHook_TraceAttackPost, + SDKHook_WeaponCanSwitchTo, + SDKHook_WeaponCanUse, + SDKHook_WeaponDrop, + SDKHook_WeaponEquip, + SDKHook_WeaponSwitch, + SDKHook_ShouldCollide, + SDKHook_PreThinkPost, + SDKHook_PostThinkPost, + SDKHook_ThinkPost +}; + +/* + Alphabetized for easy readability + + SDKHook_EndTouch + SDKHook_FireBulletsPost + SDKHook_OnTakeDamage + SDKHook_OnTakeDamagePost + SDKHook_PreThink + SDKHook_PreThinkPost + SDKHook_PostThink + SDKHook_PostThinkPost + SDKHook_SetTransmit + SDKHook_ShouldCollide + SDKHook_Spawn + SDKHook_StartTouch + SDKHook_Think + SDKHook_ThinkPost + SDKHook_Touch + SDKHook_TraceAttack + SDKHook_TraceAttackPost + SDKHook_WeaponCanSwitchTo + SDKHook_WeaponCanUse + SDKHook_WeaponDrop + SDKHook_WeaponEquip + SDKHook_WeaponSwitch +*/ + +funcenum SDKHookCB +{ + // PreThink/Post + // PostThink/Post + public(client), + // Spawn + // Think/Post + public(entity), + // EndTouch + // StartTouch + // Touch + public(entity, other), + // SetTransmit + Action:public(entity, client), + // WeaponCanSwitchTo + // WeaponCanUse + // WeaponDrop + // WeaponEquip + // WeaponSwitch + Action:public(client, weapon), + // OnTakeDamage + Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype), + // OnTakeDamagePost + public(victim, attacker, inflictor, Float:damage, damagetype), + // FireBullets + public(client, shots, const String:weaponname[]), + // TraceAttack + Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup), + // TraceAttackPost + public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup), + // ShouldCollide + Action:public(entity, &collisiongroup, &contentsmask, &bool:result) +}; + + +/** + * @brief When an entity is created + * + * @param entity Entity index + * @param classname Class name + * @noreturn + */ +forward OnEntityCreated(entity, const String:classname[]); + +/** + * @brief When an entity is destroyed + * + * @param entity Entity index + * @noreturn + */ +forward OnEntityDestroyed(entity); + +/** + * @brief When the game description is retrieved + * + * @param gameDesc Game description + * @noreturn + */ +forward Action:OnGetGameDescription(String:gameDesc[64]); + +/** + * @brief When the level is initialized + * + * @param mapName Name of the map + * @param mapEntities Entities of the map + * @noreturn + */ +forward Action:OnLevelInit(const String:mapName[], String:mapEntities[2097152]); + +/** + * @brief Hooks an entity + * + * @param entity Entity index + * @param type Type of function to hook + * @param callback Function to call when hook is called + * @noreturn + */ +native SDKHook(entity, SDKHookType:type, SDKHookCB:callback); + +/** + * @brief Hooks an entity + * + * @param entity Entity index + * @param type Type of function to hook + * @param callback Function to call when hook is called + * @return bool Hook Successful + */ +native bool:SDKHookEx(entity, SDKHookType:type, SDKHookCB:callback); + +/** + * @brief Unhooks an entity + * + * @param entity Entity index + * @param type Type of function to unhook + * @param callback Callback function to unhook + * @noreturn + */ +native SDKUnhook(entity, SDKHookType:type, SDKHookCB:callback); + +/** Do Not Edit Below This Line **/ + +public Extension:__ext_sdkhooks = +{ + name = "sdkhooks", + file = "sdkhooks.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; \ No newline at end of file diff --git a/env/include/sdktools.inc b/env/include/sdktools.inc new file mode 100644 index 0000000..573a9d0 --- /dev/null +++ b/env/include/sdktools.inc @@ -0,0 +1,213 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_included + #endinput +#endif +#define _sdktools_included + +#include +#include +#include +#if !defined SDKTOOLS_DISABLE_SOUNDAPI +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +enum SDKCallType +{ + SDKCall_Static, /**< Static call */ + SDKCall_Entity, /**< CBaseEntity call */ + SDKCall_Player, /**< CBasePlayer call */ + SDKCall_GameRules, /**< CGameRules call */ + SDKCall_EntityList, /**< CGlobalEntityList call */ +}; + +enum SDKLibrary +{ + SDKLibrary_Server, /**< server.dll/server_i486.so */ + SDKLibrary_Engine, /**< engine.dll/engine_*.so */ +}; + +enum SDKFuncConfSource +{ + SDKConf_Virtual = 0, /**< Read a virtual index from the Offsets section */ + SDKConf_Signature = 1, /**< Read a signature from the Signatures section */ +}; + +enum SDKType +{ + SDKType_CBaseEntity, /**< CBaseEntity (always as pointer) */ + SDKType_CBasePlayer, /**< CBasePlayer (always as pointer) */ + SDKType_Vector, /**< Vector (pointer, byval, or byref) */ + SDKType_QAngle, /**< QAngles (pointer, byval, or byref) */ + SDKType_PlainOldData, /**< Integer/generic data <=32bit (any) */ + SDKType_Float, /**< Float (any) */ + SDKType_Edict, /**< edict_t (always as pointer) */ + SDKType_String, /**< NULL-terminated string (always as pointer) */ + SDKType_Bool, /**< Boolean (any) */ +}; + +enum SDKPassMethod +{ + SDKPass_Pointer, /**< Pass as a pointer */ + SDKPass_Plain, /**< Pass as plain data */ + SDKPass_ByValue, /**< Pass an object by value */ + SDKPass_ByRef, /**< Pass an object by reference */ +}; + +#define VDECODE_FLAG_ALLOWNULL (1<<0) /**< Allow NULL for pointers */ +#define VDECODE_FLAG_ALLOWNOTINGAME (1<<1) /**< Allow players not in game */ +#define VDECODE_FLAG_ALLOWWORLD (1<<2) /**< Allow World entity */ +#define VDECODE_FLAG_BYREF (1<<3) /**< Floats/ints by reference */ + +#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data once done */ + +/** + * Starts the preparation of an SDK call. + * + * @param type Type of function call this will be. + * @noreturn + */ +native StartPrepSDKCall(SDKCallType:type); + +/** + * Sets the virtual index of the SDK call if it is virtual. + * + * @param vtblidx Virtual table index. + * @noreturn + */ +native PrepSDKCall_SetVirtual(vtblidx); + +/** + * Finds an address in a library and sets it as the address to use for the SDK call. + * + * @param lib Library to use. + * @param signature Binary data to search for in the library. If it starts with '@', + * the bytes parameter is ignored and the signature is interpreted + * as a symbol lookup in the library. + * @param bytes Number of bytes in the binary search string. + * @return True on success, false if nothing was found. + */ +native bool:PrepSDKCall_SetSignature(SDKLibrary:lib, const String:signature[], bytes); + +/** + * Finds an address or virtual function index in a GameConfig file and sets it as + * the calling information for the SDK call. + * + * @param gameconf GameConfig Handle, or INVALID_HANDLE to use sdktools.games.txt. + * @param source Whether to look in Offsets or Signatures. + * @param name Name of the property to find. + * @return True on success, false if nothing was found. + */ +native bool:PrepSDKCall_SetFromConf(Handle:gameconf, SDKFuncConfSource:source, const String:name[]); + +/** + * Sets the return information of an SDK call. Do not call this if there is no return data. + * This must be called if there is a return value (i.e. it is not necessarily safe to ignore + * the data). + * + * @param type Data type to convert to/from. + * @param pass How the data is passed in C++. + * @param decflags Flags on decoding from the plugin to C++. + * @param encflags Flags on encoding from C++ to the plugin. + * @noreturn + */ +native PrepSDKCall_SetReturnInfo(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0); + +/** + * Adds a parameter to the calling convention. This should be called in normal ascending order. + * + * @param type Data type to convert to/from. + * @param pass How the data is passed in C++. + * @param decflags Flags on decoding from the plugin to C++. + * @param encflags Flags on encoding from C++ to the plugin. + * @noreturn + */ +native PrepSDKCall_AddParameter(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0); + +/** + * Finalizes an SDK call preparation and returns the resultant Handle. + * + * @return A new SDKCall Handle on success, or INVALID_HANDLE on failure. + */ +native Handle:EndPrepSDKCall(); + +/** + * Calls an SDK function with the given parameters. + * + * If the call type is Entity or Player, the index MUST ALWAYS be the FIRST parameter passed. + * If the call type is GameRules, then nothing special needs to be passed. + * If the return value is a Vector or QAngles, the SECOND parameter must be a Float[3]. + * If the return value is a string, the THIRD parameter must be a String buffer, and the + * FOURTH parameter must be the maximum length. + * All parameters must be passed after the above is followed. Failure to follow these + * rules will result in crashes or wildly unexpected behavior! + * + * If the return value is a float or integer, the return value will be this value. + * If the return value is a CBaseEntity, CBasePlayer, or edict, the return value will + * always be the entity index, or -1 for NULL. + * + * @param call SDKCall Handle. + * @param ... Call Parameters. + * @return Simple return value, if any. + * @error Invalid Handle or internal decoding error. + */ +native any:SDKCall(Handle:call, any:...); + +#include + +/** + * Do not edit below this line! + */ +public Extension:__ext_sdktools = +{ + name = "SDKTools", + file = "sdktools.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/env/include/sdktools_engine.inc b/env/include/sdktools_engine.inc new file mode 100644 index 0000000..a34439e --- /dev/null +++ b/env/include/sdktools_engine.inc @@ -0,0 +1,69 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_engine_included + #endinput +#endif +#define _sdktools_engine_included + +#define MAX_LIGHTSTYLES 64 + +/** + * Sets a client's "viewing entity." + * + * @param client Client index. + * @param entity Entity index. + * @noreturn + * @error Invalid client or entity, lack of mod support, or client not in + * game. + */ +native SetClientViewEntity(client, entity); + +/** + * Sets a light style. + * + * @param style Light style (from 0 to MAX_LIGHTSTYLES-1) + * @param value Light value string (see world.cpp/light.cpp in dlls) + * @noreturn + * @error Light style index is out of range. + */ +native SetLightStyle(style, const String:value[]); + +/** + * Returns the client's eye position. + * + * @param client Player's index. + * @param pos Destination vector to store the client's eye position. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientEyePosition(client, Float:pos[3]); diff --git a/env/include/sdktools_entinput.inc b/env/include/sdktools_entinput.inc new file mode 100644 index 0000000..1eb5f6b --- /dev/null +++ b/env/include/sdktools_entinput.inc @@ -0,0 +1,116 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_entinput_included + #endinput +#endif +#define _sdktools_entinput_included + +/** + * Invokes a named input method on an entity. + * + * After completion (successful or not), the current global variant is re-initalized. + * + * @param dest Destination entity index. + * @param input Input action. + * @param activator Entity index which initiated the sequence of actions (-1 for a NULL entity). + * @param caller Entity index from which this event is sent (-1 for a NULL entity). + * @param outputid Unknown. + * @return True if successful otherwise false. + * @error Invalid entity index or no mod support. + */ +native bool:AcceptEntityInput(dest, const String:input[], activator=-1, caller=-1, outputid=0); + +/** + * Sets a bool value in the global variant object. + * + * @param val Input value. + * @noreturn + */ +native SetVariantBool(bool:val); + +/** + * Sets a string in the global variant object. + * + * @param str Input string. + * @noreturn + */ +native SetVariantString(const String:str[]); + +/** + * Sets an integer value in the global variant object. + * + * @param val Input value. + * @noreturn + */ +native SetVariantInt(val); + +/** + * Sets a floating point value in the global variant object. + * + * @param val Input value. + * @noreturn + */ +native SetVariantFloat(Float:val); + +/** + * Sets a 3D vector in the global variant object. + * + * @param vec Input vector. + * @noreturn + */ +native SetVariantVector3D(const Float:vec[3]); + +/** + * Sets a 3D position vector in the global variant object. + * + * @param vec Input position vector. + * @noreturn + */ +native SetVariantPosVector3D(const Float:vec[3]); + +/** + * Sets a color in the global variant object. + * + * @param color Input color. + * @noreturn + */ +native SetVariantColor(const color[4]); + +/** + * Sets an entity in the global variant object. + * + * @param Entity index. + * @noreturn + * @error Invalid entity index. + */ +native SetVariantEntity(entity); diff --git a/env/include/sdktools_entoutput.inc b/env/include/sdktools_entoutput.inc new file mode 100644 index 0000000..b7aeaaa --- /dev/null +++ b/env/include/sdktools_entoutput.inc @@ -0,0 +1,91 @@ +/** + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_entoutput_included + #endinput +#endif +#define _sdktools_entoutput_included + +/** + * Called when an entity output is fired. + * + * @param output Name of the output that fired. + * @param caller Entity index of the caller. + * @param activator Entity index of the activator. + * @param delay Delay in seconds? before the event gets fired. + */ +functag public EntityOutput(const String:output[], caller, activator, Float:delay); + +/** + * Add an entity output hook on a entity classname + * + * @param classname The classname to hook. + * @param output The output name to hook. + * @param callback An EntityOutput function pointer. + * @noreturn + * @error Entity Outputs disabled. + */ +native HookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback); + +/** + * Remove an entity output hook. + * @param classname The classname to hook. + * @param output The output name to hook. + * @param callback An EntityOutput function pointer. + * @return True on success, false if no valid hook was found. + * @error Entity Outputs disabled. + */ +native bool:UnhookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback); + +/** + * Add an entity output hook on a single entity instance + * + * @param entity The entity on which to add a hook. + * @param output The output name to hook. + * @param callback An EntityOutput function pointer. + * @param once Only fire this hook once and then remove itself. + * @noreturn + * @error Entity Outputs disabled or Invalid Entity index. + */ +native HookSingleEntityOutput(entity, const String:output[], EntityOutput:callback , bool:once=false); + +/** + * Remove a single entity output hook. + * + * @param entity The entity on which to remove the hook. + * @param output The output name to hook. + * @param callback An EntityOutput function pointer. + * @return True on success, false if no valid hook was found. + * @error Entity Outputs disabled or Invalid Entity index. + */ +native bool:UnhookSingleEntityOutput(entity, const String:output[], EntityOutput:callback); + diff --git a/env/include/sdktools_functions.inc b/env/include/sdktools_functions.inc new file mode 100644 index 0000000..507af1d --- /dev/null +++ b/env/include/sdktools_functions.inc @@ -0,0 +1,322 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_functions_included + #endinput +#endif +#define _sdktools_functions_included + +/** + * Removes a player's item. + * + * @param client Client index. + * @param item CBaseCombatWeapon entity index. + * @return True on success, false otherwise. + * @error Invalid client or entity, lack of mod support, or client not in + * game. + */ +native bool:RemovePlayerItem(client, item); + +/** + * Gives a named item to a player. + * + * @param client Client index. + * @param item Item classname (such as weapon_ak47). + * @param iSubType Unknown. + * @return Entity index on success, or -1 on failure. + * @error Invalid client or client not in game, or lack of mod support. + */ +native GivePlayerItem(client, const String:item[], iSubType=0); + +/** + * Returns the weapon in a player's slot. + * + * @param client Client index. + * @param slot Slot index (mod specific). + * @return Entity index on success, -1 if no weapon existed. + * @error Invalid client or client not in game, or lack of mod support. + */ +native GetPlayerWeaponSlot(client, slot); + +/** + * Ignites an entity on fire. + * + * @param entity Entity index. + * @param time Number of seconds to set on fire. + * @param npc True to only affect NPCs. + * @param size Unknown. + * @param level Unknown. + * @noreturn + * @error Invalid entity or client not in game, or lack of mod support. + */ +native IgniteEntity(entity, Float:time, bool:npc=false, Float:size=0.0, bool:level=false); + +/** + * Extinguishes a player that is on fire. + * + * @param entity Entity index. + * @noreturn + * @error Invalid entity or client not in game, or lack of mod support. + */ +native ExtinguishEntity(client); + +/** + * Teleports an entity. + * + * @param entity Client index. + * @param origin New origin, or NULL_VECTOR for no change. + * @param angles New angles, or NULL_VECTOR for no change. + * @param velocity New velocity, or NULL_VECTOR for no change. + * @noreturn + * @error Invalid entity or client not in game, or lack of mod support. + */ +native TeleportEntity(entity, const Float:origin[3], const Float:angles[3], const Float:velocity[3]); + +/** + * Forces a player to commit suicide. + * + * @param client Client index. + * @noreturn + * @error Invalid client or client not in game, or lack of mod support. + */ +native ForcePlayerSuicide(client); + +/** + * Slaps a player in a random direction. + * + * @param client Client index. + * @param health Health to subtract. + * @param sound False to disable the sound effects. + * @noreturn + * @error Invalid client or client not in game, or lack of mod support. + */ +native SlapPlayer(client, health=5, bool:sound=true); + +/** + * Searches for an entity by classname. + * + * @param startEnt The entity index after which to begin searching from. + * Use -1 to start from the first entity. + * @param classname Classname of the entity to find. + * @return Entity index >= 0 if found, -1 otherwise. + * @error Lack of mod support. + */ +native FindEntityByClassname(startEnt, const String:classname[]); + +/** + * Returns the client's eye angles. + * + * @param client Player's index. + * @param ang Destination vector to store the client's eye angles. + * @return True on success, false on failure. + * @error Invalid client index, client not in game, or no mod support. + */ +native bool:GetClientEyeAngles(client, Float:ang[3]); + +/** + * Creates an entity by string name, but does not spawn it (see DispatchSpawn). + * If ForceEdictIndex is not -1, then it will use the edict by that index. If the index is + * invalid or there is already an edict using that index, it will error out. + * + * @param classname Entity classname. + * @param ForceEdictIndex Edict index used by the created entity. + * @return Entity index on success, or -1 on failure. + * @error Invalid edict index, or no mod support. + */ +native CreateEntityByName(const String:classname[], ForceEdictIndex=-1); + +/** + * Spawns an entity into the game. + * + * @param entity Entity index of the created entity. + * @return True on success, false otherwise. + * @error Invalid entity index, or no mod support. + */ +native bool:DispatchSpawn(entity); + +/** + * Dispatches a KeyValue into given entity using a string value. + * + * @param entity Destination entity index. + * @param keyName Name of the key. + * @param value String value. + * @return True on success, false otherwise. + * @error Invalid entity index, or no mod support. + */ +native bool:DispatchKeyValue(entity, const String:keyName[], const String:value[]); + +/** + * Dispatches a KeyValue into given entity using a floating point value. + * + * @param entity Destination entity index. + * @param keyName Name of the key. + * @param value Floating point value. + * @return True on success, false otherwise. + * @error Invalid entity index, or no mod support. + */ +native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value); + +/** + * Dispatches a KeyValue into given entity using a vector value. + * + * @param entity Destination entity index. + * @param keyName Name of the key. + * @param vec Vector value. + * @return True on success, false otherwise. + * @error Invalid entity index, or no mod support. + */ +native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:vector[3]); + +/** + * Returns the entity a client is aiming at. + * + * @param client Client performing the aiming. + * @param only_clients True to exclude all entities but clients. + * @return Entity index being aimed at. + * -1 if no entity is being aimed at. + * -2 if the function is not supported. + * @error Invalid client index or client not in game. + */ +native GetClientAimTarget(client, bool:only_clients=true); + +/** + * Returns the total number of teams in a game. + * Note: This native should not be called before OnMapStart. + * + * @return Total number of teams. + */ +native GetTeamCount(); + +/** + * Retrieves the team name based on a team index. + * Note: This native should not be called before OnMapStart. + * + * @param index Team index. + * @param name Buffer to store string in. + * @param maxlength Maximum length of string buffer. + * @noreturn + * @error Invalid team index. + */ +native GetTeamName(index, String:name[], maxlength); + +/** + * Returns the score of a team based on a team index. + * Note: This native should not be called before OnMapStart. + * + * @param index Team index. + * @return Score. + * @error Invalid team index. + */ +native GetTeamScore(index); + +/** + * Sets the score of a team based on a team index. + * Note: This native should not be called before OnMapStart. + * + * @param index Team index. + * @param value New score value. + * @return Score. + * @error Invalid team index. + */ +native SetTeamScore(index, value); + +/** + * Retrieves the number of players in a certain team. + * Note: This native should not be called before OnMapStart. + * + * @param index Team index. + * @return Number of players in the team. + * @error Invalid team index. + */ +native GetTeamClientCount(index); + +/** + * Sets the model to a given entity. + * + * @param entity Entity index. + * @param model Model name. + * @noreturn + * @error Invalid entity index, or no mod support. + */ +native SetEntityModel(entity, const String:model[]); + +/** + * Retrieves the decal file name associated to a given client. + * + * @param client Player's index. + * @param hex Buffer to store the logo filename. + * @param maxlength Maximum length of string buffer. + * @return True on success, otherwise false. + * @error Invalid client or client not in game. + */ +native bool:GetPlayerDecalFile(client, String:hex[], maxlength); + +/** + * Returns the average server network traffic in bytes/sec. + * + * @param in Buffer to store the input traffic velocity. + * @param out Buffer to store the output traffic velocity. + * @noreturn + */ +native GetServerNetStats(&Float:in, &Float:out); + +/** + * Equip's a player's weapon. + * + * @param client Client index. + * @param item CBaseCombatWeapon entity index. + * @noreturn + * @error Invalid client or entity, lack of mod support, or client not in + * game. + */ +native EquipPlayerWeapon(client, weapon); + +/** + * Activates an entity (CBaseAnimating::Activate) + * + * @param entity Entity index. + * @noreturn + * @error Invalid entity or lack of mod support. + */ +native ActivateEntity(entity); + +/** + * Sets values to client info buffer keys and notifies the engine of the change. + * The change does not get propogated to mods until the next frame. + * + * @param client Player's index. + * @param key Key string. + * @param value Value string. + * @noreturn + * @error Invalid client index, or client not connected. + */ +native SetClientInfo(client, const String:key[], const String:value[]); diff --git a/env/include/sdktools_hooks.inc b/env/include/sdktools_hooks.inc new file mode 100644 index 0000000..b064b9f --- /dev/null +++ b/env/include/sdktools_hooks.inc @@ -0,0 +1,49 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2009 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_hooks_included + #endinput +#endif +#define _sdktools_hooks_included + +/** + * @brief Called when a clients movement buttons are being processed + * + * @param client Index of the client. + * @param buttons Copyback buffer containing the current commands (as bitflags - see entity_prop_stocks.inc). + * @param impulse Copyback buffer containing the current impulse command. + * @param vel Players desired velocity. + * @param angles Players desired view angles. + * @param weapon Entity index of the new weapon if player switches weapon, 0 otherwise. + * @return Plugin_Handled to block the commands from being processed, Plugin_Continue otherwise. + */ +forward Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon); diff --git a/env/include/sdktools_sound.inc b/env/include/sdktools_sound.inc new file mode 100644 index 0000000..dc9e099 --- /dev/null +++ b/env/include/sdktools_sound.inc @@ -0,0 +1,441 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_sound_included + #endinput +#endif +#define _sdktools_sound_included + +/** + * Sound should be from the target client. + */ +#define SOUND_FROM_PLAYER -2 + +/** + * Sound should be from the listen server player. + */ +#define SOUND_FROM_LOCAL_PLAYER -1 + +/** + * Sound is from the world. + */ +#define SOUND_FROM_WORLD 0 + +/** + * Sound channels. + */ +enum +{ + SNDCHAN_REPLACE = -1, /**< Unknown */ + SNDCHAN_AUTO = 0, /**< Auto */ + SNDCHAN_WEAPON = 1, /**< Weapons */ + SNDCHAN_VOICE = 2, /**< Voices */ + SNDCHAN_ITEM = 3, /**< Items */ + SNDCHAN_BODY = 4, /**< Player? */ + SNDCHAN_STREAM = 5, /**< "Stream channel from the static or dynamic area" */ + SNDCHAN_STATIC = 6, /**< "Stream channel from the static area" */ + SNDCHAN_VOICE_BASE = 7, /**< "Channel for network voice data" */ + SNDCHAN_USER_BASE = 135 /**< Anything >= this is allocated to game code */ +}; + +/** + * Sound flags for the sound emitter system. + */ +enum +{ + SND_NOFLAGS= 0, /**< Nothing */ + SND_CHANGEVOL = 1, /**< Change sound volume */ + SND_CHANGEPITCH = 2, /**< Change sound pitch */ + SND_STOP = 3, /**< Stop the sound */ + SND_SPAWNING = 4, /**< Used in some cases for ambients */ + SND_DELAY = 5, /**< Sound has an initial delay */ + SND_STOPLOOPING = 6, /**< Stop looping all sounds on the entity */ + SND_SPEAKER = 7, /**< Being played by a mic through a speaker */ + SND_SHOULDPAUSE = 8, /**< Pause if game is paused */ +}; + +/** + * Various predefined sound levels in dB. + */ +enum +{ + SNDLEVEL_NONE = 0, /**< None */ + SNDLEVEL_RUSTLE = 20, /**< Rustling leaves */ + SNDLEVEL_WHISPER = 25, /**< Whispering */ + SNDLEVEL_LIBRARY = 30, /**< In a library */ + SNDLEVEL_FRIDGE = 45, /**< Refridgerator */ + SNDLEVEL_HOME = 50, /**< Average home (3.9 attn) */ + SNDLEVEL_CONVO = 60, /**< Normal conversation (2.0 attn) */ + SNDLEVEL_DRYER = 60, /**< Clothes dryer */ + SNDLEVEL_DISHWASHER = 65, /**< Dishwasher/washing machine (1.5 attn) */ + SNDLEVEL_CAR = 70, /**< Car or vacuum cleaner (1.0 attn) */ + SNDLEVEL_NORMAL = 75, /**< Normal sound level */ + SNDLEVEL_TRAFFIC = 75, /**< Busy traffic (0.8 attn) */ + SNDLEVEL_MINIBIKE = 80, /**< Mini-bike, alarm clock (0.7 attn) */ + SNDLEVEL_SCREAMING = 90, /**< Screaming child (0.5 attn) */ + SNDLEVEL_TRAIN = 100, /**< Subway train, pneumatic drill (0.4 attn) */ + SNDLEVEL_HELICOPTER = 105, /**< Helicopter */ + SNDLEVEL_SNOWMOBILE = 110, /**< Snow mobile */ + SNDLEVEL_AIRCRAFT = 120, /**< Auto horn, aircraft */ + SNDLEVEL_RAIDSIREN = 130, /**< Air raid siren */ + SNDLEVEL_GUNFIRE = 140, /**< Gunshot, jet engine (0.27 attn) */ + SNDLEVEL_ROCKET = 180, /**< Rocket launching (0.2 attn) */ +}; + +#define SNDVOL_NORMAL 1.0 /**< Normal volume */ +#define SNDPITCH_NORMAL 100 /**< Normal pitch */ +#define SNDPITCH_LOW 95 /**< A low pitch */ +#define SNDPITCH_HIGH 120 /**< A high pitch */ +#define SNDATTN_NONE 0.0 /**< No attenuation */ +#define SNDATTN_NORMAL 0.8 /**< Normal attenuation */ +#define SNDATTN_STATIC 1.25 /**< Static attenuation? */ +#define SNDATTN_RICOCHET 1.5 /**< Ricochet effect */ +#define SNDATTN_IDLE 2.0 /**< Idle attenuation? */ + +/** + * Prefetches a sound. + * + * @param name Sound file name relative to the "sounds" folder. + * @noreturn + */ +native PrefetchSound(const String:nane[]); + +/** + * This function is not known to work, and may crash. You should + * not use it. It is provided for backwards compatibility only. + * + * @param name Sound file name relative to the "sounds" folder. + * @return Duration in seconds. + */ +#pragma deprecated Does not work, may crash. +native Float:GetSoundDuration(const String:name[]); + +/** + * Emits an ambient sound. + * + * @param name Sound file name relative to the "sounds" folder. + * @param pos Origin of sound. + * @param entity Entity index to associate sound with. + * @param level Sound level (from 0 to 255). + * @param flags Sound flags. + * @param vol Volume (from 0.0 to 1.0). + * @param pitch Pitch (from 0 to 255). + * @param delay Play delay. + * @noreturn + */ +native EmitAmbientSound(const String:name[], + const Float:pos[3], + entity = SOUND_FROM_WORLD, + level = SNDLEVEL_NORMAL, + flags = SND_NOFLAGS, + Float:vol = SNDVOL_NORMAL, + pitch = SNDPITCH_NORMAL, + Float:delay = 0.0); + +/** + * Fades a client's volume level toward silence or a given percentage. + * + * @param client Client index. + * @param percent Fade percentage. + * @param outtime Fade out time, in seconds. + * @param holdtime Hold time, in seconds. + * @param intime Fade in time, in seconds. + * @noreturn + * @error Invalid client index or client not in game. + */ +native FadeClientVolume(client, Float:percent, Float:outtime, Float:holdtime, Float:intime); + +/** + * Stops a sound. + * + * @param entity Entity index. + * @param channel Channel number. + * @param name Sound file name relative to the "sounds" folder. + * @noreturn + */ +native StopSound(entity, channel, const String:name[]); + +/** + * Emits a sound to a list of clients. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array. + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity to emit from. + * @param channel Channel to emit with. + * @param level Sound level. + * @param flags Sound flags. + * @param volume Sound volume. + * @param pitch Sound pitch. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @param ... Optional list of Float[3] arrays to specify additional origins. + * @noreturn + * @error Invalid client index. + */ +native EmitSound(const clients[], + numClients, + const String:sample[], + entity = SOUND_FROM_PLAYER, + channel = SNDCHAN_AUTO, + level = SNDLEVEL_NORMAL, + flags = SND_NOFLAGS, + Float:volume = SNDVOL_NORMAL, + pitch = SNDPITCH_NORMAL, + speakerentity = -1, + const Float:origin[3] = NULL_VECTOR, + const Float:dir[3] = NULL_VECTOR, + bool:updatePos = true, + Float:soundtime = 0.0, + any:...); + +/** + * Emits a sentence to a list of clients. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array. + * @param sentence Sentence index (from PrecacheSenteFile). + * @param entity Entity to emit from. + * @param channel Channel to emit with. + * @param level Sound level. + * @param flags Sound flags. + * @param volume Sound volume. + * @param pitch Sound pitch. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @param ... Optional list of Float[3] arrays to specify additional origins. + * @noreturn + * @error Invalid client index. + */ +native EmitSentence(const clients[], + numClients, + sentence, + entity, + channel = SNDCHAN_AUTO, + level = SNDLEVEL_NORMAL, + flags = SND_NOFLAGS, + Float:volume = SNDVOL_NORMAL, + pitch = SNDPITCH_NORMAL, + speakerentity = -1, + const Float:origin[3] = NULL_VECTOR, + const Float:dir[3] = NULL_VECTOR, + bool:updatePos = true, + Float:soundtime = 0.0, + any:...); + +/** + * Called when an ambient sound is about to be emitted to one or more clients. + * + * NOTICE: all parameters can be overwritten to modify the default behavior. + * + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity index associated to the sound. + * @param volume Volume (from 0.0 to 1.0). + * @param level Sound level (from 0 to 255). + * @param pitch Pitch (from 0 to 255). + * @param pos Origin of sound. + * @param flags Sound flags. + * @param delay Play delay. + * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + * Plugin_Changed when any parameter has been modified. + */ +functag public Action:AmbientSHook(String:sample[PLATFORM_MAX_PATH], &entity, &Float:volume, &level, &pitch, Float:pos[3], &flags, &Float:delay); + +/** + * Called when a sound is going to be emitted to one or more clients. + * NOTICE: all params can be overwritten to modify the default behaviour. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array (modify this value if you add/remove elements from the client array). + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity emitting the sound. + * @param channel Channel emitting the sound. + * @param volume Sound volume. + * @param level Sound level. + * @param pitch Sound pitch. + * @param flags Sound flags. + * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + * Plugin_Changed when any parameter has been modified. + */ +functag public Action:NormalSHook(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags); + +/** + * Hooks all played ambient sounds. + * + * @param hook Function to use as a hook. + * @noreturn + * @error Invalid function hook. + */ +native AddAmbientSoundHook(AmbientSHook:hook); + +/** + * Hooks all played normal sounds. + * + * @param hook Function to use as a hook. + * @noreturn + * @error Invalid function hook. + */ +native AddNormalSoundHook(NormalSHook:hook); + +/** + * Unhooks all played ambient sounds. + * + * @param hook Function used for the hook. + * @noreturn + * @error Invalid function hook. + */ +native RemoveAmbientSoundHook(AmbientSHook:hook); + +/** + * Unhooks all played normal sounds. + * + * @param hook Function used for the hook. + * @noreturn + * @error Invalid function hook. + */ +native RemoveNormalSoundHook(NormalSHook:hook); + +/** + * Wrapper to emit sound to one client. + * + * @param client Client index. + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity to emit from. + * @param channel Channel to emit with. + * @param level Sound level. + * @param flags Sound flags. + * @param volume Sound volume. + * @param pitch Sound pitch. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @noreturn + * @error Invalid client index. + */ +stock EmitSoundToClient(client, + const String:sample[], + entity = SOUND_FROM_PLAYER, + channel = SNDCHAN_AUTO, + level = SNDLEVEL_NORMAL, + flags = SND_NOFLAGS, + Float:volume = SNDVOL_NORMAL, + pitch = SNDPITCH_NORMAL, + speakerentity = -1, + const Float:origin[3] = NULL_VECTOR, + const Float:dir[3] = NULL_VECTOR, + bool:updatePos = true, + Float:soundtime = 0.0) +{ + new clients[1]; + clients[0] = client; + /* Save some work for SDKTools and remove SOUND_FROM_PLAYER references */ + entity = (entity == SOUND_FROM_PLAYER) ? client : entity; + EmitSound(clients, 1, sample, entity, channel, + level, flags, volume, pitch, speakerentity, + origin, dir, updatePos, soundtime); +} + +/** + * Wrapper to emit sound to all clients. + * + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity to emit from. + * @param channel Channel to emit with. + * @param level Sound level. + * @param flags Sound flags. + * @param volume Sound volume. + * @param pitch Sound pitch. + * @param speakerentity Unknown. + * @param origin Sound origin. + * @param dir Sound direction. + * @param updatePos Unknown (updates positions?) + * @param soundtime Alternate time to play sound for. + * @noreturn + * @error Invalid client index. + */ +stock EmitSoundToAll(const String:sample[], + entity = SOUND_FROM_PLAYER, + channel = SNDCHAN_AUTO, + level = SNDLEVEL_NORMAL, + flags = SND_NOFLAGS, + Float:volume = SNDVOL_NORMAL, + pitch = SNDPITCH_NORMAL, + speakerentity = -1, + const Float:origin[3] = NULL_VECTOR, + const Float:dir[3] = NULL_VECTOR, + bool:updatePos = true, + Float:soundtime = 0.0) +{ + new clients[MaxClients]; + new total = 0; + + for (new i=1; i<=MaxClients; i++) + { + if (IsClientInGame(i)) + { + clients[total++] = i; + } + } + + if (!total) + { + return; + } + + EmitSound(clients, total, sample, entity, channel, + level, flags, volume, pitch, speakerentity, + origin, dir, updatePos, soundtime); +} + +/** + * Converts an attenuation value to a sound level. + * This function is from the HL2SDK. + * + * @param attn Attenuation value. + * @return Integer sound level. + */ +stock ATTN_TO_SNDLEVEL(Float:attn) +{ + if (attn > 0.0) + { + return RoundFloat(50.0 + (20.0 / attn)); + } + return 0; +} diff --git a/env/include/sdktools_stocks.inc b/env/include/sdktools_stocks.inc new file mode 100644 index 0000000..744df58 --- /dev/null +++ b/env/include/sdktools_stocks.inc @@ -0,0 +1,76 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_stocks_included + #endinput +#endif +#define _sdktools_stocks_included + +/** + * Given a partial team name, attempts to find a matching team. + * + * The search is performed case insensitively and only against the + * first N characters of the team names, where N is the number of + * characters in the search pattern. + * + * @param name Partial or full team name. + * @return A valid team index on success. + * -1 if no team matched. + * -2 if more than one team matched. + */ +stock FindTeamByName(const String:name[]) +{ + new name_len = strlen(name); + new num_teams = GetTeamCount(); + decl String:team_name[32]; + new found_team = -1; + + for (new i = 0; i < num_teams; i++) + { + GetTeamName(i, team_name, sizeof(team_name)); + + if (strncmp(team_name, name, name_len, false) == 0) + { + if (found_team >= 0) + { + return -2; + } + else + { + found_team = i; + } + } + } + + return found_team; +} + diff --git a/env/include/sdktools_stringtables.inc b/env/include/sdktools_stringtables.inc new file mode 100644 index 0000000..b54583b --- /dev/null +++ b/env/include/sdktools_stringtables.inc @@ -0,0 +1,180 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_stringtables_included + #endinput +#endif +#define _sdktools_stringtables_included + +#define INVALID_STRING_TABLE -1 /**< An invalid string table index */ +#define INVALID_STRING_INDEX -1 /**< An invalid string index in a table */ + +/** + * Searches for a string table. + * + * @param name Name of string table to find. + * @return A string table index number if found, INVALID_STRING_TABLE otherwise. + */ +native FindStringTable(const String:name[]); + +/** + * Returns the number of string tables that currently exist. + * + * @return Number of string tables that currently exist. + */ +native GetNumStringTables(); + +/** + * Returns the number of strings that currently exist in a given string table. + * + * @param tableidx A string table index. + * @return Number of strings that currently exist. + * @error Invalid string table index. + */ +native GetStringTableNumStrings(tableidx); + +/** + * Returns the maximum number of strings that are allowed in a given string table. + * + * @param tableidx A string table index. + * @return Maximum number of strings allowed. + * @error Invalid string table index. + */ +native GetStringTableMaxStrings(tableidx); + +/** + * Retrieves the name of a string table. + * + * @param tableidx A string table index. + * @param name Buffer to store the name of the string table. + * @param maxlength Maximum length of string buffer. + * @return Number of bytes written to the buffer (UTF-8 safe). + * @error Invalid string table index. + */ +native GetStringTableName(tableidx, String:name[], maxlength); + +/** + * Searches for the index of a given string in a string table. + * + * @param tableidx A string table index. + * @param string String to find. + * @return String index if found, INVALID_STRING_INDEX otherwise. + * @error Invalid string table index. + */ +native FindStringIndex(tableidx, const String:str[]); + +/** + * Retrieves the string at a given index of a string table. + * + * @param tableidx A string table index. + * @param stringidx A string index. + * @param name Buffer to store the string value. + * @param maxlength Maximum length of string buffer. + * @return Number of bytes written to the buffer (UTF-8 safe). + * @error Invalid string table index or string index. + */ +native ReadStringTable(tableidx, stringIdx, String:str[], maxlength); + +/** + * Returns the length of the user data associated with a given string index. + * + * @param tableidx A string table index. + * @param stringidx A string index. + * @return Length of user data. This will be 0 if there is no user data. + * @error Invalid string table index or string index. + */ +native GetStringTableDataLength(tableidx, stringidx); + +/** + * Retrieves the user data associated with a given string index. + * + * @param tableidx A string table index. + * @param stringidx A string index. + * @param userdata Buffer to store the user data. This will be set to "" if there is no user data. + * @param maxlength Maximum length of string buffer. + * @return Number of bytes written to the buffer (UTF-8 safe). + * @error Invalid string table index or string index. + */ +native GetStringTableData(tableidx, stringIdx, String:userdata[], maxlength); + +/** + * Sets the user data associated with a given string index. + * + * @param tableidx A string table index. + * @param stringidx A string index. + * @param userdata User data string that will be set. + * @param length Length of user data string. This should include the null terminator. + * @return Number of bytes written to the buffer (UTF-8 safe). + * @error Invalid string table index or string index. + */ +native SetStringTableData(tableidx, stringIdx, const String:userdata[], length); + +/** + * Adds a string to a given string table. + * + * @param tableidx A string table index. + * @param string String to add. + * @param userdata An optional user data string. + * @param length Length of user data string. This should include the null terminator. + * If set to -1, then user data will be not be altered if the specified string + * already exists in the string table. + */ +native AddToStringTable(tableidx, const String:str[], const String:userdata[]="", length=-1); + +/** + * Locks or unlocks the network string tables. + * + * @param lock Determines whether network string tables should be locked. + * True means the tables should be locked for writing; false means unlocked. + * @return Previous lock state. + */ +native bool:LockStringTables(bool:lock); + +/** + * Adds a file to the downloadables network string table. + * This forces a client to download the file if they do not already have it. + * + * @param filename File that will be added to downloadables table. + */ +stock AddFileToDownloadsTable(const String:filename[]) +{ + static table = INVALID_STRING_TABLE; + + if (table == INVALID_STRING_TABLE) + { + table = FindStringTable("downloadables"); + } + + new bool:save = LockStringTables(false); + AddToStringTable(table, filename); + LockStringTables(save); +} diff --git a/env/include/sdktools_tempents.inc b/env/include/sdktools_tempents.inc new file mode 100644 index 0000000..9b980c2 --- /dev/null +++ b/env/include/sdktools_tempents.inc @@ -0,0 +1,228 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_tempents_included + #endinput +#endif +#define _sdktools_tempents_included + +/** + * Called when a temp entity is going to be sent. + * + * @param te_name TE name. + * @param Players Array containing target player indexes. + * @param numClients Number of players in the array. + * @param delay Delay in seconds to send the TE. + * @return Plugin_Continue to allow the transmission of the TE, Plugin_Stop to block it. + */ +functag public Action:TEHook(const String:te_name[], const Players[], numClients, Float:delay); + +/** + * Hooks a temp entity. + * + * @param te_name TE name to hook. + * @param hook Function to use as a hook. + * @noreturn + * @error Temp Entity name not available or invalid function hook. + */ +native AddTempEntHook(const String:te_name[], TEHook:hook); + +/** + * Removes a temp entity hook. + * + * @param te_name TE name to unhook. + * @param hook Function used for the hook. + * @noreturn + * @error Temp Entity name not available or invalid function hook. + */ +native RemoveTempEntHook(const String:te_name[], TEHook:hook); + +/** + * Starts a temp entity transmission. + * + * @param te_name TE name. + * @noreturn + * @error Temp Entity name not available. + */ +native TE_Start(const String:te_name[]); + +/** + * Checks if a certain TE property exists. + * + * @param prop Property to use. + * @return True if the property exists, otherwise false. + */ +native bool:TE_IsValidProp(const String:prop[]); + +/** + * Sets an integer value in the current temp entity. + * + * @param prop Property to use. + * @param value Integer value to set. + * @noreturn + * @error Property not found. + */ +native TE_WriteNum(const String:prop[], value); + +/** + * Reads an integer value in the current temp entity. + * + * @param prop Property to use. + * @return Property value. + * @error Property not found. + */ +native TE_ReadNum(const String:prop[]); + +/** + * Sets a floating point number in the current temp entity. + * + * @param prop Property to use. + * @param value Floating point number to set. + * @noreturn + * @error Property not found. + */ +native TE_WriteFloat(const String:prop[], Float:value); + +/** + * Reads a floating point number in the current temp entity. + * + * @param prop Property to use. + * @noreturn Property value. + * @error Property not found. + */ +native Float:TE_ReadFloat(const String:prop[]); + +/** + * Sets a vector in the current temp entity. + * + * @param prop Property to use. + * @param vector Vector to set. + * @noreturn + * @error Property not found. + */ +native TE_WriteVector(const String:prop[], const Float:vector[3]); + +/** + * Reads a vector in the current temp entity. + * + * @param prop Property to use. + * @param vector Vector to read. + * @noreturn + * @error Property not found. + */ +native TE_ReadVector(const String:prop[], Float:vector[3]); + +/** + * Sets a QAngle in the current temp entity. + * + * @param prop Property to use. + * @param angles Angles to set. + * @return True on success, otherwise false. + * @error Property not found. + */ +native TE_WriteAngles(const String:prop[], const Float:angles[3]); + +/** + * Sets an array of floats in the current temp entity. + * + * @param prop Property to use. + * @param array Array of values to copy. + * @param arraySize Number of values to copy. + * @return True on success, otherwise false. + * @error Property not found. + */ +native TE_WriteFloatArray(const String:prop[], const Float:array[], arraySize); + +/** + * Sends the current temp entity to one or more clients. + * + * @param clients Array containing player indexes to broadcast to. + * @param numClients Number of players in the array. + * @param delay Delay in seconds to send the TE. + * @noreturn + * @error Invalid client index or client not in game. + */ +native TE_Send(clients[], numClients, Float:delay=0.0); + +/** + * Sets an encoded entity index in the current temp entity. + * (This is usually used for m_nStartEntity and m_nEndEntity). + * + * @param prop Property to use. + * @param value Value to set. + * @noreturn + * @error Property not found. + */ +stock TE_WriteEncodedEnt(const String:prop[], value) +{ + new encvalue = (value & 0x0FFF) | ((1 & 0xF)<<12); + return TE_WriteNum(prop, encvalue); +} + +/** + * Broadcasts the current temp entity to all clients. + * @note See TE_Start(). + * + * @param delay Delay in seconds to send the TE. + * @noreturn + */ +stock TE_SendToAll(Float:delay=0.0) +{ + new total = 0; + new clients[MaxClients]; + for (new i=1; i<=MaxClients; i++) + { + if (IsClientInGame(i)) + { + clients[total++] = i; + } + } + return TE_Send(clients, total, delay); +} + +/** + * Sends the current TE to only a client. + * @note See TE_Start(). + * + * @param client Client to send to. + * @param delay Delay in seconds to send the TE. + * @noreturn + * @error Invalid client index or client not in game. + */ +stock TE_SendToClient(client, Float:delay=0.0) +{ + new players[1]; + + players[0] = client; + + return TE_Send(players, 1, delay); +} diff --git a/env/include/sdktools_tempents_stocks.inc b/env/include/sdktools_tempents_stocks.inc new file mode 100644 index 0000000..2a52bf1 --- /dev/null +++ b/env/include/sdktools_tempents_stocks.inc @@ -0,0 +1,458 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _te_stocks_included + #endinput +#endif +#define _te_stocks_included + +/** + * @section TE Explosion flags. + */ +#define TE_EXPLFLAG_NONE 0x0 /**< all flags clear makes default Half-Life explosion */ +#define TE_EXPLFLAG_NOADDITIVE 0x1 /**< sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite) */ +#define TE_EXPLFLAG_NODLIGHTS 0x2 /**< do not render dynamic lights */ +#define TE_EXPLFLAG_NOSOUND 0x4 /**< do not play client explosion sound */ +#define TE_EXPLFLAG_NOPARTICLES 0x8 /**< do not draw particles */ +#define TE_EXPLFLAG_DRAWALPHA 0x10 /**< sprite will be drawn alpha */ +#define TE_EXPLFLAG_ROTATE 0x20 /**< rotate the sprite randomly */ +#define TE_EXPLFLAG_NOFIREBALL 0x40 /**< do not draw a fireball */ +#define TE_EXPLFLAG_NOFIREBALLSMOKE 0x80 /**< do not draw smoke with the fireball */ + +/** + * @endsection + */ + +/** + * @section TE Beam flags. + */ +#define FBEAM_STARTENTITY 0x00000001 +#define FBEAM_ENDENTITY 0x00000002 +#define FBEAM_FADEIN 0x00000004 +#define FBEAM_FADEOUT 0x00000008 +#define FBEAM_SINENOISE 0x00000010 +#define FBEAM_SOLID 0x00000020 +#define FBEAM_SHADEIN 0x00000040 +#define FBEAM_SHADEOUT 0x00000080 +#define FBEAM_ONLYNOISEONCE 0x00000100 /**< Only calculate our noise once */ +#define FBEAM_NOTILE 0x00000200 +#define FBEAM_USE_HITBOXES 0x00000400 /**< Attachment indices represent hitbox indices instead when this is set. */ +#define FBEAM_STARTVISIBLE 0x00000800 /**< Has this client actually seen this beam's start entity yet? */ +#define FBEAM_ENDVISIBLE 0x00001000 /**< Has this client actually seen this beam's end entity yet? */ +#define FBEAM_ISACTIVE 0x00002000 +#define FBEAM_FOREVER 0x00004000 +#define FBEAM_HALOBEAM 0x00008000 /**< When drawing a beam with a halo, don't ignore the segments and endwidth */ + +/** + * @endsection + */ + +/** + * Sets up a sparks effect. + * + * @param pos Position of the sparks. + * @param dir Direction of the sparks. + * @param Magnitude Sparks size. + * @param TrailLength Trail lenght of the sparks. + * @noreturn + */ +stock TE_SetupSparks(const Float:pos[3], const Float:dir[3], Magnitude, TrailLength) +{ + TE_Start("Sparks"); + TE_WriteVector("m_vecOrigin[0]", pos); + TE_WriteVector("m_vecDir", dir); + TE_WriteNum("m_nMagnitude", Magnitude); + TE_WriteNum("m_nTrailLength", TrailLength); +} + +/** + * Sets up a smoke effect. + * + * @param pos Position of the smoke. + * @param Model Precached model index. + * @param Scale Scale of the smoke. + * @param Framerate Frame rate of the smoke. + * @noreturn + */ +stock TE_SetupSmoke(const Float:pos[3], Model, Float:Scale, FrameRate) +{ + TE_Start("Smoke"); + TE_WriteVector("m_vecOrigin", pos); + TE_WriteNum("m_nModelIndex", Model); + TE_WriteFloat("m_fScale", Scale); + TE_WriteNum("m_nFrameRate", FrameRate); +} + +/** + * Sets up a dust cloud effect. + * + * @param pos Position of the dust. + * @param dir Direction of the dust. + * @param Size Dust cloud size. + * @param Speed Dust cloud speed. + * @noreturn + */ +stock TE_SetupDust(const Float:pos[3], const Float:dir[3], Float:Size, Float:Speed) +{ + TE_Start("Dust"); + TE_WriteVector("m_vecOrigin[0]", pos); + TE_WriteVector("m_vecDirection", dir); + TE_WriteFloat("m_flSize", Size); + TE_WriteFloat("m_flSpeed", Speed); +} + +/** + * Sets up a muzzle flash effect. + * + * @param pos Position of the muzzle flash. + * @param angles Rotation angles of the muzzle flash. + * @param Scale Scale of the muzzle flash. + * @param Type Muzzle flash type to render (Mod specific). + * @noreturn + */ +stock TE_SetupMuzzleFlash(const Float:pos[3], const Float:angles[3], Float:Scale, Type) +{ + TE_Start("MuzzleFlash"); + TE_WriteVector("m_vecOrigin", pos); + TE_WriteVector("m_vecAngles", angles); + TE_WriteFloat("m_flScale", Scale); + TE_WriteNum("m_nType", Type); +} + +/** + * Sets up a metal sparks effect. + * + * @param pos Position of the metal sparks. + * @param dir Direction of the metal sparks. + * @noreturn + */ +stock TE_SetupMetalSparks(const Float:pos[3], const Float:dir[3]) +{ + TE_Start("Metal Sparks"); + TE_WriteVector("m_vecPos", pos); + TE_WriteVector("m_vecDir", dir); +} + +/** + * Sets up an energy splash effect. + * + * @param pos Position of the energy splash. + * @param dir Direction of the energy splash. + * @param Explosive Makes the effect explosive. + * @noreturn + */ +stock TE_SetupEnergySplash(const Float:pos[3], const Float:dir[3], bool:Explosive) +{ + TE_Start("Energy Splash"); + TE_WriteVector("m_vecPos", pos); + TE_WriteVector("m_vecDir", dir); + TE_WriteNum("m_bExplosive", Explosive); +} + +/** + * Sets up an armor ricochet effect. + * + * @param pos Position of the armor ricochet. + * @param dir Directon of the armor ricochet. + * @noreturn + */ +stock TE_SetupArmorRicochet(const Float:pos[3], const Float:dir[3]) +{ + TE_Start("Armor Ricochet"); + TE_WriteVector("m_vecPos", pos); + TE_WriteVector("m_vecDir", dir); +} + +/** + * Sets up a glowing sprite effect. + * + * @param pos Position of the sprite. + * @param Model Precached model index. + * @param Life Time duration of the sprite. + * @param Size Sprite size. + * @param Brightness Sprite brightness. + * @noreturn + */ +stock TE_SetupGlowSprite(const Float:pos[3], Model, Float:Life, Float:Size, Brightness) +{ + TE_Start("GlowSprite"); + TE_WriteVector("m_vecOrigin", pos); + TE_WriteNum("m_nModelIndex", Model); + TE_WriteFloat("m_fScale", Size); + TE_WriteFloat("m_fLife", Life); + TE_WriteNum("m_nBrightness", Brightness); +} + +/** + * Sets up a explosion effect. + * + * @param pos Explosion position. + * @param Model Precached model index. + * @param Scale Explosion scale. + * @param Framerate Explosion frame rate. + * @param Flags Explosion flags. + * @param Radius Explosion radius. + * @param Magnitude Explosion size. + * @param normal Normal vector to the explosion. + * @param MaterialType Exploded material type. + * @noreturn + */ +stock TE_SetupExplosion(const Float:pos[3], Model, Float:Scale, Framerate, Flags, Radius, Magnitude, const Float:normal[3]={0.0, 0.0, 1.0}, MaterialType='C') +{ + TE_Start("Explosion"); + TE_WriteVector("m_vecOrigin[0]", pos); + TE_WriteVector("m_vecNormal", normal); + TE_WriteNum("m_nModelIndex", Model); + TE_WriteFloat("m_fScale", Scale); + TE_WriteNum("m_nFrameRate", Framerate); + TE_WriteNum("m_nFlags", Flags); + TE_WriteNum("m_nRadius", Radius); + TE_WriteNum("m_nMagnitude", Magnitude); + TE_WriteNum("m_chMaterialType", MaterialType); +} + +/** + * Sets up a blood sprite effect. + * + * @param pos Position of the sprite. + * @param dir Sprite direction. + * @param color Color array (r, g, b, a). + * @param Size Sprite size. + * @param SprayModel Precached model index. + * @param BloodDropModel Precached model index. + * @noreturn + */ +stock TE_SetupBloodSprite(const Float:pos[3], const Float:dir[3], const color[4], Size, SprayModel, BloodDropModel) +{ + TE_Start("Blood Sprite"); + TE_WriteVector("m_vecOrigin", pos); + TE_WriteVector("m_vecDirection", dir); + TE_WriteNum("r", color[0]); + TE_WriteNum("g", color[1]); + TE_WriteNum("b", color[2]); + TE_WriteNum("a", color[3]); + TE_WriteNum("m_nSize", Size); + TE_WriteNum("m_nSprayModel", SprayModel); + TE_WriteNum("m_nDropModel", BloodDropModel); +} + +/** + * Sets up a beam ring point effect. + * + * @param center Center position of the ring. + * @param Start_Radius Initial ring radius. + * @param End_Radius Final ring radius. + * @param ModelIndex Precached model index. + * @param HaloIndex Precached model index. + * @param StartFrame Initital frame to render. + * @param FrameRate Ring frame rate. + * @param Life Time duration of the ring. + * @param Width Beam width. + * @param Amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param Speed Speed of the beam. + * @param Flags Beam flags. + * @noreturn + */ +stock TE_SetupBeamRingPoint(const Float:center[3], Float:Start_Radius, Float:End_Radius, ModelIndex, HaloIndex, StartFrame, + FrameRate, Float:Life, Float:Width, Float:Amplitude, const Color[4], Speed, Flags) +{ + TE_Start("BeamRingPoint"); + TE_WriteVector("m_vecCenter", center); + TE_WriteFloat("m_flStartRadius", Start_Radius); + TE_WriteFloat("m_flEndRadius", End_Radius); + TE_WriteNum("m_nModelIndex", ModelIndex); + TE_WriteNum("m_nHaloIndex", HaloIndex); + TE_WriteNum("m_nStartFrame", StartFrame); + TE_WriteNum("m_nFrameRate", FrameRate); + TE_WriteFloat("m_fLife", Life); + TE_WriteFloat("m_fWidth", Width); + TE_WriteFloat("m_fEndWidth", Width); + TE_WriteFloat("m_fAmplitude", Amplitude); + TE_WriteNum("r", Color[0]); + TE_WriteNum("g", Color[1]); + TE_WriteNum("b", Color[2]); + TE_WriteNum("a", Color[3]); + TE_WriteNum("m_nSpeed", Speed); + TE_WriteNum("m_nFlags", Flags); + TE_WriteNum("m_nFadeLength", 0); +} + +/** + * Sets up a point to point beam effect. + * + * @param start Start position of the beam. + * @param end End position of the beam. + * @param ModelIndex Precached model index. + * @param HaloIndex Precached model index. + * @param StartFrame Initital frame to render. + * @param FrameRate Beam frame rate. + * @param Life Time duration of the beam. + * @param Width Initial beam width. + * @param EndWidth Final beam width. + * @param FadeLength Beam fade time duration. + * @param Amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param Speed Speed of the beam. + * @noreturn + */ +stock TE_SetupBeamPoints(const Float:start[3], const Float:end[3], ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life, + Float:Width, Float:EndWidth, FadeLength, Float:Amplitude, const Color[4], Speed) +{ + TE_Start("BeamPoints"); + TE_WriteVector("m_vecStartPoint", start); + TE_WriteVector("m_vecEndPoint", end); + TE_WriteNum("m_nModelIndex", ModelIndex); + TE_WriteNum("m_nHaloIndex", HaloIndex); + TE_WriteNum("m_nStartFrame", StartFrame); + TE_WriteNum("m_nFrameRate", FrameRate); + TE_WriteFloat("m_fLife", Life); + TE_WriteFloat("m_fWidth", Width); + TE_WriteFloat("m_fEndWidth", EndWidth); + TE_WriteFloat("m_fAmplitude", Amplitude); + TE_WriteNum("r", Color[0]); + TE_WriteNum("g", Color[1]); + TE_WriteNum("b", Color[2]); + TE_WriteNum("a", Color[3]); + TE_WriteNum("m_nSpeed", Speed); + TE_WriteNum("m_nFadeLength", FadeLength); +} + +/** + * Sets up an entity to entity laser effect. + * + * @param StartEntity Entity index from where the beam starts. + * @param EndEntity Entity index from where the beam ends. + * @param ModelIndex Precached model index. + * @param HaloIndex Precached model index. + * @param StartFrame Initital frame to render. + * @param FrameRate Beam frame rate. + * @param Life Time duration of the beam. + * @param Width Initial beam width. + * @param EndWidth Final beam width. + * @param FadeLength Beam fade time duration. + * @param Amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param Speed Speed of the beam. + * @noreturn + */ +stock TE_SetupBeamLaser(StartEntity, EndEntity, ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life, + Float:Width, Float:EndWidth, FadeLength, Float:Amplitude, const Color[4], Speed) +{ + TE_Start("BeamLaser"); + TE_WriteEncodedEnt("m_nStartEntity", StartEntity); + TE_WriteEncodedEnt("m_nEndEntity", EndEntity); + TE_WriteNum("m_nModelIndex", ModelIndex); + TE_WriteNum("m_nHaloIndex", HaloIndex); + TE_WriteNum("m_nStartFrame", StartFrame); + TE_WriteNum("m_nFrameRate", FrameRate); + TE_WriteFloat("m_fLife", Life); + TE_WriteFloat("m_fWidth", Width); + TE_WriteFloat("m_fEndWidth", EndWidth); + TE_WriteFloat("m_fAmplitude", Amplitude); + TE_WriteNum("r", Color[0]); + TE_WriteNum("g", Color[1]); + TE_WriteNum("b", Color[2]); + TE_WriteNum("a", Color[3]); + TE_WriteNum("m_nSpeed", Speed); + TE_WriteNum("m_nFadeLength", FadeLength); +} + +/** + * Sets up a beam ring effect. + * + * @param StartEntity Entity index from where the ring starts. + * @param EndEntity Entity index from where the ring ends. + * @param ModelIndex Precached model index. + * @param HaloIndex Precached model index. + * @param StartFrame Initital frame to render. + * @param FrameRate Ring frame rate. + * @param Life Time duration of the ring. + * @param Width Beam width. + * @param Amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param Speed Speed of the beam. + * @param Flags Beam flags. + * @noreturn + */ +stock TE_SetupBeamRing(StartEntity, EndEntity, ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life, Float:Width, Float:Amplitude, const Color[4], Speed, Flags) +{ + TE_Start("BeamRing"); + TE_WriteEncodedEnt("m_nStartEntity", StartEntity); + TE_WriteEncodedEnt("m_nEndEntity", EndEntity); + TE_WriteNum("m_nModelIndex", ModelIndex); + TE_WriteNum("m_nHaloIndex", HaloIndex); + TE_WriteNum("m_nStartFrame", StartFrame); + TE_WriteNum("m_nFrameRate", FrameRate); + TE_WriteFloat("m_fLife", Life); + TE_WriteFloat("m_fWidth", Width); + TE_WriteFloat("m_fEndWidth", Width); + TE_WriteFloat("m_fAmplitude", Amplitude); + TE_WriteNum("r", Color[0]); + TE_WriteNum("g", Color[1]); + TE_WriteNum("b", Color[2]); + TE_WriteNum("a", Color[3]); + TE_WriteNum("m_nSpeed", Speed); + TE_WriteNum("m_nFadeLength", 0); + TE_WriteNum("m_nFlags", Flags); +} + +/** + * Sets up a follow beam effect. + * + * @param EntIndex Entity index from where the beam starts. + * @param ModelIndex Precached model index. + * @param HaloIndex Precached model index. + * @param Life Time duration of the beam. + * @param Width Initial beam width. + * @param EndWidth Final beam width. + * @param FadeLength Beam fade time duration. + * @param color Color array (r, g, b, a). + * @noreturn + */ +stock TE_SetupBeamFollow(EntIndex, ModelIndex, HaloIndex, Float:Life, Float:Width, Float:EndWidth, FadeLength, const Color[4]) +{ + TE_Start("BeamFollow"); + TE_WriteEncodedEnt("m_iEntIndex", EntIndex); + TE_WriteNum("m_nModelIndex", ModelIndex); + TE_WriteNum("m_nHaloIndex", HaloIndex); + TE_WriteNum("m_nStartFrame", 0); + TE_WriteNum("m_nFrameRate", 0); + TE_WriteFloat("m_fLife", Life); + TE_WriteFloat("m_fWidth", Width); + TE_WriteFloat("m_fEndWidth", EndWidth); + TE_WriteNum("m_nFadeLength", FadeLength); + TE_WriteNum("r", Color[0]); + TE_WriteNum("g", Color[1]); + TE_WriteNum("b", Color[2]); + TE_WriteNum("a", Color[3]); +} diff --git a/env/include/sdktools_trace.inc b/env/include/sdktools_trace.inc new file mode 100644 index 0000000..845a566 --- /dev/null +++ b/env/include/sdktools_trace.inc @@ -0,0 +1,374 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_trace_included + #endinput +#endif +#define _sdktools_trace_included + +#define CONTENTS_EMPTY 0 /**< No contents. */ +#define CONTENTS_SOLID 0x1 /**< an eye is never valid in a solid . */ +#define CONTENTS_WINDOW 0x2 /**< translucent, but not watery (glass). */ +#define CONTENTS_AUX 0x4 +#define CONTENTS_GRATE 0x8 /**< alpha-tested "grate" textures. Bullets/sight pass through, but solids don't. */ +#define CONTENTS_SLIME 0x10 +#define CONTENTS_WATER 0x20 +#define CONTENTS_MIST 0x40 +#define CONTENTS_OPAQUE 0x80 /**< things that cannot be seen through (may be non-solid though). */ +#define LAST_VISIBLE_CONTENTS 0x80 +#define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1)) +#define CONTENTS_TESTFOGVOLUME 0x100 +#define CONTENTS_UNUSED5 0x200 +#define CONTENTS_UNUSED6 0x4000 +#define CONTENTS_TEAM1 0x800 /**< per team contents used to differentiate collisions. */ +#define CONTENTS_TEAM2 0x1000 /**< between players and objects on different teams. */ +#define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000 /**< ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW. */ +#define CONTENTS_MOVEABLE 0x4000 /**< hits entities which are MOVETYPE_PUSH (doors, plats, etc) */ +#define CONTENTS_AREAPORTAL 0x8000 /**< remaining contents are non-visible, and don't eat brushes. */ +#define CONTENTS_PLAYERCLIP 0x10000 +#define CONTENTS_MONSTERCLIP 0x20000 + +/** + * @section currents can be added to any other contents, and may be mixed + */ +#define CONTENTS_CURRENT_0 0x40000 +#define CONTENTS_CURRENT_90 0x80000 +#define CONTENTS_CURRENT_180 0x100000 +#define CONTENTS_CURRENT_270 0x200000 +#define CONTENTS_CURRENT_UP 0x400000 +#define CONTENTS_CURRENT_DOWN 0x800000 + +/** + * @endsection + */ + +#define CONTENTS_ORIGIN 0x1000000 /**< removed before bsping an entity. */ +#define CONTENTS_MONSTER 0x2000000 /**< should never be on a brush, only in game. */ +#define CONTENTS_DEBRIS 0x4000000 +#define CONTENTS_DETAIL 0x8000000 /**< brushes to be added after vis leafs. */ +#define CONTENTS_TRANSLUCENT 0x10000000 /**< auto set if any surface has trans. */ +#define CONTENTS_LADDER 0x20000000 +#define CONTENTS_HITBOX 0x40000000 /**< use accurate hitboxes on trace. */ + +/** + * @section Trace masks. + */ +#define MASK_ALL (0xFFFFFFFF) +#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< everything that is normally solid */ +#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< everything that blocks player movement */ +#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< blocks npc movement */ +#define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME) /**< water physics in these contents */ +#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE) /**< everything that blocks line of sight for AI, lighting, etc */ +#define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER) /**< everything that blocks line of sight for AI, lighting, etc, but with monsters added. */ +#define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE) /**< everything that blocks line of sight for players */ +#define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE) /**< everything that blocks line of sight for players, but with monsters added. */ +#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX) /**< bullets see these as solid */ +#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE) /**< non-raycasted weapons see this as solid (includes grates) */ +#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW) /**< hits solids (not grates) and passes through everything else */ +#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE) /**< everything normally solid, except monsters (world+brush only) */ +#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE) /**< everything normally solid for player movement, except monsters (world+brush only) */ +#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) /**< everything normally solid for npc movement, except monsters (world+brush only) */ +#define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) /**< just the world, used for route rebuilding */ +#define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME) /**< These are things that can split areaportals */ + +/** + * @endsection + */ + +enum RayType +{ + RayType_EndPoint, /**< The trace ray will go from the start position to the end position. */ + RayType_Infinite /**< The trace ray will go from the start position to infinity using a direction vector. */ +}; + +funcenum TraceEntityFilter +{ + /** + * Called on entity filtering. + * + * @param entity Entity index. + * @param contentsMask Contents Mask. + * @return True to allow the current entity to be hit, otherwise false. + */ + bool:public(entity, contentsMask), + + /** + * Called on entity filtering. + * + * @param entity Entity index. + * @param contentsMask Contents Mask. + * @param data Data value, if used. + * @return True to allow the current entity to be hit, otherwise false. + */ + bool:public(entity, contentsMask, any:data), +}; + +/** + * Get the contents mask and the entity index at the given position. + * + * @param pos World position to test. + * @param entindex Entity index found at the given position (by reference). + * @return Contents mask. + */ +native TR_GetPointContents(const Float:pos[3], &entindex=-1); + +/** + * Get the point contents testing only the given entity index. + * + * @param entindex Entity index to test. + * @param pos World position. + * @return Contents mask. + */ +native TR_GetPointContentsEnt(entindex, const Float:pos[3]); + +/** + * Starts up a new trace ray using a global trace result. + * + * @param pos Starting position of the ray. + * @param vec Depending on RayType, it will be used as the + * ending point, or the direction angle. + * @param flags Trace flags. + * @param rtype Method to calculate the ray direction. + * @noreturn + */ +native TR_TraceRay(const Float:pos[3], + const Float:vec[3], + flags, + RayType:rtype); + +/** + * Starts up a new trace hull using a global trace result. + * + * @param pos Starting position of the ray. + * @param vec Ending position of the ray. + * @param mins Hull minimum size. + * @param maxs Hull maximum size. + * @param flags Trace flags. + * @noreturn + */ +native TR_TraceHull(const Float:pos[3], + const Float:vec[3], + const Float:mins[3], + const Float:maxs[3], + flags); + +/** + * Starts up a new trace ray using a global trace result and a customized + * trace ray filter. + * + * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter + * function is currently not allowed and may not work. + * + * @param pos Starting position of the ray. + * @param vec Depending on RayType, it will be used as the ending + * point, or the direction angle. + * @param flags Trace flags. + * @param rtype Method to calculate the ray direction. + * @param filter Function to use as a filter. + * @param data Arbitrary data value to pass through to the filter + * function. + * @noreturn + */ +native TR_TraceRayFilter(const Float:pos[3], + const Float:vec[3], + flags, + RayType:rtype, + TraceEntityFilter:filter, + any:data=0); + +/** + * Starts up a new trace hull using a global trace result and a customized + * trace ray filter. + * + * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter + * function is currently not allowed and may not work. + * + * @param pos Starting position of the ray. + * @param vec Depending on RayType, it will be used as the ending + * point, or the direction angle. + * @param mins Hull minimum size. + * @param maxs Hull maximum size. + * @param flags Trace flags. + * @param filter Function to use as a filter. + * @param data Arbitrary data value to pass through to the filter + * function. + * @noreturn + */ +native TR_TraceHullFilter(const Float:pos[3], + const Float:vec[3], + const Float:mins[3], + const Float:maxs[3], + flags, + TraceEntityFilter:filter, + any:data=0); + +/** + * Starts up a new trace ray using a new trace result. + * + * @param pos Starting position of the ray. + * @param vec Depending on RayType, it will be used as the ending + * point, or the direction angle. + * @param flags Trace flags. + * @param rtype Method to calculate the ray direction. + * @return Ray trace handle, which must be closed via CloseHandle(). + */ +native Handle:TR_TraceRayEx(const Float:pos[3], + const Float:vec[3], + flags, + RayType:rtype); + +/** + * Starts up a new trace hull using a new trace result. + * + * @param pos Starting position of the ray. + * @param vec Ending position of the ray. + * @param mins Hull minimum size. + * @param maxs Hull maximum size. + * @param flags Trace flags. + * @return Ray trace handle, which must be closed via CloseHandle(). + */ +native Handle:TR_TraceHullEx(const Float:pos[3], + const Float:vec[3], + const Float:mins[3], + const Float:maxs[3], + flags); + +/** + * Starts up a new trace ray using a new trace result and a customized + * trace ray filter. + * + * Calling TR_Trace*Filter or TR_TraceRay*Ex from inside a filter + * function is currently not allowed and may not work. + * + * @param pos Starting position of the ray. + * @param vec Depending on RayType, it will be used as the ending + * point, or the direction angle. + * @param flags Trace flags. + * @param rtype Method to calculate the ray direction. + * @param filter Function to use as a filter. + * @param data Arbitrary data value to pass through to the filter function. + * @return Ray trace handle, which must be closed via CloseHandle(). + */ +native Handle:TR_TraceRayFilterEx(const Float:pos[3], + const Float:vec[3], + flags, + RayType:rtype, + TraceEntityFilter:filter, + any:data=0); + +/** + * Starts up a new trace hull using a new trace result and a customized + * trace ray filter. + * + * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter + * function is currently not allowed and may not work. + * + * @param pos Starting position of the ray. + * @param vec Ending position of the ray. + * @param mins Hull minimum size. + * @param maxs Hull maximum size. + * @param flags Trace flags. + * @param filter Function to use as a filter. + * @param data Arbitrary data value to pass through to the filter function. + * @return Ray trace handle, which must be closed via CloseHandle(). + */ +native Handle:TR_TraceHullFilterEx(const Float:pos[3], + const Float:vec[3], + const Float:mins[3], + const Float:maxs[3], + flags, + TraceEntityFilter:filter, + any:data=0); + +/** + * Returns the time fraction from a trace result (1.0 means no collision). + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Time fraction value of the trace. + * @error Invalid Handle. + */ +native Float:TR_GetFraction(Handle:hndl=INVALID_HANDLE); + +/** + * Returns the collision position of a trace result. + * + * @param pos Vector buffer to store data in. + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @noreturn + * @error Invalid Handle. + */ +native TR_GetEndPosition(Float:pos[3], Handle:hndl=INVALID_HANDLE); + +/** + * Returns the entity index that collided with the trace. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Entity index or -1 for no collision. + * @error Invalid Handle. + */ +native TR_GetEntityIndex(Handle:hndl=INVALID_HANDLE); + +/** + * Returns if there was any kind of collision along the trace ray. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return True if any collision found, otherwise false. + * @error Invalid Handle. + */ +native bool:TR_DidHit(Handle:hndl=INVALID_HANDLE); + +/** + * Returns in which body hit group the trace collided if any. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @return Body hit group. + * @error Invalid Handle. + */ +native TR_GetHitGroup(Handle:hndl=INVALID_HANDLE); + +/** + * Find the normal vector to the collison plane of a trace. + * + * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result. + * @param normal Vector buffer to store the vector normal to the collision plane + * @noreturn + * @error Invalid Handle + */ +native TR_GetPlaneNormal(Handle:hndl, Float:normal[3]); + +/** + * Tests a point to see if it's outside any playable area + * + * @param pos Vector buffer to store data in. + * @return True if outside world, otherwise false. + */ +native TR_PointOutsideWorld(Float:pos[3]); \ No newline at end of file diff --git a/env/include/sdktools_voice.inc b/env/include/sdktools_voice.inc new file mode 100644 index 0000000..ef27180 --- /dev/null +++ b/env/include/sdktools_voice.inc @@ -0,0 +1,123 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sdktools_voice_included + #endinput +#endif +#define _sdktools_voice_included + +/** + * @section voice flags. + */ +#define VOICE_NORMAL 0 /**< Allow the client to listen and speak normally. */ +#define VOICE_MUTED 1 /**< Mutes the client from speaking to everyone. */ +#define VOICE_SPEAKALL 2 /**< Allow the client to speak to everyone. */ +#define VOICE_LISTENALL 4 /**< Allow the client to listen to everyone. */ +#define VOICE_TEAM 8 /**< Allow the client to always speak to team, even when dead. */ +#define VOICE_LISTENTEAM 16 /**< Allow the client to always hear teammates, including dead ones. */ + +/** + * @endsection + */ + +enum ListenOverride +{ + Listen_Default = 0, /**< Leave it up to the game */ + Listen_No, /**< Can't hear */ + Listen_Yes, /**< Can hear */ +}; + +/** + * Set the client listening flags. + * + * @param client The client index + * @param flags The voice flags + * @noreturn + */ +native SetClientListeningFlags(client, flags); + +/** + * Retrieve the client current listening flags. + * + * @param client The client index + * @return The current voice flags + */ +native GetClientListeningFlags(client); + +/** + * Set the receiver ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @return True if successful otherwise false. + */ +#pragma deprecated Use SetListenOverride() instead +native bool:SetClientListening(iReceiver, iSender, bool:bListen); + +/** + * Retrieves if the receiver can listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @return True if successful otherwise false. + */ +#pragma deprecated GetListenOverride() instead +native bool:GetClientListening(iReceiver, iSender); + +/** + * Override the receiver's ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @param override + * @return True if successful otherwise false. + */ +native bool:SetListenOverride(iReceiver, iSender, ListenOverride:override); + +/** + * Retrieves the override of the receiver's ability to listen to the sender. + * + * @param iReceiver The listener index. + * @param iSender The sender index. + * @return The override value. + */ +native ListenOverride:GetListenOverride(iReceiver, iSender); + +/** + * Retrieves if the muter has muted the mutee. + * + * @param iMuter The muter index. + * @param iMutee The mutee index. + * @return True if muter has muted mutee, false otherwise. + */ +native bool:IsClientMuted(iMuter, iMutee); + diff --git a/env/include/sorting.inc b/env/include/sorting.inc new file mode 100644 index 0000000..2b1bfec --- /dev/null +++ b/env/include/sorting.inc @@ -0,0 +1,176 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + + +#if defined _sorting_included + #endinput +#endif +#define _sorting_included + +/** + * Contains sorting orders. + */ +enum SortOrder +{ + Sort_Ascending = 0, /**< Ascending order */ + Sort_Descending = 1, /**< Descending order */ + Sort_Random = 2 /**< Random order */ +}; + +/** + * Data types for ADT Array Sorts + */ +enum SortType +{ + Sort_Integer = 0, + Sort_Float, + Sort_String, +}; + +/** + * Sorts an array of integers. + * + * @param array Array of integers to sort in-place. + * @param array_size Size of the array. + * @param order Sorting order to use. + * @noreturn + */ +native SortIntegers(array[], array_size, SortOrder:order = Sort_Ascending); + +/** + * Sorts an array of float point numbers. + * + * @param array Array of floating point numbers to sort in-place. + * @param array_size Size of the array. + * @param order Sorting order to use. + * @noreturn + */ +native SortFloats(Float:array[], array_size, SortOrder:order = Sort_Ascending); + +/** + * Sorts an array of strings. + * + * @param array Array of strings to sort in-place. + * @param array_size Size of the array. + * @param order Sorting order to use. + * @noreturn + */ +native SortStrings(String:array[][], num_strings, SortOrder:order = Sort_Ascending); + +/** + * Sort comparison function for 1D array elements. + * @note You may need to use explicit tags in order to use data properly. + * + * @param elem1 First element to compare. + * @param elem2 Second element 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 public SortFunc1D(elem1, elem2, const array[], Handle:hndl); + +/** + * Sorts a custom 1D array. You must pass in a comparison function. + * + * @param array Array to sort. + * @param array_size Size of the array to sort. + * @param sortfunc Sort function. + * @param hndl Optional Handle to pass through the comparison calls. + * @noreturn + */ +native SortCustom1D(array[], array_size, SortFunc1D:sortfunc, Handle:hndl=INVALID_HANDLE); + +/** + * Sort comparison function for 2D array elements (sub-arrays). + * @note You may need to use explicit tags in order to use data properly. + * + * @param elem1 First array to compare. + * @param elem2 Second array 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 + */ +funcenum SortFunc2D +{ + public(array[], array[], const array[][], Handle:hndl), + public(String:array[], String:array[], const String:array[][], Handle:hndl), +}; + +/** + * Sorts a custom 2D array. You must pass in a comparison function. + * + * @param array Array to sort. + * @param array_size Size of the major array to sort (first index, outermost). + * @param sortfunc Sort comparison function to use. + * @param hndl Optional Handle to pass through the comparison calls. + * @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, SortType:type); + +/** + * 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 public SortFuncADTArray(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); \ No newline at end of file diff --git a/env/include/sourcemod.inc b/env/include/sourcemod.inc new file mode 100644 index 0000000..bf27516 --- /dev/null +++ b/env/include/sourcemod.inc @@ -0,0 +1,636 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _sourcemod_included + #endinput +#endif +#define _sourcemod_included + +/** + * Plugin public information. + */ +struct Plugin +{ + const String:name[], /**< Plugin Name */ + const String:description[], /**< Plugin Description */ + const String:author[], /**< Plugin Author */ + const String:version[], /**< Plugin Version */ + const String:url[], /**< Plugin URL */ +}; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum APLRes +{ + APLRes_Success = 0, /**< Plugin should load */ + APLRes_Failure, /**< Plugin shouldn't load and should display an error */ + APLRes_SilentFailure /**< Plugin shouldn't load but do so silently */ +}; + +/** + * Declare this as a struct in your plugin to expose its information. + * Example: + * + * public Plugin:myinfo = + * { + * name = "My Plugin", + * //etc + * }; + */ +public Plugin:myinfo; + +/** + * Called when the plugin is fully initialized and all known external references + * are resolved. This is only called once in the lifetime of the plugin, and is + * paired with OnPluginEnd(). + * + * If any run-time error is thrown during this callback, the plugin will be marked + * as failed. + * + * It is not necessary to close any handles or remove hooks in this function. + * SourceMod guarantees that plugin shutdown automatically and correctly releases + * all resources. + * + * @noreturn + */ +forward OnPluginStart(); + +/** + * @deprecated Use AskPluginLoad2() instead. + * If a plugin contains both AskPluginLoad() and AskPluginLoad2(), the former will + * not be called, but old plugins with only AskPluginLoad() will work. + */ +#pragma deprecated Use AskPluginLoad2() instead +forward bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max); + +/** + * Called before OnPluginStart, in case the plugin wants to check for load failure. + * This is called even if the plugin type is "private." Any natives from modules are + * not available at this point. Thus, this forward should only be used for explicit + * pre-emptive things, such as adding dynamic natives, setting certain types of load + * filters (such as not loading the plugin for certain games). + * + * @note It is not safe to call externally resolved natives until OnPluginStart(). + * @note Any sort of RTE in this function will cause the plugin to fail loading. + * @note If you do not return anything, it is treated like returning success. + * @note If a plugin has an AskPluginLoad2(), AskPluginLoad() will not be called. + * + * + * @param myself Handle to the plugin. + * @param late Whether or not the plugin was loaded "late" (after map load). + * @param error Error message buffer in case load failed. + * @param err_max Maximum number of characters for error message buffer. + * @return APLRes_Success for load success, APLRes_Failure or APLRes_SilentFailure otherwise + */ +forward APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max); + +/** + * Called when the plugin is about to be unloaded. + * + * @noreturn + */ +forward OnPluginEnd(); + +/** + * Called when the plugin's pause status is changing. + * + * @param pause True if the plugin is being paused, false otherwise. + * @noreturn + */ +forward OnPluginPauseChange(bool:pause); + +/** + * Called before every server frame. Note that you should avoid + * doing expensive computations here, and you should declare large + * local arrays using 'decl' instead of 'new'. + */ +forward OnGameFrame(); + +/** + * Called when the map is loaded. + * + * @note This used to be OnServerLoad(), which is now deprecated. + * Plugins still using the old forward will work. + */ +forward OnMapStart(); + +/** + * Called right before a map ends. + */ +forward OnMapEnd(); + +/** + * Called when the map has loaded, servercfgfile (server.cfg) has been + * executed, and all plugin configs are done executing. This is the best + * place to initialize plugin functions which are based on cvar data. + * + * @note This will always be called once and only once per map. It will be + * called after OnMapStart(). + * + * @noreturn + */ +forward OnConfigsExecuted(); + +/** + * This is called once, right after OnMapStart() but any time before + * OnConfigsExecuted(). It is called after the "exec sourcemod.cfg" + * command and all AutoExecConfig() exec commands have been added to + * the ServerCommand() buffer. + * + * If you need to load per-map settings that override default values, + * adding commands to the ServerCommand() buffer here will guarantee + * that they're set before OnConfigsExecuted(). + * + * Unlike OnMapStart() and OnConfigsExecuted(), this is not called on + * late loads that occur after OnMapStart(). + * + * @noreturn + */ +forward OnAutoConfigsBuffered(); + +/** + * @deprecated Use OnConfigsExecuted() instead. + */ +#pragma deprecated Use OnConfigsExecuted() instead +forward OnServerCfg(); + +/** + * Called after all plugins have been loaded. This is called once for + * every plugin. If a plugin late loads, it will be called immediately + * after OnPluginStart(). + */ +forward OnAllPluginsLoaded(); + +/** + * Returns the calling plugin's Handle. + * + * @return Handle of the calling plugin. + */ +native Handle:GetMyHandle(); + +/** + * Returns an iterator that can be used to search through plugins. + * + * @return Handle to iterate with. Must be closed via + * CloseHandle(). + * @error Invalid Handle. + */ +native Handle:GetPluginIterator(); + +/** + * Returns whether there are more plugins available in the iterator. + * + * @param iter Handle to the plugin iterator. + * @return True on more plugins, false otherwise. + * @error Invalid Handle. + */ +native bool:MorePlugins(Handle:iter); + +/** + * Returns the current plugin in the iterator and advances the iterator. + * + * @param iter Handle to the plugin iterator. + * @return Current plugin the iterator is at, before + * the iterator is advanced. + * @error Invalid Handle. + */ +native Handle:ReadPlugin(Handle:iter); + +/** + * Returns a plugin's status. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @return Status code for the plugin. + * @error Invalid Handle. + */ +native PluginStatus:GetPluginStatus(Handle:plugin); + +/** + * Retrieves a plugin's file name relative to the plugins folder. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @param buffer Buffer to the store the file name. + * @param maxlength Maximum length of the name buffer. + * @noreturn + * @error Invalid Handle. + */ +native GetPluginFilename(Handle:plugin, String:buffer[], maxlength); + +/** + * Retrieves whether or not a plugin is being debugged. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @return True if being debugged, false otherwise. + * @error Invalid Handle. + */ +native bool:IsPluginDebugging(Handle:hndl); + +/** + * Retrieves a plugin's public info. + * + * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin). + * @param info Plugin info property to retrieve. + * @param buffer Buffer to store info in. + * @param maxlength Maximum length of buffer. + * @return True on success, false if property is not available. + * @error Invalid Handle. + */ +native bool:GetPluginInfo(Handle:plugin, PluginInfo:info, String:buffer[], maxlength); + +/** + * Finds a plugin by its order in the list from the "plugins list" server + * "sm" command. You should not use this function to loop through all plugins, + * use the iterator instead. Looping through all plugins using this native + * is O(n^2), whereas using the iterator is O(n). + * + * @param order_num Number of the plugin as it appears in "sm plugins list". + * @return Plugin Handle on success, INVALID_HANDLE if no plugin + * matches the given number. + */ +native Handle:FindPluginByNumber(order_num); + +/** + * Causes the plugin to enter a failed state. An error will be thrown and + * the plugin will be paused until it is unloaded or reloaded. + * + * For backwards compatibility, if no extra arguments are passed, no + * formatting is applied. If one or more additional arguments is passed, + * the string is formatted using Format(). If any errors are encountered + * during formatting, both the format specifier string and an additional + * error message are written. + * + * This function does not return, and no further code in the plugin is + * executed. + * + * @param string Format specifier string. + * @param ... Formatting arguments. + * @noreturn + * @error Always throws SP_ERROR_ABORT. + */ +native SetFailState(const String:string[], any:...); + +/** + * Aborts the current callback and throws an error. This function + * does not return in that no code is executed following it. + * + * @param format String format. + * @param ... Format arguments. + * @noreturn + * @error Always! + */ +native ThrowError(const String:fmt[], any:...); + +/** + * Gets the system time as a unix timestamp. + * + * @param bigStamp Optional array to store the 64bit timestamp in. + * @return 32bit timestamp (number of seconds since unix epoch). + */ +native GetTime(bigStamp[2]={0,0}); + +/** + * Produces a date and/or time string value for a timestamp. + * + * See this URL for valid parameters: + * http://cplusplus.com/reference/clibrary/ctime/strftime.html + * + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param format Formatting rules (passing NULL_STRING will use the rules defined in sm_datetime_format). + * @param stamp Optional time stamp. + * @noreturn + * @error Buffer too small or invalid time format. + */ +native FormatTime(String:buffer[], maxlength, const String:format[], stamp=-1); + +/** + * Loads a game config file. + * + * @param file File to load. The path must be relative to the 'gamedata' folder under the config folder + * and the extension should be omitted. + * @return A handle to the game config file or INVALID_HANDLE in failure. + */ +native Handle:LoadGameConfigFile(const String:file[]); + +/** + * Returns an offset value. + * + * @param gc Game config handle. + * @param key Key to retrieve from the offset section. + * @return An offset, or -1 on failure. + */ +native GameConfGetOffset(Handle:gc, const String:key[]); + +/** + * Gets the value of a key from the "Keys" section. + * + * @param gc Game config handle. + * @param key Key to retrieve from the Keys section. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @return True if key existed, false otherwise. + */ +native bool:GameConfGetKeyValue(Handle:gc, const String:key[], String:buffer[], maxlen); + +/** + * Returns the operating system's "tick count," which is a number of + * milliseconds since the operating system loaded. This can be used + * for basic benchmarks. + * + * @return Tick count in milliseconds. + */ +native GetSysTickCount(); + +/** + * Specifies that the given config file should be executed after plugin load. + * OnConfigsExecuted() will not be called until the config file has executed, + * but it will be called if the execution fails. + * + * @param autoCreate If true, and the config file does not exist, such a config + * file will be automatically created and populated with + * information from the plugin's registered cvars. + * @param name Name of the config file, excluding the .cfg extension. + * If empty, is assumed. + * @param folder Folder under cfg/ to use. By default this is "sourcemod." + * @noreturn + */ +native AutoExecConfig(bool:autoCreate=true, const String:name[]="", const String:folder[]="sourcemod"); + +/** + * Registers a library name for identifying as a dependency to + * other plugins. + * + * @param name Library name. + * @noreturn + */ +native RegPluginLibrary(const String:name[]); + +/** + * Returns whether a library exists. This function should be considered + * expensive; it should only be called on plugin to determine availability + * of resources. Use OnLibraryAdded()/OnLibraryRemoved() to detect changes + * in optional resources. + * + * @param name Library name of a plugin or extension. + * @return True if exists, false otherwise. + */ +native bool:LibraryExists(const String:name[]); + +/** + * Returns the status of an extension, by filename. + * + * @param name Extension name (like "sdktools.ext"). + * @param error Optional error message buffer. + * @param maxlength Length of optional error message buffer. + * @return -2 if the extension was not found. + * -1 if the extension was found but failed to load. + * 0 if the extension loaded but reported an error. + * 1 if the extension is running without error. + */ +native GetExtensionFileStatus(const String:name[], String:error[]="", maxlength=0); + +/** + * Called after a library is added that the current plugin references + * optionally. A library is either a plugin name or extension name, as + * exposed via its include file. + * + * @param name Library name. + */ +forward OnLibraryAdded(const String:name[]); + +/** + * Called right before a library is removed that the current plugin references + * optionally. A library is either a plugin name or extension name, as + * exposed via its include file. + * + * @param name Library name. + */ +forward OnLibraryRemoved(const String:name[]); + +#define MAPLIST_FLAG_MAPSFOLDER (1<<0) /**< On failure, use all maps in the maps folder. */ +#define MAPLIST_FLAG_CLEARARRAY (1<<1) /**< If an input array is specified, clear it before adding. */ +#define MAPLIST_FLAG_NO_DEFAULT (1<<2) /**< Do not read "default" or "mapcyclefile" on failure. */ + +/** + * Loads a map list to an ADT Array. + * + * A map list is a list of maps from a file. SourceMod allows easy configuration of + * maplists through addons/sourcemod/configs/maplists.cfg. Each entry is given a + * name and a file (for example, "rtv" => "rtv.cfg"), or a name and a redirection + * (for example, "rtv" => "default"). This native will read a map list entry, + * cache the file, and return the list of maps it holds. + * + * Serial change numbers are used to identify if a map list has changed. Thus, if + * you pass a serial change number and it's equal to what SourceMod currently knows + * about the map list, then SourceMod won't reparse the file. + * + * If the maps end up being read from the maps folder (MAPLIST_FLAG_MAPSFOLDER), they + * are automatically sorted in alphabetical, ascending order. + * + * Arrays created by this function are temporary and must be freed via CloseHandle(). + * Modifying arrays created by this function will not affect future return values or + * or the contents of arrays returned to other plugins. + * + * @param array Array to store the map list. If INVALID_HANDLE, a new blank + * array will be created. The blocksize should be at least 16; + * otherwise results may be truncated. Items are added to the array + * as strings. The array is never checked for duplicates, and it is + * not read beforehand. Only the serial number is used to detect + * changes. + * @param serial Serial number to identify last known map list change. If -1, the + * the value will not be checked. If the map list has since changed, + * the serial is updated (even if -1 was passed). If there is an error + * finding a valid maplist, then the serial is set to -1. + * @param str Config name, or "default" for the default map list. Config names + * should be somewhat descriptive. For example, the admin menu uses + * a config name of "admin menu". The list names can be configured + * by users in addons/sourcemod/configs/maplists.cfg. + * @param flags MAPLIST_FLAG flags. + * @return On failure: + * INVALID_HANDLE is returned, the serial is set to -1, and the input + * array (if any) is left unchanged. + * On no change: + INVALID_HANDLE is returned, the serial is unchanged, and the input + array (if any) is left unchanged. + * On success: + * A valid array Handle is returned, containing at least one map string. + * If an array was passed, the return value is equal to the passed Array + * Handle. If the passed array was not cleared, it will have grown by at + * least one item. The serial number is updated to a positive number. + * @error Invalid array Handle that is not INVALID_HANDLE. + */ +native Handle:ReadMapList(Handle:array=INVALID_HANDLE, + &serial=-1, + const String:str[]="default", + flags=MAPLIST_FLAG_CLEARARRAY); + +/** + * Makes a compatibility binding for map lists. For example, if a function previously used + * "clam.cfg" for map lists, this function will insert a "fake" binding to "clam.cfg" that + * will be overridden if it's in the maplists.cfg file. + * + * @param name Configuration name that would be used with ReadMapList(). + * @param file Default file to use. + * @noreturn + */ +native SetMapListCompatBind(const String:name[], const String:file[]); + +/** + * Called when a client has sent chat text. This must return either true or + * false to indicate that a client is or is not spamming the server. + * + * The return value is a hint only. Core or another plugin may decide + * otherwise. + * + * @param client Client index. The server (0) will never be passed. + * @return True if client is spamming the server, false otherwise. + */ +forward bool:OnClientFloodCheck(client); + +/** + * Called after a client's flood check has been computed. This can be used + * by antiflood algorithms to decay/increase flooding weights. + * + * Since the result from "OnClientFloodCheck" isn't guaranteed to be the + * final result, it is generally a good idea to use this to play with other + * algorithms nicely. + * + * @param client Client index. The server (0) will never be passed. + * @param blocked True if client flooded last "say", false otherwise. + * @noreturn + */ +forward OnClientFloodResult(client, bool:blocked); + +/** + * Feature types. + */ +enum FeatureType +{ + /** + * A native function call. + */ + FeatureType_Native, + + /** + * A named capability. This is distinctly different from checking for a + * native, because the underlying functionality could be enabled on-demand + * to improve loading time. Thus a native may appear to exist, but it might + * be part of a set of features that are not compatible with the current game + * or version of SourceMod. + */ + FeatureType_Capability +}; + +/** + * Feature statuses. + */ +enum FeatureStatus +{ + /** + * Feature is available for use. + */ + FeatureStatus_Available, + + /** + * Feature is not available. + */ + FeatureStatus_Unavailable, + + /** + * Feature is not known at all. + */ + FeatureStatus_Unknown +}; + +/** + * Returns whether "GetFeatureStatus" will work. Using this native + * or this function will not cause SourceMod to fail loading on older versions, + * however, GetFeatureStatus will only work if this function returns true. + * + * @return True if GetFeatureStatus will work, false otherwise. + */ +stock bool:CanTestFeatures() +{ + return LibraryExists("__CanTestFeatures__"); +} + +/** + * Returns whether a feature exists, and if so, whether it is usable. + * + * @param type Feature type. + * @param name Feature name. + * @return Feature status. + */ +native FeatureStatus:GetFeatureStatus(FeatureType:type, const String:name[]); + +/** + * Requires that a given feature is available. If it is not, SetFailState() + * is called with the given message. + * + * @param type Feature type. + * @param name Feature name. + * @param fmt Message format string, or empty to use default. + * @param ... Message format parameters, if any. + * @noreturn + */ +native RequireFeature(FeatureType:type, const String:name[], + const String:fmt[]="", any:...); + +#include +#include +#include + diff --git a/env/include/string.inc b/env/include/string.inc new file mode 100644 index 0000000..6369c8a --- /dev/null +++ b/env/include/string.inc @@ -0,0 +1,559 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _string_included + #endinput +#endif +#define _string_included + +/** + * @global Unless otherwise noted, all string functions which take in a + * writable buffer and maximum length should have the null terminator INCLUDED + * in the length. This means that this is valid: + * strcopy(string, sizeof(string), ...) + */ + +/** + * Calculates the length of a string. + * + * @param str String to check. + * @return Number of valid character bytes in the string. + */ +native strlen(const String:str[]); + +/** + * Tests whether a string is found inside another string. + * + * @param str String to search in. + * @param substr Substring to find inside the original string. + * @param caseSensitive If true (default), search is case sensitive. + * If false, search is case insensitive. + * @return -1 on failure (no match found). Any other value + * indicates a position in the string where the match starts. + */ +native StrContains(const String:str[], const String:substr[], bool:caseSensitive=true); + +/** + * Compares two strings lexographically. + * + * @param str1 First string (left). + * @param str2 Second string (right). + * @param caseSensitive If true (default), comparison is case sensitive. + * If false, comparison is case insensitive. + * @return -1 if str1 < str2 + * 0 if str1 == str2 + * 1 if str1 > str2 + */ +native strcmp(const String:str1[], const String:str2[], bool:caseSensitive=true); + +/** + * Compares two strings parts lexographically. + * + * @param str1 First string (left). + * @param str2 Second string (right). + * @param num Number of characters to compare. + * @param caseSensitive If true (default), comparison is case sensitive. + * If false, comparison is case insensitive. + * @return -1 if str1 < str2 + * 0 if str1 == str2 + * 1 if str1 > str2 + */ +native strncmp(const String:str1[], const String:str2[], num, bool:caseSensitive=true); + +/** + * Backwards compatible stock - StrCompare is now strcmp + * @deprecated Renamed to strcmp + */ +#pragma deprecated Use strcmp() instead +stock StrCompare(const String:str1[], const String:str2[], bool:caseSensitive=true) +{ + return strcmp(str1, str2, caseSensitive); +} + +/** + * Returns whether two strings are equal. + * + * @param str1 First string (left). + * @param str2 Second string (right). + * @param caseSensitive If true (default), comparison is case sensitive. + * If false, comparison is case insensitive. + * @return True if equal, false otherwise. + */ +stock bool:StrEqual(const String:str1[], const String:str2[], bool:caseSensitive=true) +{ + return (strcmp(str1, str2, caseSensitive) == 0); +} + +/** + * Copies one string to another string. + * @note If the destination buffer is too small to hold the source string, the + * destination will be truncated. + * + * @param dest Destination string buffer to copy to. + * @param destlen Destination buffer length (includes null terminator). + * @param source Source string buffer to copy from. + * @return Number of cells written. + */ +native strcopy(String:dest[], destLen, const String:source[]); + +/** + * Backwards compatibility stock - use strcopy + * @deprecated Renamed to strcopy + */ +#pragma deprecated Use strcopy() instead +stock StrCopy(String:dest[], destLen, const String:source[]) +{ + return strcopy(dest, destLen, source); +} + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return Number of cells written. + */ +native Format(String:buffer[], maxlength, const String:format[], any:...); + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * @note This is the same as Format(), except none of the input buffers can + * overlap the same memory as the output buffer. Since this security + * check is removed, it is slightly faster. + * + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return Number of cells written. + */ +native FormatEx(String:buffer[], maxlength, const String:format[], any:...); + +/** + * Formats a string according to the SourceMod format rules (see documentation). + * @note This is the same as Format(), except it grabs parameters from a + * parent parameter stack, rather than a local. This is useful for + * implementing your own variable argument functions. + * + * @param buffer Destination string buffer. + * @param maxlength Maximum length of output string buffer. + * @param format Formatting rules. + * @param varpos Argument number which contains the '...' symbol. + * Note: Arguments start at 1. + * @return Number of bytes written. + */ +native VFormat(String:buffer[], maxlength, const String:format[], varpos); + +/** + * Converts a string to an integer. + * + * @param str String to convert. + * @param nBase Numerical base to use. 10 is default. + * @return Integer conversion of string, or 0 on failure. + */ +native StringToInt(const String:str[], nBase=10); + +/** + * Converts a string to an integer with some more options. + * + * @param str String to convert. + * @param result Variable to store the result in. + * @param nBase Numerical base to use. 10 is default. + * @return Number of characters consumed. + */ +native StringToIntEx(const String:str[], &result, nBase=10); + +/** + * Converts an integer to a string. + * + * @param num Integer to convert. + * @param str Buffer to store string in. + * @param maxlength Maximum length of string buffer. + * @return Number of cells written to buffer. + */ +native IntToString(num, String:str[], maxlength); + +/** + * Converts a string to a floating point number. + * + * @param str String to convert to a foat. + * @return Floating point result, or 0.0 on error. + */ +native Float:StringToFloat(const String:str[]); + +/** + * Converts a string to a floating point number with some more options. + * + * @param str String to convert to a foat. + * @param result Variable to store result in. + * @return Number of characters consumed. + */ +native StringToFloatEx(const String:str[], &Float:result); + +/** + * Converts a floating point number to a string. + * + * @param num Floating point number to convert. + * @param str Buffer to store string in. + * @param maxlength Maximum length of string buffer. + * @return Number of cells written to buffer. + */ +native FloatToString(Float:num, String:str[], maxlength); + +/** + * Finds the first "argument" in a string; either a set of space + * terminated characters, or a fully quoted string. After the + * argument is found, whitespace is read until the next portion + * of the string is reached. If nothing remains, -1 is returned. + * Otherwise, the index to the first character is returned. + * + * @param source Source input string. + * @param arg Stores argument read from string. + * @param argLen Maximum length of argument buffer. + * @return Index to next piece of string, or -1 if none. + */ +native BreakString(const String:source[], String:arg[], argLen); + +/** + * Backwards compatibility stock - use BreakString + * @deprecated Renamed to BreakString. + */ +#pragma deprecated Use BreakString() instead +stock StrBreak(const String:source[], String:arg[], argLen) +{ + return BreakString(source, arg, argLen); +} + +/** + * Removes whitespace characters from the beginning and end of a string. + * + * @param str The string to trim. + * @return Number of bytes written (UTF-8 safe). + */ +native TrimString(String:str[]); + +/** + * Returns text in a string up until a certain character sequence is reached. + * + * @param source Source input string. + * @param split A string which specifies a search point to break at. + * @param part Buffer to store string part. + * @param partLen Maximum length of the string part buffer. + * @return -1 if no match was found; otherwise, an index into source + * marking the first index after the searched text. The + * index is always relative to the start of the input string. + */ +native SplitString(const String:source[], const String:split[], String:part[], partLen); + +/** + * Given a string, replaces all occurrences of a search string with a + * replacement string. + * + * @param text String to perform search and replacements on. + * @param maxlength Maximum length of the string buffer. + * @param search String to search for. + * @param replace String to replace the search string with. + * @param caseSensitive If true (default), search is case sensitive. + * @return Number of replacements that were performed. + */ +native ReplaceString(String:text[], maxlength, const String:search[], const String:replace[], bool:caseSensitive=true); + +/** + * Given a string, replaces the first occurrence of a search string with a + * replacement string. + * + * @param text String to perform search and replacements on. + * @param maxlength Maximum length of the string buffer. + * @param search String to search for. + * @param replace String to replace the search string with. + * @param searchLen If higher than -1, its value will be used instead of + * a strlen() call on the search parameter. + * @param replaceLen If higher than -1, its value will be used instead of + * a strlen() call on the replace parameter. + * @param caseSensitive If true (default), search is case sensitive. + * @return Index into the buffer (relative to the start) from where + * the last replacement ended, or -1 if no replacements were + * made. + */ +native ReplaceStringEx(String:text[], maxlength, const String:search[], const String:replace[], searchLen=-1, replaceLen=-1, bool:caseSensitive=true); + +/** + * Returns the number of bytes a character is using. This is + * for multi-byte characters (UTF-8). For normal ASCII characters, + * this will return 1. + * + * @param source Source input string. + * @return Number of bytes the current character uses. + */ +native GetCharBytes(const String:source[]); + +/** + * Returns whether a character is an ASCII alphabet character. + * + * @note Multi-byte characters will always return false. + * + * @param char Character to test. + * @return True if character is alphabetical, otherwise false. + */ +native bool:IsCharAlpha(chr); + +/** + * Returns whether a character is numeric. + * + * @note Multi-byte characters will always return false. + * + * @param char Character to test. + * @return True if character is numeric, otherwise false. + */ +native bool:IsCharNumeric(chr); + +/** + * Returns whether a character is whitespace. + * + * @note Multi-byte characters will always return false. + * + * @param char Character to test. + * @return True if character is whitespace, otherwise false. + */ +native bool:IsCharSpace(chr); + +/** + * Returns if a character is multi-byte or not. + * + * @param char Character to test. + * @return 0 for a normal 7-bit ASCII character, + * otherwise number of bytes in multi-byte character. + */ +native IsCharMB(chr); + +/** + * Returns whether an alphabetic character is uppercase. + * + * @note Multi-byte characters will always return false. + * + * @param char Character to test. + * @return True if character is uppercase, otherwise false. + */ +native bool:IsCharUpper(chr); + +/** + * Returns whether an alphabetic character is lowercase. + * + * @note Multi-byte characters will always return false. + * + * @param char Character to test. + * @return True if character is lowercase, otherwise false. + */ +native bool:IsCharLower(chr); + +/** + * Strips a quote pair off a string if it exists. That is, the following + * replace rule is applied once: $"(.*)"^ -> $\1^ + * + * Note that the leading and trailing quotes will only be removed if both + * exist. Otherwise, the string is left unmodified. This function should + * be considered O(k) (all characters get shifted down). + * + * @param text String to modify (in place). + * @return True if string was modified, false if there was no + * set of quotes. + */ +native bool:StripQuotes(String:text[]); + +/** + * Returns an uppercase character to a lowercase character. + * + * @param chr Characer to convert. + * @return Lowercase character on success, + * no change on failure. + */ +stock CharToUpper(chr) +{ + if (IsCharLower(chr)) + { + return (chr & ~(1<<5)); + } + return chr; +} + +/** + * Returns a lowercase character to an uppercase character. + * + * @param chr Characer to convert. + * @return Uppercase character on success, + * no change on failure. + */ +stock CharToLower(chr) +{ + if (IsCharUpper(chr)) + { + return (chr | (1<<5)); + } + return chr; +} + +/** + * Finds the first occurrence of a character in a string. + * + * @param str String. + * @param c Character to search for. + * @param reverse False (default) to search forward, true to search + * backward. + * @return The index of the first occurrence of the character + * in the string, or -1 if the character was not found. + */ +stock FindCharInString(const String:str[], c, bool:reverse = false) +{ + new i, len + + len = strlen(str); + + if (!reverse) + { + for (i = 0; i < len; i++) + { + if (str[i] == c) + { + return i; + } + } + } + else + { + for (i = len - 1; i >= 0; i--) + { + if (str[i] == c) + { + return i; + } + } + } + + return -1; +} + +/** + * Concatenates one string onto another. + * + * @param buffer String to append to. + * @param maxlength Maximum length of entire buffer. + * @param source Source string to concatenate. + * @return Number of bytes written. + */ +stock StrCat(String:buffer[], maxlength, const String:source[]) +{ + new len = strlen(buffer); + if (len >= maxlength) + { + return 0; + } + + return Format(buffer[len], maxlength-len, "%s", source); +} + +/** + * Breaks a string into pieces and stores each piece into an array of buffers. + * + * @param text The string to split. + * @param split The string to use as a split delimiter. + * @param buffers An array of string buffers (2D array). + * @param maxStrings Number of string buffers (first dimension size). + * @param maxStringLength Maximum length of each string buffer. + * @return Number of strings retrieved. + */ +stock ExplodeString(const String:text[], const String:split[], String:buffers[][], maxStrings, maxStringLength) +{ + new reloc_idx, idx, total; + + if (maxStrings < 1 || split[0] == '\0') + { + return 0; + } + + while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1) + { + reloc_idx += idx; + if (text[reloc_idx] == '\0') + { + break; + } + if (++total >= maxStrings) + { + return total; + } + } + + if (text[reloc_idx] != '\0' && total <= maxStrings - 1) + { + strcopy(buffers[total++], maxStringLength, text[reloc_idx]); + } + + return total; +} + +/** + * Joins an array of strings into one string, with a "join" string inserted in + * between each given string. This function complements ExplodeString. + * + * @param strings An array of strings. + * @param numStrings Number of strings in the array. + * @param join The join string to insert between each string. + * @param buffer Output buffer to write the joined string to. + * @param maxLength Maximum length of the output buffer. + * @return Number of bytes written to the output buffer. + */ +stock ImplodeStrings(const String:strings[][], numStrings, const String:join[], String:buffer[], maxLength) +{ + new total, length, part_length; + new join_length = strlen(join); + for (new i=0; i. + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _textparse_included + #endinput +#endif +#define _textparse_included + + +/******************************** + * Everything below describes the SMC Parse, or "SourceMod Configuration" format. + * This parser is entirely event based. You must hook events to receive data. + * The file format itself is nearly identical to Valve's KeyValues format. + ********************************/ + +/** + * Parse result directive. + */ +enum SMCResult +{ + SMCParse_Continue, /**< Continue parsing */ + SMCParse_Halt, /**< Stop parsing here */ + SMCParse_HaltFail /**< Stop parsing and return failure */ +}; + +/** + * Parse error codes. + */ +enum SMCError +{ + SMCError_Okay = 0, /**< No error */ + SMCError_StreamOpen, /**< Stream failed to open */ + SMCError_StreamError, /**< The stream died... somehow */ + SMCError_Custom, /**< A custom handler threw an error */ + SMCError_InvalidSection1, /**< A section was declared without quotes, and had extra tokens */ + SMCError_InvalidSection2, /**< A section was declared without any header */ + SMCError_InvalidSection3, /**< A section ending was declared with too many unknown tokens */ + SMCError_InvalidSection4, /**< A section ending has no matching beginning */ + SMCError_InvalidSection5, /**< A section beginning has no matching ending */ + SMCError_InvalidTokens, /**< There were too many unidentifiable strings on one line */ + SMCError_TokenOverflow, /**< The token buffer overflowed */ + SMCError_InvalidProperty1, /**< A property was declared outside of any section */ +}; + +/** + * Creates a new SMC file format parser. This is used to set parse hooks. + * + * @return A new Handle to an SMC Parse structure. + */ +native Handle:SMC_CreateParser(); + +/** + * Parses an SMC file. + * + * @param smc A Handle to an SMC Parse structure. + * @param file A string containing the file path. + * @param line An optional by reference cell to store the last line number read. + * @param col An optional by reference cell to store the last column number read. + * @return An SMCParseError result. + * @error Invalid or corrupt Handle. + */ +native SMCError:SMC_ParseFile(Handle:smc, const String:file[], &line=0, &col=0); + +/** + * Gets an error string for an SMCError code. + * @note SMCError_Okay returns false. + * @note SMCError_Custom (which is thrown on SMCParse_HaltFail) returns false. + * + * @param error The SMCParseError code. + * @param buffer A string buffer for the error (contents undefined on failure). + * @param buf_max The maximum size of the buffer. + * @return True on success, false otherwise. + */ +native bool:SMC_GetErrorString(SMCError:error, String:buffer[], buf_max); + +/** + * Called when parsing is started. + * + * @param smc The SMC Parse Handle. + * @noreturn + */ +functag public SMC_ParseStart(Handle:smc); + +/** + * Sets the SMC_ParseStart function of a parse Handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_ParseStart function. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SMC_SetParseStart(Handle:smc, SMC_ParseStart:func); + +/** + * Called when parsing is halted. + * + * @param smc The SMC Parse Handle. + * @param halted True if abnormally halted, false otherwise. + * @param failed True if parsing failed, false otherwise. + * @noreturn + */ +functag public SMC_ParseEnd(Handle:smc, bool:halted, bool:failed); + +/** + * Sets the SMC_ParseEnd of a parse handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_ParseEnd function. + * @noreturn + * @error Invalid or corrupt Handle. + */ +native SMC_SetParseEnd(Handle:smc, SMC_ParseEnd:func); + +/** + * Called when the parser is entering a new section or sub-section. + * @note Enclosing quotes are always stripped. + * + * @param smc The SMC Parse Handle. + * @param name String containing section name. + * @param opt_quotes True if the section name was quote-enclosed in the file. + * @return An SMCResult action to take. + */ +functag public SMCResult:SMC_NewSection(Handle:smc, const String:name[], bool:opt_quotes); + +/** + * Called when the parser finds a new key/value pair. + * @note Enclosing quotes are always stripped. + * + * @param smc The SMC Parse Handle. + * @param key String containing key name. + * @param value String containing value name. + * @param key_quotes Whether or not the key was enclosed in quotes. + * @param value_quotes Whether or not the value was enclosed in quotes. + * @return An SMCResult action to take. + */ +functag public SMCResult:SMC_KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes); + +/** + * Called when the parser finds the end of the current section. + * + * @param smc The SMC Parse Handle. + * @return An SMCResult action to take. + */ +functag public SMCResult:SMC_EndSection(Handle:smc); + +/** + * Sets the three main reader functions. + * + * @param smc An SMC parse Handle. + * @param ns An SMC_NewSection function pointer. + * @param kv An SMC_KeyValue function pointer. + * @param es An SMC_EndSection function pointer. + * @noreturn + */ +native SMC_SetReaders(Handle:smc, SMC_NewSection:ns, SMC_KeyValue:kv, SMC_EndSection:es); + +/** + * Called whenever a raw line is read. + * + * @param smc The SMC Parse Handle. + * @param line A string containing the raw line from the file. + * @param lineno The line number it occurs on. + * @return An SMCResult action to take. + */ +functag public SMCResult:SMC_RawLine(Handle:smc, const String:line[], lineno); + +/** + * Sets a raw line reader on an SMC parser Handle. + * + * @param smc Handle to an SMC Parse. + * @param func SMC_RawLine function. + * @noreturn + */ +native SMC_SetRawLine(Handle:smc, SMC_RawLine:func); diff --git a/env/include/tf2.inc b/env/include/tf2.inc new file mode 100644 index 0000000..34007a6 --- /dev/null +++ b/env/include/tf2.inc @@ -0,0 +1,145 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _tf2_included + #endinput +#endif +#define _tf2_included + +enum TFClassType +{ + TFClass_Unknown = 0, + TFClass_Scout, + TFClass_Sniper, + TFClass_Soldier, + TFClass_DemoMan, + TFClass_Medic, + TFClass_Heavy, + TFClass_Pyro, + TFClass_Spy, + TFClass_Engineer +}; + +enum TFTeam +{ + TFTeam_Unassigned = 0, + TFTeam_Spectator = 1, + TFTeam_Red = 2, + TFTeam_Blue = 3 +}; + +/** + * Sets a client on fire for 10 seconds. + * + * @param client Player's index. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native TF2_IgnitePlayer(client, target); + +/** + * Respawns a client + * + * @param client Player's index. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native TF2_RespawnPlayer(client); + +/** + * Disguises a client to the given model and team. Only has an effect on spies. + * + * Note: This only starts the disguise process and a delay occurs before the spy is fully disguised + * + * @param client Player's index. + * @param team Team to disguise the player as (only TFTeam_Red and TFTeam_Blue have an effect) + * @param class TFClassType class to disguise the player as + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native TF2_DisguisePlayer(client, TFTeam:team, TFClassType:class); + +/** + * Removes the current disguise from a client. Only has an effect on spies. + * + * @param client Player's index. + * @noreturn + * @error Invalid client index, client not in game, or no mod support. + */ +native TF2_RemovePlayerDisguise(client); + +/** + * Retrieves the entity index of the CPlayerResource entity + * + * @return The current resource entity index. + */ +native TF2_GetResourceEntity(); + +/** + * Finds the TFClassType for a given class name. + * + * @param classname A classname string such as "sniper" or "demoman" + * @return A TFClassType constant. + */ +native TFClassType:TF2_GetClass(const String:classname[]); + +/** + * Called on weapon fire to decide if the current shot should be critical. + * Return Plugin_Continue to let the original calculation or return a higher + * action to override the decision with the value of 'result' + * + * @note Since critical shots are also calculated client side any changes made with + * this will not show for the shooter. Projectile weapons such as the rocketlauncher + * and demoman weapons will show a critical bullet but no critical sound effect. + * Bullet hits should appear as expected. + * + * @param client Client Index. + * @param weapon Weapon entity Index. + * @param weaponname Classname of the weapon. + * @param result Buffer param for the result of the decision. + */ +forward Action:TF2_CalcIsAttackCritical(client, weapon, String:weaponname[], &bool:result); + +/** + * Do not edit below this line! + */ +public Extension:__ext_tf2 = +{ + name = "TF2 Tools", + file = "game.tf2.ext", + autoload = 1, +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; diff --git a/env/include/tf2_stocks.inc b/env/include/tf2_stocks.inc new file mode 100644 index 0000000..a7c63ca --- /dev/null +++ b/env/include/tf2_stocks.inc @@ -0,0 +1,219 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _tf2_stocks_included + #endinput +#endif +#define _tf2_stocks_included + +#include +#include + +enum TFResourceType +{ + TFResource_Ping, + TFResource_Score, + TFResource_Deaths, + TFResource_TotalScore, + TFResource_Captures, + TFResource_Defenses, + TFResource_Dominations, + TFResource_Revenge, + TFResource_BuildingsDestroyed, + TFResource_Headshots, + TFResource_Backstabs, + TFResource_HealPoints, + TFResource_Invulns, + TFResource_Teleports, + TFResource_ResupplyPoints, + TFResource_KillAssists, + TFResource_MaxHealth, + TFResource_PlayerClass +}; + +static const String:TFResourceNames[TFResourceType][] = +{ + "m_iPing", + "m_iScore", + "m_iDeaths", + "m_iTotalScore", + "m_iCaptures", + "m_iDefenses", + "m_iDominations", + "m_iRevenge", + "m_iBuildingsDestroyed", + "m_iHeadshots", + "m_iBackstabs", + "m_iHealPoints", + "m_iInvulns", + "m_iTeleports", + "m_iResupplyPoints", + "m_iKillAssists", + "m_iMaxHealth", + "m_iPlayerClass" +}; + +/** + * Get's a Clients current class. + * + * @param client Player's index. + * @return Current TFClassType of player. + * @error Invalid client index. + */ +stock TFClassType:TF2_GetPlayerClass(client) +{ + return TFClassType:GetEntProp(client, Prop_Send, "m_iClass"); +} + +/** + * Set's a Clients class. + * + * Note: If setting player class in a player spawn hook weapons should be set to false. + * + * @param client Player's index. + * @param class TFClassType class symbol. + * @param weapons This paramater is ignored. + * @param persistant If true changes the players desired class so the change stays after death. + * @noreturn + * @error Invalid client index. + */ +stock TF2_SetPlayerClass(client, TFClassType:class, bool:weapons=true, bool:persistant=true) +{ + SetEntProp(client, Prop_Send, "m_iClass", _:class); + + if (persistant) + { + SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", _:class); + } +} + +/** + * Retrieves client data from the resource entity + * + * @param client Player's index. + * @param type ResourceType constant + * @return Value or -1 on failure. + * @error Invalid client index, client not in game or failed to find resource entity. + */ +stock TF2_GetPlayerResourceData(client, TFResourceType:type) +{ + if (!IsClientConnected(client)) + { + return -1; + } + + new offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]); + + if (offset < 1) + { + return -1; + } + + new entity = TF2_GetResourceEntity(); + + if (entity == -1) + { + return -1; + } + + return GetEntData(entity, offset + (client*4)); +} + +/** + * Sets client data in the resource entity + * + * Note: The game overwrites these values every frame, so changing them will have very little effect. + * + * @param client Player's index. + * @param type ResourceType constant + * @param value Value to set. + * @return Value or -1 on failure. + * @error Invalid client index, client not in game or failed to find resource entity. + */ +stock bool:TF2_SetPlayerResourceData(client, TFResourceType:type, any:value) +{ + if (!IsClientConnected(client)) + { + return false; + } + + new offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]); + + if (offset < 1) + { + return false; + } + + new entity = TF2_GetResourceEntity(); + + if (entity == -1) + { + return false; + } + + SetEntData(entity, offset + (client*4), value); + + return true; +} + +/** + * Removes all weapons from a client's weapon slot + * + * @param client Player's index. + * @param slot Slot index (0-5) + * @noreturn + * @error Invalid client, invalid slot or lack of mod support + */ +stock TF2_RemoveWeaponSlot(client, slot) +{ + new weaponIndex; + while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1) + { + RemovePlayerItem(client, weaponIndex); + RemoveEdict(weaponIndex); + } +} + +/** + * Removes all weapons from a client + * + * @param client Player's index. + * @noreturn + */ +stock TF2_RemoveAllWeapons(client) +{ + for (new i = 0; i <= 5; i++) + { + TF2_RemoveWeaponSlot(client, i); + } +} + diff --git a/env/include/timers.inc b/env/include/timers.inc new file mode 100644 index 0000000..07e801e --- /dev/null +++ b/env/include/timers.inc @@ -0,0 +1,210 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _timers_included + #endinput +#endif +#define _timers_included + +#include + +#define TIMER_REPEAT (1<<0) /**< Timer will repeat until it returns Plugin_Stop */ +#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */ +#define TIMER_HNDL_CLOSE (1<<9) /**< Deprecated define, replaced by below */ +#define TIMER_DATA_HNDL_CLOSE (1<<9) /**< Timer will automatically call CloseHandle() on its data when finished */ + +/** + * Any of the following prototypes will work for a timed function. + */ +funcenum Timer +{ + /** + * Called when the timer interval has elapsed. + * + * @param timer Handle to the timer object. + * @param hndl Handle passed to CreateTimer() when timer was created. + * @return Plugin_Stop to stop a repeating timer, any other value for + * default behavior. + */ + Action:public(Handle:timer, Handle:hndl), + + /** + * Called when the timer interval has elapsed. + * + * @param timer Handle to the timer object. + * @param data Data passed to CreateTimer() when timer was created. + * @return Plugin_Stop to stop a repeating timer, any other value for + * default behavior. + */ + Action:public(Handle:timer, any:data), + + /** + * Called when the timer interval has elapsed. + * + * @param timer Handle to the timer object. + * @return Plugin_Stop to stop a repeating timer, any other value for + * default behavior. + */ + Action:public(Handle:timer), +}; + +/** + * Creates a basic timer. Calling CloseHandle() on a timer will end the timer. + * + * @param interval Interval from the current game time to execute the given function. + * @param func Function to execute once the given interval has elapsed. + * @param data Handle or value to pass through to the timer callback function. + * @param flags Flags to set (such as repeatability or auto-Handle closing). + * @return Handle to the timer object. You do not need to call CloseHandle(). + * If the timer could not be created, INVALID_HANDLE will be returned. + */ +native Handle:CreateTimer(Float:interval, Timer:func, any:data=INVALID_HANDLE, flags=0); + +/** + * Kills a timer. Use this instead of CloseHandle() if you need more options. + * + * @param autoClose If autoClose is true, the data that was passed to CreateTimer() will + * be closed as a handle if TIMER_DATA_HNDL_CLOSE was not specified. + * @noreturn + */ +native KillTimer(Handle:timer, bool:autoClose=false); + +/** + * Manually triggers a timer so its function will be called. + * + * @param timer Timer Handle to trigger. + * @param reset If reset is true, the elapsed time counter is reset + * so the full interval must pass again. + * @noreturn + */ +native TriggerTimer(Handle:timer, bool:reset=false); + +/** + * Returns the simulated game time. + * + * This time is internally maintained by SourceMod and is based on the game + * tick count and tick rate. Unlike GetGameTime(), it will increment past + * map changes and while no players are connected. Unlike GetEngineTime(), + * it will not increment based on the system clock (i.e. it is still bound + * to the ticking process). + * + * @return Time based on the game tick count. + */ +native Float:GetTickedTime(); + +/** + * Returns an estimate of the time left before the map ends. If the server + * has not processed any frames yet (i.e. no players have joined the map yet), + * then the time left returned will always be infinite. + * + * @param timeleft Variable to store the time, in seconds. If the + * value is less than 0, the time limit is infinite. + * @return True if the operation is supported, false otherwise. + */ +native bool:GetMapTimeLeft(&timeleft); + +/** + * Retrieves the current map time limit. If the server has not processed any + * frames yet (i.e. no players have joined the map yet), then the time limit + * returned will always be 0. + * + * @param time Set to the number of total seconds in the map time + * limit, or 0 if there is no time limit set. + * @return True on success, false if operation is not supported. + */ +native bool:GetMapTimeLimit(&time); + +/** + * Extends the map time limit in a way that will notify all plugins. + * + * @param time Number of seconds to extend map time limit by. + * The number can be negative to decrease the time limit. + * If 0, the map will be set to have no time limit. + * @return True on success, false if operation is not supported. + */ +native bool:ExtendMapTimeLimit(time); + +/** + * Returns the number of seconds in between game server ticks. + * + * Note: A tick, in this context, is a frame. + * + * @return Number of seconds in between ticks. + */ +native Float:GetTickInterval(); + +/** + * Notification that the map's time left has changed via a change in the time + * limit or a change in the game rules (such as mp_restartgame). This is useful + * for plugins trying to create timers based on the time left in the map. + * + * Calling ExtendMapTimeLimit() from here, without proper precaution, will + * cause infinite recursion. + * + * If the operation is not supported, this will never be called. + + * If the server has not yet processed any frames (i.e. no players have joined + * the map yet), then this will be called once the server begins ticking, even + * if there is no time limit set. + */ +forward OnMapTimeLeftChanged(); + +/** + * Returns whether or not the server is processing frames or not. + * + * The server does not process frames until at least one client joins the game. + * Once the first player has in, even if that player, leaves, the server's + * timers and entities will work. + * + * @return True if the server is ticking, false otherwise. + */ +native bool:IsServerProcessing(); + +/** + * Creates a timer associated with a new datapack, and returns the datapack. + * @note The datapack is automatically freed when the timer ends. + * @note The position of the datapack is not reset or changed for the timer function. + * + * @param interval Interval from the current game time to execute the given function. + * @param func Function to execute once the given interval has elapsed. + * @param datapack The newly created datapack is passed though this by-reference + * parameter to the timer callback function. + * @param flags Timer flags. + * @return Handle to the timer object. You do not need to call CloseHandle(). + */ +stock Handle:CreateDataTimer(Float:interval, Timer:func, &Handle:datapack, flags=0) +{ + datapack = CreateDataPack(); + flags |= TIMER_DATA_HNDL_CLOSE; + return CreateTimer(interval, func, datapack, flags); +} + diff --git a/env/include/topmenus.inc b/env/include/topmenus.inc new file mode 100644 index 0000000..b6fcca2 --- /dev/null +++ b/env/include/topmenus.inc @@ -0,0 +1,290 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _topmenus_included + #endinput +#endif +#define _topmenus_included + +#include + +/** + * 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 public TopMenuHandler(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 diff --git a/env/include/usermessages.inc b/env/include/usermessages.inc new file mode 100644 index 0000000..b960de3 --- /dev/null +++ b/env/include/usermessages.inc @@ -0,0 +1,202 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _eventsmsgs_included + #endinput +#endif +#define _eventsmsgs_included + +/** + * UserMsg helper values. + */ +enum UserMsg +{ + INVALID_MESSAGE_ID = -1, +}; + +/** + * @section Message Flags. + */ +#define USERMSG_RELIABLE (1<<2) /**< Message will be set on the reliable stream */ +#define USERMSG_INITMSG (1<<3) /**< Message will be considered to be an initmsg */ +#define USERMSG_BLOCKHOOKS (1<<7) /**< Prevents the message from triggering SourceMod and Metamod hooks */ + +/** + * @endsection + */ + +/** + * Returns the ID of a given message, or -1 on failure. + * + * @param msg String containing message name (case sensitive). + * @return A message index, or INVALID_MESSAGE_ID on failure. + */ +native UserMsg:GetUserMessageId(const String:msg[]); + +/** + * Retrieves the name of a message by ID. + * + * @param msg_id Message index. + * @param msg Buffer to store the name of the message. + * @param maxlength Maximum length of string buffer. + * @return True if message index is valid, false otherwise. + */ +native bool:GetUserMessageName(UserMsg:msg_id, String:msg[], maxlength); + +/** + * Starts a usermessage (network message). + * @note Only one message can be active at a time. + * @note It is illegal to send any message while a non-intercept hook is in progress. + * + * @param msgname Message name to start. + * @param clients Array containing player indexes to broadcast to. + * @param numClients Number of players in the array. + * @param flags Optional flags to set. + * @return A handle to a bf_write bit packing structure, or + * INVALID_HANDLE on failure. + * @error Invalid message name, unable to start a message, invalid client, + * or client not connected. + */ +native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0); + +/** + * Starts a usermessage (network message). + * @note Only one message can be active at a time. + * @note It is illegal to send any message while a non-intercept hook is in progress. + * + * @param msg Message index to start. + * @param clients Array containing player indexes to broadcast to. + * @param numClients Number of players in the array. + * @param flags Optional flags to set. + * @return A handle to a bf_write bit packing structure, or + * INVALID_HANDLE on failure. + * @error Invalid message name, unable to start a message, invalid client, + * or client not connected. + */ +native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags=0); + +/** + * Ends a previously started user message (network message). + * + * @noreturn + */ +native EndMessage(); + +/** + * Called when a message is hooked + * + * @param msg_id Message index. + * @param bf Handle to the input bit buffer of the message. + * @param players Array containing player indexes. + * @param playersNum Number of players in the array. + * @param reliable True if message is reliable, false otherwise. + * @param init True if message is an initmsg, false otherwise. + * @return Ignored for normal hooks. For intercept hooks, Plugin_Handled + * blocks the message from being sent, and Plugin_Continue + * resumes normal functionality. + */ +functag public Action:MsgHook(UserMsg:msg_id, Handle:bf, const players[], playersNum, bool:reliable, bool:init); + +/** + * Called when a message hook has completed. + * + * @param msg_id Message index. + * @param sent True if message was sent, false if blocked. + */ +functag public MsgPostHook(UserMsg:msg_id, bool:sent); + +/** + * Hooks a user message. + * + * @param msg_id Message index. + * @param hook Function to use as a hook. + * @param intercept If intercept is true, message will be fully intercepted, + * allowing the user to block the message. Otherwise, + * the hook is normal and ignores the return value. + * @param notify Notification function. + * @noreturn + * @error Invalid message index. + */ +native HookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false, MsgPostHook:post=MsgPostHook:-1); + +/** + * Removes one usermessage hook. + * + * @param msg_id Message index. + * @param hook Function used for the hook. + * @param intercept Specifies whether the hook was an intercept hook or not. + * @noreturn + * @error Invalid message index. + */ +native UnhookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false); + +/** + * Starts a usermessage (network message) that broadcasts to all clients. + * @note See StartMessage or StartMessageEx(). + * + * @param msgname Message name to start. + * @param flags Optional flags to set. + * @return A handle to a bf_write bit packing structure, or + * INVALID_HANDLE on failure. + */ +stock Handle:StartMessageAll(String:msgname[], flags=0) +{ + new total = 0; + new clients[MaxClients]; + for (new i=1; i<=MaxClients; i++) + { + if (IsClientConnected(i)) + { + clients[total++] = i; + } + } + return StartMessage(msgname, clients, total, flags); +} + +/** + * Starts a simpler usermessage (network message) for one client. + * @note See StartMessage or StartMessageEx(). + * + * @param msgname Message name to start. + * @param client Client to send to. + * @param flags Optional flags to set. + * @return A handle to a bf_write bit packing structure, or + * INVALID_HANDLE on failure. + */ +stock Handle:StartMessageOne(String:msgname[], client, flags=0) +{ + new players[1]; + + players[0] = client; + + return StartMessage(msgname, players, 1, flags); +} diff --git a/env/include/vector.inc b/env/include/vector.inc new file mode 100644 index 0000000..78ad093 --- /dev/null +++ b/env/include/vector.inc @@ -0,0 +1,188 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _vector_included + #endinput +#endif +#define _vector_included + +/** + * Calculates a vector's length. + * + * @param vec Vector. + * @param squared If true, the result will be squared (for optimization). + * @return Vector length (magnitude). + */ +native Float:GetVectorLength(const Float:vec[3], bool:squared=false); + +/** + * Calculates the distance between two vectors. + * + * @param vec1 First vector. + * @param vec2 Second vector. + * @param squared If true, the result will be squared (for optimization). + * @return Vector distance. + */ +native Float:GetVectorDistance(const Float:vec1[3], const Float:vec2[3], bool:squared=false); + +/** + * Calculates the dot product of two vectors. + * + * @param vec1 First vector. + * @param vec2 Second vector. + * @return Dot product of the two vectors. + */ +native Float:GetVectorDotProduct(const Float:vec1[3], const Float:vec2[3]); + +/** + * Computes the cross product of two vectors. Any input array can be the same + * as the output array. + * + * @param vec1 First vector. + * @param vec2 Second vector. + * @param result Resultant vector. + * @noreturn + */ +native GetVectorCrossProduct(const Float:vec1[3], const Float:vec2[3], Float:result[3]); + +/** + * Normalizes a vector. The input array can be the same as the output array. + * + * @param vec Vector. + * @param result Resultant vector. + * @return Vector length. + */ +native Float:NormalizeVector(const Float:vec[3], Float:result[3]); + +/** + * Returns vectors in the direction of an angle. + * + * @param angle Angle. + * @param fwd Forward vector buffer or NULL_VECTOR. + * @param right Right vector buffer or NULL_VECTOR. + * @param up Up vector buffer or NULL_VECTOR. + * @noreturn + */ +native GetAngleVectors(const Float:angle[3], Float:fwd[3], Float:right[3], Float:up[3]); + +/** + * Returns angles from a vector. + * + * @param vec Vector. + * @param angle Angle buffer. + * @noreturn + */ +native GetVectorAngles(const Float:vec[3], Float:angle[3]); + +/** + * Returns direction vectors from a vector. + * + * @param vec Vector. + * @param right Right vector buffer or NULL_VECTOR. + * @param up Up vector buffer or NULL_VECTOR. + * @noreturn + */ +native GetVectorVectors(const Float:vec[3], Float:right[3], Float:up[3]); + +/** + * Adds two vectors. It is safe to use either input buffer as an output + * buffer. + * + * @param vec1 First vector. + * @param vec2 Second vector. + * @param result Result buffer. + * @noreturn + */ +stock AddVectors(const Float:vec1[3], const Float:vec2[3], Float:result[3]) +{ + result[0] = vec1[0] + vec2[0]; + result[1] = vec1[1] + vec2[1]; + result[2] = vec1[2] + vec2[2]; +} + +/** + * Subtracts a vector from another vector. It is safe to use either input + * buffer as an output buffer. + * + * @param vec1 First vector. + * @param vec2 Second vector to subtract from first. + * @param result Result buffer. + * @noreturn + */ +stock SubtractVectors(const Float:vec1[3], const Float:vec2[3], Float:result[3]) +{ + result[0] = vec1[0] - vec2[0]; + result[1] = vec1[1] - vec2[1]; + result[2] = vec1[2] - vec2[2]; +} + +/** + * Scales a vector. + * + * @param vec Vector. + * @param scale Scale value. + * @noreturn + */ +stock ScaleVector(Float:vec[3], Float:scale) +{ + vec[0] *= scale; + vec[1] *= scale; + vec[2] *= scale; +} + +/** + * Negatives a vector. + * + * @param vec Vector. + * @noreturn + */ +stock NegateVector(Float:vec[3]) +{ + vec[0] = -vec[0]; + vec[1] = -vec[1]; + vec[2] = -vec[2]; +} + +/** + * Builds a vector from two points by subtracting the points. + * + * @param pt1 First point (to be subtracted from the second). + * @param pt2 Second point. + * @param output Output vector buffer. + * @noreturn + */ +stock MakeVectorFromPoints(const Float:pt1[3], const Float:pt2[3], Float:output[3]) +{ + output[0] = pt2[0] - pt1[0]; + output[1] = pt2[1] - pt1[1]; + output[2] = pt2[2] - pt1[2]; +} diff --git a/env/include/version.inc b/env/include/version.inc new file mode 100644 index 0000000..48206d5 --- /dev/null +++ b/env/include/version.inc @@ -0,0 +1,42 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#if defined _version_included + #endinput +#endif +#define _version_included + +#define SOURCEMOD_V_MAJOR 1 /**< SourceMod Major version */ +#define SOURCEMOD_V_MINOR 3 /**< SourceMod Minor version */ +#define SOURCEMOD_V_RELEASE 1 /**< SourceMod Release version */ + +#define SOURCEMOD_VERSION "1.3.1" /**< SourceMod version string (major.minor.release.build) */ diff --git a/env/linux/bin/spcomp b/env/linux/bin/spcomp new file mode 100644 index 0000000..e61be27 Binary files /dev/null and b/env/linux/bin/spcomp differ diff --git a/env/readme.txt b/env/readme.txt new file mode 100644 index 0000000..caeddb5 --- /dev/null +++ b/env/readme.txt @@ -0,0 +1,16 @@ +Compiling: + +- Windows: Use compile.bat in the source code repository. +- Linux: Use the makefile. + +The binary will be made in /build. + +The develop environment should be mostly stand-alone with SourcePawn compiler +some tools and include files. + +Linux requirements: +- Make +- Mercurial + +Windows requirements: +- TortoiseHg or Mercurial diff --git a/env/win32/bin/bash.exe b/env/win32/bin/bash.exe new file mode 100644 index 0000000..95f7f7b Binary files /dev/null and b/env/win32/bin/bash.exe differ diff --git a/env/win32/bin/cygiconv-2.dll b/env/win32/bin/cygiconv-2.dll new file mode 100644 index 0000000..cf77cde Binary files /dev/null and b/env/win32/bin/cygiconv-2.dll differ diff --git a/env/win32/bin/cygintl-8.dll b/env/win32/bin/cygintl-8.dll new file mode 100644 index 0000000..fd510bc Binary files /dev/null and b/env/win32/bin/cygintl-8.dll differ diff --git a/env/win32/bin/cygncurses-9.dll b/env/win32/bin/cygncurses-9.dll new file mode 100644 index 0000000..2eaada0 Binary files /dev/null and b/env/win32/bin/cygncurses-9.dll differ diff --git a/env/win32/bin/cygpath.exe b/env/win32/bin/cygpath.exe new file mode 100644 index 0000000..ce25aaf Binary files /dev/null and b/env/win32/bin/cygpath.exe differ diff --git a/env/win32/bin/cygreadline6.dll b/env/win32/bin/cygreadline6.dll new file mode 100644 index 0000000..823a888 Binary files /dev/null and b/env/win32/bin/cygreadline6.dll differ diff --git a/env/win32/bin/cygwin1.dll b/env/win32/bin/cygwin1.dll new file mode 100644 index 0000000..0296b95 Binary files /dev/null and b/env/win32/bin/cygwin1.dll differ diff --git a/env/win32/bin/date.exe b/env/win32/bin/date.exe new file mode 100644 index 0000000..e7e5eba Binary files /dev/null and b/env/win32/bin/date.exe differ diff --git a/env/win32/bin/echo.exe b/env/win32/bin/echo.exe new file mode 100644 index 0000000..4492fe7 Binary files /dev/null and b/env/win32/bin/echo.exe differ diff --git a/env/win32/bin/spcomp.exe b/env/win32/bin/spcomp.exe new file mode 100644 index 0000000..80c8517 Binary files /dev/null and b/env/win32/bin/spcomp.exe differ diff --git a/src/include/zriot.inc b/src/include/zriot.inc new file mode 100644 index 0000000..73928f2 --- /dev/null +++ b/src/include/zriot.inc @@ -0,0 +1,58 @@ +/** + * ==================== + * Zombie Riot + * File: zriot.inc + * Author: Greyscale + * ==================== + */ + +/** + * Used to check if a player is a zombie. + * @param client Client index. + * @return True if the player is a zombie, and false if human. + */ +native bool:ZRiot_IsClientZombie(client); + +/** + * Retrieves the team index of the zombies + * @note Remember these are based off cvars, 0 will be returned if called before the cvar is set + */ +native ZRiot_GetZombieTeam(); + +/** + * Retrieves the team index of the humans + * @note Remember these are based off cvars, 0 will be returned if called before the cvar is set + */ +native ZRiot_GetHumanTeam(); + +/** + * Turns a human into a zombie + * @param client Client index. + */ +native ZRiot_Zombie(client); + +/** + * Called when a player turns into a zombie. This is not called at round end. + * @param client Client index. + */ +forward ZRiot_OnClientZombie(client); + +/** + * Turns a zombie into a human (will not work for bots) + * @param client Client index. + */ +native ZRiot_Human(client); + +/** + * Called when a player turns into a human. This is not called at round end. + * @param client Client index. + */ +forward ZRiot_OnClientHuman(client); + +/** + * Called when the HUD is being updated on a client (not called for bots) + * @param client Client index. + * @param hinttext The text string being sent to the usermsg "HintText" + * @note If hinttext is modified the new value will be sent to the client + */ +forward ZRiot_OnClientHUDUpdate(client, String:hinttext[]); \ No newline at end of file diff --git a/src/zombieriot.sp b/src/zombieriot.sp new file mode 100644 index 0000000..9921d97 --- /dev/null +++ b/src/zombieriot.sp @@ -0,0 +1,253 @@ +/** + * ==================== + * Zombie Riot + * File: zombieriot.sp + * Author: Greyscale + * ==================== + */ + +#pragma semicolon 1 +#include +#include +#include +#include + +#undef REQUIRE_PLUGIN +#include + +#define VERSION "1.9.1b" + +#include "zriot/zombieriot" +#include "zriot/global" +#include "zriot/cvars" +#include "zriot/translation" +#include "zriot/offsets" +#include "zriot/ambience" +#include "zriot/zombiedata" +#include "zriot/daydata" +#include "zriot/targeting" +#include "zriot/overlays" +#include "zriot/zombie" +#include "zriot/hud" +#include "zriot/sayhooks" +#include "zriot/teamcontrol" +#include "zriot/weaponrestrict" +#include "zriot/commands" +#include "zriot/event" + +public Plugin:myinfo = +{ + name = "Zombie Riot", + author = "Greyscale", + description = "Humans stick together to fight off zombie attacks", + version = VERSION, + url = "" +}; + +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) +{ + CreateGlobals(); + + return APLRes_Success; +} + +public OnPluginStart() +{ + LoadTranslations("common.phrases.txt"); + LoadTranslations("zombieriot.phrases.txt"); + + // ====================================================================== + + ZRiot_PrintToServer("Plugin loading"); + + // ====================================================================== + + ServerCommand("bot_kick"); + + // ====================================================================== + + HookEvents(); + HookChatCmds(); + CreateCvars(); + HookCvars(); + CreateCommands(); + HookCommands(); + FindOffsets(); + SetupGameData(); + InitTeamControl(); + InitWeaponRestrict(); + + // ====================================================================== + + trieDeaths = CreateTrie(); + + // ====================================================================== + + market = LibraryExists("market"); + + // ====================================================================== + + CreateConVar("gs_zombieriot_version", VERSION, "[ZRiot] Current version of this plugin", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY); + + // ====================================================================== + + ZRiot_PrintToServer("Plugin loaded"); +} + +public OnPluginEnd() +{ + ZRiotEnd(); +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, "market")) + { + market = false; + } +} + +public OnLibraryAdded(const String:name[]) +{ + if (StrEqual(name, "market")) + { + market = true; + } +} + +public OnMapStart() +{ + MapChangeCleanup(); + + LoadModelData(); + LoadDownloadData(); + + BuildPath(Path_SM, gMapConfig, sizeof(gMapConfig), "configs/zriot"); + + LoadZombieData(true); + LoadDayData(true); + + FindMapSky(); + + CheckMapConfig(); +} + +public OnConfigsExecuted() +{ + UpdateTeams(); + + FindHostname(); + + LoadAmbienceData(); + + decl String:mapconfig[PLATFORM_MAX_PATH]; + + GetCurrentMap(mapconfig, sizeof(mapconfig)); + Format(mapconfig, sizeof(mapconfig), "sourcemod/zombieriot/%s.cfg", mapconfig); + + decl String:path[PLATFORM_MAX_PATH]; + Format(path, sizeof(path), "cfg/%s", mapconfig); + + if (FileExists(path)) + { + ServerCommand("exec %s", mapconfig); + } +} + +public OnClientPutInServer(client) +{ + new bool:fakeclient = IsFakeClient(client); + + InitClientDeathCount(client); + + new deathcount = GetClientDeathCount(client); + new deaths_before_zombie = GetDayDeathsBeforeZombie(gDay); + + bZombie[client] = !fakeclient ? ((deaths_before_zombie > 0) && (fakeclient || (deathcount >= deaths_before_zombie))) : true; + + bZVision[client] = !IsFakeClient(client); + + gZombieID[client] = -1; + + gTarget[client] = -1; + RemoveTargeters(client); + + tRespawn[client] = INVALID_HANDLE; + + ClientHookUse(client); + + FindClientDXLevel(client); +} + +public OnClientDisconnect(client) +{ + if (!IsPlayerHuman(client)) + return; + + new count; + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || !IsPlayerHuman(x) || GetClientTeam(x) <= CS_TEAM_SPECTATOR) + continue; + + count++; + } + + if (count <= 1 && tHUD != INVALID_HANDLE) + { + TerminateRound(5.0, Terrorists_Win); + } +} + +MapChangeCleanup() +{ + gDay = 0; + + ClearArray(restrictedWeapons); + ClearTrie(trieDeaths); + + tAmbience = INVALID_HANDLE; + tHUD = INVALID_HANDLE; + tFreeze = INVALID_HANDLE; +} + +CheckMapConfig() +{ + decl String:mapname[64]; + GetCurrentMap(mapname, sizeof(mapname)); + + Format(gMapConfig, sizeof(gMapConfig), "%s/%s", gMapConfig, mapname); + + LoadZombieData(false); + LoadDayData(false); +} + +ZRiotEnd() +{ + TerminateRound(3.0, Game_Commencing); + + SetHostname(hostname); + + UnhookCvars(); + UnhookEvents(); + + ServerCommand("bot_all_weapons"); + ServerCommand("bot_kick"); + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + { + continue; + } + + if (tRespawn[x] != INVALID_HANDLE) + { + CloseHandle(tRespawn[x]); + tRespawn[x] = INVALID_HANDLE; + } + } +} \ No newline at end of file diff --git a/src/zriot/ambience.inc b/src/zriot/ambience.inc new file mode 100644 index 0000000..07f45e7 --- /dev/null +++ b/src/zriot/ambience.inc @@ -0,0 +1,97 @@ +/** + * ==================== + * Zombie Riot + * File: ambience.inc + * Author: Greyscale + * ==================== + */ + +new bool:soundValid = false; + +new Handle:tAmbience = INVALID_HANDLE; + +LoadAmbienceData() +{ + new bool:ambience = GetConVarBool(gCvars[CVAR_AMBIENCE]); + if (!ambience) + { + return; + } + + decl String:sound[64]; + GetConVarString(gCvars[CVAR_AMBIENCE_FILE], sound, sizeof(sound)); + Format(sound, sizeof(sound), "sound/%s", sound); + + soundValid = FileExists(sound, true); + + if (soundValid) + { + AddFileToDownloadsTable(sound); + } + else + { + ZRiot_LogMessage("Ambient sound load failed", sound); + } +} + +RestartAmbience() +{ + if (tAmbience != INVALID_HANDLE) + { + CloseHandle(tAmbience); + } + + CreateTimer(0.0, AmbienceLoop, _, TIMER_FLAG_NO_MAPCHANGE); +} + +public Action:AmbienceLoop(Handle:timer) +{ + new bool:ambience = GetConVarBool(gCvars[CVAR_AMBIENCE]); + + if (!ambience || !soundValid) + { + return; + } + + decl String:sound[64]; + GetConVarString(gCvars[CVAR_AMBIENCE_FILE], sound, sizeof(sound)); + + EmitAmbience(sound); + + new Float:delay = GetConVarFloat(gCvars[CVAR_AMBIENCE_LENGTH]); + tAmbience = CreateTimer(delay, AmbienceLoop, _, TIMER_FLAG_NO_MAPCHANGE); +} + +StopAmbience() +{ + new bool:ambience = GetConVarBool(gCvars[CVAR_AMBIENCE]); + + if (!ambience) + { + return; + } + + decl String:sound[64]; + GetConVarString(gCvars[CVAR_AMBIENCE_FILE], sound, sizeof(sound)); + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + { + continue; + } + + StopSound(x, SNDCHAN_AUTO, sound); + } +} + +EmitAmbience(const String:sound[]) +{ + PrecacheSound(sound); + + StopAmbience(); + + new Float:volume = GetConVarFloat(gCvars[CVAR_AMBIENCE_VOLUME]); + EmitSoundToAll(sound, SOUND_FROM_PLAYER, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, volume, SNDPITCH_NORMAL, -1, NULL_VECTOR, NULL_VECTOR, true, 0.0); +} \ No newline at end of file diff --git a/src/zriot/commands.inc b/src/zriot/commands.inc new file mode 100644 index 0000000..f9c42fd --- /dev/null +++ b/src/zriot/commands.inc @@ -0,0 +1,154 @@ +/** + * ==================== + * Zombie Riot + * File: commands.inc + * Author: Greyscale + * ==================== + */ + +CreateCommands() +{ + RegAdminCmd("zriot_restrict", Command_Restrict, ADMFLAG_GENERIC, "Restrict a specified weapon"); + RegAdminCmd("zriot_unrestrict", Command_UnRestrict, ADMFLAG_GENERIC, "Unrestrict a specified weapon"); + + RegAdminCmd("zriot_setday", Command_SetDay, ADMFLAG_GENERIC, "Sets the game to a certain day"); + + RegAdminCmd("zriot_zombie", Command_Zombie, ADMFLAG_GENERIC, "Turns player into zombie"); + RegAdminCmd("zriot_human", Command_Human, ADMFLAG_GENERIC, "Turns player into human"); +} + +public Action:Command_Restrict(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (argc < 1 || !enabled) + { + return Plugin_Handled; + } + + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + new WepRestrictQuery:output = RestrictWeapon(arg1); + + if (output == Existing) + { + ZRiot_ReplyToCommand(client, "Weapon already restricted", arg1); + } + + return Plugin_Handled; +} + +public Action:Command_UnRestrict(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (argc < 1 || !enabled) + { + return Plugin_Handled; + } + + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + new WepRestrictQuery:output = UnRestrictWeapon(arg1); + + if (output == Invalid) + { + ZRiot_ReplyToCommand(client, "Weapon invalid", arg1); + } + + return Plugin_Handled; +} + +public Action:Command_SetDay(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (argc < 1 || !enabled) + { + return Plugin_Handled; + } + + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + new day = StringToInt(arg1) - 1; + day = (day >= 0) ? day : 0; + + gDay = day; + gDay = (gDay + 1 > dCount) ? dCount - 1 : gDay; + + ZRiot_PrintToChat(0, "Skip to day", gDay + 1); + + if (tHUD == INVALID_HANDLE) + { + return Plugin_Handled; + } + + TerminateRound(3.0, Round_Draw); + + return Plugin_Handled; +} + +public Action:Command_Zombie(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (argc < 1 || !enabled) + { + return Plugin_Handled; + } + + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + decl String:target_name[MAX_TARGET_LENGTH]; + new targets[MAXPLAYERS]; + new bool:tn_is_ml; + + new tcount = ProcessTargetString(arg1, client, targets, MAXPLAYERS, COMMAND_FILTER_NO_BOTS, target_name, sizeof(target_name), tn_is_ml); + if (tcount <= 0) + { + ReplyToTargetError(client, tcount); + return Plugin_Handled; + } + + for (new x = 0; x < tcount; x++) + { + ZRiot_Zombie(targets[x]); + } + + if (GetLiveHumanCount() <= 0) + { + TerminateRound(5.0, Terrorists_Win); + } + + return Plugin_Handled; +} + +public Action:Command_Human(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (argc < 1 || !enabled) + { + return Plugin_Handled; + } + + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + decl String:target_name[MAX_TARGET_LENGTH]; + new targets[MAXPLAYERS]; + new bool:tn_is_ml; + + new tcount = ProcessTargetString(arg1, client, targets, MAXPLAYERS, COMMAND_FILTER_NO_BOTS, target_name, sizeof(target_name), tn_is_ml); + if (tcount <= 0) + { + ReplyToTargetError(client, tcount); + return Plugin_Handled; + } + + for (new x = 0; x < tcount; x++) + { + ZRiot_Human(targets[x]); + } + + return Plugin_Handled; +} \ No newline at end of file diff --git a/src/zriot/cvars.inc b/src/zriot/cvars.inc new file mode 100644 index 0000000..ffa7317 --- /dev/null +++ b/src/zriot/cvars.inc @@ -0,0 +1,157 @@ +/** + * ==================== + * Zombie Riot + * File: cvars.inc + * Author: Greyscale + * ==================== + */ + +enum ZRiotSettings +{ + Handle:CVAR_ENABLE, + Handle:CVAR_AMBIENCE, + Handle:CVAR_AMBIENCE_FILE, + Handle:CVAR_AMBIENCE_LENGTH, + Handle:CVAR_AMBIENCE_VOLUME, + Handle:CVAR_HOSTNAME_UPDATE, + Handle:CVAR_ZVISION_REDISPLAY, + Handle:CVAR_ZVISION_ALLOW_DISABLE, + Handle:CVAR_NOBLOCK, + Handle:CVAR_FREEZE, + Handle:CVAR_BOTQUOTA_SILENT, + Handle:CVAR_REGRESSION, + Handle:CVAR_FIRST_RESPAWN, + Handle:CVAR_RESPAWN, + Handle:CVAR_ZOMBIETEAM, + Handle:CVAR_ZOMBIEMAX, + Handle:CVAR_HUD, + Handle:CVAR_TARGETING, + Handle:CVAR_ROUNDFADE, + Handle:CVAR_OVERLAYS, + Handle:CVAR_OVERLAYS_ZOMBIE, + Handle:CVAR_OVERLAYS_HUMAN, + Handle:CVAR_RAGDOLL_REMOVE, + Handle:CVAR_NAPALM, + Handle:CVAR_NAPALM_TIME, + Handle:CVAR_DARK, + Handle:CVAR_DARK_LEVEL, + Handle:CVAR_DARK_SKY, + Handle:CVAR_ZMARKET_BUYZONE, + Handle:CVAR_CASHFILL, + Handle:CVAR_CASHAMOUNT +} + +new gCvars[ZRiotSettings]; + +CreateCvars() +{ + gCvars[CVAR_ENABLE] = CreateConVar("zriot_enable", "1", "Enable ZombieRiot gameplay (0: Disable)"); + gCvars[CVAR_AMBIENCE] = CreateConVar("zriot_ambience", "1", "Enable creepy ambience to be played throughout the game (0: Disable)"); + gCvars[CVAR_AMBIENCE_FILE] = CreateConVar("zriot_ambience_file", "ambient/zr/zr_ambience.mp3", "Path to ambient sound file that will be played throughout the game, when zriot_ambience is 1"); + gCvars[CVAR_AMBIENCE_LENGTH] = CreateConVar("zriot_ambience_length", "60.0", "The length, in seconds, of the ambient sound file"); + gCvars[CVAR_AMBIENCE_VOLUME] = CreateConVar("zriot_ambience_volume", "0.6", "Volume of ambient sounds when zriot_ambience is 1 (0.0: Unhearable, 1.0: Max volume)"); + gCvars[CVAR_HOSTNAME_UPDATE] = CreateConVar("zriot_hostname_update", "1", "Updates the server's hostname to display the current day server is playing (0: Disable)"); + gCvars[CVAR_ZVISION_REDISPLAY] = CreateConVar("zriot_zvision_redisplay", "0.2", "Frequency, in seconds, to display zvision on the zombies' screen (Never go below 0.1, 0.2 seems safe)"); + gCvars[CVAR_ZVISION_ALLOW_DISABLE] = CreateConVar("zriot_zvision_allow_disable", "1", "Allow users to disable ZVision with their nightvision key (0: Disable)"); + gCvars[CVAR_REGRESSION] = CreateConVar("zriot_regression", "1", "If the zombies win the round, the game will regress one day (0: Disable)"); + gCvars[CVAR_NOBLOCK] = CreateConVar("zriot_noblock", "1", "Prevents zombies from getting stuck in each other (0: Disable)"); + gCvars[CVAR_FREEZE] = CreateConVar("zriot_freeze", "10", "Time, in seconds, to freeze zombies at round start to allow humans to get set up (0: Disable)"); + gCvars[CVAR_BOTQUOTA_SILENT] = CreateConVar("zriot_botquota_silent", "1", "Blocks join/leave text for bots (0: Disable)"); + gCvars[CVAR_FIRST_RESPAWN] = CreateConVar("zriot_first_respawn", "10", "Amount of time to wait before spawning a player into the game for the first time (0: Disable)"); + gCvars[CVAR_RESPAWN] = CreateConVar("zriot_respawn", "30", "Amount of time each human has to wait before they will respawn into the game (0: Disable)"); + gCvars[CVAR_ZOMBIETEAM] = CreateConVar("zriot_zombieteam", "t", "Which team zombie's will be on (t: Terrorist ct: Counter-Terrorist)"); + gCvars[CVAR_ZOMBIEMAX] = CreateConVar("zriot_zombiemax", "12", "The max amount of zombies spawned at one time"); + gCvars[CVAR_HUD] = CreateConVar("zriot_hud", "1", "Enable persistent display of the HUD which displays day, zombies left, and humans left (0: Disable)"); + gCvars[CVAR_TARGETING] = CreateConVar("zriot_targeting", "1", "Enables a system that tracks damage done to each zombie, and shows you each one's current health (0: Disable)"); + gCvars[CVAR_ROUNDFADE] = CreateConVar("zriot_roundfade", "0", "Player's screens fade blue if humans win, red if zombies in, and black in any other case (0: Disable)"); + gCvars[CVAR_OVERLAYS] = CreateConVar("zriot_overlays", "1", "Enable use of round end overlays to show the winner (0: Disable)"); + gCvars[CVAR_OVERLAYS_ZOMBIE] = CreateConVar("zriot_overlays_zombie", "overlays/zr/zombies_win", "Path to overlay shown when Zombies win, when zriot_overlays is 1"); + gCvars[CVAR_OVERLAYS_HUMAN] = CreateConVar("zriot_overlays_human", "overlays/zr/humans_win", "Path to overlay shown when Humans win, when zriot_overlays is 1"); + gCvars[CVAR_RAGDOLL_REMOVE] = CreateConVar("zriot_ragdoll_remove", "20", "The time, in seconds, before the ragdoll of dead zombies will be deleted (0: Disable)"); + gCvars[CVAR_NAPALM] = CreateConVar("zriot_napalm", "1", "Turns grenades into napalm grenades that light zombies on fire (0: Disable)"); + gCvars[CVAR_NAPALM_TIME] = CreateConVar("zriot_napalm_time", "20", "How long the zombie burns when zr_napalm is 1"); + gCvars[CVAR_DARK] = CreateConVar("zriot_dark", "0", "Darkens the map (0: Disable)"); + gCvars[CVAR_DARK_LEVEL] = CreateConVar("zriot_dark_level", "a", "The darkness of the map, a being the darkest, z being extremely bright when zriot_dark is 1 (n: Default)"); + gCvars[CVAR_DARK_SKY] = CreateConVar("zriot_dark_sky", "sky_borealis01", "The sky the map will have when zriot_dark is 1"); + gCvars[CVAR_ZMARKET_BUYZONE] = CreateConVar("zriot_zmarket_buyzone", "0", "Must be in buyzone to access !zmarket, if Market is installed (0: Can be used anywhere)"); + gCvars[CVAR_CASHFILL] = CreateConVar("zriot_cashfill", "1", "Enable the mod to set the players cash to zriot_cashamount (0: Disabled)"); + gCvars[CVAR_CASHAMOUNT] = CreateConVar("zriot_cashamount", "12000", "How much money players will have when they spawn when zriot_cashfill is 1"); + + HookConVarChange(gCvars[CVAR_ENABLE], EnableHook); + + AutoExecConfig(true, "zombieriot", "sourcemod/zombieriot"); +} + +HookCvars() +{ + SetConVarBool(FindConVar("mp_autoteambalance"), false); + SetConVarInt(FindConVar("mp_limitteams"), 0); + + HookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook); + HookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook); + + HookConVarChange(gCvars[CVAR_ZOMBIETEAM], ZombieTeamHook); + + HookConVarChange(FindConVar("mp_restartgame"), RestartGameHook); +} + +UnhookCvars() +{ + UnhookConVarChange(FindConVar("mp_autoteambalance"), AutoTeamBalanceHook); + UnhookConVarChange(FindConVar("mp_limitteams"), LimitTeamsHook); + + UnhookConVarChange(gCvars[CVAR_ZOMBIETEAM], ZombieTeamHook); + + UnhookConVarChange(FindConVar("mp_restartgame"), RestartGameHook); +} + +public EnableHook(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + new bool:enable = bool:StringToInt(newValue); + + if (enable) + { + FindMapSky(); + + FindHostname(); + UpdateHostname(); + + HookEvents(); + HookCvars(); + + ServerCommand("bot_kick"); + + gDay = 0; + + TerminateRound(3.0, Game_Commencing); + } + else + { + ZRiotEnd(); + } +} + +public AutoTeamBalanceHook(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + SetConVarBool(convar, false); +} + +public LimitTeamsHook(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + SetConVarInt(convar, 0); +} + +public ZombieTeamHook(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + if (StrEqual(newValue, "t", false) || StrEqual(newValue, "ct", false)) + { + UpdateTeams(); + } +} + +public RestartGameHook(Handle:convar, const String:oldValue[], const String:newValue[]) +{ + gDay = 0; + + ResetZombies(true); +} \ No newline at end of file diff --git a/src/zriot/daydata.inc b/src/zriot/daydata.inc new file mode 100644 index 0000000..c9b4bb1 --- /dev/null +++ b/src/zriot/daydata.inc @@ -0,0 +1,220 @@ +/** + * ==================== + * Zombie Riot + * File: daydata.inc + * Author: Greyscale + * ==================== + */ + +enum ZRiot_DayData +{ + String:data_display[32], + String:data_zombieoverride[32*MAXZOMBIES], + String:data_storyline[192], + data_count, + data_healthboost, + bool:data_respawn, + data_deaths_before_zombie, + Float:data_fademin, + Float:data_fademax +} + +#define MAXDAYS 25 + +new Handle:kvDays = INVALID_HANDLE; + +new arrayDays[MAXDAYS][ZRiot_DayData]; +new dCount; + +LoadDayData(bool:defaultconfig) +{ + decl String:path[PLATFORM_MAX_PATH]; + Format(path, sizeof(path), "%s/days.txt", gMapConfig); + + if (!defaultconfig && !FileExists(path)) + { + return; + } + + if (kvDays != INVALID_HANDLE) + { + CloseHandle(kvDays); + } + + kvDays = CreateKeyValues("days"); + KvSetEscapeSequences(kvDays, true); + + if (!FileToKeyValues(kvDays, path)) + { + SetFailState("\"%s\" failed to load", path); + } + + KvRewind(kvDays); + if (!KvGotoFirstSubKey(kvDays)) + { + SetFailState("No day data defined in \"%s\"", path); + } + + decl String:display[32]; + decl String:zombieoverride[32*MAXZOMBIES]; + decl String:storyline[192]; + + dCount = 0; + do + { + KvGetSectionName(kvDays, display, sizeof(display)); + strcopy(arrayDays[dCount][data_display], 32, display); + + KvGetString(kvDays, "zombieoverride", zombieoverride, sizeof(zombieoverride)); + strcopy(arrayDays[dCount][data_zombieoverride], 32*MAXZOMBIES, zombieoverride); + + KvGetString(kvDays, "storyline", storyline, sizeof(storyline)); + strcopy(arrayDays[dCount][data_storyline], 192, storyline); + + arrayDays[dCount][data_count] = KvGetNum(kvDays, "count", 25); + arrayDays[dCount][data_healthboost] = KvGetNum(kvDays, "healthboost"); + arrayDays[dCount][data_respawn] = bool:KvGetNum(kvDays, "respawn"); + arrayDays[dCount][data_deaths_before_zombie] = KvGetNum(kvDays, "deaths_before_zombie"); + arrayDays[dCount][data_fademin] = KvGetFloat(kvDays, "fademin"); + arrayDays[dCount][data_fademax] = KvGetFloat(kvDays, "fademax"); + + dCount++; + } while (KvGotoNextKey(kvDays)); +} + +GetDayDisplay(day, String:display[], len) +{ + strcopy(display, len, arrayDays[day][data_display]); +} + +bool:ExplodeZombieOverrides(day) +{ + if (adtZombies != INVALID_HANDLE) + { + CloseHandle(adtZombies); + adtZombies = INVALID_HANDLE; + } + + decl String:zombieoverride[32*MAXZOMBIES]; + GetDayZombieOverride(day, zombieoverride, sizeof(zombieoverride)); + + if (zombieoverride[0]) + { + adtZombies = CreateArray(); + + new String:sZombies[MAXZOMBIES][64]; + ExplodeString(zombieoverride, ",", sZombies, MAXZOMBIES, 64); + + for (new x = 0; x < MAXZOMBIES; x++) + { + if (!sZombies[x][0]) + continue; + + TrimString(sZombies[x]); + new zombieid = FindZombieIDByName(sZombies[x]); + + if (zombieid == -1) + continue; + + PushArrayCell(adtZombies, zombieid); + } + + return true; + } + + return false; +} + +GetDayZombieOverride(day, String:zombieoverride[], len) +{ + strcopy(zombieoverride, len, arrayDays[day][data_zombieoverride]); +} + +GetDayStoryLine(day, String:storyline[], len) +{ + strcopy(storyline, len, arrayDays[day][data_storyline]); +} + +GetDayCount(day) +{ + return arrayDays[day][data_count]; +} + +GetDayHealthBoost(day) +{ + return arrayDays[day][data_healthboost]; +} + +bool:GetDayRespawn(day) +{ + return arrayDays[day][data_respawn]; +} + +GetDayDeathsBeforeZombie(day) +{ + return arrayDays[day][data_deaths_before_zombie]; +} + +Float:GetDayMinFade(day) +{ + return arrayDays[day][data_fademin]; +} + +Float:GetDayMaxFade(day) +{ + return arrayDays[day][data_fademax]; +} + +BeginDay() +{ + gZombiesKilled = 0; + + new zombiecount = GetDayCount(gDay); + new zombiemax = GetConVarInt(gCvars[CVAR_ZOMBIEMAX]); + + new spawncount; + new bool:respawn = GetDayRespawn(gDay); + + if (respawn) + { + spawncount = zombiemax; + } + else + { + spawncount = (zombiecount < zombiemax) ? zombiecount : zombiemax; + } + + ServerCommand("bot_quota %d", spawncount); + + decl String:display[32]; + GetDayDisplay(gDay, display, sizeof(display)); + + new bool:override = ExplodeZombieOverrides(gDay); + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + { + continue; + } + + ChangeClientDeathCount(x, 0); + + if (!IsPlayerZombie(x)) + { + continue; + } + + if (override) + { + new size = GetArraySize(adtZombies); + if (size) + { + new zombieid = GetRandomInt(0, size - 1); + + Zombify(x, GetArrayCell(adtZombies, zombieid)); + } + } + } +} diff --git a/src/zriot/event.inc b/src/zriot/event.inc new file mode 100644 index 0000000..a956373 --- /dev/null +++ b/src/zriot/event.inc @@ -0,0 +1,531 @@ +/** + * ==================== + * Zombie Riot + * File: events.inc + * Author: Greyscale + * ==================== + */ + +HookEvents() +{ + HookEvent("player_connect", PlayerConnect, EventHookMode_Pre); + HookEvent("player_disconnect", PlayerDisconnect, EventHookMode_Pre); + HookEvent("round_start", RoundStart); + HookEvent("round_freeze_end", RoundFreezeEnd); + HookEvent("round_end", RoundEnd); + HookEvent("player_team", PlayerTeam_Pre, EventHookMode_Pre); + HookEvent("player_team", PlayerTeam_Post, EventHookMode_Post); + HookEvent("player_spawn", PlayerSpawn); + HookEvent("player_hurt", PlayerHurt); + HookEvent("player_death", PlayerDeath); + HookEvent("player_jump", PlayerJump); +} + +UnhookEvents() +{ + UnhookEvent("player_connect", PlayerConnect, EventHookMode_Pre); + UnhookEvent("player_disconnect", PlayerDisconnect, EventHookMode_Pre); + UnhookEvent("round_start", RoundStart); + UnhookEvent("round_freeze_end", RoundFreezeEnd); + UnhookEvent("round_end", RoundEnd); + UnhookEvent("player_team", PlayerTeam_Pre, EventHookMode_Pre); + UnhookEvent("player_team", PlayerTeam_Post, EventHookMode_Post); + UnhookEvent("player_spawn", PlayerSpawn); + UnhookEvent("player_hurt", PlayerHurt); + UnhookEvent("player_death", PlayerDeath); + UnhookEvent("player_jump", PlayerJump); +} + +new bool:pcFire = true; +public Action:PlayerConnect(Handle:event, const String:name[], bool:dontBroadcast) +{ + new bool:botquota_silent = GetConVarBool(gCvars[CVAR_BOTQUOTA_SILENT]); + if (!botquota_silent) + return Plugin_Continue; + + decl String:address[64]; + GetEventString(event, "address", address, sizeof(address)); + + if (pcFire && StrEqual(address, "none")) + { + decl String:pname[64]; + decl String:networkid[64]; + + GetEventString(event, "name", pname, sizeof(pname)); + GetEventString(event, "networkid", networkid, sizeof(networkid)); + new Handle:hPlayerConnect = CreateEvent("player_connect", true); + + SetEventString(hPlayerConnect, "name", pname); + SetEventInt(hPlayerConnect, "index", GetEventInt(event, "index")); + SetEventInt(hPlayerConnect, "userid", GetEventInt(event, "userid")); + SetEventString(hPlayerConnect, "networkid", networkid); + SetEventString(hPlayerConnect, "address", address); + + pcFire = false; + FireEvent(hPlayerConnect, true); + pcFire = true; + + return Plugin_Handled; + } + + return Plugin_Continue; +} + +new bool:pdFire = true; +public Action:PlayerDisconnect(Handle:event, const String:name[], bool:dontBroadcast) +{ + new bool:botquota_silent = GetConVarBool(gCvars[CVAR_BOTQUOTA_SILENT]); + if (!botquota_silent) + return Plugin_Continue; + + new userid = GetEventInt(event, "userid"); + new index = GetClientOfUserId(userid); + + if (!index || !IsClientInGame(index)) + return Plugin_Continue; + + if (pdFire && IsFakeClient(index)) + { + decl String:reason[192]; + decl String:pname[64]; + decl String:networkid[64]; + + GetEventString(event, "reason", reason, sizeof(reason)); + GetEventString(event, "name", pname, sizeof(pname)); + GetEventString(event, "networkid", networkid, sizeof(networkid)); + + new Handle:hPlayerDisconnect = CreateEvent("player_disconnect", true); + + SetEventInt(hPlayerDisconnect, "userid", userid); + SetEventString(hPlayerDisconnect, "reason", reason); + SetEventString(hPlayerDisconnect, "name", pname); + SetEventString(hPlayerDisconnect, "networkid", networkid); + + pdFire = false; + FireEvent(hPlayerDisconnect, true); + pdFire = true; + + return Plugin_Handled; + } + + return Plugin_Continue; +} + +public Action:RoundStart(Handle:event, const String:name[], bool:dontBroadcast) +{ + UpdateHostname(); + + ChangeLightStyle(); + + RestartAmbience(); + + ServerCommand("bot_knives_only"); + + ZRiot_PrintToChat(0, "Round objective"); + + decl String:storyline[192]; + GetDayStoryLine(gDay, storyline, sizeof(storyline)); + + if (storyline[0]) + { + FormatTextString(storyline, sizeof(storyline)); + + PrintToChatAll(storyline); + } + + BeginDay(); + + if (tHUD != INVALID_HANDLE) + { + CloseHandle(tHUD); + tHUD = INVALID_HANDLE; + } + + new bool:hud = GetConVarBool(gCvars[CVAR_HUD]); + if (hud) + { + tHUD = CreateTimer(5.0, HUD, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); + + UpdateHUDAll(); + } + + if (tFreeze != INVALID_HANDLE) + { + CloseHandle(tFreeze); + tFreeze = INVALID_HANDLE; + } +} + +public Action:RoundFreezeEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + RemoveObjectives(); + + if (tFreeze != INVALID_HANDLE) + { + CloseHandle(tFreeze); + tFreeze = INVALID_HANDLE; + } + + new Float:freeze = GetConVarFloat(gCvars[CVAR_FREEZE]); + if (freeze > 0) + { + FreezeZombies(); + + tFreeze = CreateTimer(freeze, UnfreezeZombies); + } +} + +public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + ResetZombies(false); + ClearTrie(trieDeaths); + + CreateTimer(0.0, AssignTeamTimer); + + new reason = GetEventInt(event, "reason"); + + if (reason == CTs_Win || reason == Terrorists_Win) + { + new winner = GetEventInt(event, "winner"); + + if (winner == gZombieTeam) + { + ZombiesWin(); + } + else if (winner == gHumanTeam) + { + HumansWin(); + } + } + else + { + RoundDraw(); + } + + if (tHUD != INVALID_HANDLE) + { + CloseHandle(tHUD); + tHUD = INVALID_HANDLE; + } + + if (tFreeze != INVALID_HANDLE) + { + CloseHandle(tFreeze); + tFreeze = INVALID_HANDLE; + } +} + +new bool:ptFire = true; +public Action:PlayerTeam_Pre(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (ptFire) + { + new Handle:hPlayerTeam = CreateEvent("player_team", true); + + SetEventInt(hPlayerTeam, "userid", GetEventInt(event, "userid")); + SetEventInt(hPlayerTeam, "team", GetEventInt(event, "team")); + SetEventInt(hPlayerTeam, "oldteam", GetEventInt(event, "oldteam")); + SetEventBool(hPlayerTeam, "disconnect", GetEventBool(event, "disconnect")); + + ptFire = false; + FireEvent(hPlayerTeam, true); + ptFire = true; + + return Plugin_Handled; + } + + return Plugin_Continue; +} + +public Action:PlayerTeam_Post(Handle:event, const String:name[], bool:dontBroadcast) +{ + new bool:disconnect = GetEventBool(event, "disconnect"); + if (disconnect) + { + return; + } + + new index = GetClientOfUserId(GetEventInt(event, "userid")); + new oldteam = GetEventInt(event, "oldteam"); + new team = GetEventInt(event, "team"); + + if (team != CS_TEAM_SPECTATOR && oldteam == CS_TEAM_NONE || oldteam == CS_TEAM_SPECTATOR) + { + CreateTimer(0.0, CheckTeam, index); + } + + if (team == gHumanTeam) + { + StopZVision(index); + SetPlayerFOV(index, DEFAULT_FOV); + SetEntityGravity(index, DEFAULT_GRAVITY); + + if (IsPlayerAlive(index) || tRespawn[index] != INVALID_HANDLE || tHUD == INVALID_HANDLE) + { + return; + } + + StartRespawnTimer(index, true); + } +} + +public Action:CheckTeam(Handle:timer, any:index) +{ + AssignTeamClient(index, IsPlayerAlive(index)); +} + +public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) +{ + new index = GetClientOfUserId(GetEventInt(event, "userid")); + + new team = GetClientTeam(index); + if (team != CS_TEAM_T && team != CS_TEAM_CT) + { + return; + } + + gZombieID[index] = -1; + + if (IsPlayerZombie(index)) + { + RemoveTargeters(index); + + InitClientDeathCount(index); + + SetPlayerMoney(index, 0); + + new bool:noblock = GetConVarBool(gCvars[CVAR_NOBLOCK]); + if (noblock) + { + NoCollide(index, true); + } + + decl String:zombieoverride[4]; + GetDayZombieOverride(gDay, zombieoverride, sizeof(zombieoverride)); + + new zombieid; + + if (adtZombies != INVALID_HANDLE && zombieoverride[0]) + { + new size = GetArraySize(adtZombies); + if (size) + { + zombieid = GetRandomInt(0, size - 1); + + Zombify(index, GetArrayCell(adtZombies, zombieid)); + } + } + else + { + do + { + zombieid = GetRandomInt(0, zCount - 1); + } while(IsOverrideRequired(zombieid)); + + Zombify(index, zombieid); + } + + new health = GetClientHealth(index); + SetEntityHealth(index, health + GetDayHealthBoost(gDay)); + + new Float:fademin = GetDayMinFade(gDay); + new Float:fademax = GetDayMaxFade(gDay); + + SetPlayerMinDist(index, fademin); + SetPlayerMaxDist(index, fademax); + + new knife = GetPlayerWeaponSlot(index, 2); + + if (knife != -1) + { + SetEntityRenderMode(knife, RENDER_TRANSALPHA); + SetEntityRenderColor(knife, 255, 255, 255, 0); + } + } + else + { + if (market) + { + ZRiot_PrintToChat(index, "!market reminder"); + } + + new bool:noblock = GetConVarBool(gCvars[CVAR_NOBLOCK]); + if (noblock) + { + NoCollide(index, false); + } + + SetPlayerMinDist(index, 0.0); + SetPlayerMaxDist(index, 0.0); + + SetPlayerFOV(index, DEFAULT_FOV); + SetEntityGravity(index, DEFAULT_GRAVITY); + + new bool:cashfill = GetConVarBool(gCvars[CVAR_CASHFILL]); + if (cashfill) + { + new cash = GetConVarInt(gCvars[CVAR_CASHAMOUNT]); + SetPlayerMoney(index, cash); + } + + if (tZVision[index] != INVALID_HANDLE) + { + CloseHandle(tZVision[index]); + tZVision[index] = INVALID_HANDLE; + } + + ClientCommand(index, "r_screenoverlay \"\""); + + RemoveTargeters(index); + UpdateHUDAll(); + } + + if (tRespawn[index] != INVALID_HANDLE) + { + CloseHandle(tRespawn[index]); + tRespawn[index] = INVALID_HANDLE; + } +} + +public Action:PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +{ + new index = GetClientOfUserId(GetEventInt(event, "userid")); + new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); + + decl String:weapon[32]; + GetEventString(event, "weapon", weapon, sizeof(weapon)); + + if (!IsPlayerZombie(index)) + { + return; + } + + if (attacker) + { + TargetPlayer(attacker, index); + } + + new maxplayers = GetMaxClients(); + new clients[maxplayers]; + new numClients = GetClientTargeters(index, clients, maxplayers); + + UpdateHUD(clients, numClients); + + if (GetRandomInt(1, 5) == 1) + { + decl String:sound[64]; + new randsound = GetRandomInt(1, 6); + + Format(sound, sizeof(sound), "npc/zombie/zombie_pain%d.wav", randsound); + + PrecacheSound(sound); + EmitSoundToAll(sound, index); + } + + new bool:napalm = GetConVarBool(gCvars[CVAR_NAPALM]); + + if (napalm && StrEqual(weapon, "hegrenade", false)) + { + new Float:burntime = GetConVarFloat(gCvars[CVAR_NAPALM_TIME]); + IgniteEntity(index, burntime); + } +} + +public Action:PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + new index = GetClientOfUserId(GetEventInt(event, "userid")); + + if (tHUD == INVALID_HANDLE) + { + return; + } + + new bool:respawn = GetDayRespawn(gDay); + + if (IsPlayerZombie(index)) + { + ExtinguishEntity(index); + + SetEntProp(index, Prop_Data, "m_takedamage", 2, 1); + SetEntProp(index, Prop_Data, "m_fFlags", FL_ONGROUND); + + decl String:sound[64]; + + new randsound = GetRandomInt(1, 3); + Format(sound, sizeof(sound), "npc/zombie/zombie_die%d.wav", randsound); + + PrecacheSound(sound); + EmitSoundToAll(sound, index); + + new zombiecount = GetLiveZombieCount(); + new zombiemax = GetConVarInt(gCvars[CVAR_ZOMBIEMAX]); + + if (respawn || zombiecount > zombiemax) + { + CreateTimer(0.5, ZombieRespawn, index, TIMER_FLAG_NO_MAPCHANGE); + } + + gZombiesKilled++; + + RemoveTargeters(index); + UpdateHUDAll(); + + if (gZombiesKilled >= GetDayCount(gDay) && respawn) + { + TerminateRound(5.0, CTs_Win); + } + } + else + { + ChangeClientDeathCount(index, 1); + new deaths_before_zombie = GetDayDeathsBeforeZombie(gDay); + + if (deaths_before_zombie > 0 && GetClientDeathCount(index) >= deaths_before_zombie && GetLiveHumanCount() > 0) + { + ZRiot_PrintToChat(index, "You are now a zombie"); + + CreateTimer(0.5, JoinZombie, index); + } + else + { + StartRespawnTimer(index, false); + } + + RemoveTargeters(index); + UpdateHUDAll(); + + if (GetLiveHumanCount() <= 0 && respawn) + { + TerminateRound(5.0, Terrorists_Win); + } + } + + new Float:delay = GetConVarFloat(gCvars[CVAR_RAGDOLL_REMOVE]); + if (delay > 0.0) + { + new ragdoll = GetEntPropEnt(index, Prop_Send, "m_hRagdoll"); + + CreateTimer(delay, RemoveRagdoll, ragdoll); + } + + if (tZVision[index] != INVALID_HANDLE) + { + CloseHandle(tZVision[index]); + tZVision[index] = INVALID_HANDLE; + } +} + +public Action:PlayerJump(Handle:event, const String:name[], bool:dontBroadcast) +{ + new index = GetClientOfUserId(GetEventInt(event, "userid")); + + if (!IsPlayerZombie(index)) + { + return; + } + + new Float:vel[3] = {0.0, 0.0, 0.0}; + vel[2] = GetZombieJump(gZombieID[index]); + + SetPlayerVelocity(index, vel); +} \ No newline at end of file diff --git a/src/zriot/global.inc b/src/zriot/global.inc new file mode 100644 index 0000000..ef20548 --- /dev/null +++ b/src/zriot/global.inc @@ -0,0 +1,64 @@ +/** + * ==================== + * Zombie Riot + * File: global.inc + * Author: Greyscale + * ==================== + */ + +new Handle:hOnClientZombie = INVALID_HANDLE; +new Handle:hOnClientHuman = INVALID_HANDLE; +new Handle:hOnClientHUDUpdate = INVALID_HANDLE; + +CreateGlobals() +{ + CreateNative("ZRiot_IsClientZombie", Native_IsClientZombie); + CreateNative("ZRiot_Zombie", Native_Zombie); + CreateNative("ZRiot_Human", Native_Human); + CreateNative("ZRiot_GetZombieTeam", Native_GetZombieTeam); + CreateNative("ZRiot_GetHumanTeam", Native_GetHumanTeam); + + hOnClientZombie = CreateGlobalForward("ZRiot_OnClientZombie", ET_Ignore, Param_Cell); + hOnClientHuman = CreateGlobalForward("ZRiot_OnClientHuman", ET_Ignore, Param_Cell); + hOnClientHUDUpdate = CreateGlobalForward("ZRiot_OnClientHUDUpdate", ET_Ignore, Param_Cell, Param_String); +} + +public Native_IsClientZombie(Handle:plugin, argc) +{ + new client = GetNativeCell(1); + if (!client) + ThrowNativeError(SP_ERROR_INDEX, "Client index %d is not in the game", client); + + return bZombie[GetNativeCell(1)]; +} + +public Native_GetZombieTeam(Handle:plugin, argc) +{ + return gZombieTeam; +} + +public Native_GetHumanTeam(Handle:plugin, argc) +{ + return gHumanTeam; +} + +public Native_Zombie(Handle:plugin, argc) +{ + new client = GetNativeCell(1); + if (!client) + ThrowNativeError(SP_ERROR_INDEX, "Client index %d is not in the game", client); + + ZRiot_Zombie(client); +} + +public Native_Human(Handle:plugin, argc) +{ + new client = GetNativeCell(1); + if (!client) + ThrowNativeError(SP_ERROR_INDEX, "Client index %d is not in the game", client); + + if (IsFakeClient(client)) + ThrowNativeError(SP_ERROR_INDEX, "Bots cannot be moved to the human team"); + + ZRiot_Human(client); +} \ No newline at end of file diff --git a/src/zriot/hud.inc b/src/zriot/hud.inc new file mode 100644 index 0000000..3e4276b --- /dev/null +++ b/src/zriot/hud.inc @@ -0,0 +1,110 @@ +/** + * ==================== + * Zombie Riot + * File: hud.inc + * Author: Greyscale + * ==================== + */ + +public Action:HUD(Handle:timer) +{ + UpdateHUDAll(); +} + +UpdateHUD(clients[], numClients) +{ + new bool:hud = GetConVarBool(gCvars[CVAR_HUD]); + + if (tHUD == INVALID_HANDLE || !hud) + { + return; + } + + new bool:targeting = GetConVarBool(gCvars[CVAR_TARGETING]); + + new livezombies = GetLiveZombieCount(); + new livehumans = GetLiveHumanCount(); + + decl String:display[32]; + decl String:targetname[64]; + + GetDayDisplay(gDay, display, sizeof(display)); + + for (new x = 0; x < numClients; x++) + { + if (!IsClientInGame(clients[x]) || IsFakeClient(clients[x]) || GetClientTeam(clients[x]) == CS_TEAM_NONE) + { + continue; + } + + new target = GetClientTarget(clients[x]); + if (targeting && target != -1 && IsPlayerZombie(target) && GetClientTeam(clients[x]) != CS_TEAM_SPECTATOR) + { + GetClientName(target, targetname, sizeof(targetname)); + + new health = GetClientHealth(target); + health = (health >= 0) ? health : 0; + + ZRiot_HudHint(clients[x], "HUD target", gDay + 1, dCount, display, livezombies, livehumans, target, health); + } + else + { + ZRiot_HudHint(clients[x], "HUD", gDay + 1, dCount, display, livezombies, livehumans); + } + } +} + +stock UpdateHUDClient(client) +{ + if (!IsClientInGame(client) || GetClientTeam(x) == CS_TEAM_NONE) + { + return; + } + + new clients[1]; + clients[0] = client; + + UpdateHUD(clients, 1); +} + +stock UpdateHUDAll() +{ + new maxplayers = GetMaxClients(); + + new clients[maxplayers]; + new count = 0; + + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || GetClientTeam(x) == CS_TEAM_NONE) + { + continue; + } + + clients[count++] = x; + } + + UpdateHUD(clients, count); +} + +GetLiveHumanCount() +{ + new humansleft = 0; + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || !IsPlayerAlive(x) || !IsPlayerHuman(x)) + { + continue; + } + + humansleft++; + } + + return humansleft; +} + +GetLiveZombieCount() +{ + return GetDayCount(gDay) - gZombiesKilled; +} \ No newline at end of file diff --git a/src/zriot/offsets.inc b/src/zriot/offsets.inc new file mode 100644 index 0000000..db22581 --- /dev/null +++ b/src/zriot/offsets.inc @@ -0,0 +1,194 @@ +/** + * ==================== + * Zombie Riot + * File: offsets.inc + * Author: Greyscale + * ==================== + */ + +new offsBaseVelocity; +new offsGetVelocity2; +new offsSpeed; +new offsCollision; +new offsMoney; +new offsFOV; +new offsBuyZone; +new offsFadeMin; +new offsFadeMax; + +new Handle:hGameConf = INVALID_HANDLE; +new Handle:hTerminateRound = INVALID_HANDLE; + +FindOffsets() +{ + offsBaseVelocity = FindSendPropInfo("CBasePlayer", "m_vecBaseVelocity"); + if (offsBaseVelocity == -1) + { + SetFailState("Couldn't find \"m_vecBaseVelocity\"!"); + } + + offsGetVelocity2 = FindSendPropInfo("CBasePlayer", "m_vecVelocity[2]"); + if (offsGetVelocity2 == -1) + { + SetFailState("Couldn't find \"m_vecVelocity[2]\"!"); + } + + offsSpeed = FindSendPropInfo("CCSPlayer", "m_flLaggedMovementValue"); + if (offsSpeed == -1) + { + SetFailState("Couldn't find \"m_flLaggedMovementValue\"!"); + } + + offsCollision = FindSendPropInfo("CBaseEntity", "m_CollisionGroup"); + if (offsCollision == -1) + { + SetFailState("Couldn't find \"m_CollisionGroup\"!"); + } + + offsMoney = FindSendPropInfo("CCSPlayer", "m_iAccount"); + if (offsMoney == -1) + { + SetFailState("Couldn't find \"m_iAccount\"!"); + } + + offsFOV = FindSendPropInfo("CBasePlayer", "m_iDefaultFOV"); + if (offsFOV == -1) + { + SetFailState("Couldn't find \"m_iDefaultFOV\"!"); + } + + offsBuyZone = FindSendPropInfo("CCSPlayer", "m_bInBuyZone"); + if (offsBuyZone == -1) + { + SetFailState("Couldn't find \"m_bInBuyZone\"!"); + } + + offsFadeMin = FindSendPropInfo("CCSPlayer", "m_fadeMinDist"); + if (offsFadeMin == -1) + { + SetFailState("Couldn't find \"m_fadeMinDist\"!"); + } + + offsFadeMax = FindSendPropInfo("CCSPlayer", "m_fadeMaxDist"); + if (offsFadeMax == -1) + { + SetFailState("Couldn't find \"m_fadeMaxDist\"!"); + } +} + +SetupGameData() +{ + hGameConf = LoadGameConfigFile("plugin.zombieriot"); + + StartPrepSDKCall(SDKCall_GameRules); + PrepSDKCall_SetFromConf(hGameConf, SDKConf_Signature, "TerminateRound"); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + hTerminateRound = EndPrepSDKCall(); +} + +SetPlayerVelocity(client, const Float:vec[3]) +{ + SetEntDataVector(client, offsBaseVelocity, vec, true); +} + +SetPlayerSpeed(client, Float:speed) +{ + new Float:newspeed = speed / 300.0; + SetEntDataFloat(client, offsSpeed, newspeed, true); +} + +NoCollide(client, bool:nocollide) +{ + if (nocollide) + { + SetEntData(client, offsCollision, 2, 1, true); + } + else + { + SetEntData(client, offsCollision, 5, 1, true); + } +} + +SetPlayerMoney(client, amount) +{ + SetEntData(client, offsMoney, amount, 4, true); +} + +SetPlayerFOV(client, fov) +{ + SetEntData(client, offsFOV, fov, 1, true); +} + +bool:IsClientInBuyZone(client) +{ + return bool:GetEntData(client, offsBuyZone); +} + +SetPlayerMinDist(client, Float:mindist) +{ + SetEntDataFloat(client, offsFadeMin, mindist); +} + +SetPlayerMaxDist(client, Float:maxdist) +{ + SetEntDataFloat(client, offsFadeMax, maxdist); +} + +/** + * Remove all weapons. + * + * @param client The client index. + * @param weapons An array of boolean values for each weapon slot. True means remove, false means ignore. + */ +stock RemoveAllPlayersWeapons(client) +{ + new weaponindex; + for (new weaponslot = 0; weaponslot < 5; weaponslot++) + { + weaponindex = GetPlayerWeaponSlot(client, weaponslot); + if (weaponindex != -1) + { + Util_RemovePlayerItem(client, weaponindex); + } + } + + // Remove left-over projectiles. + WepLib_GrenadeStripAll(client); +} + +/** + * Used to explicitly remove projectiles from a client. + * + * @param client The client index. + */ +stock WepLib_GrenadeStripAll(client) +{ + // While GetPlayerWeaponSlot returns a valid projectile, remove it and then test again. + new grenade = GetPlayerWeaponSlot(client, 3); + while (grenade != -1) + { + Util_RemovePlayerItem(client, grenade); + grenade = GetPlayerWeaponSlot(client, 3); + } +} + +/** + * Fully remove a weapon from a client's inventory and the world. + * + * @param client The client whose weapon to remove. + * @param weaponindex The weapon index. + */ +stock Util_RemovePlayerItem(client, weaponindex) +{ + RemovePlayerItem(client, weaponindex); + RemoveEdict(weaponindex); +} + +TerminateRound(Float:delay, reason) +{ + if (tHUD == INVALID_HANDLE) + return; + + SDKCall(hTerminateRound, delay, reason); +} \ No newline at end of file diff --git a/src/zriot/overlays.inc b/src/zriot/overlays.inc new file mode 100644 index 0000000..029026c --- /dev/null +++ b/src/zriot/overlays.inc @@ -0,0 +1,43 @@ +/** + * ==================== + * Zombie Riot + * File: overlays.inc + * Author: Greyscale + * ==================== + */ + +ShowOverlays(Float:time, winner) +{ + decl String:overlay[64]; + if (winner == gZombieTeam) + { + GetConVarString(gCvars[CVAR_OVERLAYS_ZOMBIE], overlay, sizeof(overlay)); + } + else if (winner == gHumanTeam) + { + GetConVarString(gCvars[CVAR_OVERLAYS_HUMAN], overlay, sizeof(overlay)); + } + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + continue; + + DisplayClientOverlay(x, overlay); + } + + CreateTimer(time, KillOverlays); +} + +public Action:KillOverlays(Handle:timer) +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + continue; + + ClientCommand(x, "r_screenoverlay \"\""); + } +} \ No newline at end of file diff --git a/src/zriot/sayhooks.inc b/src/zriot/sayhooks.inc new file mode 100644 index 0000000..31fbc8f --- /dev/null +++ b/src/zriot/sayhooks.inc @@ -0,0 +1,113 @@ +/** + * ==================== + * Zombie Riot + * File: sayhooks.inc + * Author: Greyscale + * ==================== + */ + +HookChatCmds() +{ + RegConsoleCmd("say", SayCommand); + RegConsoleCmd("say_team", SayCommand); +} + +public Action:SayCommand(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!client || !enabled) + { + return Plugin_Continue; + } + + decl String:args[192]; + + GetCmdArgString(args, sizeof(args)); + ReplaceString(args, sizeof(args), "\"", ""); + + if (StrEqual(args, "!market", false)) + { + Market(client); + return Plugin_Handled; + } + + return Plugin_Continue; +} + +Market(client) +{ + if (!market) + { + ZRiot_PrintToChat(client, "Feature is disabled"); + + return; + } + + new bool:buyzone = GetConVarBool(gCvars[CVAR_ZMARKET_BUYZONE]); + if (!IsClientInBuyZone(client) && buyzone) + { + ZRiot_PrintCenterText(client, "Market out of buyzone"); + + return; + } + + SetGlobalTransTarget(client); + + decl String:title[64]; + decl String:rebuy[64]; + + Format(title, sizeof(title), "%t\n ", "Market title"); + Format(rebuy, sizeof(rebuy), "%t\n ", "Market rebuy"); + + Market_Send(client, title, rebuy); +} + +public bool:Market_OnWeaponSelected(client, String:weaponid[]) +{ + if (!weaponid[0] || !IsPlayerAlive(client)) + { + return false; + } + + if (IsPlayerZombie(client)) + { + ZRiot_PrintToChat(client, "Zombie cant use weapon"); + + return false; + } + + if (StrEqual(weaponid, "rebuy")) + { + return true; + } + + decl String:display[64]; + decl String:weapon[32]; + new price; + + if (!Market_GetWeaponIDInfo(weaponid, display, weapon, price)) + { + return false; + } + + ReplaceString(weapon, sizeof(weapon), "weapon_", ""); + + if (IsWeaponRestricted(weapon)) + { + ZRiot_PrintToChat(client, "Weapon is restricted", weapon); + + return false; + } + + return true; +} + +public Market_PostOnWeaponSelected(client, &bool:allowed) +{ + if (!allowed) + { + return; + } + + Market(client); +} \ No newline at end of file diff --git a/src/zriot/targeting.inc b/src/zriot/targeting.inc new file mode 100644 index 0000000..c329276 --- /dev/null +++ b/src/zriot/targeting.inc @@ -0,0 +1,82 @@ +/** + * ==================== + * Zombie Riot + * File: targeting.inc + * Author: Greyscale + * ==================== + */ + +new gTarget[MAXPLAYERS+1]; + +new bool:bTargeted[MAXPLAYERS+1][MAXPLAYERS+1]; + +TargetPlayer(attacker, client) +{ + if (!IsClientInGame(attacker) || !IsClientInGame(client)) + { + return; + } + + gTarget[attacker] = client; + + bTargeted[client][attacker] = true; +} + +GetClientTarget(client) +{ + if (gTarget[client] == -1 || !IsClientInGame(gTarget[client])) + { + return -1; + } + + return gTarget[client]; +} + +GetClientTargeters(client, clients[], maxClients) +{ + new count = 0; + for (new x = 1; x <= maxClients; x++) + { + if (!IsClientInGame(x) || !bTargeted[client][x]) + { + continue; + } + + clients[count++] = x; + } + + return count; +} + +FindClientNextTarget(client) +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + { + continue; + } + + if (bTargeted[x][client]) + { + return x; + } + } + + return -1; +} + +RemoveTargeters(client) +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + bTargeted[client][x] = false; + + if (gTarget[x] == client) + { + gTarget[x] = FindClientNextTarget(x); + } + } +} \ No newline at end of file diff --git a/src/zriot/teamcontrol.inc b/src/zriot/teamcontrol.inc new file mode 100644 index 0000000..b26e67b --- /dev/null +++ b/src/zriot/teamcontrol.inc @@ -0,0 +1,202 @@ +/** + * ==================== + * Zombie Riot + * File: teamcontrol.inc + * Author: Greyscale + * ==================== + */ + +#define JOINTEAM_AUTOASSIGN 0 +#define JOINTEAM_SPECTATOR 1 +#define JOINTEAM_T 2 +#define JOINTEAM_CT 3 + +InitTeamControl() +{ + RegConsoleCmd("jointeam", Command_JoinTeam); + RegConsoleCmd("kill", Command_Kill); + RegConsoleCmd("spectate", Command_Spectate); +} + +public Action:Command_JoinTeam(client, argc) +{ + if (!client) + { + return Plugin_Continue; + } + + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!enabled) + { + return Plugin_Continue; + } + + decl String:args[8]; + GetCmdArgString(args, sizeof(args)); + + new jointeam = StringToInt(args); + + new team = GetClientTeam(client); + if (team == CS_TEAM_T || team == CS_TEAM_CT) + { + if (jointeam != JOINTEAM_SPECTATOR) + { + return Plugin_Handled; + } + else if (IsPlayerAlive(client)) + { + ChangeClientDeathCount(client, -1); + } + } + + return Plugin_Continue; +} + +public Action:Command_Kill(client, argc) +{ + if (!client) + { + return Plugin_Continue; + } + + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!enabled) + { + return Plugin_Continue; + } + + ZRiot_ReplyToCommand(client, "Suicide text"); + + return Plugin_Handled; +} + +public Action:Command_Spectate(client, argc) +{ + if (!client || !IsPlayerAlive(client)) + { + return Plugin_Continue; + } + + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!enabled) + { + return Plugin_Continue; + } + + ChangeClientDeathCount(client, -1); + + return Plugin_Continue; +} + +UpdateTeams() +{ + decl String:zombieteam[8]; + GetConVarString(gCvars[CVAR_ZOMBIETEAM], zombieteam, sizeof(zombieteam)); + + if (StrEqual(zombieteam, "t", false)) + { + gZombieTeam = CS_TEAM_T; + gHumanTeam = CS_TEAM_CT; + } + else if (StrEqual(zombieteam, "ct", false)) + { + gZombieTeam = CS_TEAM_CT; + gHumanTeam = CS_TEAM_T; + } + else + { + SetFailState("Invalid value for cvar zriot_zombieteam, see config file"); + return; + } + + AssignTeamAll(true); +} + +ResetZombies(bool:switchteam) +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x)) + { + continue; + } + + bZombie[x] = IsFakeClient(x); + } + + if (switchteam) + { + AssignTeamAll(false); + } +} + +public Action:AssignTeamTimer(Handle:timer) +{ + AssignTeamAll(false); +} + +AssignTeam(clients[], numClients, bool:spawn) +{ + for (new x = 0; x < numClients; x++) + { + if (!IsClientInGame(clients[x])) + { + continue; + } + + new team = GetClientTeam(clients[x]); + + if (IsPlayerZombie(clients[x])) + { + CS_SwitchTeam(clients[x], gZombieTeam); + + if (spawn && team != gZombieTeam) + { + CS_RespawnPlayer(clients[x]); + } + } + else + { + CS_SwitchTeam(clients[x], gHumanTeam); + + if (spawn && team != gHumanTeam) + { + CS_RespawnPlayer(clients[x]); + } + } + } +} + +stock AssignTeamClient(client, bool:spawn) +{ + if (!IsClientInGame(client)) + { + return; + } + + new clients[1]; + clients[0] = client; + + AssignTeam(clients, 1, spawn); +} + +stock AssignTeamAll(bool:spawn) +{ + new maxplayers = GetMaxClients(); + + new clients[maxplayers]; + new count = 0; + + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || GetClientTeam(x) < CS_TEAM_T) + { + continue; + } + + clients[count++] = x; + } + + AssignTeam(clients, count, spawn); +} \ No newline at end of file diff --git a/src/zriot/translation.inc b/src/zriot/translation.inc new file mode 100644 index 0000000..2868f64 --- /dev/null +++ b/src/zriot/translation.inc @@ -0,0 +1,124 @@ +/** + * ==================== + * Zombie Riot + * File: translation.inc + * Author: Greyscale + * ==================== + */ + +FormatTextString(String:text[], maxlen) +{ + Format(text, maxlen, "@green[%t] @default%s", "ZRiot", text); + + ReplaceString(text, maxlen, "@default","\x01"); + ReplaceString(text, maxlen, "@lgreen","\x03"); + ReplaceString(text, maxlen, "@green","\x04"); +} + +stock ZRiot_PrintToChat(client, any:...) +{ + decl String:phrase[192]; + + if (client) + { + SetGlobalTransTarget(client); + + VFormat(phrase, sizeof(phrase), "%t", 2); + FormatTextString(phrase, sizeof(phrase)); + + PrintToChat(client, phrase); + } + else + { + SetGlobalTransTarget(client); + + VFormat(phrase, sizeof(phrase), "%t", 2); + FormatTextString(phrase, sizeof(phrase)); + + PrintToServer(phrase); + + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (IsClientInGame(x)) + { + SetGlobalTransTarget(x); + + VFormat(phrase, sizeof(phrase), "%t", 2); + FormatTextString(phrase, sizeof(phrase)); + + PrintToChat(x, phrase); + } + } + } +} + +stock ZRiot_PrintCenterText(client, any:...) +{ + SetGlobalTransTarget(client); + + decl String:phrase[192]; + + VFormat(phrase, sizeof(phrase), "%t", 2); + + PrintCenterText(client, phrase); +} + +stock ZRiot_HudHint(client, any:...) +{ + SetGlobalTransTarget(client); + + decl String:phrase[192]; + + VFormat(phrase, sizeof(phrase), "%t", 2); + + new Handle:hHintText = StartMessageOne("HintText", client); + if (hHintText != INVALID_HANDLE) + { + BfWriteByte(hHintText, -1); + + Call_StartForward(hOnClientHUDUpdate); + Call_PushCell(client); + Call_PushStringEx(phrase, sizeof(phrase), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + Call_Finish(); + + BfWriteString(hHintText, phrase); + EndMessage(); + } +} + +stock ZRiot_PrintToServer(any:...) +{ + SetGlobalTransTarget(LANG_SERVER); + + decl String:phrase[192]; + decl String:buffer[192]; + + VFormat(phrase, sizeof(phrase), "%t", 1); + Format(buffer, sizeof(buffer), "[%t] %s", "ZRiot", phrase); + + PrintToServer(buffer); +} + +stock ZRiot_LogMessage(any:...) +{ + SetGlobalTransTarget(LANG_SERVER); + + decl String:phrase[192]; + + VFormat(phrase, sizeof(phrase), "%t", 1); + + LogMessage(phrase); +} + +stock ZRiot_ReplyToCommand(client, any:...) +{ + decl String:phrase[192]; + + SetGlobalTransTarget(client); + + VFormat(phrase, sizeof(phrase), "%t", 2); + FormatTextString(phrase, sizeof(phrase)); + + ReplyToCommand(client, phrase); +} \ No newline at end of file diff --git a/src/zriot/weaponrestrict.inc b/src/zriot/weaponrestrict.inc new file mode 100644 index 0000000..c6f3668 --- /dev/null +++ b/src/zriot/weaponrestrict.inc @@ -0,0 +1,279 @@ +/** + * ==================== + * Zombie Riot + * File: weaponrestrict.inc + * Author: Greyscale + * ==================== + */ + +new Handle:restrictedWeapons = INVALID_HANDLE; + +enum WepRestrictQuery +{ + Successful, /** Weapon (un)restrict query was successful */ + Invalid, /** Weapon invalid */ + Existing, /** Already restricted */ +} + +InitWeaponRestrict() +{ + RegConsoleCmd("buy", BuyHook); + + restrictedWeapons = CreateArray(32, 0); +} + +ClientHookUse(client) +{ + SDKHook(client, SDKHook_WeaponCanUse, Weapon_CanUse); +} + +public Action:BuyHook(client, argc) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!enabled) + { + return Plugin_Continue; + } + + if (IsPlayerZombie(client)) + { + ZRiot_PrintToChat(client, "Zombie cant use weapon"); + + return Plugin_Handled; + } + + decl String:weapon[64]; + GetCmdArg(1, weapon, sizeof(weapon)); + + ReplaceString(weapon, sizeof(weapon), "weapon_", ""); + + if (IsWeaponRestricted(weapon)) + { + ZRiot_PrintToChat(client, "Weapon is restricted", weapon); + return Plugin_Handled; + } + + return Plugin_Continue; +} + +WepRestrictQuery:RestrictWeapon(const String:weapon[]) +{ + if (IsWeaponGroup(weapon)) + { + RestrictWeaponGroup(weapon); + + ZRiot_PrintToChat(0, "Weapon group has been restricted", weapon); + + return Successful; + } + + if (!IsWeaponRestricted(weapon)) + { + PushArrayString(restrictedWeapons, weapon); + + ZRiot_PrintToChat(0, "Weapon has been restricted", weapon); + + return Successful; + } + + return Existing; +} + +RestrictWeaponGroup(const String:group[]) +{ + if (StrEqual(group, "pistols", false)) + { + PushArrayString(restrictedWeapons, "glock"); + PushArrayString(restrictedWeapons, "usp"); + PushArrayString(restrictedWeapons, "p228"); + PushArrayString(restrictedWeapons, "deagle"); + PushArrayString(restrictedWeapons, "elite"); + PushArrayString(restrictedWeapons, "fiveseven"); + } + else if (StrEqual(group, "shotguns", false)) + { + PushArrayString(restrictedWeapons, "m3"); + PushArrayString(restrictedWeapons, "xm1014"); + } + else if (StrEqual(group, "smgs", false)) + { + PushArrayString(restrictedWeapons, "tmp"); + PushArrayString(restrictedWeapons, "mac10"); + PushArrayString(restrictedWeapons, "mp5navy"); + PushArrayString(restrictedWeapons, "ump45"); + PushArrayString(restrictedWeapons, "p90"); + } + else if (StrEqual(group, "rifles", false)) + { + PushArrayString(restrictedWeapons, "galil"); + PushArrayString(restrictedWeapons, "famas"); + PushArrayString(restrictedWeapons, "ak47"); + PushArrayString(restrictedWeapons, "m4a1"); + PushArrayString(restrictedWeapons, "sg552"); + PushArrayString(restrictedWeapons, "bullpup"); + } + else if (StrEqual(group, "snipers", false)) + { + PushArrayString(restrictedWeapons, "scout"); + PushArrayString(restrictedWeapons, "sg550"); + PushArrayString(restrictedWeapons, "g3sg1"); + PushArrayString(restrictedWeapons, "awp"); + } +} + +WepRestrictQuery:UnRestrictWeapon(const String:weapon[]) +{ + if (IsWeaponGroup(weapon)) + { + UnRestrictWeaponGroup(weapon); + + ZRiot_PrintToChat(0, "Weapon group has been unrestricted", weapon); + + return Successful; + } + + new index = GetRestrictedWeaponIndex(weapon); + + if (index > -1) + { + RemoveFromArray(restrictedWeapons, index); + + ZRiot_PrintToChat(0, "Weapon has been unrestricted", weapon); + + return Successful; + } + + return Invalid; +} + +UnRestrictWeaponGroup(const String:group[]) +{ + if (StrEqual(group, "pistols", false)) + { + UnRestrictWeapon("glock"); + UnRestrictWeapon("usp"); + UnRestrictWeapon("p228"); + UnRestrictWeapon("deagle"); + UnRestrictWeapon("elite"); + UnRestrictWeapon("fiveseven"); + } + else if (StrEqual(group, "shotguns", false)) + { + UnRestrictWeapon("m3"); + UnRestrictWeapon("xm1014"); + } + else if (StrEqual(group, "smgs", false)) + { + UnRestrictWeapon("tmp"); + UnRestrictWeapon("mac10"); + UnRestrictWeapon("mp5navy"); + UnRestrictWeapon("ump45"); + UnRestrictWeapon("p90"); + } + else if (StrEqual(group, "rifles", false)) + { + UnRestrictWeapon("galil"); + UnRestrictWeapon("famas"); + UnRestrictWeapon("ak47"); + UnRestrictWeapon("m4a1"); + UnRestrictWeapon("sg552"); + UnRestrictWeapon("bullpup"); + } + else if (StrEqual(group, "snipers", false)) + { + UnRestrictWeapon("scout"); + UnRestrictWeapon("sg550"); + UnRestrictWeapon("g3sg1"); + UnRestrictWeapon("awp"); + } +} + +bool:IsWeaponRestricted(const String:weapon[]) +{ + for (new x = 0; x < GetArraySize(restrictedWeapons); x++) + { + decl String:restrictedweapon[32]; + GetArrayString(restrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon)); + + if (StrEqual(weapon, restrictedweapon, false)) + { + return true; + } + } + + return false; +} + +GetRestrictedWeaponIndex(const String:weapon[]) +{ + for (new x = 0; x < GetArraySize(restrictedWeapons); x++) + { + decl String:restrictedweapon[32]; + GetArrayString(restrictedWeapons, x, restrictedweapon, sizeof(restrictedweapon)); + ReplaceString(restrictedweapon, sizeof(restrictedweapon), "weapon_", ""); + + if (StrEqual(weapon, restrictedweapon, false)) + { + return x; + } + } + + return -1; +} + +bool:IsWeaponGroup(const String:weapon[]) +{ + return (StrEqual(weapon, "pistols", false) || StrEqual(weapon, "shotguns", false) || StrEqual(weapon, "smgs", false) || StrEqual(weapon, "rifles", false) || StrEqual(weapon, "snipers", false)); +} + +public Action:Weapon_CanUse(client, weapon) +{ + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!enabled) + { + return Plugin_Continue; + } + + new String:weaponname[32]; + if (!weapon || !GetEdictClassname(weapon, weaponname, sizeof(weaponname))) + { + return Plugin_Continue; + } + + ReplaceString(weaponname, sizeof(weaponname), "weapon_", ""); + + decl String:model[256]; + GetClientModel(client, model, sizeof(model)); + + ReplaceString(model, sizeof(model), ".mdl", ""); + + if (FindStringInArray(adtModels, model) > -1 && !StrEqual(weaponname, "knife")) + { + return Plugin_Handled; + } + + if (IsWeaponRestricted(weaponname)) + { + return Plugin_Handled; + } + + if (IsPlayerZombie(client) && !StrEqual(weaponname, "knife")) + { + if (StrEqual(weaponname, "glock") || StrEqual(weaponname, "usp")) + { + CreateTimer(0.0, RemoveSpawnWeapon, weapon); + } + + return Plugin_Handled; + } + + return Plugin_Continue; +} + +public Action:RemoveSpawnWeapon(Handle:timer, any:weapon) +{ + if (IsValidEdict(weapon)) + { + RemoveEdict(weapon); + } +} \ No newline at end of file diff --git a/src/zriot/zombie.inc b/src/zriot/zombie.inc new file mode 100644 index 0000000..e9fb9ca --- /dev/null +++ b/src/zriot/zombie.inc @@ -0,0 +1,493 @@ +/** + * ==================== + * Zombie Riot + * File: zombie.inc + * Author: Greyscale + * ==================== + */ + +new String:skyname[32]; +new String:hostname[256]; + +new gZombieID[MAXPLAYERS+1]; + +HookCommands() +{ + RegConsoleCmd("nightvision", Command_NightVision); +} + +public Action:Command_NightVision(client, argc) +{ + new bool:allow_disable = GetConVarBool(gCvars[CVAR_ZVISION_ALLOW_DISABLE]); + new bool:enabled = GetConVarBool(gCvars[CVAR_ENABLE]); + if (!allow_disable || !enabled) + { + return; + } + + if (!IsPlayerZombie(client)) + { + return; + } + + bZVision[client] = !bZVision[client]; + + if (bZVision[client]) + { + StartZVision(client); + } + else + { + StopZVision(client); + ClientCommand(client, "r_screenoverlay \"\""); + } +} + +FindMapSky() +{ + GetConVarString(FindConVar("sv_skyname"), skyname, sizeof(skyname)); +} + +FindHostname() +{ + GetConVarString(FindConVar("hostname"), hostname, sizeof(hostname)); +} + +ChangeLightStyle() +{ + new bool:dark = GetConVarBool(gCvars[CVAR_DARK]); + if (dark) + { + decl String:darkness[2]; + decl String:sky[32]; + + GetConVarString(gCvars[CVAR_DARK_LEVEL], darkness, sizeof(darkness)); + GetConVarString(gCvars[CVAR_DARK_SKY], sky, sizeof(sky)); + + SetLightStyle(0, darkness); + SetConVarString(FindConVar("sv_skyname"), sky, true); + } + else + { + SetLightStyle(0, "n"); + SetConVarString(FindConVar("sv_skyname"), skyname, true); + } +} + +UpdateHostname() +{ + decl String:hostname_prefixed[256]; + + SetGlobalTransTarget(LANG_SERVER); + Format(hostname_prefixed, sizeof(hostname_prefixed), "%s %t", "Hostname prefix", hostname, gDay + 1, dCount); + + SetHostname(hostname_prefixed); +} + +Zombify(client, zombieid) +{ + gZombieID[client] = zombieid; + + RemoveAllPlayersWeapons(client); + new knife = GivePlayerItem(client, "weapon_knife"); + + if (knife != -1) + { + SetEntityRenderMode(knife, RENDER_TRANSALPHA); + SetEntityRenderColor(knife, 255, 255, 255, 0); + } + + ApplyZombieModel(client, zombieid); + ApplyZombieHealth(client, zombieid); + ApplyZombieSpeed(client, zombieid); + ApplyZombieGravity(client, zombieid); + ApplyZombieFOV(client, zombieid); + + if (bZVision[client]) + { + StartZVision(client); + } +} + +ZombiesWin() +{ + new bool:regression = GetConVarBool(gCvars[CVAR_REGRESSION]); + + if (gDay > 0 && regression) + { + gDay--; + } + + new bool:fade = GetConVarBool(gCvars[CVAR_ROUNDFADE]); + if (fade) + Fade(0, 2000, 2000, 2, 255, 0, 0, 255); + + new bool:overlays = GetConVarBool(gCvars[CVAR_OVERLAYS]); + if (overlays) + ShowOverlays(5.0, gZombieTeam); + + FreezeZombies(); +} + +HumansWin() +{ + gDay++; + + if (gDay + 1 > dCount) + { + gDay = 0; + + ZRiot_PrintToChat(0, "Game won"); + + GotoNextMap(); + } + + new bool:fade = GetConVarBool(gCvars[CVAR_ROUNDFADE]); + if (fade) + Fade(0, 2000, 2000, 2, 0, 0, 255, 255); + + new bool:overlays = GetConVarBool(gCvars[CVAR_OVERLAYS]); + if (overlays) + ShowOverlays(5.0, gHumanTeam); + + FreezeZombies(); +} + +RoundDraw() +{ + Fade(0, 1000, 2000, 2, 0, 0, 0, 255); +} + +FreezeZombies() +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || !IsPlayerAlive(x) || !IsPlayerZombie(x)) + { + continue; + } + + SetEntProp(x, Prop_Data, "m_takedamage", 0, 1); + SetEntProp(x, Prop_Data, "m_fFlags", FL_ATCONTROLS); + } +} + +public Action:UnfreezeZombies(Handle:timer) +{ + new maxplayers = GetMaxClients(); + for (new x = 1; x <= maxplayers; x++) + { + if (!IsClientInGame(x) || !IsPlayerAlive(x) || !IsPlayerZombie(x)) + { + continue; + } + + SetEntProp(x, Prop_Data, "m_takedamage", 2, 1); + SetEntProp(x, Prop_Data, "m_fFlags", FL_ONGROUND); + } + + tFreeze = INVALID_HANDLE; +} + +RemoveObjectives() +{ + decl String:classname[64]; + + new maxentities = GetMaxEntities(); + for (new x = 0; x <= maxentities; x++) + { + if(!IsValidEdict(x)) + { + continue; + } + + GetEdictClassname(x, classname, sizeof(classname)); + if( StrEqual(classname, "func_bomb_target") || + StrEqual(classname, "func_hostage_rescue") || + StrEqual(classname, "c4") || + StrEqual(classname, "hostage_entity")) + { + RemoveEdict(x); + } + } +} + +public Action:JoinZombie(Handle:timer, any:index) +{ + if (!IsClientInGame(index)) + { + return; + } + + ZRiot_Zombie(index); +} + +public Action:ZombieRespawn(Handle:timer, any:index) +{ + if (!IsClientInGame(index)) + { + return; + } + + CS_RespawnPlayer(index); +} + +StartRespawnTimer(client, bool:firstspawn) +{ + new respawn; + if (firstspawn) + { + respawn = GetConVarInt(gCvars[CVAR_FIRST_RESPAWN]); + } + else + { + respawn = GetConVarInt(gCvars[CVAR_RESPAWN]); + } + + if (!respawn) + { + return; + } + + if (tRespawn[client] != INVALID_HANDLE) + { + CloseHandle(tRespawn[client]); + } + + ZRiot_PrintCenterText(client, "Respawn time", respawn); + + gRespawnTime[client] = respawn; + tRespawn[client] = CreateTimer(1.0, HumanRespawn, client, TIMER_REPEAT); +} + +public Action:HumanRespawn(Handle:timer, any:index) +{ + if (!IsClientInGame(index)) + { + tRespawn[index] = INVALID_HANDLE; + + return Plugin_Stop; + } + + new team = GetClientTeam(index); + if (team == CS_TEAM_T || team == CS_TEAM_CT) + { + gRespawnTime[index]--; + } + + new timeremaining = (gRespawnTime[index] < 0) ? 0 : gRespawnTime[index]; + + ZRiot_PrintCenterText(index, "Respawn time", timeremaining); + + if (gRespawnTime[index] > 0) + { + return Plugin_Continue; + } + + tRespawn[index] = INVALID_HANDLE; + + CS_RespawnPlayer(index); + + return Plugin_Stop; +} + +StartZVision(client) +{ + if (tZVision[client] != INVALID_HANDLE) + { + CloseHandle(tZVision[client]); + tZVision[client] = INVALID_HANDLE; + } + + new bool:zvision = ZVision(client); + if (zvision) + { + new Float:redisplay = GetConVarFloat(gCvars[CVAR_ZVISION_REDISPLAY]); + tZVision[client] = CreateTimer(redisplay, ZVisionTimer, client, TIMER_REPEAT); + } +} + +StopZVision(client) +{ + if (tZVision[client] != INVALID_HANDLE) + { + CloseHandle(tZVision[client]); + tZVision[client] = INVALID_HANDLE; + } +} + +bool:ZVision(client) +{ + if (IsFakeClient(client)) + { + return false; + } + + decl String:zvision[256]; + GetZombieZVision(gZombieID[client], zvision, sizeof(zvision)); + + if (zvision[0]) + { + DisplayClientOverlay(client, zvision); + + return true; + } + + return false; +} + +public Action:ZVisionTimer(Handle:timer, any:index) +{ + if (!IsClientInGame(index) || !IsPlayerZombie(index)) + { + tZVision[index] = INVALID_HANDLE; + + return Plugin_Stop; + } + + ZVision(index); + + return Plugin_Continue; +} + +public Action:RemoveRagdoll(Handle:timer, any:ragdoll) +{ + if (ragdoll == -1 || !IsValidEdict(ragdoll)) + { + return; + } + + decl String:classname[64]; + GetEdictClassname(ragdoll, classname, sizeof(classname)); + + if (!StrEqual(classname, "cs_ragdoll")) + { + return; + } + + RemoveEdict(ragdoll); +} + +Fade(client, speed, hold, type, red, green, blue, alpha) +{ + new Handle:hFade = INVALID_HANDLE; + + if (client) + { + hFade = StartMessageOne("Fade", client); + } + else + { + hFade = StartMessageAll("Fade"); + } + + if (hFade != INVALID_HANDLE) + { + // type 1 = IN + // type 2 = OUT + + BfWriteShort(hFade, speed); + BfWriteShort(hFade, hold); + BfWriteShort(hFade, type); + BfWriteByte(hFade, red); + BfWriteByte(hFade, green); + BfWriteByte(hFade, blue); + BfWriteByte(hFade, alpha); + EndMessage(); + } +} + +InitClientDeathCount(client) +{ + if (IsFakeClient(client)) + return; + + decl String:steamid[64]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + StrCat(steamid, sizeof(steamid), "_iDeaths"); + + SetTrieValue(trieDeaths, steamid, 0, false); +} + +ChangeClientDeathCount(client, value) +{ + if (IsFakeClient(client)) + return; + + decl String:steamid[64]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + StrCat(steamid, sizeof(steamid), "_iDeaths"); + + new newvalue = value != 0 ? GetClientDeathCount(client) + value : 0; + SetTrieValue(trieDeaths, steamid, newvalue, true); +} + +GetClientDeathCount(client) +{ + if (IsFakeClient(client)) + return 0; + + decl String:steamid[64]; + GetClientAuthString(client, steamid, sizeof(steamid)); + + StrCat(steamid, sizeof(steamid), "_iDeaths"); + + new value; + GetTrieValue(trieDeaths, steamid, value); + + return value; +} + +SetHostname(const String:name[]) +{ + new bool:update_hostname = GetConVarBool(gCvars[CVAR_HOSTNAME_UPDATE]); + if (!update_hostname) + { + return; + } + + ServerCommand("hostname \"%s\"", name); +} + +ZRiot_Zombie(client) +{ + if (bZombie[client]) + { + return; + } + + bZombie[client] = true; + AssignTeamClient(client, true); + + Call_StartForward(hOnClientZombie); + Call_PushCell(client); + Call_Finish(); +} + +ZRiot_Human(client) +{ + if (!bZombie[client]) + { + return; + } + + bZombie[client] = false; + AssignTeamClient(client, true); + + Call_StartForward(hOnClientHuman); + Call_PushCell(client); + Call_Finish(); +} + +bool:IsPlayerZombie(client) +{ + return bZombie[client]; +} + +bool:IsPlayerHuman(client) +{ + return !bZombie[client]; +} \ No newline at end of file diff --git a/src/zriot/zombiedata.inc b/src/zriot/zombiedata.inc new file mode 100644 index 0000000..1ebca56 --- /dev/null +++ b/src/zriot/zombiedata.inc @@ -0,0 +1,297 @@ +/** + * ==================== + * Zombie Riot + * File: zombiedata.inc + * Author: Greyscale + * ==================== + */ + +enum ZRiot_ZombieData +{ + String:data_name[32], + String:data_model[256], + String:data_zvision[256], + bool:data_override_required, + data_health, + Float:data_speed, + Float:data_gravity, + Float:data_jump, + data_fov +} + +#define MAXZOMBIES 25 + +new String:modelSuffix[8][16] = {".dx80.vtx", ".dx90.vtx", ".mdl", ".phy", ".sw.vtx", ".vvd", ".xbox", ".xbox.vtx"}; + +new Handle:kvZombies = INVALID_HANDLE; + +new Handle:adtModels = INVALID_HANDLE; + +new arrayZombies[MAXZOMBIES][ZRiot_ZombieData]; +new Handle:adtZombies = INVALID_HANDLE; +new zCount; + +FileLinesToArray(Handle:array, const Handle:file) +{ + ClearArray(array); + + decl String:line[128]; + + while(!IsEndOfFile(file) && ReadFileLine(file, line, sizeof(line))) + { + if (StrContains(line, ";") == -1) + { + if (StrContains(line, "//") > -1) + { + SplitString(line, "//", line, sizeof(line)); + } + TrimString(line); + + if (!StrEqual(line, "", false)) + { + PushArrayString(array, line); + } + } + } +} + +LoadZombieData(bool:defaultconfig) +{ + decl String:path[PLATFORM_MAX_PATH]; + Format(path, sizeof(path), "%s/zombies.txt", gMapConfig); + + if (!defaultconfig && !FileExists(path)) + { + return; + } + + if (kvZombies != INVALID_HANDLE) + { + CloseHandle(kvZombies); + } + + kvZombies = CreateKeyValues("zombies"); + + if (!FileToKeyValues(kvZombies, path)) + { + SetFailState("\"%s\" failed to load", path); + } + + KvRewind(kvZombies); + if (!KvGotoFirstSubKey(kvZombies)) + { + SetFailState("No zombie data defined in \"%s\"", path); + } + + decl String:name[64]; + decl String:type[32]; + decl String:model[256]; + decl String:zvision[256]; + + zCount = 0; + + do + { + KvGetSectionName(kvZombies, name, sizeof(name)); + strcopy(arrayZombies[zCount][data_name], 32, name); + + KvGetString(kvZombies, "type", type, sizeof(type)); + arrayZombies[zCount][data_override_required] = (StrEqual(type, "override_required", false)); + + KvGetString(kvZombies, "model", model, sizeof(model)); + strcopy(arrayZombies[zCount][data_model], 256, model); + + KvGetString(kvZombies, "zvision", zvision, sizeof(zvision)); + strcopy(arrayZombies[zCount][data_zvision], 256, zvision); + + arrayZombies[zCount][data_health] = KvGetNum(kvZombies, "health", 500); + + arrayZombies[zCount][data_speed] = KvGetFloat(kvZombies, "speed", 300.0); + + arrayZombies[zCount][data_gravity] = KvGetFloat(kvZombies, "gravity", 1.0); + + arrayZombies[zCount][data_jump] = KvGetFloat(kvZombies, "jump", 1.0); + + arrayZombies[zCount][data_fov] = KvGetNum(kvZombies, "fov", 90); + + zCount++; + } while (KvGotoNextKey(kvZombies)); +} + +LoadModelData() +{ + decl String:path[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, path, sizeof(path), "configs/zriot/models.txt"); + + new Handle:fileModels = OpenFile(path, "r"); + + if (fileModels == INVALID_HANDLE) + { + SetFailState("\"%s\" missing from server", path); + } + + if (adtModels != INVALID_HANDLE) + { + CloseHandle(adtModels); + } + + adtModels = CreateArray(256, 0); + + FileLinesToArray(adtModels, fileModels); + + if (!GetArraySize(adtModels)) + { + SetFailState("No models listed in models.txt, please add some models then restart"); + } + + decl String:model[256]; + decl String:modelpath[256]; + + new modelsize = GetArraySize(adtModels); + for (new x = 0; x < modelsize; x++) + { + for (new y = 0; y < 8; y++) + { + GetArrayString(adtModels, x, model, sizeof(model)); + Format(modelpath, sizeof(modelpath), "%s%s", model, modelSuffix[y]); + + if (FileExists(modelpath)) + { + AddFileToDownloadsTable(modelpath); + } + } + } + + CloseHandle(fileModels); +} + +LoadDownloadData() +{ + decl String:path[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, path, sizeof(path), "configs/zriot/downloads.txt"); + + new Handle:fileDownloads = OpenFile(path, "r"); + + if (fileDownloads == INVALID_HANDLE) + { + SetFailState("\"%s\" missing from server", path); + } + + new Handle:arrayDownloads = CreateArray(256, 0); + + FileLinesToArray(arrayDownloads, fileDownloads); + + decl String:file[256]; + + new downloadsize = GetArraySize(arrayDownloads); + for (new x = 0; x < downloadsize; x++) + { + GetArrayString(arrayDownloads, x, file, sizeof(file)); + if (FileExists(file)) + { + AddFileToDownloadsTable(file); + } + else + { + ZRiot_LogMessage("File load failed", file); + } + } + + CloseHandle(fileDownloads); + CloseHandle(arrayDownloads); +} + +FindZombieIDByName(const String:name[]) +{ + for (new x = 0; x < zCount; x++) + { + if (StrEqual(name, arrayZombies[x][data_name], false)) + { + return x; + } + } + + return -1; +} + +bool:IsValidZombieID(zombieid) +{ + if (zombieid > -1 && zombieid < zCount) + { + return true; + } + + return false; +} + +bool:IsOverrideRequired(zombieid) +{ + if (IsValidZombieID(zombieid)) + { + return arrayZombies[zombieid][data_override_required]; + } + + return false; +} + +ApplyZombieModel(client, zombieid) +{ + if (IsValidZombieID(zombieid)) + { + decl String:model[256]; + strcopy(model, sizeof(model), arrayZombies[zombieid][data_model]); + + PrecacheModel(model); + SetEntityModel(client, model); + } +} + +GetZombieZVision(zombieid, String:zvision[], maxlen) +{ + if (IsValidZombieID(zombieid)) + { + strcopy(zvision, maxlen, arrayZombies[zombieid][data_zvision]); + } +} + +ApplyZombieHealth(client, zombieid) +{ + if (IsValidZombieID(zombieid)) + { + SetEntityHealth(client, arrayZombies[zombieid][data_health]); + } +} + +ApplyZombieSpeed(client, zombieid) +{ + if (IsValidZombieID(zombieid)) + { + SetPlayerSpeed(client, arrayZombies[zombieid][data_speed]); + } +} + +ApplyZombieGravity(client, zombieid) +{ + if (IsValidZombieID(zombieid)) + { + SetEntityGravity(client, arrayZombies[zombieid][data_gravity]); + } +} + +Float:GetZombieJump(zombieid) +{ + if (IsValidZombieID(zombieid)) + { + return arrayZombies[zombieid][data_jump]; + } + + return 0.0; +} + +ApplyZombieFOV(client, zombieid) +{ + if (IsValidZombieID(zombieid)) + { + SetPlayerFOV(client, arrayZombies[zombieid][data_fov]); + } +} \ No newline at end of file diff --git a/src/zriot/zombieriot.inc b/src/zriot/zombieriot.inc new file mode 100644 index 0000000..a91f1c0 --- /dev/null +++ b/src/zriot/zombieriot.inc @@ -0,0 +1,117 @@ +/** + * ==================== + * Zombie Riot + * File: zombieriot.inc + * Author: Greyscale + * ==================== + */ + +#define Target_Bombed 0 // Target Successfully Bombed! +#define VIP_Escaped 1 // The VIP has escaped! +#define VIP_Assassinated 2 // VIP has been assassinated! +#define Terrorists_Escaped 3 // The terrorists have escaped! +#define CTs_PreventEscape 4 // The CT's have prevented most of the terrorists from escaping! +#define Escaping_Terrorists_Neutralized 5 // Escaping terrorists have all been neutralized! +#define Bomb_Defused 6 // The bomb has been defused! +#define CTs_Win 7 // Counter-Terrorists Win! +#define Terrorists_Win 8 // Terrorists Win! +#define Round_Draw 9 // Round Draw! +#define All_Hostages_Rescued 10 // All Hostages have been rescued! +#define Target_Saved 11 // Target has been saved! +#define Hostages_Not_Rescued 12 // Hostages have not been rescued! +#define Terrorists_Not_Escaped 13 // Terrorists have not escaped! +#define VIP_Not_Escaped 14 // VIP has not escaped! +#define Game_Commencing 15 // Game Commencing! + +#define DXLEVEL_MIN 90 + +#define DEFAULT_FOV 90 +#define DEFAULT_GRAVITY 1.0 + +new bool:market; + +new String:gMapConfig[PLATFORM_MAX_PATH]; + +new gDay; + +new gZombieTeam; +new gHumanTeam; + +new gZombiesKilled; + +new dxLevel[MAXPLAYERS+1]; + +new bool:bZombie[MAXPLAYERS+1]; +new Handle:trieDeaths = INVALID_HANDLE; + +new gRespawnTime[MAXPLAYERS+1]; +new Handle:tRespawn[MAXPLAYERS+1]; +new Handle:tZVision[MAXPLAYERS+1]; + +new bool:bZVision[MAXPLAYERS+1]; + +new Handle:tHUD = INVALID_HANDLE; +new Handle:tFreeze = INVALID_HANDLE; + +new QueryCookie:mat_dxlevel; + +FindClientDXLevel(client) +{ + if (IsFakeClient(client)) + { + return; + } + + mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", DXLevelClientQuery); +} + +public DXLevelClientQuery(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) +{ + if (cookie != mat_dxlevel) + { + return; + } + + dxLevel[client] = 0; + + if (result != ConVarQuery_Okay) + { + return; + } + + dxLevel[client] = StringToInt(cvarValue); +} + +DisplayClientOverlay(client, const String:overlay[]) +{ + if (!dxLevel[client]) + { + FindClientDXLevel(client); + + return; + } + + if (dxLevel[client] >= DXLEVEL_MIN) + { + ClientCommand(client, "r_screenoverlay \"%s\"", overlay); + } + else + { + ZRiot_PrintCenterText(client, "DX90 not supported", dxLevel[client], DXLEVEL_MIN); + } +} + +stock GotoNextMap() +{ + new Handle:timelimit = FindConVar("mp_timelimit"); + + if (timelimit == INVALID_HANDLE) + { + return; + } + + new flags = GetConVarFlags(timelimit) & FCVAR_NOTIFY; + SetConVarFlags(timelimit, flags); + + SetConVarInt(timelimit, 1); +} \ No newline at end of file